diff options
| author | Jakub Zelenka <bukka@php.net> | 2016-02-29 19:31:20 +0000 |
|---|---|---|
| committer | Jakub Zelenka <bukka@php.net> | 2016-02-29 19:31:20 +0000 |
| commit | 70141093a731049ee9220e9e965f61ded56ed4d5 (patch) | |
| tree | 6e67b382253a186889bfdc37c31062d6fb9880d9 | |
| parent | e453af3851daf08f5af9b45fc7819c3a9c336f1e (diff) | |
| parent | 97294aca7e066443291cc2d77f8674ac23eabb32 (diff) | |
| download | php-git-70141093a731049ee9220e9e965f61ded56ed4d5.tar.gz | |
Merge branch 'master' into openssl_aead
541 files changed, 25624 insertions, 12268 deletions
diff --git a/Makefile.global b/Makefile.global index c571f3455d..9b29d5112b 100644 --- a/Makefile.global +++ b/Makefile.global @@ -53,7 +53,7 @@ install-headers: paths="$$paths $(INSTALL_ROOT)$(phpincludedir)/$$i"; \ done; \ $(mkinstalldirs) $$paths && \ - echo "Installing header files: $(INSTALL_ROOT)$(phpincludedir)/" && \ + echo "Installing header files: $(INSTALL_ROOT)$(phpincludedir)/" && \ for i in `echo $(INSTALL_HEADERS)`; do \ if test "$(PHP_PECL_EXTENSION)"; then \ src=`echo $$i | $(SED) -e "s#ext/$(PHP_PECL_EXTENSION)/##g"`; \ @@ -4,6 +4,9 @@ PHP NEWS - Core: . Fixed bug #62210 (Exceptions can leak temporary variables). (Dmitry, Bob) + . Fixed bug #69989 (Generators don't participate in cycle GC). (Nikita) + . Fixed buf #71572 (String offset assignment from an empty string inserts + null byte). (Francois) . Implemented the RFC `Support Class Constant Visibility`. (Sean DuBois, Reeze Xia, Dmitry) . Added void return type. (Andrea) @@ -15,14 +18,29 @@ PHP NEWS - Hash: . Added SHA3 fixed mode algorithms (224, 256, 384, and 512 bit). (Sara) +- JSON: + . Escaped U+2028 and U+2029 when JSON_UNESCAPED_UNICODE is supplied as + json_encode options and added JSON_UNESCAPED_LINE_TERMINATORS to restore + the previous behaviour. (Eddie Kohler) + - PDO_Firebird: - . Fixed bug #60052 (Integer returned as a 64bit integer on X64_86). (Mariuz) + . Fixed bug #60052 (Integer returned as a 64bit integer on X86_64). (Mariuz) - Pgsql: . Implemented FR #31021 (pg_last_notice() is needed to get all notice messages). (Yasuo) . Implemented FR #48532 (Allow pg_fetch_all() to index numerically). (Yasuo) +- Session: + . Improved fix for bug #68063 (Empty session IDs do still start sessions). + (Yasuo) + . Fixed bug #71038 (session_start() returns TRUE on failure). + Session save handlers must return 'string' always for successful read. + i.e. Non-existing session read must return empty string. PHP 7.0 is made + not to tolerate buggy return value. (Yasuo) + . Fixed bug #71394 (session_regenerate_id() must close opened session on + errors). (Yasuo) + - SQLite3: . Implemented FR #71159 (Upgraded bundled SQLite lib to 3.9.2). (Laruence) diff --git a/README.GIT-RULES b/README.GIT-RULES index 5f35cc4f3e..a88a8c9f32 100644 --- a/README.GIT-RULES +++ b/README.GIT-RULES @@ -79,7 +79,7 @@ The next few rules are more of a technical nature:: should be noted in both PHP-5.4/NEWS and PHP-5.5/NEWS but not master, which is not a public released version yet. - 3. Do not commit multiple file and dump all messages in one commit. If you + 3. Do not commit multiple files and dump all messages in one commit. If you modified several unrelated files, commit each group separately and provide a nice commit message for each one. See example below. diff --git a/README.REDIST.BINS b/README.REDIST.BINS index 968c3ec0c8..9779827534 100644 --- a/README.REDIST.BINS +++ b/README.REDIST.BINS @@ -5,17 +5,16 @@ 5. ext/standard crypt 6. ext/standard crypt's blowfish implementation 7. Sqlite/Sqlite3 ext/sqlite3 ext/sqlite -8. ext/json/json_parser -9. ext/standard/rand -10. ext/standard/scanf -11. ext/standard/strnatcmp.c -12. ext/standard/uuencode -13. libxmlrpc ext/xmlrpc -14. libzip ext/zip -15. main/snprintf.c -16. main/strlcat -17. main/strlcpy -18. libgd see ext/gd/libgd/COPYING +8. ext/standard/rand +9. ext/standard/scanf +10. ext/standard/strnatcmp.c +11. ext/standard/uuencode +12. libxmlrpc ext/xmlrpc +13. libzip ext/zip +14. main/snprintf.c +15. main/strlcat +16. main/strlcpy +17. libgd see ext/gd/libgd/COPYING 5. ext/standard crypt @@ -104,31 +103,7 @@ a legal notice, here is a blessing: May you share freely, never taking more than you give. -8. ext/json/json_parser -Copyright (c) 2005 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. - - -9. ext/standard/rand +8. ext/standard/rand The following php_mt_...() functions are based on a C++ class MTRand by Richard J. Wagner. For more information see the web page at http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html @@ -181,7 +156,7 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -10. ext/standard/scanf +9. ext/standard/scanf scanf.c -- This file contains the base code which implements sscanf and by extension @@ -227,7 +202,7 @@ authors grant the U.S. Government and others acting in its behalf permission to use and distribute the software in accordance with the terms specified in this license. -11. ext/standard/strnatcmp.c +10. ext/standard/strnatcmp.c strnatcmp.c -- Perform 'natural order' comparisons of strings in C. Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au> @@ -248,7 +223,7 @@ freely, subject to the following restrictions: misrepresented as being the original software. 3. This notice may not be removed or altered from any source distribution. -12. ext/standard/uuencode +11. ext/standard/uuencode Portions of this code are based on Berkeley's uuencode/uudecode implementation. @@ -284,7 +259,7 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -13. libxmlrpc ext/xmlrpc +12. libxmlrpc ext/xmlrpc Copyright 2000 Epinions, Inc. @@ -308,7 +283,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. -14. libzip ext/zip +13. libzip ext/zip zip.h -- exported declarations. Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner @@ -340,7 +315,7 @@ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -15. main/snprintf.c +14. main/snprintf.c Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com> Permission to use, copy, modify, and distribute this software for any @@ -413,8 +388,8 @@ This code is based on, and used with the permission of, the SIO stdio-replacement strx_* functions by Panos Tsirigotis <panos@alumni.cs.colorado.edu> for xinetd. -16. main/strlcat -17. main/strlcpy +15. main/strlcat +16. main/strlcpy Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com> All rights reserved. diff --git a/README.RELEASE_PROCESS b/README.RELEASE_PROCESS index 38bc6e1845..3411ed903e 100644 --- a/README.RELEASE_PROCESS +++ b/README.RELEASE_PROCESS @@ -17,7 +17,7 @@ It is recommended to do so a couple of days before the packaging day, to have enough time to investigate failures, communicate with the authors and commit the fixes. The RM for the branch is also responsible for keeping the CI green on -ongoing bases between the releases. Check the CI status for your branch +ongoing basis between the releases. Check the CI status for your branch periodically and resolve the failures ASAP. See more in: https://wiki.php.net/rfc/travis_ci @@ -271,8 +271,8 @@ to upgrade. 10. Wait an hour or two, then send a mail to php-announce@lists.php.net, php-general@lists.php.net and internals@lists.php.net with a text similar to http://news.php.net/php.internals/17222. -Please make sure that the mail to php-announce@ is its own completely seperate email. -This is to make sure that repiles to the announcement on php-general@ or internals@ +Please make sure that the mail to php-announce@ is its own completely separate email. +This is to make sure that replies to the announcement on php-general@ or internals@ will not accidentally hit the php-announce@ mailinglist. Re-releasing the same version (or -pl) @@ -309,6 +309,6 @@ to upgrade. 5. Wait an hour or two, then send a mail to php-announce@lists.php.net, php-general@lists.php.net and internals@lists.php.net with a text similar to the news entry. -Please make sure that the mail to php-announce@ is its own completely seperate email. -This is to make sure that repiles to the announcement on php-general@ or internals@ +Please make sure that the mail to php-announce@ is its own completely separate email. +This is to make sure that replies to the announcement on php-general@ or internals@ will not accidentally hit the php-announce@ mailinglist. @@ -22,6 +22,10 @@ PHP 7.1 UPGRADE NOTES . 'void' can no longer be used as the name of a class, interface, or trait. This applies to declarations, class_alias() and use statements. +- JSON: + . When calling json_encode with JSON_UNESCAPED_UNICODE option, U+2028 and + U+2029 are escaped. + ======================================== 2. New Features ======================================== @@ -45,6 +49,9 @@ PHP 7.1 UPGRADE NOTES - The first $varname argument for getenv() is no longer mandatory, the current environment variables will be returned as an associative array when omitted. +- json_encode() accepts new option JSON_UNESCAPED_LINE_TERMINATORS that + disables escaping of U+2028 and U+2029 characters when + JSON_UNESCAPED_UNICODE is supplied. - long2ip() accepts integer as parameter now - pg_last_notice() accepts optional long parameter to specify operation. PGSQL_NOTICE_LAST - Get last notice (Default) @@ -79,6 +86,9 @@ PHP 7.1 UPGRADE NOTES 10. New Global Constants ======================================== +- JSON: + . JSON_UNESCAPED_LINE_TERMINATORS + - Pgsql: PGSQL_NOTICE_LAST PGSQL_NOTICE_ALL @@ -95,6 +105,21 @@ PHP 7.1 UPGRADE NOTES - Core: . Support for ftok() +- FCGI + . PHP_FCGI_CHILDREN is respected. If this environment variable is defined, + the first php-fcgi.exe process will exec the specified number of children. + Those will share the same TCP socket. + +- readline: + . The readline extension is supported through the WinEditLine library + (http://mingweditline.sourceforge.net/). Thereby, the interactive CLI + shell is supported as well (php.exe -a). + + It is well known, but nevertheless is worth mentioning again, that + the readline extension is not thread safe and will never be. Thus, + the usage of it with any true thread safe SAPI (like Apache mod_winnt) is + strongely discouraged. + ======================================== 13. Other Changes ======================================== diff --git a/Zend/tests/bug68652.phpt b/Zend/tests/bug68652.phpt index e86312ba63..8e54af2e34 100644 --- a/Zend/tests/bug68652.phpt +++ b/Zend/tests/bug68652.phpt @@ -28,6 +28,7 @@ class Bar { } public function __destruct() { + if (!isset(self::$instance)) return; Foo::getInstance(); } } diff --git a/Zend/tests/bug69989_1.phpt b/Zend/tests/bug69989_1.phpt new file mode 100644 index 0000000000..816c55410e --- /dev/null +++ b/Zend/tests/bug69989_1.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #69989: Cycle collection for yielded values +--FILE-- +<?php + +function gen() { + yield yield; +} +$gen = gen(); +$gen->send($gen); + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/bug69989_2.phpt b/Zend/tests/bug69989_2.phpt new file mode 100644 index 0000000000..a6f320da3b --- /dev/null +++ b/Zend/tests/bug69989_2.phpt @@ -0,0 +1,42 @@ +--TEST-- +Collection of some cycles on unfinished generators +--FILE-- +<?php + +// CV +function gen1() { + $gen = yield; + yield; +} + +$gen = gen1(); +$gen->send($gen); + +// This +class Test { + public $gen; + public function gen2() { + yield; + } +} + +$test = new Test; +$test->gen = $test->gen2(); + +// Closure object +$gen3 = (function() use (&$gen3) { + yield; +})(); + +// Yield from array +function gen4() { + yield from [yield]; +} + +$gen = gen4(); +$gen->send($gen); + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/bug69989_3.phpt b/Zend/tests/bug69989_3.phpt new file mode 100644 index 0000000000..260819197b --- /dev/null +++ b/Zend/tests/bug69989_3.phpt @@ -0,0 +1,44 @@ +--TEST-- +Generator cycle collection edge cases +--FILE-- +<?php + +// Extra args +function gen1() { + yield; +} +$obj = new stdClass; +$obj->gen = gen1($obj); + +// Symtable +function gen2() { + $varName = 'a'; + $$varName = yield; + yield; +} +$gen = gen2(); +$gen->send($gen); + +// Symtable indirect +function gen3() { + $varName = 'a'; + $$varName = 42; + $var = yield; + yield; +} +$gen = gen3(); +$gen->send($gen); + +// Yield from root +function gen4() { + yield from yield; +} +$gen = gen4(); +$gen2 = gen4($gen); +$gen2->send([1, 2, 3]); +$gen->send($gen2); + +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/bug71248.phpt b/Zend/tests/bug71248.phpt new file mode 100644 index 0000000000..6be2585767 --- /dev/null +++ b/Zend/tests/bug71248.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #71248 (Wrong interface is enforced) +--FILE-- +<?php +class Hint1 { } +class Hint2 { } + +abstract class Base { + public function __construct(Hint1 $x) { } +} + +interface Iface { + public function __construct(Hint1 $x); +} + +class Foo extends Base implements Iface { +} + +$code = <<<'PHP' +abstract class Bar extends Base { + public function __construct(Hint2 $x) { } +} +PHP; +eval($code); +?> +OK +--EXPECT-- +OK diff --git a/Zend/tests/bug71300.phpt b/Zend/tests/bug71300.phpt new file mode 100644 index 0000000000..3589c4764e --- /dev/null +++ b/Zend/tests/bug71300.phpt @@ -0,0 +1,28 @@ +--TEST-- +Bug #71300 (Segfault in zend_fetch_string_offset) +--FILE-- +<?php +function test1() { + for ($n = 'a'; $n < 'g'; $n++) { + $$n = 1; + } + $$n = $$n[++$n] = "test"; + return $$n; +} + +var_dump(test1()); + +function test2() { + /* See #71303 for why not using for loop here */ + $n = "a"; + $$n .= $$n[++$n] = "test"; + return $$n; +} + +var_dump(test2()); +?> +--EXPECTF-- +string(4) "test" + +Notice: Array to string conversion in %sbug71300.php on line %d +string(9) "Arraytest" diff --git a/Zend/tests/bug71336.phpt b/Zend/tests/bug71336.phpt new file mode 100644 index 0000000000..c5da420da0 --- /dev/null +++ b/Zend/tests/bug71336.phpt @@ -0,0 +1,48 @@ +--TEST-- +Bug #71336 (Wrong is_ref on properties as exposed via get_object_vars()) +--FILE-- +<?php +class A +{ + protected $bar = array('baz'); + + function bar() + { + array_pop($this->bar); + $vars = get_object_vars($this); + $this->bar[] = array('buz'); + print_r($vars); + } + + function foo() { + array_pop($this->bar); + $dummy = &$this->bar; + $vars = get_object_vars($this); + $this->bar[] = array('buz'); + print_r($vars); + } +} + +(new A())->bar(); +(new A())->foo(); +?> +--EXPECT-- +Array +( + [bar] => Array + ( + ) + +) +Array +( + [bar] => Array + ( + [0] => Array + ( + [0] => buz + ) + + ) + +) diff --git a/Zend/tests/bug71470.phpt b/Zend/tests/bug71470.phpt new file mode 100644 index 0000000000..6f8b4f0103 --- /dev/null +++ b/Zend/tests/bug71470.phpt @@ -0,0 +1,13 @@ +--TEST-- +Bug #71470: Leaked 1 hashtable iterators +--FILE-- +<?php + +$array = [1, 2, 3]; +foreach ($array as &$v) { + die("foo\n"); +} + +?> +--EXPECT-- +foo diff --git a/Zend/tests/bug71474.phpt b/Zend/tests/bug71474.phpt new file mode 100644 index 0000000000..e67bb9b240 --- /dev/null +++ b/Zend/tests/bug71474.phpt @@ -0,0 +1,23 @@ +--TEST--
+Bug #71474: Crash because of VM stack corruption on Magento2
+--FILE--
+<?php
+class foo {
+ function __call($name, $args) {
+ $a = $b = $c = $d = $e = $f = 1;
+ }
+}
+
+function test($n, $x) {
+// var_dump($n);
+ if ($n > 0) {
+ $x->bug();
+ test($n - 1, $x);
+ }
+}
+
+test(3000, new foo());
+echo "OK\n";
+?>
+--EXPECT--
+OK
diff --git a/Zend/tests/bug71529.phpt b/Zend/tests/bug71529.phpt new file mode 100644 index 0000000000..5a5e323414 --- /dev/null +++ b/Zend/tests/bug71529.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #71529: Variable references on array elements don't work when using count +--FILE-- +<?php + +$a = [1]; +$a[] = &$a[out(count($a) - 1)]; +var_dump($a); + +function out($what) { + var_dump($what); + return $what; +} + +?> +--EXPECT-- +int(0) +array(2) { + [0]=> + &int(1) + [1]=> + &int(1) +} diff --git a/Zend/tests/bug71572.phpt b/Zend/tests/bug71572.phpt new file mode 100644 index 0000000000..4a823ec72f --- /dev/null +++ b/Zend/tests/bug71572.phpt @@ -0,0 +1,27 @@ +--TEST-- +Bug #71572: String offset assignment from an empty string inserts null byte +--FILE-- +<?php + +$str = "abc"; +var_dump($str{0} = ""); +var_dump($str{1} = ""); +var_dump($str{3} = ""); +var_dump($str{10} = ""); +var_dump($str); +?> +==DONE== +--EXPECTF-- +Warning: Cannot assign an empty string to a string offset in %s on line %d +NULL + +Warning: Cannot assign an empty string to a string offset in %s on line %d +NULL + +Warning: Cannot assign an empty string to a string offset in %s on line %d +NULL + +Warning: Cannot assign an empty string to a string offset in %s on line %d +NULL +string(3) "abc" +==DONE==
\ No newline at end of file diff --git a/Zend/tests/bug71622.phpt b/Zend/tests/bug71622.phpt new file mode 100644 index 0000000000..3ef0ba80e1 --- /dev/null +++ b/Zend/tests/bug71622.phpt @@ -0,0 +1,30 @@ +--TEST-- +Bug #71622 (Strings used in pass-as-reference cannot be used to invoke C::$callable()) +--FILE-- +<?php + +function getMethodName(&$methodName) { + $methodName = Abc::METHOD_NAME; +} + +class Abc { + const METHOD_NAME = "goal"; + + private static function goal() { + echo "success\n"; + } + + public static function run() { + $method = "foobar"; + getMethodName($method); + var_dump(is_callable("self::$method")); + self::$method(); + } +} + +Abc::run(); + +?> +--EXPECT-- +bool(true) +success diff --git a/Zend/tests/closure_use_auto_global.phpt b/Zend/tests/closure_use_auto_global.phpt new file mode 100644 index 0000000000..9ab0897e12 --- /dev/null +++ b/Zend/tests/closure_use_auto_global.phpt @@ -0,0 +1,16 @@ +--TEST-- +Cannot use() auto-global +--FILE-- +<?php + +function test() { + $fn = function() use($GLOBALS) { + var_dump($GLOBALS); + }; + $fn(); +} +test(); + +?> +--EXPECTF-- +Fatal error: Cannot use auto-global as lexical variable in %s on line %d diff --git a/Zend/tests/closure_use_parameter_name.phpt b/Zend/tests/closure_use_parameter_name.phpt new file mode 100644 index 0000000000..7ecc6d8dd1 --- /dev/null +++ b/Zend/tests/closure_use_parameter_name.phpt @@ -0,0 +1,14 @@ +--TEST-- +Can't use name of lexical variable for parameter +--FILE-- +<?php + +$a = 1; +$fn = function ($a) use ($a) { + var_dump($a); +}; +$fn(2); + +?> +--EXPECTF-- +Fatal error: Cannot use lexical variable $a as a parameter name in %s on line %d diff --git a/Zend/tests/closure_use_variable_twice.phpt b/Zend/tests/closure_use_variable_twice.phpt new file mode 100644 index 0000000000..06c2645809 --- /dev/null +++ b/Zend/tests/closure_use_variable_twice.phpt @@ -0,0 +1,15 @@ +--TEST-- +Closure cannot use one variable twice +--FILE-- +<?php + +$a = 1; +$fn = function() use ($a, &$a) { + $a = 2; +}; +$fn(); +var_dump($a); + +?> +--EXPECTF-- +Fatal error: Cannot use variable $a twice in %s on line %d diff --git a/Zend/tests/foreach_017.phpt b/Zend/tests/foreach_017.phpt index 55eeeb0891..e27b04c934 100644 --- a/Zend/tests/foreach_017.phpt +++ b/Zend/tests/foreach_017.phpt @@ -45,7 +45,7 @@ $done = 0; $a = [0,1,2,3,4]; foreach($a as &$v) { echo "$v\n"; - if ($done && $v == 3) { + if (!$done && $v == 3) { $done = 1; array_splice($a, 1, 2, $replacement); } diff --git a/Zend/tests/generators/bug71297.phpt b/Zend/tests/generators/bug71297.phpt new file mode 100644 index 0000000000..eed7278601 --- /dev/null +++ b/Zend/tests/generators/bug71297.phpt @@ -0,0 +1,25 @@ +--TEST-- +Bug #71297 (Memory leak with consecutive yield from) +--FILE-- +<?php + +function foo() { + yield array_fill(0, 10000, 4); +} + +function genLeak() { + $i = 0; + while (1) { + yield from foo(); + print $i++; + } +} + +$x = 0; +foreach (genLeak() as $i) { + if ($x++ == 3) break; +} + +?> +--EXPECT-- +012 diff --git a/Zend/tests/generators/bug71441.phpt b/Zend/tests/generators/bug71441.phpt new file mode 100644 index 0000000000..3a103888b0 --- /dev/null +++ b/Zend/tests/generators/bug71441.phpt @@ -0,0 +1,29 @@ +--TEST-- +Bug #71441 (Typehinted Generator with return in try/finally crashes) +--FILE-- +<?php + +$num = 2000; /* to be sure to be in wild memory */ +$add = str_repeat("1 +", $num); +$gen = (eval(<<<PHP +return function (): \Generator { + try { + \$a = 1; + \$foo = \$a + $add \$a; + return yield \$foo; + } finally { + print "Ok\n"; + } +}; +PHP +))(); +var_dump($gen->current()); +$gen->send("Success"); +var_dump($gen->getReturn()); + +?> +--EXPECT-- +int(2002) +Ok +string(7) "Success" + diff --git a/Zend/tests/generators/bug71601.phpt b/Zend/tests/generators/bug71601.phpt new file mode 100644 index 0000000000..e3f21692e7 --- /dev/null +++ b/Zend/tests/generators/bug71601.phpt @@ -0,0 +1,40 @@ +--TEST-- +Bug #71601 (finally block not executed after yield from) +--FILE-- +<?php + +function gen1() { + try { + yield 1; + yield 2; + return true; + } finally { + echo "Inner finally\n"; + } +} + +function gen2() { + try { + echo "Entered try/catch\n"; + var_dump(yield from gen1()); + } finally { + echo "Finally\n"; + } +} + +$generator = gen2(); + +var_dump($generator->current()); + +unset($generator); + +echo "Done\n"; + +?> +--EXPECT-- +Entered try/catch +int(1) +Inner finally +Finally +Done + diff --git a/Zend/tests/generators/dangling_send_target.phpt b/Zend/tests/generators/dangling_send_target.phpt new file mode 100644 index 0000000000..c62c24a2f5 --- /dev/null +++ b/Zend/tests/generators/dangling_send_target.phpt @@ -0,0 +1,22 @@ +--TEST-- +Yield from does not leave a dangling send target +--FILE-- +<?php +function gen1() { + yield from [yield]; +} + +$gen = gen1(); +$gen->send(new stdClass); + +function gen2() { + $x = yield; + yield from [1, 2, 3]; +} +$gen = gen2(); +$gen->send(new stdClass); +$gen->send(new stdClass); +?> +===DONE=== +--EXPECT-- +===DONE=== diff --git a/Zend/tests/generators/yield_from_by_reference.phpt b/Zend/tests/generators/yield_from_by_reference.phpt new file mode 100644 index 0000000000..8412a32af5 --- /dev/null +++ b/Zend/tests/generators/yield_from_by_reference.phpt @@ -0,0 +1,12 @@ +--TEST-- +Yield from by reference is not supported +--FILE-- +<?php + +function &gen() { + yield from []; +} + +?> +--EXPECTF-- +Fatal error: Cannot use "yield from" inside a by-reference generator in %s on line %d diff --git a/Zend/tests/overloaded_func_001.phpt b/Zend/tests/overloaded_func_001.phpt new file mode 100644 index 0000000000..2702772a46 --- /dev/null +++ b/Zend/tests/overloaded_func_001.phpt @@ -0,0 +1,15 @@ +--TEST-- +Overloaded function 001 +--SKIPIF-- +<?php +if (!PHP_DEBUG) die("skip only run in debug version"); +?> +--FILE-- +<?php +var_dump(_ZendTestClass::test()); +?> +--EXPECTF-- +Fatal error: Uncaught Error: Cannot call overloaded function for non-object in %soverloaded_func_001.php:%d +Stack trace: +#0 {main} + thrown in %soverloaded_func_001.php on line %d diff --git a/Zend/tests/overloaded_func_002.phpt b/Zend/tests/overloaded_func_002.phpt new file mode 100644 index 0000000000..6c16965919 --- /dev/null +++ b/Zend/tests/overloaded_func_002.phpt @@ -0,0 +1,13 @@ +--TEST-- +Overloaded function 002 +--SKIPIF-- +<?php +if (!PHP_DEBUG) die("skip only run in debug version"); +?> +--FILE-- +<?php +$a = new _ZendTestClass(); +var_dump($a->{trim(" test")}()); +?> +--EXPECT-- +string(4) "test" diff --git a/Zend/tests/temporary_cleaning_012.phpt b/Zend/tests/temporary_cleaning_012.phpt new file mode 100644 index 0000000000..fdbea6d41d --- /dev/null +++ b/Zend/tests/temporary_cleaning_012.phpt @@ -0,0 +1,20 @@ +--TEST-- +Live range of ZEND_NEW must be assigned to correct variable +--FILE-- +<?php + +class Foo { + public static function test() { + self::$property = new self; + } +} + +try { + Foo::test(); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +?> +--EXPECT-- +Access to undeclared static property: Foo::$property diff --git a/Zend/zend.c b/Zend/zend.c index b7c040363c..9591a67c5b 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -967,6 +967,10 @@ ZEND_API void zend_deactivate(void) /* {{{ */ shutdown_executor(); zend_try { + zend_ini_deactivate(); + } zend_end_try(); + + zend_try { shutdown_compiler(); } zend_end_try(); @@ -984,10 +988,6 @@ ZEND_API void zend_deactivate(void) /* {{{ */ fprintf(stderr, " -------- -------- ----------- ------\n"); fprintf(stderr, "ZVAL %8d %8d %9d %8d\n", GC_G(zval_possible_root), GC_G(zval_buffered), GC_G(zval_remove_from_buffer), GC_G(zval_marked_grey)); #endif - - zend_try { - zend_ini_deactivate(); - } zend_end_try(); } /* }}} */ diff --git a/Zend/zend.h b/Zend/zend.h index 5a12374335..b1bd8a1cd0 100644 --- a/Zend/zend.h +++ b/Zend/zend.h @@ -61,7 +61,7 @@ #define USED_RET() \ (!EX(prev_execute_data) || \ !ZEND_USER_CODE(EX(prev_execute_data)->func->common.type) || \ - !(EX(prev_execute_data)->opline->result_type & EXT_TYPE_UNUSED)) + (EX(prev_execute_data)->opline->result_type != IS_UNUSED)) #ifdef ZEND_ENABLE_STATIC_TSRMLS_CACHE #define ZEND_TSRMG TSRMG_STATIC diff --git a/Zend/zend_API.c b/Zend/zend_API.c index 580d4afb84..e9cf134ede 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -1229,8 +1229,15 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties) size_t prop_name_len; if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) { zend_string *pname = zend_string_init(prop_name, prop_name_len, 0); + zend_class_entry *prev_scope = EG(scope); + if (class_name && class_name[0] != '*') { + zend_string *cname = zend_string_init(class_name, strlen(class_name), 0); + EG(scope) = zend_lookup_class(cname); + zend_string_release(cname); + } property_info = zend_get_property_info(object->ce, pname, 1); zend_string_release(pname); + EG(scope) = prev_scope; } else { property_info = ZEND_WRONG_PROPERTY_INFO; } @@ -1641,7 +1648,7 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */ result = zend_symtable_update(ht, ZSTR_EMPTY_ALLOC(), value); break; case IS_RESOURCE: - zend_error(E_NOTICE, "Resource ID#" ZEND_LONG_FMT " used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key)); + zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key)); result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value); break; case IS_FALSE: diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c index cfc277f136..2e0de26378 100644 --- a/Zend/zend_alloc.c +++ b/Zend/zend_alloc.c @@ -1353,6 +1353,10 @@ static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t si /* special handling for zero-size allocation */ size = MAX(size, 1); size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)); + if (UNEXPECTED(size < real_size)) { + zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info))); + return NULL; + } #endif if (size <= ZEND_MM_MAX_SMALL_SIZE) { ptr = zend_mm_alloc_small(heap, size, ZEND_MM_SMALL_SIZE_TO_BIN(size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC); diff --git a/Zend/zend_arena.h b/Zend/zend_arena.h index 7456610b65..e89e06b1b0 100644 --- a/Zend/zend_arena.h +++ b/Zend/zend_arena.h @@ -103,11 +103,12 @@ static zend_always_inline void zend_arena_release(zend_arena **arena_ptr, void * zend_arena *arena = *arena_ptr; while (UNEXPECTED((char*)checkpoint > arena->end) || - UNEXPECTED((char*)checkpoint < (char*)arena)) { + UNEXPECTED((char*)checkpoint <= (char*)arena)) { zend_arena *prev = arena->prev; efree(arena); *arena_ptr = arena = prev; } + ZEND_ASSERT((char*)checkpoint > (char*)arena && (char*)checkpoint <= arena->end); arena->ptr = (char*)checkpoint; } diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c index b015438b72..0b48df48bf 100644 --- a/Zend/zend_builtin_functions.c +++ b/Zend/zend_builtin_functions.c @@ -31,6 +31,12 @@ #undef ZEND_TEST_EXCEPTIONS +#if ZEND_DEBUG +static zend_class_entry *zend_test_interface; +static zend_class_entry *zend_test_class; +static zend_object_handlers zend_test_class_handlers; +#endif + static ZEND_FUNCTION(zend_version); static ZEND_FUNCTION(func_num_args); static ZEND_FUNCTION(func_get_arg); @@ -257,6 +263,51 @@ ZEND_END_ARG_INFO() /* }}} */ +#if ZEND_DEBUG +static zend_object *zend_test_class_new(zend_class_entry *class_type) /* {{{ */ { + zend_object *obj = zend_objects_new(class_type); + obj->handlers = &zend_test_class_handlers; + return obj; +} +/* }}} */ + +static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) /* {{{ */ { + zend_internal_function *fptr = emalloc(sizeof(zend_internal_function)); + fptr->type = ZEND_OVERLOADED_FUNCTION_TEMPORARY; + fptr->num_args = 1; + fptr->arg_info = NULL; + fptr->scope = (*object)->ce; + fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER; + fptr->function_name = zend_string_copy(name); + fptr->handler = ZEND_FN(zend_test_func); + zend_set_function_arg_flags((zend_function*)fptr); + + return (zend_function*)fptr; +} +/* }}} */ + +static zend_function *zend_test_class_static_method_get(zend_class_entry *ce, zend_string *name) /* {{{ */ { + zend_internal_function *fptr = emalloc(sizeof(zend_internal_function)); + fptr->type = ZEND_OVERLOADED_FUNCTION; + fptr->num_args = 1; + fptr->arg_info = NULL; + fptr->scope = ce; + fptr->fn_flags = ZEND_ACC_CALL_VIA_HANDLER|ZEND_ACC_STATIC; + fptr->function_name = name; + fptr->handler = ZEND_FN(zend_test_func); + zend_set_function_arg_flags((zend_function*)fptr); + + return (zend_function*)fptr; +} +/* }}} */ + +static int zend_test_class_call_method(zend_string *method, zend_object *object, INTERNAL_FUNCTION_PARAMETERS) /* {{{ */ { + RETVAL_STR(zend_string_copy(method)); + return 0; +} +/* }}} */ +#endif + static const zend_function_entry builtin_functions[] = { /* {{{ */ ZEND_FE(zend_version, arginfo_zend__void) ZEND_FE(func_num_args, arginfo_zend__void) @@ -339,6 +390,21 @@ ZEND_MINIT_FUNCTION(core) { /* {{{ */ zend_register_default_classes(); +#if ZEND_DEBUG + INIT_CLASS_ENTRY(class_entry, "_ZendTestInterface", NULL); + zend_test_interface = zend_register_internal_interface(&class_entry); + zend_declare_class_constant_long(zend_test_interface, ZEND_STRL("DUMMY"), 0); + INIT_CLASS_ENTRY(class_entry, "_ZendTestClass", NULL); + zend_test_class = zend_register_internal_class_ex(&class_entry, NULL); + zend_class_implements(zend_test_class, 1, zend_test_interface); + zend_test_class->create_object = zend_test_class_new; + zend_test_class->get_static_method = zend_test_class_static_method_get; + + memcpy(&zend_test_class_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); + zend_test_class_handlers.get_method = zend_test_class_method_get; + zend_test_class_handlers.call_method = zend_test_class_call_method; +#endif + return SUCCESS; } /* }}} */ @@ -1198,8 +1264,12 @@ ZEND_FUNCTION(get_object_vars) ZEND_HASH_FOREACH_STR_KEY_VAL_IND(properties, key, value) { if (key) { if (zend_check_property_access(zobj, key) == SUCCESS) { - /* Not separating references */ - if (Z_REFCOUNTED_P(value)) Z_ADDREF_P(value); + if (Z_ISREF_P(value) && Z_REFCOUNT_P(value) == 1) { + value = Z_REFVAL_P(value); + } + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } if (ZSTR_VAL(key)[0] == 0) { const char *prop_name, *class_name; size_t prop_len; @@ -2042,7 +2112,6 @@ ZEND_FUNCTION(zend_test_func2) zend_parse_parameters(ZEND_NUM_ARGS(), "|zz", &arg1, &arg2); } - #ifdef ZTS ZEND_FUNCTION(zend_thread_id) { diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 0384e8b5cf..7cf00a0ebe 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -743,7 +743,7 @@ void zend_do_free(znode *op1) /* {{{ */ their selves */ zend_emit_op(NULL, ZEND_FREE, op1, NULL); } else { - opline->result_type |= EXT_TYPE_UNUSED; + opline->result_type = IS_UNUSED; } } else { while (opline >= CG(active_op_array)->opcodes) { @@ -756,12 +756,7 @@ void zend_do_free(znode *op1) /* {{{ */ if (opline->result_type==IS_VAR && opline->result.var == op1->u.op.var) { if (opline->opcode == ZEND_NEW) { - opline->result_type |= EXT_TYPE_UNUSED; - opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1]; - while (opline->opcode != ZEND_DO_FCALL || opline->op1.num != ZEND_CALL_CTOR) { - opline--; - } - opline->op1.num |= ZEND_CALL_CTOR_RESULT_UNUSED; + zend_emit_op(NULL, ZEND_FREE, op1, NULL); } break; } @@ -1993,11 +1988,12 @@ static void zend_find_live_range(zend_op *opline, zend_uchar type, uint32_t var) break; } } + zend_end_live_range(CG(active_op_array), zend_start_live_range_ex(CG(active_op_array), def + 1 - CG(active_op_array)->opcodes), opline - CG(active_op_array)->opcodes, - ZEND_LIVE_TMPVAR, def->result.var); + ZEND_LIVE_TMPVAR, var); break; } } @@ -2242,7 +2238,7 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */ zend_op *opline = NULL, *oplines = zend_stack_base(&CG(delayed_oplines_stack)); uint32_t i, count = zend_stack_count(&CG(delayed_oplines_stack)); - ZEND_ASSERT(count > offset); + ZEND_ASSERT(count >= offset); for (i = offset; i < count; ++i) { opline = get_next_op(CG(active_op_array)); memcpy(opline, &oplines[i], sizeof(zend_op)); @@ -2833,8 +2829,10 @@ void zend_compile_assign(znode *result, zend_ast *ast) /* {{{ */ switch (var_ast->kind) { case ZEND_AST_VAR: case ZEND_AST_STATIC_PROP: - zend_compile_var(&var_node, var_ast, BP_VAR_W); + offset = zend_delayed_compile_begin(); + zend_delayed_compile_var(&var_node, var_ast, BP_VAR_W); zend_compile_expr(&expr_node, expr_ast); + zend_delayed_compile_end(offset); zend_emit_op(result, ZEND_ASSIGN, &var_node, &expr_node); return; case ZEND_AST_DIM: @@ -2885,23 +2883,23 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */ znode target_node, source_node; zend_op *opline; + uint32_t offset; if (is_this_fetch(target_ast)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this"); } zend_ensure_writable_variable(target_ast); - zend_compile_var(&target_node, target_ast, BP_VAR_W); - zend_compile_var(&source_node, source_ast, BP_VAR_W); + offset = zend_delayed_compile_begin(); + zend_delayed_compile_var(&target_node, target_ast, BP_VAR_W); + zend_delayed_compile_var(&source_node, source_ast, BP_VAR_W); + zend_delayed_compile_end(offset); if (source_node.op_type != IS_VAR && zend_is_call(source_ast)) { zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context"); } opline = zend_emit_op(result, ZEND_ASSIGN_REF, &target_node, &source_node); - if (!result) { - opline->result_type |= EXT_TYPE_UNUSED; - } if (zend_is_call(source_ast)) { opline->extended_value = ZEND_RETURNS_FUNCTION; @@ -2932,8 +2930,10 @@ void zend_compile_compound_assign(znode *result, zend_ast *ast) /* {{{ */ switch (var_ast->kind) { case ZEND_AST_VAR: case ZEND_AST_STATIC_PROP: - zend_compile_var(&var_node, var_ast, BP_VAR_RW); + offset = zend_delayed_compile_begin(); + zend_delayed_compile_var(&var_node, var_ast, BP_VAR_RW); zend_compile_expr(&expr_node, expr_ast); + zend_delayed_compile_end(offset); zend_emit_op(result, opcode, &var_node, &expr_node); return; case ZEND_AST_DIM: @@ -3245,6 +3245,14 @@ int zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */ return FAILURE; } + if (zend_try_ct_eval_const(&result->u.constant, name, 0)) { + zend_string_release(name); + zval_ptr_dtor(&result->u.constant); + ZVAL_TRUE(&result->u.constant); + result->op_type = IS_CONST; + return SUCCESS; + } + opline = zend_emit_op_tmp(result, ZEND_DEFINED, NULL, NULL); opline->op1_type = IS_CONST; LITERAL_STR(opline->op1, name); @@ -3261,6 +3269,46 @@ int zend_compile_func_defined(znode *result, zend_ast_list *args) /* {{{ */ } /* }}} */ +int zend_compile_func_chr(znode *result, zend_ast_list *args) /* {{{ */ +{ + + if (args->children == 1 && + args->child[0]->kind == ZEND_AST_ZVAL && + Z_TYPE_P(zend_ast_get_zval(args->child[0])) == IS_LONG) { + + zend_long c = Z_LVAL_P(zend_ast_get_zval(args->child[0])) & 0xff; + + result->op_type = IS_CONST; + if (CG(one_char_string)[c]) { + ZVAL_INTERNED_STR(&result->u.constant, CG(one_char_string)[c]); + } else { + ZVAL_NEW_STR(&result->u.constant, zend_string_alloc(1, 0)); + Z_STRVAL_P(&result->u.constant)[0] = (char)c; + Z_STRVAL_P(&result->u.constant)[1] = '\0'; + } + return SUCCESS; + } else { + return FAILURE; + } +} +/* }}} */ + +int zend_compile_func_ord(znode *result, zend_ast_list *args) /* {{{ */ +{ + if (args->children == 1 && + args->child[0]->kind == ZEND_AST_ZVAL && + Z_TYPE_P(zend_ast_get_zval(args->child[0])) == IS_STRING) { + + result->op_type = IS_CONST; + ZVAL_LONG(&result->u.constant, (unsigned char)Z_STRVAL_P(zend_ast_get_zval(args->child[0]))[0]); + return SUCCESS; + } else { + return FAILURE; + } +} +/* }}} */ + + static int zend_try_compile_ct_bound_init_user_func(zend_ast *name_ast, uint32_t num_args) /* {{{ */ { zend_string *name, *lcname; @@ -3439,7 +3487,7 @@ static int zend_compile_assert(znode *result, zend_ast_list *args, zend_string * } /* }}} */ -int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc) /* {{{ */ +int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_list *args, zend_function *fbc, uint32_t type) /* {{{ */ { if (fbc->internal_function.handler == ZEND_FN(display_disabled_function)) { return FAILURE; @@ -3471,6 +3519,10 @@ int zend_try_compile_special_func(znode *result, zend_string *lcname, zend_ast_l return zend_compile_func_typecheck(result, args, IS_RESOURCE); } else if (zend_string_equals_literal(lcname, "defined")) { return zend_compile_func_defined(result, args); + } else if (zend_string_equals_literal(lcname, "chr") && type == BP_VAR_R) { + return zend_compile_func_chr(result, args); + } else if (zend_string_equals_literal(lcname, "ord") && type == BP_VAR_R) { + return zend_compile_func_ord(result, args); } else if (zend_string_equals_literal(lcname, "call_user_func_array")) { return zend_compile_func_cufa(result, args, lcname); } else if (zend_string_equals_literal(lcname, "call_user_func")) { @@ -3527,7 +3579,7 @@ void zend_compile_call(znode *result, zend_ast *ast, uint32_t type) /* {{{ */ } if (zend_try_compile_special_func(result, lcname, - zend_ast_get_list(args_ast), fbc) == SUCCESS + zend_ast_get_list(args_ast), fbc, type) == SUCCESS ) { zend_string_release(lcname); zval_ptr_dtor(&name_node.u.constant); @@ -3721,7 +3773,7 @@ void zend_compile_global_var(zend_ast *ast) /* {{{ */ static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_bool by_ref) /* {{{ */ { - znode var_node, result; + znode var_node; zend_op *opline; zend_compile_expr(&var_node, var_ast); @@ -3742,16 +3794,10 @@ static void zend_compile_static_var_common(zend_ast *var_ast, zval *value, zend_ } zend_hash_update(CG(active_op_array)->static_variables, Z_STR(var_node.u.constant), value); - opline = zend_emit_op(&result, by_ref ? ZEND_FETCH_W : ZEND_FETCH_R, &var_node, NULL); - opline->extended_value = ZEND_FETCH_STATIC; - - if (by_ref) { - zend_ast *fetch_ast = zend_ast_create(ZEND_AST_VAR, var_ast); - zend_emit_assign_ref_znode(fetch_ast, &result); - } else { - zend_ast *fetch_ast = zend_ast_create(ZEND_AST_VAR, var_ast); - zend_emit_assign_znode(fetch_ast, &result); - } + opline = zend_emit_op(NULL, ZEND_BIND_STATIC, NULL, &var_node); + opline->op1_type = IS_CV; + opline->op1.var = lookup_cv(CG(active_op_array), zend_string_copy(Z_STR(var_node.u.constant))); + opline->extended_value = by_ref; } /* }}} */ @@ -3836,7 +3882,7 @@ static int zend_handle_loops_and_finally_ex(zend_long depth) /* {{{ */ } else { zend_op *opline; - ZEND_ASSERT(loop_var->var_type == IS_VAR || loop_var->var_type == IS_TMP_VAR); + ZEND_ASSERT(loop_var->var_type & (IS_VAR|IS_TMP_VAR)); opline = get_next_op(CG(active_op_array)); opline->opcode = loop_var->opcode; opline->op1_type = loop_var->var_type; @@ -4365,7 +4411,7 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */ zend_end_loop(get_next_op_number(CG(active_op_array)), &expr_node); - if (expr_node.op_type == IS_VAR || expr_node.op_type == IS_TMP_VAR) { + if (expr_node.op_type & (IS_VAR|IS_TMP_VAR)) { /* don't use emit_op() to prevent automatic live-range construction */ opline = get_next_op(CG(active_op_array)); opline->opcode = ZEND_FREE; @@ -4925,15 +4971,33 @@ static void zend_compile_closure_binding(znode *closure, zend_ast *uses_ast) /* void zend_compile_closure_uses(zend_ast *ast) /* {{{ */ { + zend_op_array *op_array = CG(active_op_array); zend_ast_list *list = zend_ast_get_list(ast); uint32_t i; for (i = 0; i < list->children; ++i) { zend_ast *var_ast = list->child[i]; + zend_string *var_name = zend_ast_get_str(var_ast); zend_bool by_ref = var_ast->attr; - zval zv; ZVAL_NULL(&zv); + + if (op_array->static_variables + && zend_hash_exists(op_array->static_variables, var_name)) { + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot use variable $%s twice", ZSTR_VAL(var_name)); + } + + { + int i; + for (i = 0; i < op_array->last_var; i++) { + if (zend_string_equals(op_array->vars[i], var_name)) { + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot use lexical variable $%s as a parameter name", ZSTR_VAL(var_name)); + } + } + } + zend_compile_static_var_common(var_ast, &zv, by_ref); } } @@ -6605,6 +6669,11 @@ void zend_compile_yield_from(znode *result, zend_ast *ast) /* {{{ */ zend_mark_function_as_generator(); + if (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + zend_error_noreturn(E_COMPILE_ERROR, + "Cannot use \"yield from\" inside a by-reference generator"); + } + zend_compile_expr(&expr_node, expr_ast); zend_emit_op_tmp(result, ZEND_YIELD_FROM, &expr_node, NULL); } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 2984f75b64..ecff23d1cd 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -470,7 +470,7 @@ struct _zend_execute_data { #define ZEND_CALL_TOP (1 << 1) #define ZEND_CALL_FREE_EXTRA_ARGS (1 << 2) /* equal to IS_TYPE_REFCOUNTED */ #define ZEND_CALL_CTOR (1 << 3) -#define ZEND_CALL_CTOR_RESULT_UNUSED (1 << 4) +/* Unused flag (1 << 4) */ #define ZEND_CALL_CLOSURE (1 << 5) #define ZEND_CALL_RELEASE_THIS (1 << 6) #define ZEND_CALL_ALLOCATED (1 << 7) @@ -683,8 +683,6 @@ struct _zend_execute_data { #define IS_UNUSED (1<<3) /* Unused variable */ #define IS_CV (1<<4) /* Compiled variable */ -#define EXT_TYPE_UNUSED (1<<5) - #include "zend_globals.h" BEGIN_EXTERN_C() @@ -890,7 +888,6 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name); /* global/local fetches */ #define ZEND_FETCH_GLOBAL 0x00000000 #define ZEND_FETCH_LOCAL 0x10000000 -#define ZEND_FETCH_STATIC 0x20000000 #define ZEND_FETCH_GLOBAL_LOCK 0x40000000 #define ZEND_FETCH_TYPE_MASK 0x70000000 diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 8f30373e87..de5875fdba 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -68,7 +68,7 @@ static void zend_extension_statement_handler(const zend_extension *extension, ze static void zend_extension_fcall_begin_handler(const zend_extension *extension, zend_op_array *op_array); static void zend_extension_fcall_end_handler(const zend_extension *extension, zend_op_array *op_array); -#define RETURN_VALUE_USED(opline) (!((opline)->result_type & EXT_TYPE_UNUSED)) +#define RETURN_VALUE_USED(opline) ((opline)->result_type != IS_UNUSED) static ZEND_FUNCTION(pass) { @@ -1098,164 +1098,6 @@ static ZEND_COLD int zend_verify_missing_return_type(zend_function *zf, void **c return 1; } -static zend_always_inline void zend_assign_to_object(zval *retval, zval *object, uint32_t object_op_type, zval *property_name, uint32_t property_op_type, int value_type, znode_op value_op, const zend_execute_data *execute_data, void **cache_slot) -{ - zend_free_op free_value; - zval *value = get_zval_ptr_r(value_type, value_op, execute_data, &free_value); - zval tmp; - - if (object_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { - do { - if (object_op_type == IS_VAR && UNEXPECTED(object == &EG(error_zval))) { - if (retval) { - ZVAL_NULL(retval); - } - FREE_OP(free_value); - return; - } - if (Z_ISREF_P(object)) { - object = Z_REFVAL_P(object); - if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { - break; - } - } - if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || - (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { - zend_object *obj; - - zval_ptr_dtor(object); - object_init(object); - Z_ADDREF_P(object); - obj = Z_OBJ_P(object); - zend_error(E_WARNING, "Creating default object from empty value"); - if (GC_REFCOUNT(obj) == 1) { - /* the enclosing container was deleted, obj is unreferenced */ - if (retval) { - ZVAL_NULL(retval); - } - FREE_OP(free_value); - OBJ_RELEASE(obj); - return; - } - Z_DELREF_P(object); - } else { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - if (retval) { - ZVAL_NULL(retval); - } - FREE_OP(free_value); - return; - } - } while (0); - } - - if (property_op_type == IS_CONST && - EXPECTED(Z_OBJCE_P(object) == CACHED_PTR_EX(cache_slot))) { - uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR_EX(cache_slot + 1); - zend_object *zobj = Z_OBJ_P(object); - zval *property; - - if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { - property = OBJ_PROP(zobj, prop_offset); - if (Z_TYPE_P(property) != IS_UNDEF) { -fast_assign: - value = zend_assign_to_variable(property, value, value_type); - if (retval && EXPECTED(!EG(exception))) { - ZVAL_COPY(retval, value); - } - return; - } - } else { - if (EXPECTED(zobj->properties != NULL)) { - if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { - if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { - GC_REFCOUNT(zobj->properties)--; - } - zobj->properties = zend_array_dup(zobj->properties); - } - property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); - if (property) { - goto fast_assign; - } - } - - if (!zobj->ce->__set) { - - if (EXPECTED(zobj->properties == NULL)) { - rebuild_object_properties(zobj); - } - /* separate our value if necessary */ - if (value_type == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { - ZVAL_COPY_VALUE(&tmp, value); - zval_copy_ctor_func(&tmp); - value = &tmp; - } - } else if (value_type != IS_TMP_VAR) { - if (Z_ISREF_P(value)) { - if (value_type == IS_VAR) { - zend_reference *ref = Z_REF_P(value); - if (--(GC_REFCOUNT(ref)) == 0) { - ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); - efree_size(ref, sizeof(zend_reference)); - value = &tmp; - } else { - value = Z_REFVAL_P(value); - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - } - } else { - value = Z_REFVAL_P(value); - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - } - } else if (value_type == IS_CV && Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - } - zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); - if (retval) { - ZVAL_COPY(retval, value); - } - return; - } - } - } - - if (!Z_OBJ_HT_P(object)->write_property) { - zend_error(E_WARNING, "Attempt to assign property of non-object"); - if (retval) { - ZVAL_NULL(retval); - } - FREE_OP(free_value); - return; - } - - /* separate our value if necessary */ - if (value_type == IS_CONST) { - if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { - ZVAL_COPY_VALUE(&tmp, value); - zval_copy_ctor_func(&tmp); - value = &tmp; - } - } else if (value_type != IS_TMP_VAR) { - ZVAL_DEREF(value); - } - - Z_OBJ_HT_P(object)->write_property(object, property_name, value, cache_slot); - - if (retval && EXPECTED(!EG(exception))) { - ZVAL_COPY(retval, value); - } - if (value_type == IS_CONST) { - zval_ptr_dtor_nogc(value); - } else { - FREE_OP(free_value); - } -} - static zend_never_inline void zend_assign_to_object_dim(zval *retval, zval *object, zval *property_name, int value_type, znode_op value_op, const zend_execute_data *execute_data) { zend_free_op free_value; @@ -1327,8 +1169,11 @@ static zend_never_inline void zend_binary_assign_op_obj_dim(zval *object, zval * static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *value, zval *result) { zend_string *old_str; + zend_uchar c; + size_t string_len; if (offset < 0) { + /* Error on negative offset */ zend_error(E_WARNING, "Illegal string offset: " ZEND_LONG_FMT, offset); zend_string_release(Z_STR_P(str)); if (result) { @@ -1337,8 +1182,31 @@ static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *valu return; } + if (Z_TYPE_P(value) != IS_STRING) { + /* Convert to string, just the time to pick the 1st byte */ + zend_string *tmp = zval_get_string(value); + + string_len = ZSTR_LEN(tmp); + c = (zend_uchar)ZSTR_VAL(tmp)[0]; + zend_string_release(tmp); + } else { + string_len = Z_STRLEN_P(value); + c = (zend_uchar)Z_STRVAL_P(value)[0]; + } + + if (string_len == 0) { + /* Error on empty input string */ + zend_error(E_WARNING, "Cannot assign an empty string to a string offset"); + zend_string_release(Z_STR_P(str)); + if (result) { + ZVAL_NULL(result); + } + return; + } + old_str = Z_STR_P(str); if ((size_t)offset >= Z_STRLEN_P(str)) { + /* Extend string if needed */ zend_long old_len = Z_STRLEN_P(str); Z_STR_P(str) = zend_string_extend(Z_STR_P(str), offset + 1, 0); Z_TYPE_INFO_P(str) = IS_STRING_EX; @@ -1349,23 +1217,11 @@ static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *valu Z_TYPE_INFO_P(str) = IS_STRING_EX; } - if (Z_TYPE_P(value) != IS_STRING) { - zend_string *tmp = zval_get_string(value); - - Z_STRVAL_P(str)[offset] = ZSTR_VAL(tmp)[0]; - zend_string_release(tmp); - } else { - Z_STRVAL_P(str)[offset] = Z_STRVAL_P(value)[0]; - } - /* - * the value of an assignment to a string offset is undefined - T(result->u.var).var = &T->str_offset.str; - */ + Z_STRVAL_P(str)[offset] = c; zend_string_release(old_str); if (result) { - zend_uchar c = (zend_uchar)Z_STRVAL_P(str)[offset]; - + /* Return the new character */ if (CG(one_char_string)[c]) { ZVAL_INTERNED_STR(result, CG(one_char_string)[c]); } else { @@ -1537,15 +1393,6 @@ static zend_always_inline HashTable *zend_get_target_symbol_table(zend_execute_d if (EXPECTED(fetch_type == ZEND_FETCH_GLOBAL_LOCK) || EXPECTED(fetch_type == ZEND_FETCH_GLOBAL)) { ht = &EG(symbol_table); - } else if (EXPECTED(fetch_type == ZEND_FETCH_STATIC)) { - ZEND_ASSERT(EX(func)->op_array.static_variables != NULL); - ht = EX(func)->op_array.static_variables; - if (GC_REFCOUNT(ht) > 1) { - if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { - GC_REFCOUNT(ht)--; - } - EX(func)->op_array.static_variables = ht = zend_array_dup(ht); - } } else { ZEND_ASSERT(fetch_type == ZEND_FETCH_LOCAL); if (!EX(symbol_table)) { @@ -1658,7 +1505,7 @@ str_index: default: zend_error(E_WARNING, "Illegal offset type"); retval = (type == BP_VAR_W || type == BP_VAR_RW) ? - &EG(error_zval) : &EG(uninitialized_zval); + NULL : &EG(uninitialized_zval); } } return retval; @@ -1841,10 +1688,15 @@ fetch_from_array: retval = zend_hash_next_index_insert(Z_ARRVAL_P(container), &EG(uninitialized_zval)); if (UNEXPECTED(retval == NULL)) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - retval = &EG(error_zval); + ZVAL_ERROR(result); + return; } } else { retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type); + if (UNEXPECTED(!retval)) { + ZVAL_ERROR(result); + return; + } } ZVAL_INDIRECT(result, retval); return; @@ -1869,11 +1721,11 @@ convert_to_array: zend_check_string_offset(dim, type); zend_wrong_string_offset(); } - ZVAL_INDIRECT(result, &EG(error_zval)); + ZVAL_ERROR(result); } else if (EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) { if (!Z_OBJ_HT_P(container)->read_dimension) { zend_throw_error(NULL, "Cannot use object as array"); - retval = &EG(error_zval); + ZVAL_ERROR(result); } else { retval = Z_OBJ_HT_P(container)->read_dimension(container, dim, type, result); @@ -1906,25 +1758,25 @@ convert_to_array: ZVAL_INDIRECT(result, retval); } } else { - ZVAL_INDIRECT(result, &EG(error_zval)); + ZVAL_ERROR(result); } } } else if (EXPECTED(Z_TYPE_P(container) <= IS_FALSE)) { - if (UNEXPECTED(container == &EG(error_zval))) { - ZVAL_INDIRECT(result, &EG(error_zval)); - } else if (type != BP_VAR_UNSET) { + if (type != BP_VAR_UNSET) { goto convert_to_array; } else { /* for read-mode only */ ZVAL_NULL(result); } + } else if (EXPECTED(Z_ISERROR_P(container))) { + ZVAL_ERROR(result); } else { if (type == BP_VAR_UNSET) { zend_error(E_WARNING, "Cannot unset offset in a non-array variable"); ZVAL_NULL(result); } else { zend_error(E_WARNING, "Cannot use a scalar value as an array"); - ZVAL_INDIRECT(result, &EG(error_zval)); + ZVAL_ERROR(result); } } } @@ -2053,8 +1905,8 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c { if (container_op_type != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) { do { - if (container_op_type == IS_VAR && UNEXPECTED(container == &EG(error_zval))) { - ZVAL_INDIRECT(result, &EG(error_zval)); + if (container_op_type == IS_VAR && UNEXPECTED(Z_ISERROR_P(container))) { + ZVAL_ERROR(result); return; } @@ -2073,7 +1925,7 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c object_init(container); } else { zend_error(E_WARNING, "Attempt to modify property of non-object"); - ZVAL_INDIRECT(result, &EG(error_zval)); + ZVAL_ERROR(result); return; } } while (0); @@ -2116,7 +1968,7 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c } } else { zend_throw_error(NULL, "Cannot access undefined property for object with overloaded property access"); - ZVAL_INDIRECT(result, &EG(error_zval)); + ZVAL_ERROR(result); } } else { ZVAL_INDIRECT(result, ptr); @@ -2130,7 +1982,7 @@ static zend_always_inline void zend_fetch_property_address(zval *result, zval *c } } else { zend_error(E_WARNING, "This object doesn't support property references"); - ZVAL_INDIRECT(result, &EG(error_zval)); + ZVAL_ERROR(result); } } @@ -2255,33 +2107,35 @@ static zend_always_inline void i_init_func_execute_data(zend_execute_data *execu first_extra_arg = op_array->num_args; num_args = EX_NUM_ARGS(); if (UNEXPECTED(num_args > first_extra_arg)) { - zval *end, *src, *dst; - uint32_t type_flags = 0; + if (EXPECTED(!(op_array->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))) { + zval *end, *src, *dst; + uint32_t type_flags = 0; - if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) { - /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */ - EX(opline) += first_extra_arg; - } + if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) { + /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */ + EX(opline) += first_extra_arg; + } - /* move extra args into separate array after all CV and TMP vars */ - end = EX_VAR_NUM(first_extra_arg - 1); - src = end + (num_args - first_extra_arg); - dst = src + (op_array->last_var + op_array->T - first_extra_arg); - if (EXPECTED(src != dst)) { - do { - type_flags |= Z_TYPE_INFO_P(src); - ZVAL_COPY_VALUE(dst, src); - ZVAL_UNDEF(src); - src--; - dst--; - } while (src != end); - } else { - do { - type_flags |= Z_TYPE_INFO_P(src); - src--; - } while (src != end); + /* move extra args into separate array after all CV and TMP vars */ + end = EX_VAR_NUM(first_extra_arg - 1); + src = end + (num_args - first_extra_arg); + dst = src + (op_array->last_var + op_array->T - first_extra_arg); + if (EXPECTED(src != dst)) { + do { + type_flags |= Z_TYPE_INFO_P(src); + ZVAL_COPY_VALUE(dst, src); + ZVAL_UNDEF(src); + src--; + dst--; + } while (src != end); + } else { + do { + type_flags |= Z_TYPE_INFO_P(src); + src--; + } while (src != end); + } + ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED)); } - ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED)); } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) { /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */ EX(opline) += num_args; @@ -2368,33 +2222,35 @@ static zend_always_inline void i_init_execute_data(zend_execute_data *execute_da first_extra_arg = op_array->num_args; num_args = EX_NUM_ARGS(); if (UNEXPECTED(num_args > first_extra_arg)) { - zval *end, *src, *dst; - uint32_t type_flags = 0; + if (EXPECTED(!(op_array->fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))) { + zval *end, *src, *dst; + uint32_t type_flags = 0; - if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) { - /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */ - EX(opline) += first_extra_arg; - } + if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) { + /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */ + EX(opline) += first_extra_arg; + } - /* move extra args into separate array after all CV and TMP vars */ - end = EX_VAR_NUM(first_extra_arg - 1); - src = end + (num_args - first_extra_arg); - dst = src + (op_array->last_var + op_array->T - first_extra_arg); - if (EXPECTED(src != dst)) { - do { - type_flags |= Z_TYPE_INFO_P(src); - ZVAL_COPY_VALUE(dst, src); - ZVAL_UNDEF(src); - src--; - dst--; - } while (src != end); - } else { - do { - type_flags |= Z_TYPE_INFO_P(src); - src--; - } while (src != end); + /* move extra args into separate array after all CV and TMP vars */ + end = EX_VAR_NUM(first_extra_arg - 1); + src = end + (num_args - first_extra_arg); + dst = src + (op_array->last_var + op_array->T - first_extra_arg); + if (EXPECTED(src != dst)) { + do { + type_flags |= Z_TYPE_INFO_P(src); + ZVAL_COPY_VALUE(dst, src); + ZVAL_UNDEF(src); + src--; + dst--; + } while (src != end); + } else { + do { + type_flags |= Z_TYPE_INFO_P(src); + src--; + } while (src != end); + } + ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED)); } - ZEND_ADD_CALL_FLAG(execute_data, ((type_flags >> Z_TYPE_FLAGS_SHIFT) & IS_TYPE_REFCOUNTED)); } else if (EXPECTED((op_array->fn_flags & ZEND_ACC_HAS_TYPE_HINTS) == 0)) { /* Skip useless ZEND_RECV and ZEND_RECV_INIT opcodes */ EX(opline) += num_args; @@ -2501,6 +2357,10 @@ ZEND_API void zend_init_execute_data(zend_execute_data *execute_data, zend_op_ar static zend_always_inline zend_bool zend_is_by_ref_func_arg_fetch(const zend_op *opline, zend_execute_data *call) /* {{{ */ { uint32_t arg_num = opline->extended_value & ZEND_FETCH_ARG_MASK; + + if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + return QUICK_ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num); + } return ARG_SHOULD_BE_SENT_BY_REF(call->func, arg_num); } /* }}} */ @@ -2664,9 +2524,7 @@ static void cleanup_unfinished_calls(zend_execute_data *execute_data, uint32_t o if (ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS) { if (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR) { - if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) { - GC_REFCOUNT(Z_OBJ(call->This))--; - } + GC_REFCOUNT(Z_OBJ(call->This))--; if (GC_REFCOUNT(Z_OBJ(call->This)) == 1) { zend_object_store_ctor_failed(Z_OBJ(call->This)); } diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c index 0c6f0377da..ed2170d5df 100644 --- a/Zend/zend_execute_API.c +++ b/Zend/zend_execute_API.c @@ -130,7 +130,7 @@ void init_executor(void) /* {{{ */ zend_init_fpu(); ZVAL_NULL(&EG(uninitialized_zval)); - ZVAL_NULL(&EG(error_zval)); + ZVAL_ERROR(&EG(error_zval)); /* destroys stack frame, therefore makes core dumps worthless */ #if 0&&ZEND_DEBUG original_sigsegv_handler = signal(SIGSEGV, zend_handle_sigsegv); @@ -398,7 +398,7 @@ void shutdown_executor(void) /* {{{ */ zend_shutdown_fpu(); #ifdef ZEND_DEBUG - if (EG(ht_iterators_used)) { + if (EG(ht_iterators_used) && !CG(unclean_shutdown)) { zend_error(E_WARNING, "Leaked %" PRIu32 " hashtable iterators", EG(ht_iterators_used)); } #endif diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c index b5e6c6a221..9633fc4f2d 100644 --- a/Zend/zend_generators.c +++ b/Zend/zend_generators.c @@ -35,11 +35,6 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato { zend_execute_data *execute_data = generator->execute_data; - if (generator->send_target) { - Z_TRY_DELREF_P(generator->send_target); - generator->send_target = NULL; - } - if (execute_data->opline != execute_data->func->op_array.opcodes) { /* -1 required because we want the last run opcode, not the next to-be-run one. */ uint32_t op_num = execute_data->opline - execute_data->func->op_array.opcodes - 1; @@ -65,11 +60,6 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution) /* {{{ */ { - if (UNEXPECTED(Z_TYPE(generator->values) != IS_UNDEF)) { - zval_ptr_dtor(&generator->values); - ZVAL_UNDEF(&generator->values); - } - if (EXPECTED(generator->execute_data)) { zend_execute_data *execute_data = generator->execute_data; @@ -103,12 +93,20 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished OBJ_RELEASE((zend_object *) EX(func)->common.prototype); } + /* Free GC buffer. GC for closed generators doesn't need an allocated buffer */ + if (generator->gc_buffer) { + efree(generator->gc_buffer); + generator->gc_buffer = NULL; + } + efree(generator->stack); generator->execute_data = NULL; } } /* }}} */ +static zend_generator *zend_generator_get_child(zend_generator_node *node, zend_generator *leaf); + static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ { zend_generator *generator = (zend_generator*) object; @@ -116,6 +114,22 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ uint32_t op_num, finally_op_num, finally_op_end; int i; + /* leave yield from mode to properly allow finally execution */ + if (UNEXPECTED(Z_TYPE(generator->values) != IS_UNDEF)) { + zval_ptr_dtor(&generator->values); + ZVAL_UNDEF(&generator->values); + } + + if (EXPECTED(generator->node.children == 0)) { + zend_generator *root = generator->node.ptr.root, *next; + while (UNEXPECTED(root != generator)) { + next = zend_generator_get_child(&root->node, generator); + OBJ_RELEASE(&root->std); + root = next; + } + generator->node.parent = NULL; + } + if (EXPECTED(!ex) || EXPECTED(!(ex->func->op_array.fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK))) { return; } @@ -156,8 +170,6 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */ } /* }}} */ -static zend_generator *zend_generator_get_child(zend_generator_node *node, zend_generator *leaf); - static void zend_generator_free_storage(zend_object *object) /* {{{ */ { zend_generator *generator = (zend_generator*) object; @@ -181,15 +193,102 @@ static void zend_generator_free_storage(zend_object *object) /* {{{ */ if (generator->iterator) { zend_iterator_dtor(generator->iterator); } +} +/* }}} */ - if (EXPECTED(generator->node.children == 0)) { - zend_generator *root = generator->node.ptr.root, *next; - while (UNEXPECTED(root != generator)) { - next = zend_generator_get_child(&root->node, generator); - OBJ_RELEASE(&root->std); - root = next; +static uint32_t calc_gc_buffer_size(zend_generator *generator) /* {{{ */ +{ + uint32_t size = 4; /* value, key, retval, values */ + if (generator->execute_data) { + zend_execute_data *execute_data = generator->execute_data; + zend_op_array *op_array = &EX(func)->op_array; + + /* Compiled variables */ + if (!execute_data->symbol_table) { + size += op_array->last_var; + } + /* Extra args */ + if (EX_CALL_INFO() & ZEND_CALL_FREE_EXTRA_ARGS) { + size += EX_NUM_ARGS() - op_array->num_args; + } + size += Z_OBJ(execute_data->This) != NULL; /* $this */ + size += (EX_CALL_INFO() & ZEND_CALL_CLOSURE) != 0; /* Closure object */ + + /* Yield from root references */ + if (generator->node.children == 0) { + zend_generator *root = generator->node.ptr.root; + while (root != generator) { + size++; + root = zend_generator_get_child(&root->node, generator); + } } } + return size; +} +/* }}} */ + +static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* {{{ */ +{ + zend_generator *generator = (zend_generator*) Z_OBJ_P(object); + zend_execute_data *execute_data = generator->execute_data; + zend_op_array *op_array; + zval *gc_buffer; + uint32_t gc_buffer_size; + + if (!execute_data) { + /* If the generator has been closed, it can only hold on to three values: The value, key + * and retval. These three zvals are stored sequentially starting at &generator->value. */ + *table = &generator->value; + *n = 3; + return NULL; + } + + op_array = &EX(func)->op_array; + gc_buffer_size = calc_gc_buffer_size(generator); + if (generator->gc_buffer_size < gc_buffer_size) { + generator->gc_buffer = safe_erealloc(generator->gc_buffer, sizeof(zval), gc_buffer_size, 0); + generator->gc_buffer_size = gc_buffer_size; + } + + *n = gc_buffer_size; + *table = gc_buffer = generator->gc_buffer; + + ZVAL_COPY_VALUE(gc_buffer++, &generator->value); + ZVAL_COPY_VALUE(gc_buffer++, &generator->key); + ZVAL_COPY_VALUE(gc_buffer++, &generator->retval); + ZVAL_COPY_VALUE(gc_buffer++, &generator->values); + + if (!execute_data->symbol_table) { + uint32_t i, num_cvs = EX(func)->op_array.last_var; + for (i = 0; i < num_cvs; i++) { + ZVAL_COPY_VALUE(gc_buffer++, EX_VAR_NUM(i)); + } + } + + if (EX_CALL_INFO() & ZEND_CALL_FREE_EXTRA_ARGS) { + zval *zv = EX_VAR_NUM(op_array->last_var + op_array->T); + zval *end = zv + (EX_NUM_ARGS() - op_array->num_args); + while (zv != end) { + ZVAL_COPY_VALUE(gc_buffer++, zv++); + } + } + + if (Z_OBJ(execute_data->This)) { + ZVAL_OBJ(gc_buffer++, Z_OBJ(execute_data->This)); + } + if (EX_CALL_INFO() & ZEND_CALL_CLOSURE) { + ZVAL_OBJ(gc_buffer++, (zend_object *) EX(func)->common.prototype); + } + + if (generator->node.children == 0) { + zend_generator *child = generator, *root = generator->node.ptr.root; + while (root != child) { + ZVAL_OBJ(gc_buffer++, &child->std); + child = child->node.parent; + } + } + + return execute_data->symbol_table; } /* }}} */ @@ -495,7 +594,7 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator if (EXPECTED(EG(exception) == NULL)) { zend_op *yield_from = (zend_op *) root->execute_data->opline - 1; - if (yield_from->opcode == ZEND_YIELD_FROM && !(yield_from->result_type & EXT_TYPE_UNUSED)) { + if (yield_from->opcode == ZEND_YIELD_FROM) { if (Z_ISUNDEF(root->node.parent->retval)) { /* Throw the exception in the context of the generator */ zend_execute_data *original_execute_data = EG(current_execute_data); @@ -512,6 +611,7 @@ ZEND_API zend_generator *zend_generator_update_current(zend_generator *generator EG(current_execute_data) = original_execute_data; } else { + zval_ptr_dtor(&root->value); ZVAL_COPY(&root->value, &root->node.parent->value); ZVAL_COPY(ZEND_CALL_VAR(root->execute_data, yield_from->result.var), &root->node.parent->retval); } @@ -872,7 +972,6 @@ ZEND_METHOD(Generator, send) root = zend_generator_get_current(generator); /* Put sent value in the target VAR slot, if it is used */ if (root->send_target) { - Z_TRY_DELREF_P(root->send_target); ZVAL_COPY(root->send_target, value); } @@ -1127,6 +1226,7 @@ void zend_register_generator_ce(void) /* {{{ */ memcpy(&zend_generator_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); zend_generator_handlers.free_obj = zend_generator_free_storage; zend_generator_handlers.dtor_obj = zend_generator_dtor_storage; + zend_generator_handlers.get_gc = zend_generator_get_gc; zend_generator_handlers.clone_obj = NULL; zend_generator_handlers.get_constructor = zend_generator_get_constructor; diff --git a/Zend/zend_generators.h b/Zend/zend_generators.h index 26ee646b65..95c5147a93 100644 --- a/Zend/zend_generators.h +++ b/Zend/zend_generators.h @@ -82,7 +82,7 @@ struct _zend_generator { * by-value foreach. */ zval values; - /* Node of waiting generators when multiple "yield *" expressions + /* Node of waiting generators when multiple "yield from" expressions * are nested. */ zend_generator_node node; @@ -91,6 +91,9 @@ struct _zend_generator { /* ZEND_GENERATOR_* flags */ zend_uchar flags; + + zval *gc_buffer; + uint32_t gc_buffer_size; }; static const zend_uchar ZEND_GENERATOR_CURRENTLY_RUNNING = 0x1; diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h index 0f1580df88..b1c9affb3c 100644 --- a/Zend/zend_hash.h +++ b/Zend/zend_hash.h @@ -248,7 +248,7 @@ END_EXTERN_C() static zend_always_inline int _zend_handle_numeric_str(const char *key, size_t length, zend_ulong *idx) { - register const char *tmp = key; + const char *tmp = key; if (*tmp > '9') { return 0; diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index ce7dd99026..e3ef6a6991 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -585,7 +585,20 @@ static zend_function *do_inherit_method(zend_string *key, zend_function *parent, zval *child = zend_hash_find(&ce->function_table, key); if (child) { - do_inheritance_check_on_method((zend_function*)Z_PTR_P(child), parent); + zend_function *func = (zend_function*)Z_PTR_P(child); + zend_function *orig_prototype = func->common.prototype; + + do_inheritance_check_on_method(func, parent); + if (func->common.prototype != orig_prototype && + func->type == ZEND_USER_FUNCTION && + func->common.scope != ce && + !func->op_array.static_variables) { + /* Lazy duplication */ + zend_function *new_function = zend_arena_alloc(&CG(arena), sizeof(zend_op_array)); + memcpy(new_function, func, sizeof(zend_op_array)); + Z_PTR_P(child) = new_function; + func->common.prototype = orig_prototype; + } return NULL; } @@ -711,15 +724,15 @@ static void do_inherit_class_constant(zend_string *name, zend_class_constant *pa if (Z_CONSTANT(parent_const->value)) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } - if (Z_REFCOUNTED(parent_const->value)) { - Z_ADDREF(parent_const->value); - } if (ce->type & ZEND_INTERNAL_CLASS) { + if (Z_REFCOUNTED(parent_const->value)) { + Z_ADDREF(parent_const->value); + } c = pemalloc(sizeof(zend_class_constant), 1); + memcpy(c, parent_const, sizeof(zend_class_constant)); } else { - c = zend_arena_alloc(&CG(arena), sizeof(zend_class_constant)); + c = parent_const; } - memcpy(c, parent_const, sizeof(zend_class_constant)); _zend_hash_append_ptr(&ce->constants_table, name, c); } } @@ -920,13 +933,20 @@ static zend_bool do_inherit_constant_check(HashTable *child_constants_table, zen static void do_inherit_iface_constant(zend_string *name, zend_class_constant *c, zend_class_entry *ce, zend_class_entry *iface) /* {{{ */ { if (do_inherit_constant_check(&ce->constants_table, c, name, iface)) { - if (Z_REFCOUNTED(c->value)) { - Z_ADDREF(c->value); - } + zend_class_constant *ct; if (Z_CONSTANT(c->value)) { ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED; } - zend_hash_update_ptr(&ce->constants_table, name, c); + if (ce->type & ZEND_INTERNAL_CLASS) { + if (Z_REFCOUNTED(c->value)) { + Z_ADDREF(c->value); + } + ct = pemalloc(sizeof(zend_class_constant), 1); + memcpy(ct, c, sizeof(zend_class_constant)); + } else { + ct = c; + } + zend_hash_update_ptr(&ce->constants_table, name, ct); } } /* }}} */ diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c index 98e537ad28..c66f8ad7c3 100644 --- a/Zend/zend_object_handlers.c +++ b/Zend/zend_object_handlers.c @@ -1054,6 +1054,8 @@ ZEND_API zend_function *zend_get_call_trampoline_func(zend_class_entry *ce, zend func->prototype = fbc; func->scope = fbc->common.scope; + /* reserve space for arguments, local and temorary variables */ + func->T = (fbc->type == ZEND_USER_FUNCTION)? MAX(fbc->op_array.last_var + fbc->op_array.T, 2) : 2; func->filename = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.filename : ZSTR_EMPTY_ALLOC(); func->line_start = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_start : 0; func->line_end = (fbc->type == ZEND_USER_FUNCTION)? fbc->op_array.line_end : 0; diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c index 9f5afcebe6..ab67a88272 100644 --- a/Zend/zend_opcode.c +++ b/Zend/zend_opcode.c @@ -291,9 +291,11 @@ ZEND_API void destroy_zend_class(zval *zv) zend_class_constant *c; ZEND_HASH_FOREACH_PTR(&ce->constants_table, c) { - zval_ptr_dtor(&c->value); - if (c->doc_comment && c->ce == ce) { - zend_string_release(c->doc_comment); + if (c->ce == ce) { + zval_ptr_dtor(&c->value); + if (c->doc_comment) { + zend_string_release(c->doc_comment); + } } } ZEND_HASH_FOREACH_END(); zend_hash_destroy(&ce->constants_table); @@ -609,7 +611,7 @@ ZEND_API int pass_two(zend_op_array *op_array) zend_update_extended_info(op_array); } if (CG(compiler_options) & ZEND_COMPILE_HANDLE_OP_ARRAY) { - if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_PERSIST) { + if (zend_extension_flags & ZEND_EXTENSIONS_HAVE_OP_ARRAY_HANDLER) { zend_llist_apply_with_argument(&zend_extensions, (llist_apply_with_arg_func_t) zend_extension_op_array_handler, op_array); } } @@ -678,8 +680,8 @@ ZEND_API int pass_two(zend_op_array *op_array) break; case ZEND_ASSERT_CHECK: /* If result of assert is unused, result of check is unused as well */ - if (op_array->opcodes[opline->op2.opline_num - 1].result_type & EXT_TYPE_UNUSED) { - opline->result_type |= EXT_TYPE_UNUSED; + if (op_array->opcodes[opline->op2.opline_num - 1].result_type == IS_UNUSED) { + opline->result_type = IS_UNUSED; } ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op2); break; @@ -694,9 +696,13 @@ ZEND_API int pass_two(zend_op_array *op_array) case ZEND_VERIFY_RETURN_TYPE: if (op_array->fn_flags & ZEND_ACC_GENERATOR) { if (opline->op1_type != IS_UNUSED) { - (opline + 1)->op1 = opline->op1; - (opline + 1)->op1_type = opline->op1_type; + zend_op *ret = opline; + do ret++; while (ret->opcode != ZEND_RETURN); + + ret->op1 = opline->op1; + ret->op1_type = opline->op1_type; } + MAKE_NOP(opline); } break; diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h index f0ad0300fb..b0b167bd74 100644 --- a/Zend/zend_operators.h +++ b/Zend/zend_operators.h @@ -185,7 +185,7 @@ zend_memnstr(const char *haystack, const char *needle, size_t needle_len, const static zend_always_inline const void *zend_memrchr(const void *s, int c, size_t n) { - register const unsigned char *e; + const unsigned char *e; if (n <= 0) { return NULL; } diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index f187129416..298dfb53fa 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -284,7 +284,7 @@ char *alloca(); # endif # elif defined(_MSC_VER) # define zend_always_inline __forceinline -# define zend_never_inline +# define zend_never_inline __declspec(noinline) # else # if __has_attribute(always_inline) # define zend_always_inline inline __attribute__((always_inline)) diff --git a/Zend/zend_sprintf.c b/Zend/zend_sprintf.c index 2620a8ed41..37d876d423 100644 --- a/Zend/zend_sprintf.c +++ b/Zend/zend_sprintf.c @@ -30,13 +30,14 @@ #if ZEND_BROKEN_SPRINTF int zend_sprintf(char *buffer, const char *format, ...) { + int len; va_list args; va_start(args, format); - vsprintf(buffer, format, args); + len = vsprintf(buffer, format, args); va_end(args); - return strlen(buffer); + return len; } #endif diff --git a/Zend/zend_string.h b/Zend/zend_string.h index 722fc3ae46..28aebb0ffc 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -323,7 +323,7 @@ static zend_always_inline zend_bool zend_string_equals(zend_string *s1, zend_str static zend_always_inline zend_ulong zend_inline_hash_func(const char *str, size_t len) { - register zend_ulong hash = Z_UL(5381); + zend_ulong hash = Z_UL(5381); /* variant with the hash unrolled eight times */ for (; len >= 8; len -= 8) { diff --git a/Zend/zend_types.h b/Zend/zend_types.h index da0c985481..5207386ccf 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -324,6 +324,7 @@ struct _zend_ast_ref { /* internal types */ #define IS_INDIRECT 15 #define IS_PTR 17 +#define _IS_ERROR 19 static zend_always_inline zend_uchar zval_get_type(const zval* pz) { return pz->u1.v.type; @@ -502,6 +503,9 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { #define Z_ISNULL(zval) (Z_TYPE(zval) == IS_NULL) #define Z_ISNULL_P(zval_p) Z_ISNULL(*(zval_p)) +#define Z_ISERROR(zval) (Z_TYPE(zval) == _IS_ERROR) +#define Z_ISERROR_P(zval_p) Z_ISERROR(*(zval_p)) + #define Z_LVAL(zval) (zval).value.lval #define Z_LVAL_P(zval_p) Z_LVAL(*(zval_p)) @@ -781,6 +785,10 @@ static zend_always_inline zend_uchar zval_get_type(const zval* pz) { Z_TYPE_INFO_P(z) = IS_PTR; \ } while (0) +#define ZVAL_ERROR(z) do { \ + Z_TYPE_INFO_P(z) = _IS_ERROR; \ + } while (0) + #define Z_REFCOUNT_P(pz) zval_refcount_p(pz) #define Z_SET_REFCOUNT_P(pz, rc) zval_set_refcount_p(pz, rc) #define Z_ADDREF_P(pz) zval_addref_p(pz) diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index b0637fcc55..de67318bed 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -789,14 +789,14 @@ ZEND_VM_HELPER(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR|UNU zend_fetch_dimension_address_RW(&rv, container, dim, OP2_TYPE); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -825,7 +825,7 @@ ZEND_VM_HELPER(zend_binary_assign_op_helper, VAR|CV, CONST|TMPVAR|CV, binary_op_ value = GET_OP2_ZVAL_PTR(BP_VAR_R); var_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_RW); - if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -1231,7 +1231,7 @@ ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV) ZEND_VM_DISPATCH_TO_HELPER(zend_post_incdec_property_helper, inc, 0); } -ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY) +ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY, SPEC(RETVAL)) { USE_OPLINE zend_free_op free_op1; @@ -1247,7 +1247,7 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } - if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -1271,7 +1271,7 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY) ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY) +ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY, SPEC(RETVAL)) { USE_OPLINE zend_free_op free_op1; @@ -1287,7 +1287,7 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } - if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -1325,7 +1325,7 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } - if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -1358,7 +1358,7 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY) ZEND_VM_NEXT_OPCODE(); } - if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -1474,14 +1474,7 @@ ZEND_VM_HELPER(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type) } } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { - FREE_OP1(); - HANDLE_EXCEPTION(); - } - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { + if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { FREE_OP1(); } @@ -1751,7 +1744,7 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUS SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { + if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); FREE_UNFETCHED_OP2(); FREE_UNFETCHED_OP1(); @@ -2013,7 +2006,7 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|THIS|CV, CONST FREE_OP2(); HANDLE_EXCEPTION(); } - if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { + if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); FREE_OP2(); FREE_OP1_VAR_PTR(); @@ -2101,12 +2094,11 @@ ZEND_VM_C_LABEL(try_fetch_list): ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV) +ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV, SPEC(OP_DATA=CONST|TMP|VAR|CV)) { USE_OPLINE - zend_free_op free_op1, free_op2; - zval *object; - zval *property_name; + zend_free_op free_op1, free_op2, free_op_data; + zval *object, *property_name, *value, tmp; SAVE_OPLINE(); object = GET_OP1_OBJ_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); @@ -2118,20 +2110,171 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|THIS|CV, CONST|TMPVAR|CV) } property_name = GET_OP2_ZVAL_PTR(BP_VAR_R); + value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); + + if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_DATA(); + ZEND_VM_C_GOTO(exit_assign_obj); + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_DATA(); + OBJ_RELEASE(obj); + ZEND_VM_C_GOTO(exit_assign_obj); + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_DATA(); + ZEND_VM_C_GOTO(exit_assign_obj); + } + } while (0); + } + + if (OP2_TYPE == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +ZEND_VM_C_LABEL(fast_assign_obj): + value = zend_assign_to_variable(property, value, OP_DATA_TYPE); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + ZEND_VM_C_GOTO(exit_assign_obj); + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + ZEND_VM_C_GOTO(fast_assign_obj); + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (OP_DATA_TYPE == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (OP_DATA_TYPE != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (OP_DATA_TYPE == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (OP_DATA_TYPE == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + ZEND_VM_C_GOTO(exit_assign_obj); + } + } + } - zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, OP1_TYPE, property_name, OP2_TYPE, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + FREE_OP_DATA(); + ZEND_VM_C_GOTO(exit_assign_obj); + } + + /* separate our value if necessary */ + if (OP_DATA_TYPE == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (OP_DATA_TYPE != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (OP_DATA_TYPE == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + FREE_OP_DATA(); + } +ZEND_VM_C_LABEL(exit_assign_obj): FREE_OP2(); FREE_OP1_VAR_PTR(); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV) +ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|NEXT|CV, SPEC(OP_DATA=CONST|TMP|VAR|CV)) { USE_OPLINE zend_free_op free_op1; zval *object_ptr; - zend_free_op free_op2, free_op_data1; + zend_free_op free_op2, free_op_data; zval *value; zval *variable_ptr; zval *dim; @@ -2146,7 +2289,7 @@ ZEND_VM_C_LABEL(try_assign_dim_array): variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); if (UNEXPECTED(variable_ptr == NULL)) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - variable_ptr = &EG(error_zval); + variable_ptr = NULL; } } else { dim = GET_OP2_ZVAL_PTR(BP_VAR_R); @@ -2154,14 +2297,14 @@ ZEND_VM_C_LABEL(try_assign_dim_array): variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, OP2_TYPE, BP_VAR_W); FREE_OP2(); } - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); + if (UNEXPECTED(variable_ptr == NULL)) { + FREE_UNFETCHED_OP_DATA(); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type); + value = GET_OP_DATA_ZVAL_PTR(BP_VAR_R); + value = zend_assign_to_variable(variable_ptr, value, OP_DATA_TYPE); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -2177,13 +2320,13 @@ ZEND_VM_C_LABEL(try_assign_dim_array): zend_free_op free_op2; zval *property_name = GET_OP2_ZVAL_PTR(BP_VAR_R); - zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data); + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, OP_DATA_TYPE, (opline+1)->op1, execute_data); FREE_OP2(); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { if (OP2_TYPE == IS_UNUSED) { zend_throw_error(NULL, "[] operator not supported for strings"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + FREE_UNFETCHED_OP_DATA(); FREE_OP1_VAR_PTR(); HANDLE_EXCEPTION(); } else { @@ -2192,9 +2335,9 @@ ZEND_VM_C_LABEL(try_assign_dim_array): dim = GET_OP2_ZVAL_PTR(BP_VAR_R); offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); FREE_OP2(); - value = get_zval_ptr_r_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); + value = GET_OP_DATA_ZVAL_PTR_DEREF(BP_VAR_R); zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + FREE_OP_DATA(); } } else { zval_ptr_dtor_nogc(object_ptr); @@ -2204,17 +2347,14 @@ ZEND_VM_C_LABEL(assign_dim_convert_to_array): ZEND_VM_C_GOTO(try_assign_dim_array); } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { - ZEND_VM_C_GOTO(assign_dim_clean); - } ZEND_VM_C_GOTO(assign_dim_convert_to_array); + } else if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + ZEND_VM_C_GOTO(assign_dim_clean); } else { zend_error(E_WARNING, "Cannot use a scalar value as an array"); ZEND_VM_C_LABEL(assign_dim_clean): - dim = GET_OP2_ZVAL_PTR(BP_VAR_R); - FREE_OP2(); - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - FREE_OP(free_op_data1); + FREE_UNFETCHED_OP2(); + FREE_UNFETCHED_OP_DATA(); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -2225,7 +2365,7 @@ ZEND_VM_C_LABEL(assign_dim_clean): ZEND_VM_NEXT_OPCODE_EX(1, 2); } -ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV) +ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV, SPEC(RETVAL)) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -2236,7 +2376,7 @@ ZEND_VM_HANDLER(38, ZEND_ASSIGN, VAR|CV, CONST|TMP|VAR|CV) value = GET_OP2_ZVAL_PTR(BP_VAR_R); variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { FREE_OP2(); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); @@ -2262,44 +2402,50 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV, SRC) SAVE_OPLINE(); value_ptr = GET_OP2_ZVAL_PTR_PTR(BP_VAR_W); + variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var)))) { + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var))) && + UNEXPECTED(!Z_ISERROR_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); FREE_OP2_VAR_PTR(); HANDLE_EXCEPTION(); - } - if (OP2_TYPE == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!OP2_FREE && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op2.var)) != IS_INDIRECT)) { /* undo the effect of get_zval_ptr_ptr() */ - Z_TRY_ADDREF_P(value_ptr); - } + + } else if (OP2_TYPE == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { FREE_OP2_VAR_PTR(); HANDLE_EXCEPTION(); } - ZEND_VM_DISPATCH_TO_HANDLER(ZEND_ASSIGN); - } - variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); - if ((OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || - (OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { - variable_ptr = &EG(uninitialized_zval); + value_ptr = zend_assign_to_variable(variable_ptr, value_ptr, OP2_TYPE); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value_ptr); + } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + if ((OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) || + (OP2_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr)))) { + variable_ptr = &EG(uninitialized_zval); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } + + FREE_OP2_VAR_PTR(); } FREE_OP1_VAR_PTR(); - FREE_OP2_VAR_PTR(); - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -2325,13 +2471,10 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY) object = Z_OBJ(old_execute_data->This); #if 0 if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { - if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { #else if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { - if (!(call_info & ZEND_CALL_CTOR_RESULT_UNUSED)) { #endif - GC_REFCOUNT(object)--; - } + GC_REFCOUNT(object)--; if (GC_REFCOUNT(object) == 1) { zend_object_store_ctor_failed(object); } @@ -2906,7 +3049,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|THIS|CV, CONST|T } } if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { FREE_OP2(); HANDLE_EXCEPTION(); @@ -3022,15 +3165,22 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CLASS_FETCH|CONST|VAR, function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R); if (OP2_TYPE != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (OP2_TYPE & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); - FREE_OP2(); - HANDLE_EXCEPTION(); + zend_throw_error(NULL, "Function name must be a string"); + FREE_OP2(); + HANDLE_EXCEPTION(); + } while (0); } } @@ -3445,7 +3595,7 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST, NUM) +ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, NUM, CONST, NUM) { USE_OPLINE zend_free_op free_op2; @@ -3475,12 +3625,13 @@ ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST, NUM) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY) +ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY, SPEC(RETVAL)) { USE_OPLINE zend_execute_data *call = EX(call); zend_function *fbc = call->func; zval *ret; + zval retval; SAVE_OPLINE(); EX(call) = call->prev_execute_data; @@ -3488,7 +3639,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY) call->prev_execute_data = execute_data; EG(current_execute_data) = call; - ret = EX_VAR(opline->result.var); + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = 0; @@ -3496,9 +3647,9 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY) #if ZEND_DEBUG ZEND_ASSERT( - !call->func || + EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -3506,7 +3657,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY) zend_vm_stack_free_call_frame(call); if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } if (UNEXPECTED(EG(exception) != NULL)) { @@ -3521,7 +3672,7 @@ ZEND_VM_HANDLER(129, ZEND_DO_ICALL, ANY, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY) +ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY, SPEC(RETVAL)) { USE_OPLINE zend_execute_data *call = EX(call); @@ -3546,7 +3697,7 @@ ZEND_VM_HANDLER(130, ZEND_DO_UCALL, ANY, ANY) ZEND_VM_ENTER(); } -ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY) +ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY, SPEC(RETVAL)) { USE_OPLINE zend_execute_data *call = EX(call); @@ -3584,6 +3735,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY) } EG(scope) = EX(func)->op_array.scope; } else { + zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { @@ -3616,7 +3768,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY) } } - ret = EX_VAR(opline->result.var); + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; @@ -3624,9 +3776,9 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY) #if ZEND_DEBUG ZEND_ASSERT( - !call->func || + EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -3634,7 +3786,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY) zend_vm_stack_free_call_frame(call); if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } } @@ -3649,7 +3801,7 @@ ZEND_VM_HANDLER(131, ZEND_DO_FCALL_BY_NAME, ANY, ANY) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) +ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY, SPEC(RETVAL)) { USE_OPLINE zend_execute_data *call = EX(call); @@ -3711,6 +3863,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) } } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { int should_change_scope = 0; + zval retval; if (fbc->common.scope) { should_change_scope = 1; @@ -3742,7 +3895,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) } } - ret = EX_VAR(opline->result.var); + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; @@ -3755,16 +3908,16 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) #if ZEND_DEBUG ZEND_ASSERT( - !call->func || + EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } if (UNEXPECTED(should_change_scope)) { @@ -3773,6 +3926,7 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) ZEND_VM_C_GOTO(fcall_end); } } else { /* ZEND_OVERLOADED_FUNCTION */ + zval retval; /* Not sure what should be done here if it's a static method */ object = Z_OBJ(call->This); if (UNEXPECTED(object == NULL)) { @@ -3789,11 +3943,12 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) EG(scope) = fbc->common.scope; - ZVAL_NULL(EX_VAR(opline->result.var)); + ret = RETURN_VALUE_USED(opline) ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); call->prev_execute_data = execute_data; EG(current_execute_data) = call; - object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var)); + object->handlers->call_method(fbc->common.function_name, object, call, ret); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -3804,9 +3959,9 @@ ZEND_VM_HANDLER(60, ZEND_DO_FCALL, ANY, ANY) efree(fbc); if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + zval_ptr_dtor(ret); } else { - Z_VAR_FLAGS_P(EX_VAR(opline->result.var)) = 0; + Z_VAR_FLAGS_P(ret) = 0; } } @@ -3815,13 +3970,10 @@ ZEND_VM_C_LABEL(fcall_end_change_scope): object = Z_OBJ(call->This); #if 0 if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) { - if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { #else if (UNEXPECTED(EG(exception) != NULL) && (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR)) { - if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) { #endif - GC_REFCOUNT(object)--; - } + GC_REFCOUNT(object)--; if (GC_REFCOUNT(object) == 1) { zend_object_store_ctor_failed(object); } @@ -3913,14 +4065,14 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY) ZVAL_NULL(EX(return_value)); } } else if (!EX(return_value)) { - if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_TMP_VAR ) { + if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { SAVE_OPLINE(); zval_dtor_func_for_ptr(Z_COUNTED_P(free_op1)); } } } else { - if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { + if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); if (OP1_TYPE == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) { @@ -3958,7 +4110,7 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY, SRC) SAVE_OPLINE(); do { - if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR || + if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR)) || (OP1_TYPE == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); @@ -4018,7 +4170,7 @@ ZEND_VM_HANDLER(161, ZEND_GENERATOR_RETURN, CONST|TMP|VAR|CV, ANY) retval = GET_OP1_ZVAL_PTR(BP_VAR_R); /* Copy return value into generator->retval */ - if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { + if ((OP1_TYPE & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(&generator->retval, retval); if (OP1_TYPE == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->retval))) { @@ -4158,7 +4310,7 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, NUM) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, NUM) +ZEND_VM_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, NUM, SPEC(QUICK_ARG)) { USE_OPLINE zval *value, *arg; @@ -4275,7 +4427,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, NUM) varptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W); arg = ZEND_CALL_VAR(EX(call), opline->result.var); - if (OP1_TYPE == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) { + if (OP1_TYPE == IS_VAR && UNEXPECTED(Z_ISERROR_P(varptr))) { ZVAL_NEW_REF(arg, &EG(uninitialized_zval)); ZEND_VM_NEXT_OPCODE(); } @@ -4293,7 +4445,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, NUM) ZEND_VM_NEXT_OPCODE(); } -ZEND_VM_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, NUM) +ZEND_VM_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, NUM, SPEC(QUICK_ARG)) { USE_OPLINE zval *varptr, *arg; @@ -4853,7 +5005,7 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV) ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, JMP_ADDR, NUM) { USE_OPLINE - zval object_zval; + zval *result; zend_function *constructor; zend_class_entry *ce; @@ -4876,33 +5028,26 @@ ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CLASS_FETCH|CONST|VAR, JMP_ADDR, NUM) } else { ce = Z_CE_P(EX_VAR(opline->op1.var)); } - if (UNEXPECTED(object_init_ex(&object_zval, ce) != SUCCESS)) { + + result = EX_VAR(opline->result.var); + if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) { HANDLE_EXCEPTION(); } - constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); + constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); if (constructor == NULL) { - if (EXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); - } else { - OBJ_RELEASE(Z_OBJ(object_zval)); - } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { /* We are not handling overloaded classes right now */ zend_execute_data *call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | - (EXPECTED(RETURN_VALUE_USED(opline)) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED), + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, constructor, opline->extended_value, ce, - Z_OBJ(object_zval)); + Z_OBJ_P(result)); call->prev_execute_data = EX(call); EX(call) = call; - - if (EXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); - } + Z_ADDREF_P(result); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -7344,14 +7489,14 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) { + if (OP1_TYPE & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = GET_OP1_ZVAL_PTR(BP_VAR_R); ZVAL_COPY_VALUE(&generator->value, value); - if (OP1_TYPE != IS_CONST) { + if (OP1_TYPE == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -7532,6 +7677,9 @@ ZEND_VM_HANDLER(142, ZEND_YIELD_FROM, CONST|TMP|VAR|CV, ANY) ZVAL_NULL(EX_VAR(opline->result.var)); } + /* This generator has no send target (though the generator we delegate to might have one) */ + generator->send_target = NULL; + /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ ZEND_VM_INC_OPCODE(); @@ -7863,10 +8011,8 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) { zend_array *args; zend_function *fbc = EX(func); - zend_object *object = Z_OBJ(EX(This)); zval *ret = EX(return_value); uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS); - zend_class_entry *scope = EX(called_scope); uint32_t num_args = EX_NUM_ARGS(); zend_execute_data *call; USE_OPLINE @@ -7889,9 +8035,11 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) SAVE_OPLINE(); call = execute_data; execute_data = EG(current_execute_data) = EX(prev_execute_data); - zend_vm_stack_free_call_frame(call); - call = zend_vm_stack_push_call_frame(call_info, fbc->common.prototype, 2, scope, object); - call->prev_execute_data = execute_data; + + ZEND_ASSERT(zend_vm_calc_used_stack(2, fbc->common.prototype) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call)); + + call->func = fbc->common.prototype; + ZEND_CALL_NUM_ARGS(call) = 2; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); ZVAL_ARR(ZEND_CALL_ARG(call, 2), args); @@ -7955,9 +8103,9 @@ ZEND_VM_HANDLER(158, ZEND_CALL_TRAMPOLINE, ANY, ANY) #if ZEND_DEBUG ZEND_ASSERT( - !call->func || + EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -7979,7 +8127,7 @@ ZEND_VM_C_LABEL(call_trampoline_end): opline = EX(opline); if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { - object = Z_OBJ(call->This); + zend_object *object = Z_OBJ(call->This); OBJ_RELEASE(object); } EG(scope) = EX(func)->op_array.scope; @@ -8028,4 +8176,55 @@ ZEND_VM_HANDLER(182, ZEND_BIND_LEXICAL, TMP, CV, REF) ZEND_VM_NEXT_OPCODE(); } +ZEND_VM_HANDLER(183, ZEND_BIND_STATIC, CV, CONST, REF) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + HashTable *ht; + zval *varname; + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + variable_ptr = GET_OP1_ZVAL_PTR_PTR_UNDEF(BP_VAR_W); + zval_ptr_dtor(variable_ptr); + + ht = EX(func)->op_array.static_variables; + ZEND_ASSERT(ht != NULL); + if (GC_REFCOUNT(ht) > 1) { + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_REFCOUNT(ht)--; + } + EX(func)->op_array.static_variables = ht = zend_array_dup(ht); + } + + varname = GET_OP2_ZVAL_PTR(BP_VAR_R); + value = zend_hash_find(ht, Z_STR_P(varname)); + + if (opline->extended_value) { + if (Z_CONSTANT_P(value)) { + if (UNEXPECTED(zval_update_constant_ex(value, 1, NULL) != SUCCESS)) { + ZVAL_NULL(variable_ptr); + HANDLE_EXCEPTION(); + } + } + if (UNEXPECTED(!Z_ISREF_P(value))) { + zend_reference *ref = (zend_reference*)emalloc(sizeof(zend_reference)); + GC_REFCOUNT(ref) = 2; + GC_TYPE_INFO(ref) = IS_REFERENCE; + ZVAL_COPY_VALUE(&ref->val, value); + Z_REF_P(value) = ref; + Z_TYPE_INFO_P(value) = IS_REFERENCE_EX; + ZVAL_REF(variable_ptr, ref); + } else { + Z_ADDREF_P(value); + ZVAL_REF(variable_ptr, Z_REF_P(value)); + } + } else { + ZVAL_COPY(variable_ptr, value); + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + ZEND_VM_DEFINE_OP(137, ZEND_OP_DATA); diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index 4de081d476..40d75a7d27 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -306,6 +306,14 @@ static zend_uchar zend_user_opcodes[256] = {0, 241,242,243,244,245,246,247,248,249,250,251,252,253,254,255 }; +#define SPEC_START_MASK 0x0000ffff +#define SPEC_RULE_OP1 0x00010000 +#define SPEC_RULE_OP2 0x00020000 +#define SPEC_RULE_OP_DATA 0x00040000 +#define SPEC_RULE_RETVAL 0x00080000 +#define SPEC_RULE_QUICK_ARG 0x00100000 + +static const uint32_t *zend_spec_handlers; static const void **zend_opcode_handlers; static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op); @@ -408,7 +416,7 @@ ZEND_API void execute_ex(zend_execute_data *ex) while (1) { #if !defined(ZEND_VM_FP_GLOBAL_REG) || !defined(ZEND_VM_IP_GLOBAL_REG) - int ret; + int ret; #endif #if defined(ZEND_VM_FP_GLOBAL_REG) && defined(ZEND_VM_IP_GLOBAL_REG) ((opcode_handler_t)OPLINE->handler)(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU); @@ -481,13 +489,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_leave_helper_SPEC(ZEND_OPCODE_ object = Z_OBJ(old_execute_data->This); #if 0 if (UNEXPECTED(EG(exception) != NULL) && (EX(opline)->op1.num & ZEND_CALL_CTOR)) { - if (!(EX(opline)->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { #else if (UNEXPECTED(EG(exception) != NULL) && (call_info & ZEND_CALL_CTOR)) { - if (!(call_info & ZEND_CALL_CTOR_RESULT_UNUSED)) { #endif - GC_REFCOUNT(object)--; - } + GC_REFCOUNT(object)--; if (GC_REFCOUNT(object) == 1) { zend_object_store_ctor_failed(object); } @@ -566,12 +571,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_JMP_SPEC_HANDLER(ZEND_OPCODE_H ZEND_VM_CONTINUE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); zend_function *fbc = call->func; zval *ret; + zval retval; SAVE_OPLINE(); EX(call) = call->prev_execute_data; @@ -579,7 +585,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_HANDLER(ZEND_OPC call->prev_execute_data = execute_data; EG(current_execute_data) = call; - ret = EX_VAR(opline->result.var); + ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = 0; @@ -587,22 +593,69 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_HANDLER(ZEND_OPC #if ZEND_DEBUG ZEND_ASSERT( - !call->func || + EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); zend_vm_stack_free_call_frame(call); - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + if (!0) { + zval_ptr_dtor(ret); } if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL); - if (RETURN_VALUE_USED(opline)) { + if (0) { + zval_ptr_dtor(EX_VAR(opline->result.var)); + } + HANDLE_EXCEPTION(); + } + + ZEND_VM_INTERRUPT_CHECK(); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zend_function *fbc = call->func; + zval *ret; + zval retval; + + SAVE_OPLINE(); + EX(call) = call->prev_execute_data; + + call->prev_execute_data = execute_data; + EG(current_execute_data) = call; + + ret = 1 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + Z_VAR_FLAGS_P(ret) = 0; + + fbc->internal_function.handler(call, ret); + +#if ZEND_DEBUG + ZEND_ASSERT( + EG(exception) || !call->func || + !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); +#endif + + EG(current_execute_data) = call->prev_execute_data; + zend_vm_stack_free_args(call); + zend_vm_stack_free_call_frame(call); + + if (!1) { + zval_ptr_dtor(ret); + } + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL); + if (1) { zval_ptr_dtor(EX_VAR(opline->result.var)); } HANDLE_EXCEPTION(); @@ -612,7 +665,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_ICALL_SPEC_HANDLER(ZEND_OPC ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -625,7 +678,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_HANDLER(ZEND_OPC EG(scope) = NULL; ret = NULL; call->symbol_table = NULL; - if (RETURN_VALUE_USED(opline)) { + if (0) { + ret = EX_VAR(opline->result.var); + ZVAL_NULL(ret); + Z_VAR_FLAGS_P(ret) = 0; + } + + call->prev_execute_data = execute_data; + i_init_func_execute_data(call, &fbc->op_array, ret, 0); + + ZEND_VM_ENTER(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zend_function *fbc = call->func; + zval *ret; + + SAVE_OPLINE(); + EX(call) = call->prev_execute_data; + + EG(scope) = NULL; + ret = NULL; + call->symbol_table = NULL; + if (1) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = 0; @@ -637,7 +715,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_UCALL_SPEC_HANDLER(ZEND_OPC ZEND_VM_ENTER(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -650,7 +728,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER( if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { EG(scope) = NULL; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { - if (EXPECTED(RETURN_VALUE_USED(opline))) { + if (EXPECTED(0)) { ret = EX_VAR(opline->result.var); zend_generator_create_zval(call, &fbc->op_array, ret); Z_VAR_FLAGS_P(ret) = 0; @@ -662,7 +740,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER( } else { ret = NULL; call->symbol_table = NULL; - if (RETURN_VALUE_USED(opline)) { + if (0) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = 0; @@ -675,6 +753,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER( } EG(scope) = EX(func)->op_array.scope; } else { + zval retval; ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { @@ -707,7 +786,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER( } } - ret = EX_VAR(opline->result.var); + ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; @@ -715,23 +794,127 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER( #if ZEND_DEBUG ZEND_ASSERT( - !call->func || + EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); zend_vm_stack_free_call_frame(call); - if (!RETURN_VALUE_USED(opline)) { + if (!0) { + zval_ptr_dtor(ret); + } + } + + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL); + if (0) { zval_ptr_dtor(EX_VAR(opline->result.var)); } + HANDLE_EXCEPTION(); + } + ZEND_VM_INTERRUPT_CHECK(); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zend_function *fbc = call->func; + zval *ret; + + SAVE_OPLINE(); + EX(call) = call->prev_execute_data; + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + EG(scope) = NULL; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { + if (EXPECTED(1)) { + ret = EX_VAR(opline->result.var); + zend_generator_create_zval(call, &fbc->op_array, ret); + Z_VAR_FLAGS_P(ret) = 0; + } else { + zend_vm_stack_free_args(call); + } + + zend_vm_stack_free_call_frame(call); + } else { + ret = NULL; + call->symbol_table = NULL; + if (1) { + ret = EX_VAR(opline->result.var); + ZVAL_NULL(ret); + Z_VAR_FLAGS_P(ret) = 0; + } + + call->prev_execute_data = execute_data; + i_init_func_execute_data(call, &fbc->op_array, ret, 0); + + ZEND_VM_ENTER(); + } + EG(scope) = EX(func)->op_array.scope; + } else { + zval retval; + ZEND_ASSERT(fbc->type == ZEND_INTERNAL_FUNCTION); + + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { + zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", + fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "", + fbc->common.scope ? "::" : "", + ZSTR_VAL(fbc->common.function_name)); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + + call->prev_execute_data = execute_data; + EG(current_execute_data) = call; + + if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { + uint32_t i; + uint32_t num_args = ZEND_CALL_NUM_ARGS(call); + zval *p = ZEND_CALL_ARG(call, 1); + + for (i = 0; i < num_args; ++i) { + if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { + EG(current_execute_data) = call->prev_execute_data; + zend_vm_stack_free_args(call); + zend_vm_stack_free_call_frame(call); + zend_throw_exception_internal(NULL); + HANDLE_EXCEPTION(); + } + p++; + } + } + + ret = 1 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; + + fbc->internal_function.handler(call, ret); + +#if ZEND_DEBUG + ZEND_ASSERT( + EG(exception) || !call->func || + !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); +#endif + + EG(current_execute_data) = call->prev_execute_data; + zend_vm_stack_free_args(call); + zend_vm_stack_free_call_frame(call); + + if (!1) { + zval_ptr_dtor(ret); + } } if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL); - if (RETURN_VALUE_USED(opline)) { + if (1) { zval_ptr_dtor(EX_VAR(opline->result.var)); } HANDLE_EXCEPTION(); @@ -740,7 +923,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER( ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_execute_data *call = EX(call); @@ -771,7 +954,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { EG(scope) = fbc->common.scope; if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { - if (EXPECTED(RETURN_VALUE_USED(opline))) { + if (EXPECTED(0)) { ret = EX_VAR(opline->result.var); zend_generator_create_zval(call, &fbc->op_array, ret); Z_VAR_FLAGS_P(ret) = 0; @@ -784,7 +967,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC } else { ret = NULL; call->symbol_table = NULL; - if (RETURN_VALUE_USED(opline)) { + if (0) { ret = EX_VAR(opline->result.var); ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = 0; @@ -802,6 +985,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC } } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { int should_change_scope = 0; + zval retval; if (fbc->common.scope) { should_change_scope = 1; @@ -820,7 +1004,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); - if (RETURN_VALUE_USED(opline)) { + if (0) { ZVAL_UNDEF(EX_VAR(opline->result.var)); } if (UNEXPECTED(should_change_scope)) { @@ -833,7 +1017,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC } } - ret = EX_VAR(opline->result.var); + ret = 0 ? EX_VAR(opline->result.var) : &retval; ZVAL_NULL(ret); Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; @@ -846,16 +1030,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC #if ZEND_DEBUG ZEND_ASSERT( - !call->func || + EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + if (!0) { + zval_ptr_dtor(ret); } if (UNEXPECTED(should_change_scope)) { @@ -864,6 +1048,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC goto fcall_end; } } else { /* ZEND_OVERLOADED_FUNCTION */ + zval retval; /* Not sure what should be done here if it's a static method */ object = Z_OBJ(call->This); if (UNEXPECTED(object == NULL)) { @@ -880,11 +1065,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC EG(scope) = fbc->common.scope; - ZVAL_NULL(EX_VAR(opline->result.var)); + ret = 0 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); call->prev_execute_data = execute_data; EG(current_execute_data) = call; - object->handlers->call_method(fbc->common.function_name, object, call, EX_VAR(opline->result.var)); + object->handlers->call_method(fbc->common.function_name, object, call, ret); EG(current_execute_data) = call->prev_execute_data; zend_vm_stack_free_args(call); @@ -894,10 +1080,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_HANDLER(ZEND_OPC } efree(fbc); - if (!RETURN_VALUE_USED(opline)) { - zval_ptr_dtor(EX_VAR(opline->result.var)); + if (!0) { + zval_ptr_dtor(ret); } else { - Z_VAR_FLAGS_P(EX_VAR(opline->result.var)) = 0; + Z_VAR_FLAGS_P(ret) = 0; } } @@ -906,13 +1092,205 @@ fcall_end_change_scope: object = Z_OBJ(call->This); #if 0 if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) { - if (!(opline->op1.num & ZEND_CALL_CTOR_RESULT_UNUSED)) { #else if (UNEXPECTED(EG(exception) != NULL) && (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR)) { - if (!(ZEND_CALL_INFO(call) & ZEND_CALL_CTOR_RESULT_UNUSED)) { #endif - GC_REFCOUNT(object)--; + GC_REFCOUNT(object)--; + if (GC_REFCOUNT(object) == 1) { + zend_object_store_ctor_failed(object); + } + } + OBJ_RELEASE(object); + } + EG(scope) = EX(func)->op_array.scope; + +fcall_end: + zend_vm_stack_free_call_frame(call); + if (UNEXPECTED(EG(exception) != NULL)) { + zend_throw_exception_internal(NULL); + if (0) { + zval_ptr_dtor(EX_VAR(opline->result.var)); + } + HANDLE_EXCEPTION(); + } + + ZEND_VM_INTERRUPT_CHECK(); + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_execute_data *call = EX(call); + zend_function *fbc = call->func; + zend_object *object; + zval *ret; + + SAVE_OPLINE(); + EX(call) = call->prev_execute_data; + if (UNEXPECTED((fbc->common.fn_flags & (ZEND_ACC_ABSTRACT|ZEND_ACC_DEPRECATED)) != 0)) { + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_ABSTRACT) != 0)) { + zend_throw_error(NULL, "Cannot call abstract method %s::%s()", ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name)); + HANDLE_EXCEPTION(); + } + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_DEPRECATED) != 0)) { + zend_error(E_DEPRECATED, "Function %s%s%s() is deprecated", + fbc->common.scope ? ZSTR_VAL(fbc->common.scope->name) : "", + fbc->common.scope ? "::" : "", + ZSTR_VAL(fbc->common.function_name)); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } + } + } + + LOAD_OPLINE(); + + if (EXPECTED(fbc->type == ZEND_USER_FUNCTION)) { + EG(scope) = fbc->common.scope; + if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_GENERATOR) != 0)) { + if (EXPECTED(1)) { + ret = EX_VAR(opline->result.var); + zend_generator_create_zval(call, &fbc->op_array, ret); + Z_VAR_FLAGS_P(ret) = 0; + } else { + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_CLOSURE)) { + OBJ_RELEASE((zend_object*)fbc->op_array.prototype); + } + zend_vm_stack_free_args(call); + } + } else { + ret = NULL; + call->symbol_table = NULL; + if (1) { + ret = EX_VAR(opline->result.var); + ZVAL_NULL(ret); + Z_VAR_FLAGS_P(ret) = 0; + } + + call->prev_execute_data = execute_data; + i_init_func_execute_data(call, &fbc->op_array, ret, 1); + + if (EXPECTED(zend_execute_ex == execute_ex)) { + ZEND_VM_ENTER(); + } else { + ZEND_ADD_CALL_FLAG(call, ZEND_CALL_TOP); + zend_execute_ex(call); + } + } + } else if (EXPECTED(fbc->type < ZEND_USER_FUNCTION)) { + int should_change_scope = 0; + zval retval; + + if (fbc->common.scope) { + should_change_scope = 1; + EG(scope) = fbc->common.scope; + } + + call->prev_execute_data = execute_data; + EG(current_execute_data) = call; + + if (fbc->common.fn_flags & ZEND_ACC_HAS_TYPE_HINTS) { + uint32_t i; + uint32_t num_args = ZEND_CALL_NUM_ARGS(call); + zval *p = ZEND_CALL_ARG(call, 1); + + for (i = 0; i < num_args; ++i) { + if (UNEXPECTED(!zend_verify_internal_arg_type(fbc, i + 1, p))) { + EG(current_execute_data) = call->prev_execute_data; + zend_vm_stack_free_args(call); + if (1) { + ZVAL_UNDEF(EX_VAR(opline->result.var)); + } + if (UNEXPECTED(should_change_scope)) { + goto fcall_end_change_scope; + } else { + goto fcall_end; + } + } + p++; + } + } + + ret = 1 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + Z_VAR_FLAGS_P(ret) = (fbc->common.fn_flags & ZEND_ACC_RETURN_REFERENCE) != 0 ? IS_VAR_RET_REF : 0; + + if (!zend_execute_internal) { + /* saves one function call if zend_execute_internal is not used */ + fbc->internal_function.handler(call, ret); + } else { + zend_execute_internal(call, ret); + } + +#if ZEND_DEBUG + ZEND_ASSERT( + EG(exception) || !call->func || + !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || + zend_verify_internal_return_type(call->func, ret)); +#endif + + EG(current_execute_data) = call->prev_execute_data; + zend_vm_stack_free_args(call); + + if (!1) { + zval_ptr_dtor(ret); + } + + if (UNEXPECTED(should_change_scope)) { + goto fcall_end_change_scope; + } else { + goto fcall_end; + } + } else { /* ZEND_OVERLOADED_FUNCTION */ + zval retval; + /* Not sure what should be done here if it's a static method */ + object = Z_OBJ(call->This); + if (UNEXPECTED(object == NULL)) { + zend_vm_stack_free_args(call); + if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { + zend_string_release(fbc->common.function_name); } + efree(fbc); + zend_vm_stack_free_call_frame(call); + + zend_throw_error(NULL, "Cannot call overloaded function for non-object"); + HANDLE_EXCEPTION(); + } + + EG(scope) = fbc->common.scope; + + ret = 1 ? EX_VAR(opline->result.var) : &retval; + ZVAL_NULL(ret); + + call->prev_execute_data = execute_data; + EG(current_execute_data) = call; + object->handlers->call_method(fbc->common.function_name, object, call, ret); + EG(current_execute_data) = call->prev_execute_data; + + zend_vm_stack_free_args(call); + + if (fbc->type == ZEND_OVERLOADED_FUNCTION_TEMPORARY) { + zend_string_release(fbc->common.function_name); + } + efree(fbc); + + if (!1) { + zval_ptr_dtor(ret); + } else { + Z_VAR_FLAGS_P(ret) = 0; + } + } + +fcall_end_change_scope: + if (UNEXPECTED(ZEND_CALL_INFO(call) & ZEND_CALL_RELEASE_THIS)) { + object = Z_OBJ(call->This); +#if 0 + if (UNEXPECTED(EG(exception) != NULL) && (opline->op1.num & ZEND_CALL_CTOR)) { +#else + if (UNEXPECTED(EG(exception) != NULL) && (ZEND_CALL_INFO(call) & ZEND_CALL_CTOR)) { +#endif + GC_REFCOUNT(object)--; if (GC_REFCOUNT(object) == 1) { zend_object_store_ctor_failed(object); } @@ -925,7 +1303,7 @@ fcall_end: zend_vm_stack_free_call_frame(call); if (UNEXPECTED(EG(exception) != NULL)) { zend_throw_exception_internal(NULL); - if (RETURN_VALUE_USED(opline)) { + if (1) { zval_ptr_dtor(EX_VAR(opline->result.var)); } HANDLE_EXCEPTION(); @@ -1682,10 +2060,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z { zend_array *args; zend_function *fbc = EX(func); - zend_object *object = Z_OBJ(EX(This)); zval *ret = EX(return_value); uint32_t call_info = EX_CALL_INFO() & (ZEND_CALL_NESTED | ZEND_CALL_TOP | ZEND_CALL_RELEASE_THIS); - zend_class_entry *scope = EX(called_scope); uint32_t num_args = EX_NUM_ARGS(); zend_execute_data *call; USE_OPLINE @@ -1708,9 +2084,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z SAVE_OPLINE(); call = execute_data; execute_data = EG(current_execute_data) = EX(prev_execute_data); - zend_vm_stack_free_call_frame(call); - call = zend_vm_stack_push_call_frame(call_info, fbc->common.prototype, 2, scope, object); - call->prev_execute_data = execute_data; + + ZEND_ASSERT(zend_vm_calc_used_stack(2, fbc->common.prototype) <= (size_t)(((char*)EG(vm_stack_end)) - (char*)call)); + + call->func = fbc->common.prototype; + ZEND_CALL_NUM_ARGS(call) = 2; ZVAL_STR(ZEND_CALL_ARG(call, 1), fbc->common.function_name); ZVAL_ARR(ZEND_CALL_ARG(call, 2), args); @@ -1774,9 +2152,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CALL_TRAMPOLINE_SPEC_HANDLER(Z #if ZEND_DEBUG ZEND_ASSERT( - !call->func || + EG(exception) || !call->func || !(call->func->common.fn_flags & ZEND_ACC_HAS_RETURN_TYPE) || - zend_verify_internal_return_type(call->func, EX_VAR(opline->result.var))); + zend_verify_internal_return_type(call->func, ret)); #endif EG(current_execute_data) = call->prev_execute_data; @@ -1798,7 +2176,7 @@ call_trampoline_end: opline = EX(opline); if (UNEXPECTED(call_info & ZEND_CALL_RELEASE_THIS)) { - object = Z_OBJ(call->This); + zend_object *object = Z_OBJ(call->This); OBJ_RELEASE(object); } EG(scope) = EX(func)->op_array.scope; @@ -3089,14 +3467,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND ZVAL_NULL(EX(return_value)); } } else if (!EX(return_value)) { - if (IS_CONST == IS_VAR || IS_CONST == IS_TMP_VAR ) { + if (IS_CONST & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { SAVE_OPLINE(); zval_dtor_func_for_ptr(Z_COUNTED_P(free_op1)); } } } else { - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) { @@ -3134,7 +3512,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDL SAVE_OPLINE(); do { - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR || + if ((IS_CONST & (IS_CONST|IS_TMP_VAR)) || (IS_CONST == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); @@ -3193,7 +3571,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CONST_HA retval = EX_CONSTANT(opline->op1); /* Copy return value into generator->retval */ - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(&generator->retval, retval); if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->retval))) { @@ -3290,7 +3668,38 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER uint32_t arg_num = opline->op2.num; - if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (EXPECTED(0)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref: + SAVE_OPLINE(); + zend_throw_error(NULL, "Cannot pass parameter %d by reference", arg_num); + + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_UNDEF(arg); + HANDLE_EXCEPTION(); + } + value = EX_CONSTANT(opline->op1); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_COPY_VALUE(arg, value); + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) { + zval_copy_ctor_func(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_CONST_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + + uint32_t arg_num = opline->op2.num; + + if (EXPECTED(1)) { if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { goto send_val_by_ref; } @@ -3342,7 +3751,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_SPEC_CONST_HANDLER(ZEND_O static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval object_zval; + zval *result; zend_function *constructor; zend_class_entry *ce; @@ -3365,33 +3774,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OP } else { ce = Z_CE_P(EX_VAR(opline->op1.var)); } - if (UNEXPECTED(object_init_ex(&object_zval, ce) != SUCCESS)) { + + result = EX_VAR(opline->result.var); + if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) { HANDLE_EXCEPTION(); } - constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); + constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); if (constructor == NULL) { - if (EXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); - } else { - OBJ_RELEASE(Z_OBJ(object_zval)); - } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { /* We are not handling overloaded classes right now */ zend_execute_data *call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | - (EXPECTED(RETURN_VALUE_USED(opline)) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED), + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, constructor, opline->extended_value, ce, - Z_OBJ(object_zval)); + Z_OBJ_P(result)); call->prev_execute_data = EX(call); EX(call) = call; - - if (EXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); - } + Z_ADDREF_P(result); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -4182,6 +4584,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER( ZVAL_NULL(EX_VAR(opline->result.var)); } + /* This generator has no send target (though the generator we delegate to might have one) */ + generator->send_target = NULL; + /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ ZEND_VM_INC_OPCODE(); @@ -5104,7 +5509,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -5295,7 +5700,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_ HANDLE_EXCEPTION(); } - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -5479,7 +5884,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CO } } if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -5593,15 +5998,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C function_name = EX_CONSTANT(opline->op2); if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_CONST & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Function name must be a string"); - HANDLE_EXCEPTION(); + HANDLE_EXCEPTION(); + } while (0); } } @@ -6402,14 +6814,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if (IS_CONST & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = EX_CONSTANT(opline->op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CONST != IS_CONST) { + if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -6573,14 +6985,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if (IS_CONST & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = EX_CONSTANT(opline->op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CONST != IS_CONST) { + if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -7024,14 +7436,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if (IS_CONST & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = EX_CONSTANT(opline->op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CONST != IS_CONST) { + if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -7199,14 +7611,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { - - HANDLE_EXCEPTION(); - } - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { + if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { } @@ -7410,7 +7815,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -7488,15 +7893,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C function_name = NULL; if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_UNUSED & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Function name must be a string"); - HANDLE_EXCEPTION(); + HANDLE_EXCEPTION(); + } while (0); } } @@ -8061,14 +8473,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if (IS_CONST & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = EX_CONSTANT(opline->op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CONST != IS_CONST) { + if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -8843,7 +9255,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -9034,7 +9446,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_ HANDLE_EXCEPTION(); } - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -9174,7 +9586,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV } } if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -9288,15 +9700,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_CV & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Function name must be a string"); - HANDLE_EXCEPTION(); + HANDLE_EXCEPTION(); + } while (0); } } @@ -9888,14 +10307,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if (IS_CONST & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = EX_CONSTANT(opline->op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CONST != IS_CONST) { + if (IS_CONST == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -10634,7 +11053,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_ SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -10827,7 +11246,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_ zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); } - if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) { + if ((IS_CONST & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(free_op2); @@ -10967,7 +11386,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TM } } if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); @@ -11082,15 +11501,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); + zend_throw_error(NULL, "Function name must be a string"); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); + } while (0); } } @@ -11621,14 +12047,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_O ZVAL_NULL(EX(return_value)); } } else if (!EX(return_value)) { - if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_TMP_VAR ) { + if (IS_TMP_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { SAVE_OPLINE(); zval_dtor_func_for_ptr(Z_COUNTED_P(free_op1)); } } } else { - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) { @@ -11666,7 +12092,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER SAVE_OPLINE(); do { - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR || + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) || (IS_TMP_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); @@ -11725,7 +12151,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_TMP_HAND retval = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); /* Copy return value into generator->retval */ - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(&generator->retval, retval); if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->retval))) { @@ -11822,7 +12248,38 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER(Z zend_free_op free_op1; uint32_t arg_num = opline->op2.num; - if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (EXPECTED(0)) { + if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_val_by_ref; + } + } else if (ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_val_by_ref: + SAVE_OPLINE(); + zend_throw_error(NULL, "Cannot pass parameter %d by reference", arg_num); + zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_UNDEF(arg); + HANDLE_EXCEPTION(); + } + value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_COPY_VALUE(arg, value); + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(arg))) { + zval_copy_ctor_func(arg); + } + } + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAL_EX_SPEC_TMP_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *value, *arg; + zend_free_op free_op1; + uint32_t arg_num = opline->op2.num; + + if (EXPECTED(1)) { if (QUICK_ARG_MUST_BE_SENT_BY_REF(EX(call)->func, arg_num)) { goto send_val_by_ref; } @@ -12413,6 +12870,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMP_HANDLER(ZE ZVAL_NULL(EX_VAR(opline->result.var)); } + /* This generator has no send target (though the generator we delegate to might have one) */ + generator->send_target = NULL; + /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ ZEND_VM_INC_OPCODE(); @@ -12505,7 +12965,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CO SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -12624,7 +13084,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CO HANDLE_EXCEPTION(); } - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -12880,14 +13340,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR != IS_CONST) { + if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -13051,14 +13511,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR != IS_CONST) { + if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -13222,14 +13682,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR != IS_CONST) { + if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -13339,7 +13799,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UN SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -13574,14 +14034,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER( if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR != IS_CONST) { + if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -13727,7 +14187,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -13846,7 +14306,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV HANDLE_EXCEPTION(); } - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -14102,14 +14562,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if (IS_TMP_VAR & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_TMP_VAR != IS_CONST) { + if (IS_TMP_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -14250,7 +14710,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TM SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -14370,7 +14830,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TM zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); } - if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) { + if ((IS_TMP_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(free_op2); @@ -14599,7 +15059,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HAN } } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -14609,14 +15069,54 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_ if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_increment_function(var_ptr); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); } ZEND_VM_NEXT_OPCODE(); } - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { + if (UNEXPECTED(0)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + var_ptr = GET_OP1_UNDEF_CV(var_ptr, BP_VAR_RW); + } + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + increment_function(var_ptr); + + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_increment_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { + if (UNEXPECTED(1)) { ZVAL_NULL(EX_VAR(opline->result.var)); } ZEND_VM_NEXT_OPCODE(); @@ -14631,7 +15131,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_ increment_function(var_ptr); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(1)) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } @@ -14639,7 +15139,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -14649,14 +15149,54 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_ if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_decrement_function(var_ptr); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); } ZEND_VM_NEXT_OPCODE(); } - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { + if (UNEXPECTED(0)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + var_ptr = GET_OP1_UNDEF_CV(var_ptr, BP_VAR_RW); + } + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + decrement_function(var_ptr); + + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *var_ptr; + + var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { + if (UNEXPECTED(1)) { ZVAL_NULL(EX_VAR(opline->result.var)); } ZEND_VM_NEXT_OPCODE(); @@ -14671,7 +15211,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_ decrement_function(var_ptr); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(1)) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } @@ -14693,7 +15233,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND ZEND_VM_NEXT_OPCODE(); } - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -14726,7 +15266,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND ZEND_VM_NEXT_OPCODE(); } - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -14759,14 +15299,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_O ZVAL_NULL(EX(return_value)); } } else if (!EX(return_value)) { - if (IS_VAR == IS_VAR || IS_VAR == IS_TMP_VAR ) { + if (IS_VAR & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { SAVE_OPLINE(); zval_dtor_func_for_ptr(Z_COUNTED_P(free_op1)); } } } else { - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) { @@ -14804,7 +15344,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER SAVE_OPLINE(); do { - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR || + if ((IS_VAR & (IS_CONST|IS_TMP_VAR)) || (IS_VAR == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); @@ -14864,7 +15404,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_VAR_HAND retval = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); /* Copy return value into generator->retval */ - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(&generator->retval, retval); if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->retval))) { @@ -15023,7 +15563,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND varptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); arg = ZEND_CALL_VAR(EX(call), opline->result.var); - if (IS_VAR == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(varptr))) { ZVAL_NEW_REF(arg, &EG(uninitialized_zval)); ZEND_VM_NEXT_OPCODE(); } @@ -15048,7 +15588,56 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER(Z zend_free_op free_op1; uint32_t arg_num = opline->op2.num; - if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (EXPECTED(0)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); + if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + GET_OP1_UNDEF_CV(varptr, BP_VAR_R); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_VAR == IS_CV) { + ZVAL_OPT_DEREF(varptr); + ZVAL_COPY(arg, varptr); + } else /* if (IS_VAR == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_VAR_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + zend_free_op free_op1; + uint32_t arg_num = opline->op2.num; + + if (EXPECTED(1)) { if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { goto send_var_by_ref; } @@ -15148,7 +15737,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_USER_SPEC_VAR_HANDLER(ZEN static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval object_zval; + zval *result; zend_function *constructor; zend_class_entry *ce; @@ -15171,33 +15760,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCO } else { ce = Z_CE_P(EX_VAR(opline->op1.var)); } - if (UNEXPECTED(object_init_ex(&object_zval, ce) != SUCCESS)) { + + result = EX_VAR(opline->result.var); + if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) { HANDLE_EXCEPTION(); } - constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); + constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); if (constructor == NULL) { - if (EXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); - } else { - OBJ_RELEASE(Z_OBJ(object_zval)); - } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { /* We are not handling overloaded classes right now */ zend_execute_data *call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | - (EXPECTED(RETURN_VALUE_USED(opline)) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED), + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, constructor, opline->extended_value, ce, - Z_OBJ(object_zval)); + Z_OBJ_P(result)); call->prev_execute_data = EX(call); EX(call) = call; - - if (EXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); - } + Z_ADDREF_P(result); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -16137,6 +16719,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_VAR_HANDLER(ZE ZVAL_NULL(EX_VAR(opline->result.var)); } + /* This generator has no send target (though the generator we delegate to might have one) */ + generator->send_target = NULL; + /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ ZEND_VM_INC_OPCODE(); @@ -16310,14 +16895,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -16345,7 +16930,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_V value = EX_CONSTANT(opline->op2); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -16793,7 +17378,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CO SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -16981,7 +17566,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CO HANDLE_EXCEPTION(); } - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; @@ -17025,12 +17610,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *object; - zval *property_name; + zval *object, *property_name, *value, tmp; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -17042,20 +17626,696 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HAND } property_name = EX_CONSTANT(opline->op2); + value = EX_CONSTANT((opline+1)->op1); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CONST); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + ZVAL_DEREF(value); + } - zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CONST == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = EX_CONSTANT(opline->op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_TMP_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = EX_CONSTANT(opline->op2); + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = EX_CONSTANT(opline->op2); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CV == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; zval *object_ptr; - zend_free_op free_op_data1; + zval *value; zval *variable_ptr; zval *dim; @@ -17070,7 +18330,7 @@ try_assign_dim_array: variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); if (UNEXPECTED(variable_ptr == NULL)) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - variable_ptr = &EG(error_zval); + variable_ptr = NULL; } } else { dim = EX_CONSTANT(opline->op2); @@ -17078,14 +18338,14 @@ try_assign_dim_array: variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CONST, BP_VAR_W); } - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); + if (UNEXPECTED(variable_ptr == NULL)) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type); + value = EX_CONSTANT((opline+1)->op1); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -17101,13 +18361,13 @@ try_assign_dim_array: zval *property_name = EX_CONSTANT(opline->op2); - zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data); + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CONST, (opline+1)->op1, execute_data); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { if (IS_CONST == IS_UNUSED) { zend_throw_error(NULL, "[] operator not supported for strings"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; HANDLE_EXCEPTION(); } else { @@ -17116,9 +18376,9 @@ try_assign_dim_array: dim = EX_CONSTANT(opline->op2); offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - value = get_zval_ptr_r_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); + value = EX_CONSTANT((opline+1)->op1); zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); @@ -17128,17 +18388,302 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { - goto assign_dim_clean; + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CONST == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = EX_CONSTANT(opline->op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CONST, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = EX_CONSTANT(opline->op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_TMP_VAR, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CONST == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = EX_CONSTANT(opline->op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; } else { zend_error(E_WARNING, "Cannot use a scalar value as an array"); assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CONST == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { dim = EX_CONSTANT(opline->op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CONST, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = EX_CONSTANT(opline->op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_VAR, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CONST == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = EX_CONSTANT(opline->op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_var_deref((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CONST == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = EX_CONSTANT(opline->op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CONST, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = EX_CONSTANT(opline->op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CV, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CONST == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = EX_CONSTANT(opline->op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, (opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - FREE_OP(free_op_data1); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -17149,7 +18694,7 @@ assign_dim_clean: ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -17160,14 +18705,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER( value = EX_CONSTANT(opline->op2); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CONST); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = EX_CONSTANT(opline->op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CONST); + if (UNEXPECTED(1)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; @@ -17227,15 +18800,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V function_name = EX_CONSTANT(opline->op2); if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_CONST & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Function name must be a string"); - HANDLE_EXCEPTION(); + HANDLE_EXCEPTION(); + } while (0); } } @@ -17683,14 +19263,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR != IS_CONST) { + if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -17828,7 +19408,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -17839,14 +19419,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER(ZE value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + zval_ptr_dtor_nogc(free_op2); + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); + if (UNEXPECTED(1)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; @@ -17883,14 +19491,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR != IS_CONST) { + if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -18028,7 +19636,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; @@ -18039,14 +19647,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZE value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_VAR); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + zval_ptr_dtor_nogc(free_op2); + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(1)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; @@ -18065,44 +19701,50 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE SAVE_OPLINE(); value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var)))) { + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var))) && + UNEXPECTED(!Z_ISERROR_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; HANDLE_EXCEPTION(); - } - if (IS_VAR == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!(free_op2 != NULL) && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op2.var)) != IS_INDIRECT)) { /* undo the effect of get_zval_ptr_ptr() */ - Z_TRY_ADDREF_P(value_ptr); - } + + } else if (IS_VAR == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; HANDLE_EXCEPTION(); } - ZEND_VM_TAIL_CALL(ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || - (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { - variable_ptr = &EG(uninitialized_zval); + value_ptr = zend_assign_to_variable(variable_ptr, value_ptr, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value_ptr); + } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + if ((IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) || + (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr)))) { + variable_ptr = &EG(uninitialized_zval); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } + + if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; } if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -18133,14 +19775,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR != IS_CONST) { + if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -18274,14 +19916,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -18583,7 +20225,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UN SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -18611,12 +20253,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UN ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; zval *object_ptr; - zend_free_op free_op_data1; + zval *value; zval *variable_ptr; zval *dim; @@ -18631,7 +20273,7 @@ try_assign_dim_array: variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); if (UNEXPECTED(variable_ptr == NULL)) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - variable_ptr = &EG(error_zval); + variable_ptr = NULL; } } else { dim = NULL; @@ -18639,14 +20281,14 @@ try_assign_dim_array: variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_UNUSED, BP_VAR_W); } - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); + if (UNEXPECTED(variable_ptr == NULL)) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type); + value = EX_CONSTANT((opline+1)->op1); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -18662,13 +20304,13 @@ try_assign_dim_array: zval *property_name = NULL; - zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data); + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CONST, (opline+1)->op1, execute_data); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { if (IS_UNUSED == IS_UNUSED) { zend_throw_error(NULL, "[] operator not supported for strings"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; HANDLE_EXCEPTION(); } else { @@ -18677,9 +20319,9 @@ try_assign_dim_array: dim = NULL; offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - value = get_zval_ptr_r_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); + value = EX_CONSTANT((opline+1)->op1); zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); @@ -18689,17 +20331,302 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { - goto assign_dim_clean; + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_UNUSED == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = NULL; + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_UNUSED, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = NULL; + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_TMP_VAR, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_UNUSED == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = NULL; + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; } else { zend_error(E_WARNING, "Cannot use a scalar value as an array"); assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_UNUSED == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { dim = NULL; + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_UNUSED, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = NULL; + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_VAR, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_UNUSED == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = NULL; + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_var_deref((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_UNUSED == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = NULL; + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_UNUSED, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = NULL; + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CV, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_UNUSED == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = NULL; + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, (opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - FREE_OP(free_op_data1); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -18760,15 +20687,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V function_name = NULL; if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_UNUSED & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Function name must be a string"); - HANDLE_EXCEPTION(); + HANDLE_EXCEPTION(); + } while (0); } } @@ -19075,14 +21009,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER( if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR != IS_CONST) { + if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -19310,14 +21244,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -19345,7 +21279,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_V value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -19793,7 +21727,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -19981,7 +21915,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV HANDLE_EXCEPTION(); } - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; @@ -20025,12 +21959,186 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; - zval *object; - zval *property_name; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = EX_CONSTANT((opline+1)->op1); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CONST); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CONST == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op_data; + zval *object, *property_name, *value, tmp; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -20042,20 +22150,521 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER } property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); - zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_TMP_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CV == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; zval *object_ptr; - zend_free_op free_op_data1; + zval *value; zval *variable_ptr; zval *dim; @@ -20070,7 +22679,7 @@ try_assign_dim_array: variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); if (UNEXPECTED(variable_ptr == NULL)) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - variable_ptr = &EG(error_zval); + variable_ptr = NULL; } } else { dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); @@ -20078,14 +22687,110 @@ try_assign_dim_array: variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CV, BP_VAR_W); } - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); + if (UNEXPECTED(variable_ptr == NULL)) { + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = EX_CONSTANT((opline+1)->op1); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CONST, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CV == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = EX_CONSTANT((opline+1)->op1); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CV == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CV, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -20101,13 +22806,13 @@ try_assign_dim_array: zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data); + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_TMP_VAR, (opline+1)->op1, execute_data); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { if (IS_CV == IS_UNUSED) { zend_throw_error(NULL, "[] operator not supported for strings"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; HANDLE_EXCEPTION(); } else { @@ -20116,9 +22821,9 @@ try_assign_dim_array: dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - value = get_zval_ptr_r_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + zval_ptr_dtor_nogc(free_op_data); } } else { zval_ptr_dtor_nogc(object_ptr); @@ -20128,17 +22833,206 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { - goto assign_dim_clean; + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CV == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CV, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_VAR, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CV == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_var_deref((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; } else { zend_error(E_WARNING, "Cannot use a scalar value as an array"); assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CV == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CV, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CV, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CV == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, (opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - FREE_OP(free_op_data1); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -20149,7 +23043,7 @@ assign_dim_clean: ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; @@ -20160,14 +23054,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEN value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CV); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(1)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; @@ -20186,43 +23108,49 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER SAVE_OPLINE(); value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var); + variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); if (IS_VAR == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var)))) { + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var))) && + UNEXPECTED(!Z_ISERROR_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); HANDLE_EXCEPTION(); - } - if (IS_CV == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!0 && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op2.var)) != IS_INDIRECT)) { /* undo the effect of get_zval_ptr_ptr() */ - Z_TRY_ADDREF_P(value_ptr); - } + + } else if (IS_CV == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - ZEND_VM_TAIL_CALL(ZEND_ASSIGN_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - variable_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if ((IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || - (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { - variable_ptr = &EG(uninitialized_zval); + value_ptr = zend_assign_to_variable(variable_ptr, value_ptr, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value_ptr); + } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + if ((IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) || + (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr)))) { + variable_ptr = &EG(uninitialized_zval); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } + } if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; - ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -20276,15 +23204,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_CV & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Function name must be a string"); - HANDLE_EXCEPTION(); + HANDLE_EXCEPTION(); + } while (0); } } @@ -20650,14 +23585,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if (IS_VAR & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_VAR != IS_CONST) { + if (IS_VAR == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -20849,14 +23784,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, (IS_TMP_VAR|IS_VAR)); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -20885,7 +23820,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_V value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); var_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); - if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -21336,7 +24271,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TM SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); zval_ptr_dtor_nogc(EX_VAR(opline->op1.var)); @@ -21525,7 +24460,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TM zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); } - if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) { + if ((IS_VAR & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(free_op2); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; @@ -21569,12 +24504,361 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVA ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1, free_op2; - zval *object; - zval *property_name; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = EX_CONSTANT((opline+1)->op1); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CONST); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CONST == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + zval_ptr_dtor_nogc(free_op2); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2, free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_TMP_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + zval_ptr_dtor_nogc(free_op2); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2, free_op_data; + zval *object, *property_name, *value, tmp; SAVE_OPLINE(); object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); @@ -21586,20 +24870,346 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HAN } property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } - zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: zval_ptr_dtor_nogc(free_op2); if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1, free_op2; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (IS_VAR == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + + if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CV == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + zval_ptr_dtor_nogc(free_op2); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op1; zval *object_ptr; - zend_free_op free_op2, free_op_data1; + zend_free_op free_op2; zval *value; zval *variable_ptr; zval *dim; @@ -21614,7 +25224,7 @@ try_assign_dim_array: variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); if (UNEXPECTED(variable_ptr == NULL)) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - variable_ptr = &EG(error_zval); + variable_ptr = NULL; } } else { dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); @@ -21622,14 +25232,14 @@ try_assign_dim_array: variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_W); zval_ptr_dtor_nogc(free_op2); } - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); + if (UNEXPECTED(variable_ptr == NULL)) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type); + value = EX_CONSTANT((opline+1)->op1); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -21645,13 +25255,13 @@ try_assign_dim_array: zend_free_op free_op2; zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data); + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CONST, (opline+1)->op1, execute_data); zval_ptr_dtor_nogc(free_op2); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_throw_error(NULL, "[] operator not supported for strings"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; HANDLE_EXCEPTION(); } else { @@ -21660,9 +25270,9 @@ try_assign_dim_array: dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_r_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); + value = EX_CONSTANT((opline+1)->op1); zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); @@ -21672,17 +25282,302 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { - goto assign_dim_clean; + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + zend_free_op free_op2, free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_TMP_VAR, (opline+1)->op1, execute_data); + zval_ptr_dtor_nogc(free_op2); + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + zend_free_op free_op2, free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_VAR, (opline+1)->op1, execute_data); + zval_ptr_dtor_nogc(free_op2); + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + value = _get_zval_ptr_var_deref((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; } else { zend_error(E_WARNING, "Cannot use a scalar value as an array"); assign_dim_clean: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op1; + zval *object_ptr; + zend_free_op free_op2; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + } + if (UNEXPECTED(variable_ptr == NULL)) { + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CV, (opline+1)->op1, execute_data); zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - FREE_OP(free_op_data1); + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + + if (UNEXPECTED(free_op1)) {zval_ptr_dtor_nogc(free_op1);}; + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, (opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -21743,15 +25638,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); + zend_throw_error(NULL, "Function name must be a string"); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); + } while (0); } } @@ -22095,7 +25997,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval object_zval; + zval *result; zend_function *constructor; zend_class_entry *ce; @@ -22118,33 +26020,26 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_HANDLER(ZEND_O } else { ce = Z_CE_P(EX_VAR(opline->op1.var)); } - if (UNEXPECTED(object_init_ex(&object_zval, ce) != SUCCESS)) { + + result = EX_VAR(opline->result.var); + if (UNEXPECTED(object_init_ex(result, ce) != SUCCESS)) { HANDLE_EXCEPTION(); } - constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval)); + constructor = Z_OBJ_HT_P(result)->get_constructor(Z_OBJ_P(result)); if (constructor == NULL) { - if (EXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY_VALUE(EX_VAR(opline->result.var), &object_zval); - } else { - OBJ_RELEASE(Z_OBJ(object_zval)); - } ZEND_VM_JMP(OP_JMP_ADDR(opline, opline->op2)); } else { /* We are not handling overloaded classes right now */ zend_execute_data *call = zend_vm_stack_push_call_frame( - ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR | - (EXPECTED(RETURN_VALUE_USED(opline)) ? 0 : ZEND_CALL_CTOR_RESULT_UNUSED), + ZEND_CALL_FUNCTION | ZEND_CALL_RELEASE_THIS | ZEND_CALL_CTOR, constructor, opline->extended_value, ce, - Z_OBJ(object_zval)); + Z_OBJ_P(result)); call->prev_execute_data = EX(call); EX(call) = call; - - if (EXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), &object_zval); - } + Z_ADDREF_P(result); ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -22344,14 +26239,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -22966,7 +26861,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED HANDLE_EXCEPTION(); } - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -23010,12 +26905,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CO ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; - zval *property_name; + zval *object, *property_name, *value, tmp; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data); @@ -23027,8 +26921,684 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_H } property_name = EX_CONSTANT(opline->op2); + value = EX_CONSTANT((opline+1)->op1); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CONST); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CONST == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + + if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = EX_CONSTANT(opline->op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_TMP_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + + if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = EX_CONSTANT(opline->op2); + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + + if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = EX_CONSTANT(opline->op2); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } - zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CV == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: /* assign_obj has two opcodes! */ @@ -23123,7 +27693,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C } } if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -23237,15 +27807,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U function_name = EX_CONSTANT(opline->op2); if (IS_CONST != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_CONST & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Function name must be a string"); - HANDLE_EXCEPTION(); + HANDLE_EXCEPTION(); + } while (0); } } @@ -23826,14 +28403,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + if (IS_UNUSED & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (IS_UNUSED != IS_CONST) { + if (IS_UNUSED == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -23961,14 +28538,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER( if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + if (IS_UNUSED & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (IS_UNUSED != IS_CONST) { + if (IS_UNUSED == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -24096,14 +28673,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER( if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + if (IS_UNUSED & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (IS_UNUSED != IS_CONST) { + if (IS_UNUSED == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -24236,14 +28813,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -24550,15 +29127,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U function_name = NULL; if (IS_UNUSED != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_UNUSED & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Function name must be a string"); - HANDLE_EXCEPTION(); + HANDLE_EXCEPTION(); + } while (0); } } @@ -24754,14 +29338,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + if (IS_UNUSED & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (IS_UNUSED != IS_CONST) { + if (IS_UNUSED == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -24952,14 +29536,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -25574,7 +30158,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED HANDLE_EXCEPTION(); } - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -25618,12 +30202,361 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; - zval *property_name; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + + if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = EX_CONSTANT((opline+1)->op1); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CONST); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CONST == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + + if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_TMP_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op_data; + zval *object, *property_name, *value, tmp; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data); @@ -25635,8 +30568,334 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HAND } property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } - zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + + if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CV == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: /* assign_obj has two opcodes! */ @@ -25731,7 +30990,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C } } if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -25845,15 +31104,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var); if (IS_CV != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if (IS_CV & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); + zend_throw_error(NULL, "Function name must be a string"); - HANDLE_EXCEPTION(); + HANDLE_EXCEPTION(); + } while (0); } } @@ -26308,14 +31574,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + if (IS_UNUSED & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = NULL; ZVAL_COPY_VALUE(&generator->value, value); - if (IS_UNUSED != IS_CONST) { + if (IS_UNUSED == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -26506,14 +31772,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, (IS_TMP_VAR|IS_VAR)); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -27133,7 +32399,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); } - if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) { + if ((IS_UNUSED & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(free_op2); @@ -27177,12 +32443,186 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TM ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; - zval *object; - zval *property_name; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + + if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = EX_CONSTANT((opline+1)->op1); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CONST); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CONST == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + zval_ptr_dtor_nogc(free_op2); + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2, free_op_data; + zval *object, *property_name, *value, tmp; SAVE_OPLINE(); object = _get_obj_zval_ptr_unused(execute_data); @@ -27194,8 +32634,509 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_ } property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } - zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_TMP_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + zval_ptr_dtor_nogc(free_op2); + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2, free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + + if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + zval_ptr_dtor_nogc(free_op2); + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_obj_zval_ptr_unused(execute_data); + + if (IS_UNUSED == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + + if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_UNUSED == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CV == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: zval_ptr_dtor_nogc(free_op2); /* assign_obj has two opcodes! */ @@ -27290,7 +33231,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T } } if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); @@ -27405,15 +33346,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_U function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); if ((IS_TMP_VAR|IS_VAR) != IS_CONST) { if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) { - if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { - GET_OP2_UNDEF_CV(function_name, BP_VAR_R); - if (UNEXPECTED(EG(exception) != NULL)) { - HANDLE_EXCEPTION(); + do { + if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) { + function_name = Z_REFVAL_P(function_name); + if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) { + break; + } + } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) { + GET_OP2_UNDEF_CV(function_name, BP_VAR_R); + if (UNEXPECTED(EG(exception) != NULL)) { + HANDLE_EXCEPTION(); + } } - } - zend_throw_error(NULL, "Function name must be a string"); - zval_ptr_dtor_nogc(free_op2); - HANDLE_EXCEPTION(); + zend_throw_error(NULL, "Function name must be a string"); + zval_ptr_dtor_nogc(free_op2); + HANDLE_EXCEPTION(); + } while (0); } } @@ -27881,7 +33829,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_NOT_SPEC_CV_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -27891,14 +33839,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_O if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_increment_function(var_ptr); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); } ZEND_VM_NEXT_OPCODE(); } - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { + if (UNEXPECTED(0)) { ZVAL_NULL(EX_VAR(opline->result.var)); } ZEND_VM_NEXT_OPCODE(); @@ -27913,14 +33861,53 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_O increment_function(var_ptr); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *var_ptr; + + var_ptr = _get_zval_ptr_cv_undef_BP_VAR_RW(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_increment_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + var_ptr = GET_OP1_UNDEF_CV(var_ptr, BP_VAR_RW); + } + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + increment_function(var_ptr); + + if (UNEXPECTED(1)) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -27930,14 +33917,53 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_O if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { fast_long_decrement_function(var_ptr); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); } ZEND_VM_NEXT_OPCODE(); } - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { + if (UNEXPECTED(0)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + ZEND_VM_NEXT_OPCODE(); + } + + SAVE_OPLINE(); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var_ptr) == IS_UNDEF)) { + var_ptr = GET_OP1_UNDEF_CV(var_ptr, BP_VAR_RW); + } + ZVAL_DEREF(var_ptr); + SEPARATE_ZVAL_NOREF(var_ptr); + + decrement_function(var_ptr); + + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *var_ptr; + + var_ptr = _get_zval_ptr_cv_undef_BP_VAR_RW(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(var_ptr) == IS_LONG)) { + fast_long_decrement_function(var_ptr); + if (UNEXPECTED(1)) { + ZVAL_COPY_VALUE(EX_VAR(opline->result.var), var_ptr); + } + ZEND_VM_NEXT_OPCODE(); + } + + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { + if (UNEXPECTED(1)) { ZVAL_NULL(EX_VAR(opline->result.var)); } ZEND_VM_NEXT_OPCODE(); @@ -27952,7 +33978,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_O decrement_function(var_ptr); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(1)) { ZVAL_COPY(EX_VAR(opline->result.var), var_ptr); } @@ -27973,7 +33999,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -28005,7 +34031,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_ ZEND_VM_NEXT_OPCODE(); } - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { ZVAL_NULL(EX_VAR(opline->result.var)); ZEND_VM_NEXT_OPCODE(); } @@ -28255,14 +34281,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OP ZVAL_NULL(EX(return_value)); } } else if (!EX(return_value)) { - if (IS_CV == IS_VAR || IS_CV == IS_TMP_VAR ) { + if (IS_CV & (IS_VAR|IS_TMP_VAR)) { if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) { SAVE_OPLINE(); zval_dtor_func_for_ptr(Z_COUNTED_P(free_op1)); } } } else { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(EX(return_value), retval_ptr); if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE_P(EX(return_value)))) { @@ -28300,7 +34326,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER( SAVE_OPLINE(); do { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR || + if ((IS_CV & (IS_CONST|IS_TMP_VAR)) || (IS_CV == IS_VAR && opline->extended_value == ZEND_RETURNS_VALUE)) { /* Not supposed to happen, but we'll allow it */ zend_error(E_NOTICE, "Only variable references should be returned by reference"); @@ -28359,7 +34385,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GENERATOR_RETURN_SPEC_CV_HANDL retval = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); /* Copy return value into generator->retval */ - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { ZVAL_COPY_VALUE(&generator->retval, retval); if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->retval))) { @@ -28481,7 +34507,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_ varptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var); arg = ZEND_CALL_VAR(EX(call), opline->result.var); - if (IS_CV == IS_VAR && UNEXPECTED(varptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(varptr))) { ZVAL_NEW_REF(arg, &EG(uninitialized_zval)); ZEND_VM_NEXT_OPCODE(); } @@ -28505,7 +34531,56 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_HANDLER(ZE uint32_t arg_num = opline->op2.num; - if (EXPECTED(arg_num <= MAX_ARG_FLAG_NUM)) { + if (EXPECTED(0)) { + if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { + goto send_var_by_ref; + } + } else if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { +send_var_by_ref: + ZEND_VM_TAIL_CALL(ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); + } + + varptr = _get_zval_ptr_cv_undef(execute_data, opline->op1.var); + if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(varptr) == IS_UNDEF)) { + SAVE_OPLINE(); + GET_OP1_UNDEF_CV(varptr, BP_VAR_R); + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + ZVAL_NULL(arg); + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); + } + + arg = ZEND_CALL_VAR(EX(call), opline->result.var); + + if (IS_CV == IS_CV) { + ZVAL_OPT_DEREF(varptr); + ZVAL_COPY(arg, varptr); + } else /* if (IS_CV == IS_VAR) */ { + if (UNEXPECTED(Z_ISREF_P(varptr))) { + zend_refcounted *ref = Z_COUNTED_P(varptr); + + varptr = Z_REFVAL_P(varptr); + ZVAL_COPY_VALUE(arg, varptr); + if (UNEXPECTED(--GC_REFCOUNT(ref) == 0)) { + efree_size(ref, sizeof(zend_reference)); + } else if (Z_OPT_REFCOUNTED_P(arg)) { + Z_ADDREF_P(arg); + } + } else { + ZVAL_COPY_VALUE(arg, varptr); + } + } + + ZEND_VM_NEXT_OPCODE(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_VAR_EX_SPEC_CV_QUICK_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zval *varptr, *arg; + + uint32_t arg_num = opline->op2.num; + + if (EXPECTED(1)) { if (QUICK_ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) { goto send_var_by_ref; } @@ -29410,6 +35485,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN ZVAL_NULL(EX_VAR(opline->result.var)); } + /* This generator has no send target (though the generator we delegate to might have one) */ + generator->send_target = NULL; + /* We increment to the next op, so we are at the correct position when the * generator is resumed. */ ZEND_VM_INC_OPCODE(); @@ -30227,14 +36305,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, IS_CONST); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -30262,7 +36340,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_C value = EX_CONSTANT(opline->op2); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -30877,7 +36955,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CON SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -31137,7 +37215,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CON HANDLE_EXCEPTION(); } - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -31225,12 +37303,186 @@ try_fetch_list: ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; - zval *property_name; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = EX_CONSTANT(opline->op2); + value = EX_CONSTANT((opline+1)->op1); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CONST); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CONST == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op_data; + zval *object, *property_name, *value, tmp; SAVE_OPLINE(); object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); @@ -31242,20 +37494,521 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDL } property_name = EX_CONSTANT(opline->op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_TMP_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = EX_CONSTANT(opline->op2); + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = EX_CONSTANT(opline->op2); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CONST == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CV == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { - zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); + } +exit_assign_obj: /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr; - zend_free_op free_op_data1; + zval *value; zval *variable_ptr; zval *dim; @@ -31270,7 +38023,7 @@ try_assign_dim_array: variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); if (UNEXPECTED(variable_ptr == NULL)) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - variable_ptr = &EG(error_zval); + variable_ptr = NULL; } } else { dim = EX_CONSTANT(opline->op2); @@ -31278,14 +38031,14 @@ try_assign_dim_array: variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CONST, BP_VAR_W); } - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); + if (UNEXPECTED(variable_ptr == NULL)) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type); + value = EX_CONSTANT((opline+1)->op1); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -31301,13 +38054,13 @@ try_assign_dim_array: zval *property_name = EX_CONSTANT(opline->op2); - zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data); + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CONST, (opline+1)->op1, execute_data); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { if (IS_CONST == IS_UNUSED) { zend_throw_error(NULL, "[] operator not supported for strings"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + HANDLE_EXCEPTION(); } else { @@ -31316,9 +38069,9 @@ try_assign_dim_array: dim = EX_CONSTANT(opline->op2); offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - value = get_zval_ptr_r_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); + value = EX_CONSTANT((opline+1)->op1); zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); @@ -31328,17 +38081,206 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { - goto assign_dim_clean; + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CONST == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = EX_CONSTANT(opline->op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CONST, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = EX_CONSTANT(opline->op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_TMP_VAR, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CONST == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = EX_CONSTANT(opline->op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; } else { zend_error(E_WARNING, "Cannot use a scalar value as an array"); assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CONST == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { dim = EX_CONSTANT(opline->op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CONST, BP_VAR_W); - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - FREE_OP(free_op_data1); + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = EX_CONSTANT(opline->op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_VAR, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CONST == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = EX_CONSTANT(opline->op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_var_deref((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -31349,7 +38291,103 @@ assign_dim_clean: ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CONST == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = EX_CONSTANT(opline->op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CONST, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = EX_CONSTANT(opline->op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CV, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CONST == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = EX_CONSTANT(opline->op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, (opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -31360,14 +38398,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_HANDLER(Z value = EX_CONSTANT(opline->op2); variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CONST); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = EX_CONSTANT(opline->op2); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CONST); + if (UNEXPECTED(1)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -31499,7 +38565,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST } } if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -32287,14 +39353,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if (IS_CV & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV != IS_CONST) { + if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -32486,6 +39552,57 @@ check_indirect: ZEND_VM_NEXT_OPCODE(); } +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BIND_STATIC_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + HashTable *ht; + zval *varname; + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + zval_ptr_dtor(variable_ptr); + + ht = EX(func)->op_array.static_variables; + ZEND_ASSERT(ht != NULL); + if (GC_REFCOUNT(ht) > 1) { + if (!(GC_FLAGS(ht) & IS_ARRAY_IMMUTABLE)) { + GC_REFCOUNT(ht)--; + } + EX(func)->op_array.static_variables = ht = zend_array_dup(ht); + } + + varname = EX_CONSTANT(opline->op2); + value = zend_hash_find(ht, Z_STR_P(varname)); + + if (opline->extended_value) { + if (Z_CONSTANT_P(value)) { + if (UNEXPECTED(zval_update_constant_ex(value, 1, NULL) != SUCCESS)) { + ZVAL_NULL(variable_ptr); + HANDLE_EXCEPTION(); + } + } + if (UNEXPECTED(!Z_ISREF_P(value))) { + zend_reference *ref = (zend_reference*)emalloc(sizeof(zend_reference)); + GC_REFCOUNT(ref) = 2; + GC_TYPE_INFO(ref) = IS_REFERENCE; + ZVAL_COPY_VALUE(&ref->val, value); + Z_REF_P(value) = ref; + Z_TYPE_INFO_P(value) = IS_REFERENCE_EX; + ZVAL_REF(variable_ptr, ref); + } else { + Z_ADDREF_P(value); + ZVAL_REF(variable_ptr, Z_REF_P(value)); + } + } else { + ZVAL_COPY(variable_ptr, value); + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -32522,7 +39639,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_H ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; @@ -32533,14 +39650,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_HANDLER(ZEN value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + zval_ptr_dtor_nogc(free_op2); + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); + if (UNEXPECTED(1)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -32577,14 +39722,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if (IS_CV & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV != IS_CONST) { + if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -32860,7 +40005,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_CV_V ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC)); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; @@ -32871,14 +40016,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEN value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { zval_ptr_dtor_nogc(free_op2); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_VAR); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + zval_ptr_dtor_nogc(free_op2); + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(1)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -32897,42 +40070,48 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER SAVE_OPLINE(); value_ptr = _get_zval_ptr_ptr_var(opline->op2.var, execute_data, &free_op2); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var)))) { + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var))) && + UNEXPECTED(!Z_ISERROR_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; HANDLE_EXCEPTION(); - } - if (IS_VAR == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!(free_op2 != NULL) && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op2.var)) != IS_INDIRECT)) { /* undo the effect of get_zval_ptr_ptr() */ - Z_TRY_ADDREF_P(value_ptr); - } + + } else if (IS_VAR == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; HANDLE_EXCEPTION(); } - ZEND_VM_TAIL_CALL(ZEND_ASSIGN_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || - (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { - variable_ptr = &EG(uninitialized_zval); + value_ptr = zend_assign_to_variable(variable_ptr, value_ptr, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value_ptr); + } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); - } + if ((IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) || + (IS_VAR == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr)))) { + variable_ptr = &EG(uninitialized_zval); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } - if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; + if (UNEXPECTED(free_op2)) {zval_ptr_dtor_nogc(free_op2);}; + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -33156,14 +40335,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if (IS_CV & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV != IS_CONST) { + if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -33296,14 +40475,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, IS_UNUSED); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -33627,14 +40806,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { - - HANDLE_EXCEPTION(); - } - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { + if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { } @@ -33874,7 +41046,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNU SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -33902,12 +41074,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNU ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr; - zend_free_op free_op_data1; + zval *value; zval *variable_ptr; zval *dim; @@ -33922,7 +41094,7 @@ try_assign_dim_array: variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); if (UNEXPECTED(variable_ptr == NULL)) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - variable_ptr = &EG(error_zval); + variable_ptr = NULL; } } else { dim = NULL; @@ -33930,14 +41102,14 @@ try_assign_dim_array: variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_UNUSED, BP_VAR_W); } - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); + if (UNEXPECTED(variable_ptr == NULL)) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type); + value = EX_CONSTANT((opline+1)->op1); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -33953,13 +41125,13 @@ try_assign_dim_array: zval *property_name = NULL; - zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data); + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CONST, (opline+1)->op1, execute_data); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { if (IS_UNUSED == IS_UNUSED) { zend_throw_error(NULL, "[] operator not supported for strings"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + HANDLE_EXCEPTION(); } else { @@ -33968,9 +41140,9 @@ try_assign_dim_array: dim = NULL; offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - value = get_zval_ptr_r_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); + value = EX_CONSTANT((opline+1)->op1); zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); @@ -33980,17 +41152,302 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { - goto assign_dim_clean; + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_UNUSED == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = NULL; + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_UNUSED, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = NULL; + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_TMP_VAR, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_UNUSED == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = NULL; + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; } else { zend_error(E_WARNING, "Cannot use a scalar value as an array"); assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_UNUSED == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { dim = NULL; + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_UNUSED, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = NULL; + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_VAR, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_UNUSED == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = NULL; + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_var_deref((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_UNUSED == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = NULL; + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_UNUSED, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = NULL; + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CV, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_UNUSED == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = NULL; + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, (opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - FREE_OP(free_op_data1); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -34512,14 +41969,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if (IS_CV & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV != IS_CONST) { + if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -35347,14 +42804,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, IS_CV); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -35382,7 +42839,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_C value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -35858,7 +43315,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_ SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -36118,7 +43575,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_ HANDLE_EXCEPTION(); } - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); @@ -36162,12 +43619,361 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HAN ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE - zval *object; - zval *property_name; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = EX_CONSTANT((opline+1)->op1); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CONST); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CONST == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_TMP_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op_data; + zval *object, *property_name, *value, tmp; SAVE_OPLINE(); object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); @@ -36179,20 +43985,346 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER( } property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } - zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if (IS_CV == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, (IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CV == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr; - zend_free_op free_op_data1; + zval *value; zval *variable_ptr; zval *dim; @@ -36207,7 +44339,7 @@ try_assign_dim_array: variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); if (UNEXPECTED(variable_ptr == NULL)) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - variable_ptr = &EG(error_zval); + variable_ptr = NULL; } } else { dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); @@ -36215,14 +44347,14 @@ try_assign_dim_array: variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CV, BP_VAR_W); } - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); + if (UNEXPECTED(variable_ptr == NULL)) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type); + value = EX_CONSTANT((opline+1)->op1); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -36238,13 +44370,13 @@ try_assign_dim_array: zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); - zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data); + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CONST, (opline+1)->op1, execute_data); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { if (IS_CV == IS_UNUSED) { zend_throw_error(NULL, "[] operator not supported for strings"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + HANDLE_EXCEPTION(); } else { @@ -36253,9 +44385,9 @@ try_assign_dim_array: dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); - value = get_zval_ptr_r_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); + value = EX_CONSTANT((opline+1)->op1); zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); @@ -36265,17 +44397,302 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { - goto assign_dim_clean; + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CV == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CV, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_TMP_VAR, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CV == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + zend_free_op free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CV == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CV, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_VAR, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CV == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_var_deref((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; } else { zend_error(E_WARNING, "Cannot use a scalar value as an array"); assign_dim_clean: + + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if (IS_CV == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, IS_CV, BP_VAR_W); + + } + if (UNEXPECTED(variable_ptr == NULL)) { + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + + zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CV, (opline+1)->op1, execute_data); + + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if (IS_CV == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, (opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - FREE_OP(free_op_data1); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -36286,7 +44703,7 @@ assign_dim_clean: ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE @@ -36297,14 +44714,42 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { value = zend_assign_to_variable(variable_ptr, value, IS_CV); - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + if (UNEXPECTED(0)) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } + + ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *value; + zval *variable_ptr; + + SAVE_OPLINE(); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) { + + if (UNEXPECTED(1)) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(1)) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -36323,41 +44768,47 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER( SAVE_OPLINE(); value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op2.var); + variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); if (IS_CV == IS_VAR && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op1.var)) != IS_INDIRECT) && - UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var)))) { + UNEXPECTED(!Z_ISREF_P(EX_VAR(opline->op1.var))) && + UNEXPECTED(!Z_ISERROR_P(EX_VAR(opline->op1.var)))) { + zend_throw_error(NULL, "Cannot assign by reference to overloaded object"); HANDLE_EXCEPTION(); - } - if (IS_CV == IS_VAR && - (value_ptr == &EG(uninitialized_zval) || - (opline->extended_value == ZEND_RETURNS_FUNCTION && - !(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF)))) { - if (!0 && UNEXPECTED(Z_TYPE_P(EX_VAR(opline->op2.var)) != IS_INDIRECT)) { /* undo the effect of get_zval_ptr_ptr() */ - Z_TRY_ADDREF_P(value_ptr); - } + + } else if (IS_CV == IS_VAR && + opline->extended_value == ZEND_RETURNS_FUNCTION && + UNEXPECTED(!(Z_VAR_FLAGS_P(value_ptr) & IS_VAR_RET_REF))) { + zend_error(E_NOTICE, "Only variables should be assigned by reference"); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); } - ZEND_VM_TAIL_CALL(ZEND_ASSIGN_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS_PASSTHRU)); - } - variable_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); - if ((IS_CV == IS_VAR && UNEXPECTED(variable_ptr == &EG(error_zval))) || - (IS_CV == IS_VAR && UNEXPECTED(value_ptr == &EG(error_zval)))) { - variable_ptr = &EG(uninitialized_zval); + value_ptr = zend_assign_to_variable(variable_ptr, value_ptr, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value_ptr); + } + /* zend_assign_to_variable() always takes care of op2, never free it! */ + } else { - zend_assign_to_variable_reference(variable_ptr, value_ptr); - } - if (UNEXPECTED(RETURN_VALUE_USED(opline))) { - ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); - } + if ((IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(variable_ptr))) || + (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(value_ptr)))) { + variable_ptr = &EG(uninitialized_zval); + } else { + zend_assign_to_variable_reference(variable_ptr, value_ptr); + } + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), variable_ptr); + } + } ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } @@ -36484,7 +44935,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA } } if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -37080,14 +45531,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) { /* Constants and temporary variables aren't yieldable by reference, * but we still allow them with a notice. */ - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if (IS_CV & (IS_CONST|IS_TMP_VAR)) { zval *value; zend_error(E_NOTICE, "Only variable references should be yielded by reference"); value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var); ZVAL_COPY_VALUE(&generator->value, value); - if (IS_CV != IS_CONST) { + if (IS_CV == IS_CONST) { if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) { zval_copy_ctor_func(&generator->value); } @@ -37879,14 +46330,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP zend_fetch_dimension_address_RW(&rv, container, dim, (IS_TMP_VAR|IS_VAR)); value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); - var_ptr = Z_INDIRECT(rv); - if (UNEXPECTED(var_ptr == &EG(error_zval))) { + if (UNEXPECTED(Z_ISERROR(rv))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { + ZEND_ASSERT(Z_TYPE(rv) == IS_INDIRECT); + var_ptr = Z_INDIRECT(rv); ZVAL_DEREF(var_ptr); SEPARATE_ZVAL_NOREF(var_ptr); @@ -37915,7 +46366,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_C value = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); var_ptr = _get_zval_ptr_cv_BP_VAR_RW(execute_data, opline->op1.var); - if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == &EG(error_zval))) { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(var_ptr))) { if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -38394,7 +46845,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP SAVE_OPLINE(); if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) { - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); @@ -38656,7 +47107,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); } - if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) { + if ((IS_CV & (IS_CONST|IS_TMP_VAR))) { zend_throw_error(NULL, "Cannot use temporary expression in write context"); zval_ptr_dtor_nogc(free_op2); @@ -38700,12 +47151,536 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION(); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zend_free_op free_op2; - zval *object; - zval *property_name; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = EX_CONSTANT((opline+1)->op1); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CONST); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CONST == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CONST == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CONST == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CONST != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CONST == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + + } +exit_assign_obj: + zval_ptr_dtor_nogc(free_op2); + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2, free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_TMP_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_TMP_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_TMP_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_TMP_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_TMP_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + zval_ptr_dtor_nogc(free_op2); + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2, free_op_data; + zval *object, *property_name, *value, tmp; + + SAVE_OPLINE(); + object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) { + zend_throw_error(NULL, "Using $this when not in object context"); + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + HANDLE_EXCEPTION(); + } + + property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_VAR == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_VAR == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + zval_ptr_dtor_nogc(free_op_data); + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_VAR == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_VAR != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_VAR == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { + zval_ptr_dtor_nogc(free_op_data); + } +exit_assign_obj: + zval_ptr_dtor_nogc(free_op2); + + /* assign_obj has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + zend_free_op free_op2; + zval *object, *property_name, *value, tmp; SAVE_OPLINE(); object = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); @@ -38717,20 +47692,171 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HAND } property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + + if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) { + do { + if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object))) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + if (Z_ISREF_P(object)) { + object = Z_REFVAL_P(object); + if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) { + break; + } + } + if (EXPECTED(Z_TYPE_P(object) <= IS_FALSE || + (Z_TYPE_P(object) == IS_STRING && Z_STRLEN_P(object) == 0))) { + zend_object *obj; + + zval_ptr_dtor(object); + object_init(object); + Z_ADDREF_P(object); + obj = Z_OBJ_P(object); + zend_error(E_WARNING, "Creating default object from empty value"); + if (GC_REFCOUNT(obj) == 1) { + /* the enclosing container was deleted, obj is unreferenced */ + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + OBJ_RELEASE(obj); + goto exit_assign_obj; + } + Z_DELREF_P(object); + } else { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + } while (0); + } + + if ((IS_TMP_VAR|IS_VAR) == IS_CONST && + EXPECTED(Z_OBJCE_P(object) == CACHED_PTR(Z_CACHE_SLOT_P(property_name)))) { + uint32_t prop_offset = (uint32_t)(intptr_t)CACHED_PTR(Z_CACHE_SLOT_P(property_name) + sizeof(void*)); + zend_object *zobj = Z_OBJ_P(object); + zval *property; + + if (EXPECTED(prop_offset != (uint32_t)ZEND_DYNAMIC_PROPERTY_OFFSET)) { + property = OBJ_PROP(zobj, prop_offset); + if (Z_TYPE_P(property) != IS_UNDEF) { +fast_assign_obj: + value = zend_assign_to_variable(property, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } else { + if (EXPECTED(zobj->properties != NULL)) { + if (UNEXPECTED(GC_REFCOUNT(zobj->properties) > 1)) { + if (EXPECTED(!(GC_FLAGS(zobj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(zobj->properties)--; + } + zobj->properties = zend_array_dup(zobj->properties); + } + property = zend_hash_find(zobj->properties, Z_STR_P(property_name)); + if (property) { + goto fast_assign_obj; + } + } + + if (!zobj->ce->__set) { + + if (EXPECTED(zobj->properties == NULL)) { + rebuild_object_properties(zobj); + } + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + if (Z_ISREF_P(value)) { + if (IS_CV == IS_VAR) { + zend_reference *ref = Z_REF_P(value); + if (--GC_REFCOUNT(ref) == 0) { + ZVAL_COPY_VALUE(&tmp, Z_REFVAL_P(value)); + efree_size(ref, sizeof(zend_reference)); + value = &tmp; + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else { + value = Z_REFVAL_P(value); + if (Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + } else if (IS_CV == IS_CV && Z_REFCOUNTED_P(value)) { + Z_ADDREF_P(value); + } + } + zend_hash_add_new(zobj->properties, Z_STR_P(property_name), value); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + goto exit_assign_obj; + } + } + } + + if (!Z_OBJ_HT_P(object)->write_property) { + zend_error(E_WARNING, "Attempt to assign property of non-object"); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + + goto exit_assign_obj; + } + + /* separate our value if necessary */ + if (IS_CV == IS_CONST) { + if (UNEXPECTED(Z_OPT_COPYABLE_P(value))) { + ZVAL_COPY_VALUE(&tmp, value); + zval_copy_ctor_func(&tmp); + value = &tmp; + } + } else if (IS_CV != IS_TMP_VAR) { + ZVAL_DEREF(value); + } + + Z_OBJ_HT_P(object)->write_property(object, property_name, value, ((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL); + + if (UNEXPECTED(RETURN_VALUE_USED(opline)) && EXPECTED(!EG(exception))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + if (IS_CV == IS_CONST) { + zval_ptr_dtor_nogc(value); + } else { - zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL)); + } +exit_assign_obj: zval_ptr_dtor_nogc(free_op2); /* assign_obj has two opcodes! */ ZEND_VM_NEXT_OPCODE_EX(1, 2); } -static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS) { USE_OPLINE zval *object_ptr; - zend_free_op free_op2, free_op_data1; + zend_free_op free_op2; zval *value; zval *variable_ptr; zval *dim; @@ -38745,7 +47871,7 @@ try_assign_dim_array: variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); if (UNEXPECTED(variable_ptr == NULL)) { zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); - variable_ptr = &EG(error_zval); + variable_ptr = NULL; } } else { dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); @@ -38753,14 +47879,14 @@ try_assign_dim_array: variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_W); zval_ptr_dtor_nogc(free_op2); } - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - if (UNEXPECTED(variable_ptr == &EG(error_zval))) { - FREE_OP(free_op_data1); + if (UNEXPECTED(variable_ptr == NULL)) { + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } } else { - value = zend_assign_to_variable(variable_ptr, value, (opline+1)->op1_type); + value = EX_CONSTANT((opline+1)->op1); + value = zend_assign_to_variable(variable_ptr, value, IS_CONST); if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_COPY(EX_VAR(opline->result.var), value); } @@ -38776,13 +47902,13 @@ try_assign_dim_array: zend_free_op free_op2; zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); - zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data); + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CONST, (opline+1)->op1, execute_data); zval_ptr_dtor_nogc(free_op2); } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { zend_throw_error(NULL, "[] operator not supported for strings"); - FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var); + HANDLE_EXCEPTION(); } else { @@ -38791,9 +47917,9 @@ try_assign_dim_array: dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_r_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); + value = EX_CONSTANT((opline+1)->op1); zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); - FREE_OP(free_op_data1); + } } else { zval_ptr_dtor_nogc(object_ptr); @@ -38803,17 +47929,302 @@ assign_dim_convert_to_array: goto try_assign_dim_array; } } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { - if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) { - goto assign_dim_clean; + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + zend_free_op free_op2, free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_TMP_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_TMP_VAR, (opline+1)->op1, execute_data); + zval_ptr_dtor_nogc(free_op2); + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + value = _get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; } else { zend_error(E_WARNING, "Cannot use a scalar value as an array"); assign_dim_clean: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + zend_free_op free_op2, free_op_data; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_W); zval_ptr_dtor_nogc(free_op2); - value = get_zval_ptr_r((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1); - FREE_OP(free_op_data1); + } + if (UNEXPECTED(variable_ptr == NULL)) { + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data); + value = zend_assign_to_variable(variable_ptr, value, IS_VAR); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_VAR, (opline+1)->op1, execute_data); + zval_ptr_dtor_nogc(free_op2); + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + value = _get_zval_ptr_var_deref((opline+1)->op1.var, execute_data, &free_op_data); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + zval_ptr_dtor_nogc(free_op_data); + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } + } + + /* assign_dim has two opcodes! */ + ZEND_VM_NEXT_OPCODE_EX(1, 2); +} + +static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS) +{ + USE_OPLINE + + zval *object_ptr; + zend_free_op free_op2; + zval *value; + zval *variable_ptr; + zval *dim; + + SAVE_OPLINE(); + object_ptr = _get_zval_ptr_cv_undef_BP_VAR_W(execute_data, opline->op1.var); + + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { +try_assign_dim_array: + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_hash_next_index_insert(Z_ARRVAL_P(object_ptr), &EG(uninitialized_zval)); + if (UNEXPECTED(variable_ptr == NULL)) { + zend_error(E_WARNING, "Cannot add element to the array as the next element is already occupied"); + variable_ptr = NULL; + } + } else { + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + SEPARATE_ARRAY(object_ptr); + variable_ptr = zend_fetch_dimension_address_inner(Z_ARRVAL_P(object_ptr), dim, (IS_TMP_VAR|IS_VAR), BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + } + if (UNEXPECTED(variable_ptr == NULL)) { + + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_NULL(EX_VAR(opline->result.var)); + } + } else { + value = _get_zval_ptr_cv_BP_VAR_R(execute_data, (opline+1)->op1.var); + value = zend_assign_to_variable(variable_ptr, value, IS_CV); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { + ZVAL_COPY(EX_VAR(opline->result.var), value); + } + } + } else { + if (EXPECTED(Z_ISREF_P(object_ptr))) { + object_ptr = Z_REFVAL_P(object_ptr); + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) { + goto try_assign_dim_array; + } + } + if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) { + zend_free_op free_op2; + zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + + zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, IS_CV, (opline+1)->op1, execute_data); + zval_ptr_dtor_nogc(free_op2); + } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) { + if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) { + if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) { + zend_throw_error(NULL, "[] operator not supported for strings"); + + + HANDLE_EXCEPTION(); + } else { + zend_long offset; + + dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2); + offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W); + zval_ptr_dtor_nogc(free_op2); + value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, (opline+1)->op1.var); + zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL)); + + } + } else { + zval_ptr_dtor_nogc(object_ptr); +assign_dim_convert_to_array: + ZVAL_NEW_ARR(object_ptr); + zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0); + goto try_assign_dim_array; + } + } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) { + goto assign_dim_convert_to_array; + } else if (IS_CV == IS_VAR && UNEXPECTED(Z_ISERROR_P(object_ptr))) { + goto assign_dim_clean; + } else { + zend_error(E_WARNING, "Cannot use a scalar value as an array"); +assign_dim_clean: + zval_ptr_dtor_nogc(EX_VAR(opline->op2.var)); + if (UNEXPECTED(RETURN_VALUE_USED(opline))) { ZVAL_NULL(EX_VAR(opline->result.var)); } @@ -38946,7 +48357,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA } } if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); @@ -41108,7 +50519,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } } if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -42016,14 +51427,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_ } } - if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_STATIC) { - if (Z_CONSTANT_P(retval)) { - if (UNEXPECTED(zval_update_constant_ex(retval, 1, NULL) != SUCCESS)) { - zval_ptr_dtor_nogc(free_op1); - HANDLE_EXCEPTION(); - } - } - } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { + if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) { zval_ptr_dtor_nogc(free_op1); } @@ -43349,7 +52753,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C } } if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { HANDLE_EXCEPTION(); @@ -44487,7 +53891,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T } } if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) { - GET_OP1_UNDEF_CV(object, BP_VAR_R); + object = GET_OP1_UNDEF_CV(object, BP_VAR_R); if (UNEXPECTED(EG(exception) != NULL)) { zval_ptr_dtor_nogc(free_op2); HANDLE_EXCEPTION(); @@ -44814,4608 +54218,3148 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NULL_HANDLER(ZEND_OPCODE_HANDL void zend_init_opcodes_handlers(void) { - static const void *labels[] = { - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_NOP_SPEC_HANDLER, - ZEND_ADD_SPEC_CONST_CONST_HANDLER, - ZEND_ADD_SPEC_CONST_TMPVAR_HANDLER, - ZEND_ADD_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_SPEC_CONST_CV_HANDLER, - ZEND_ADD_SPEC_TMPVAR_CONST_HANDLER, - ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_SPEC_TMPVAR_CV_HANDLER, - ZEND_ADD_SPEC_TMPVAR_CONST_HANDLER, - ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_SPEC_CV_CONST_HANDLER, - ZEND_ADD_SPEC_CV_TMPVAR_HANDLER, - ZEND_ADD_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_SPEC_CV_CV_HANDLER, - ZEND_SUB_SPEC_CONST_CONST_HANDLER, - ZEND_SUB_SPEC_CONST_TMPVAR_HANDLER, - ZEND_SUB_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SUB_SPEC_CONST_CV_HANDLER, - ZEND_SUB_SPEC_TMPVAR_CONST_HANDLER, - ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SUB_SPEC_TMPVAR_CV_HANDLER, - ZEND_SUB_SPEC_TMPVAR_CONST_HANDLER, - ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SUB_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SUB_SPEC_CV_CONST_HANDLER, - ZEND_SUB_SPEC_CV_TMPVAR_HANDLER, - ZEND_SUB_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SUB_SPEC_CV_CV_HANDLER, - ZEND_MUL_SPEC_CONST_CONST_HANDLER, - ZEND_MUL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_MUL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_MUL_SPEC_CONST_CV_HANDLER, - ZEND_MUL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_MUL_SPEC_TMPVAR_CV_HANDLER, - ZEND_MUL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_MUL_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_MUL_SPEC_CV_CONST_HANDLER, - ZEND_MUL_SPEC_CV_TMPVAR_HANDLER, - ZEND_MUL_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_MUL_SPEC_CV_CV_HANDLER, - ZEND_DIV_SPEC_CONST_CONST_HANDLER, - ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER, - ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DIV_SPEC_CONST_CV_HANDLER, - ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER, - ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DIV_SPEC_TMPVAR_CV_HANDLER, - ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER, - ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DIV_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DIV_SPEC_CV_CONST_HANDLER, - ZEND_DIV_SPEC_CV_TMPVAR_HANDLER, - ZEND_DIV_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DIV_SPEC_CV_CV_HANDLER, - ZEND_MOD_SPEC_CONST_CONST_HANDLER, - ZEND_MOD_SPEC_CONST_TMPVAR_HANDLER, - ZEND_MOD_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_MOD_SPEC_CONST_CV_HANDLER, - ZEND_MOD_SPEC_TMPVAR_CONST_HANDLER, - ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_MOD_SPEC_TMPVAR_CV_HANDLER, - ZEND_MOD_SPEC_TMPVAR_CONST_HANDLER, - ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_MOD_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_MOD_SPEC_CV_CONST_HANDLER, - ZEND_MOD_SPEC_CV_TMPVAR_HANDLER, - ZEND_MOD_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_MOD_SPEC_CV_CV_HANDLER, - ZEND_SL_SPEC_CONST_CONST_HANDLER, - ZEND_SL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_SL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SL_SPEC_CONST_CV_HANDLER, - ZEND_SL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SL_SPEC_TMPVAR_CV_HANDLER, - ZEND_SL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SL_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SL_SPEC_CV_CONST_HANDLER, - ZEND_SL_SPEC_CV_TMPVAR_HANDLER, - ZEND_SL_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SL_SPEC_CV_CV_HANDLER, - ZEND_SR_SPEC_CONST_CONST_HANDLER, - ZEND_SR_SPEC_CONST_TMPVAR_HANDLER, - ZEND_SR_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SR_SPEC_CONST_CV_HANDLER, - ZEND_SR_SPEC_TMPVAR_CONST_HANDLER, - ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SR_SPEC_TMPVAR_CV_HANDLER, - ZEND_SR_SPEC_TMPVAR_CONST_HANDLER, - ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SR_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SR_SPEC_CV_CONST_HANDLER, - ZEND_SR_SPEC_CV_TMPVAR_HANDLER, - ZEND_SR_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SR_SPEC_CV_CV_HANDLER, - ZEND_CONCAT_SPEC_CONST_CONST_HANDLER, - ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDLER, - ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CONCAT_SPEC_CONST_CV_HANDLER, - ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER, - ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER, - ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER, - ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CONCAT_SPEC_CV_CONST_HANDLER, - ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER, - ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CONCAT_SPEC_CV_CV_HANDLER, - ZEND_BW_OR_SPEC_CONST_CONST_HANDLER, - ZEND_BW_OR_SPEC_CONST_TMPVAR_HANDLER, - ZEND_BW_OR_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_OR_SPEC_CONST_CV_HANDLER, - ZEND_BW_OR_SPEC_TMPVAR_CONST_HANDLER, - ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_OR_SPEC_TMPVAR_CV_HANDLER, - ZEND_BW_OR_SPEC_TMPVAR_CONST_HANDLER, - ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_OR_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_OR_SPEC_CV_CONST_HANDLER, - ZEND_BW_OR_SPEC_CV_TMPVAR_HANDLER, - ZEND_BW_OR_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_OR_SPEC_CV_CV_HANDLER, - ZEND_BW_AND_SPEC_CONST_CONST_HANDLER, - ZEND_BW_AND_SPEC_CONST_TMPVAR_HANDLER, - ZEND_BW_AND_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_AND_SPEC_CONST_CV_HANDLER, - ZEND_BW_AND_SPEC_TMPVAR_CONST_HANDLER, - ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_AND_SPEC_TMPVAR_CV_HANDLER, - ZEND_BW_AND_SPEC_TMPVAR_CONST_HANDLER, - ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_AND_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_AND_SPEC_CV_CONST_HANDLER, - ZEND_BW_AND_SPEC_CV_TMPVAR_HANDLER, - ZEND_BW_AND_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_AND_SPEC_CV_CV_HANDLER, - ZEND_BW_XOR_SPEC_CONST_CONST_HANDLER, - ZEND_BW_XOR_SPEC_CONST_TMPVAR_HANDLER, - ZEND_BW_XOR_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_XOR_SPEC_CONST_CV_HANDLER, - ZEND_BW_XOR_SPEC_TMPVAR_CONST_HANDLER, - ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_XOR_SPEC_TMPVAR_CV_HANDLER, - ZEND_BW_XOR_SPEC_TMPVAR_CONST_HANDLER, - ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_XOR_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_XOR_SPEC_CV_CONST_HANDLER, - ZEND_BW_XOR_SPEC_CV_TMPVAR_HANDLER, - ZEND_BW_XOR_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_XOR_SPEC_CV_CV_HANDLER, - ZEND_BW_NOT_SPEC_CONST_HANDLER, - ZEND_BW_NOT_SPEC_CONST_HANDLER, - ZEND_BW_NOT_SPEC_CONST_HANDLER, - ZEND_BW_NOT_SPEC_CONST_HANDLER, - ZEND_BW_NOT_SPEC_CONST_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BW_NOT_SPEC_CV_HANDLER, - ZEND_BW_NOT_SPEC_CV_HANDLER, - ZEND_BW_NOT_SPEC_CV_HANDLER, - ZEND_BW_NOT_SPEC_CV_HANDLER, - ZEND_BW_NOT_SPEC_CV_HANDLER, - ZEND_BOOL_NOT_SPEC_CONST_HANDLER, - ZEND_BOOL_NOT_SPEC_CONST_HANDLER, - ZEND_BOOL_NOT_SPEC_CONST_HANDLER, - ZEND_BOOL_NOT_SPEC_CONST_HANDLER, - ZEND_BOOL_NOT_SPEC_CONST_HANDLER, - ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BOOL_NOT_SPEC_CV_HANDLER, - ZEND_BOOL_NOT_SPEC_CV_HANDLER, - ZEND_BOOL_NOT_SPEC_CV_HANDLER, - ZEND_BOOL_NOT_SPEC_CV_HANDLER, - ZEND_BOOL_NOT_SPEC_CV_HANDLER, - ZEND_BOOL_XOR_SPEC_CONST_CONST_HANDLER, - ZEND_BOOL_XOR_SPEC_CONST_TMPVAR_HANDLER, - ZEND_BOOL_XOR_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BOOL_XOR_SPEC_CONST_CV_HANDLER, - ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER, - ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BOOL_XOR_SPEC_TMPVAR_CV_HANDLER, - ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER, - ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BOOL_XOR_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER, - ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLER, - ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER, - ZEND_IS_IDENTICAL_SPEC_CONST_CONST_HANDLER, - ZEND_IS_IDENTICAL_SPEC_CONST_TMP_HANDLER, - ZEND_IS_IDENTICAL_SPEC_CONST_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_IDENTICAL_SPEC_CONST_CV_HANDLER, - ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER, - ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER, - ZEND_IS_IDENTICAL_SPEC_TMP_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER, - ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER, - ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER, - ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER, - ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER, - ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_CONST_TMP_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_CONST_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CV_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_TMP_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CV_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER, - ZEND_IS_EQUAL_SPEC_CONST_CONST_HANDLER, - ZEND_IS_EQUAL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_IS_EQUAL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER, - ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_EQUAL_SPEC_TMPVAR_CV_HANDLER, - ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_EQUAL_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER, - ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER, - ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CV_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER, - ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER, - ZEND_IS_SMALLER_SPEC_CONST_TMPVAR_HANDLER, - ZEND_IS_SMALLER_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_SMALLER_SPEC_CONST_CV_HANDLER, - ZEND_IS_SMALLER_SPEC_TMPVAR_CONST_HANDLER, - ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_SMALLER_SPEC_TMPVAR_CV_HANDLER, - ZEND_IS_SMALLER_SPEC_TMPVAR_CONST_HANDLER, - ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_SMALLER_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_SMALLER_SPEC_CV_CONST_HANDLER, - ZEND_IS_SMALLER_SPEC_CV_TMPVAR_HANDLER, - ZEND_IS_SMALLER_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_SMALLER_SPEC_CV_CV_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CV_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CV_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CONST_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMPVAR_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CV_HANDLER, - ZEND_CAST_SPEC_CONST_HANDLER, - ZEND_CAST_SPEC_CONST_HANDLER, - ZEND_CAST_SPEC_CONST_HANDLER, - ZEND_CAST_SPEC_CONST_HANDLER, - ZEND_CAST_SPEC_CONST_HANDLER, - ZEND_CAST_SPEC_TMP_HANDLER, - ZEND_CAST_SPEC_TMP_HANDLER, - ZEND_CAST_SPEC_TMP_HANDLER, - ZEND_CAST_SPEC_TMP_HANDLER, - ZEND_CAST_SPEC_TMP_HANDLER, - ZEND_CAST_SPEC_VAR_HANDLER, - ZEND_CAST_SPEC_VAR_HANDLER, - ZEND_CAST_SPEC_VAR_HANDLER, - ZEND_CAST_SPEC_VAR_HANDLER, - ZEND_CAST_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CAST_SPEC_CV_HANDLER, - ZEND_CAST_SPEC_CV_HANDLER, - ZEND_CAST_SPEC_CV_HANDLER, - ZEND_CAST_SPEC_CV_HANDLER, - ZEND_CAST_SPEC_CV_HANDLER, - ZEND_QM_ASSIGN_SPEC_CONST_HANDLER, - ZEND_QM_ASSIGN_SPEC_CONST_HANDLER, - ZEND_QM_ASSIGN_SPEC_CONST_HANDLER, - ZEND_QM_ASSIGN_SPEC_CONST_HANDLER, - ZEND_QM_ASSIGN_SPEC_CONST_HANDLER, - ZEND_QM_ASSIGN_SPEC_TMP_HANDLER, - ZEND_QM_ASSIGN_SPEC_TMP_HANDLER, - ZEND_QM_ASSIGN_SPEC_TMP_HANDLER, - ZEND_QM_ASSIGN_SPEC_TMP_HANDLER, - ZEND_QM_ASSIGN_SPEC_TMP_HANDLER, - ZEND_QM_ASSIGN_SPEC_VAR_HANDLER, - ZEND_QM_ASSIGN_SPEC_VAR_HANDLER, - ZEND_QM_ASSIGN_SPEC_VAR_HANDLER, - ZEND_QM_ASSIGN_SPEC_VAR_HANDLER, - ZEND_QM_ASSIGN_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_QM_ASSIGN_SPEC_CV_HANDLER, - ZEND_QM_ASSIGN_SPEC_CV_HANDLER, - ZEND_QM_ASSIGN_SPEC_CV_HANDLER, - ZEND_QM_ASSIGN_SPEC_CV_HANDLER, - ZEND_QM_ASSIGN_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_ADD_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_ADD_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_ADD_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_ADD_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_ADD_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_ADD_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_ADD_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_ADD_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_ADD_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_ADD_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_ADD_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_ADD_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_ADD_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_ADD_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_ADD_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_SUB_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_SUB_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_SUB_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_SUB_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_SUB_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_SUB_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_SUB_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_SUB_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_SUB_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_SUB_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_SUB_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_SUB_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_SUB_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_SUB_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_SUB_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_MUL_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_MUL_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_MUL_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_MUL_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_MUL_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_MUL_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_MUL_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_MUL_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_MUL_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_MUL_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_MUL_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_MUL_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_MUL_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_MUL_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_MUL_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_DIV_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_DIV_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_DIV_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_DIV_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_DIV_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_DIV_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_DIV_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_DIV_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_DIV_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_DIV_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_DIV_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_DIV_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_DIV_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_DIV_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_DIV_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_MOD_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_MOD_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_MOD_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_MOD_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_MOD_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_MOD_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_MOD_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_MOD_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_MOD_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_MOD_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_MOD_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_MOD_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_MOD_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_MOD_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_MOD_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_SL_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_SL_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_SL_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_SL_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_SL_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_SL_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_SL_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_SL_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_SL_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_SL_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_SL_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_SL_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_SL_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_SL_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_SL_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_SR_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_SR_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_SR_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_SR_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_SR_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_SR_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_SR_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_SR_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_SR_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_SR_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_SR_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_SR_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_SR_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_SR_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_SR_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_CONCAT_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_BW_OR_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_BW_AND_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_BW_XOR_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_INC_SPEC_VAR_HANDLER, - ZEND_PRE_INC_SPEC_VAR_HANDLER, - ZEND_PRE_INC_SPEC_VAR_HANDLER, - ZEND_PRE_INC_SPEC_VAR_HANDLER, - ZEND_PRE_INC_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_INC_SPEC_CV_HANDLER, - ZEND_PRE_INC_SPEC_CV_HANDLER, - ZEND_PRE_INC_SPEC_CV_HANDLER, - ZEND_PRE_INC_SPEC_CV_HANDLER, - ZEND_PRE_INC_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_DEC_SPEC_VAR_HANDLER, - ZEND_PRE_DEC_SPEC_VAR_HANDLER, - ZEND_PRE_DEC_SPEC_VAR_HANDLER, - ZEND_PRE_DEC_SPEC_VAR_HANDLER, - ZEND_PRE_DEC_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_DEC_SPEC_CV_HANDLER, - ZEND_PRE_DEC_SPEC_CV_HANDLER, - ZEND_PRE_DEC_SPEC_CV_HANDLER, - ZEND_PRE_DEC_SPEC_CV_HANDLER, - ZEND_PRE_DEC_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_INC_SPEC_VAR_HANDLER, - ZEND_POST_INC_SPEC_VAR_HANDLER, - ZEND_POST_INC_SPEC_VAR_HANDLER, - ZEND_POST_INC_SPEC_VAR_HANDLER, - ZEND_POST_INC_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_INC_SPEC_CV_HANDLER, - ZEND_POST_INC_SPEC_CV_HANDLER, - ZEND_POST_INC_SPEC_CV_HANDLER, - ZEND_POST_INC_SPEC_CV_HANDLER, - ZEND_POST_INC_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_DEC_SPEC_VAR_HANDLER, - ZEND_POST_DEC_SPEC_VAR_HANDLER, - ZEND_POST_DEC_SPEC_VAR_HANDLER, - ZEND_POST_DEC_SPEC_VAR_HANDLER, - ZEND_POST_DEC_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_DEC_SPEC_CV_HANDLER, - ZEND_POST_DEC_SPEC_CV_HANDLER, - ZEND_POST_DEC_SPEC_CV_HANDLER, - ZEND_POST_DEC_SPEC_CV_HANDLER, - ZEND_POST_DEC_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_SPEC_VAR_TMP_HANDLER, - ZEND_ASSIGN_SPEC_VAR_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_SPEC_VAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_SPEC_CV_TMP_HANDLER, - ZEND_ASSIGN_SPEC_CV_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER, - ZEND_ECHO_SPEC_CONST_HANDLER, - ZEND_ECHO_SPEC_CONST_HANDLER, - ZEND_ECHO_SPEC_CONST_HANDLER, - ZEND_ECHO_SPEC_CONST_HANDLER, - ZEND_ECHO_SPEC_CONST_HANDLER, - ZEND_ECHO_SPEC_TMPVAR_HANDLER, - ZEND_ECHO_SPEC_TMPVAR_HANDLER, - ZEND_ECHO_SPEC_TMPVAR_HANDLER, - ZEND_ECHO_SPEC_TMPVAR_HANDLER, - ZEND_ECHO_SPEC_TMPVAR_HANDLER, - ZEND_ECHO_SPEC_TMPVAR_HANDLER, - ZEND_ECHO_SPEC_TMPVAR_HANDLER, - ZEND_ECHO_SPEC_TMPVAR_HANDLER, - ZEND_ECHO_SPEC_TMPVAR_HANDLER, - ZEND_ECHO_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ECHO_SPEC_CV_HANDLER, - ZEND_ECHO_SPEC_CV_HANDLER, - ZEND_ECHO_SPEC_CV_HANDLER, - ZEND_ECHO_SPEC_CV_HANDLER, - ZEND_ECHO_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMP_SPEC_HANDLER, - ZEND_JMPZ_SPEC_CONST_HANDLER, - ZEND_JMPZ_SPEC_CONST_HANDLER, - ZEND_JMPZ_SPEC_CONST_HANDLER, - ZEND_JMPZ_SPEC_CONST_HANDLER, - ZEND_JMPZ_SPEC_CONST_HANDLER, - ZEND_JMPZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_JMPZ_SPEC_CV_HANDLER, - ZEND_JMPZ_SPEC_CV_HANDLER, - ZEND_JMPZ_SPEC_CV_HANDLER, - ZEND_JMPZ_SPEC_CV_HANDLER, - ZEND_JMPZ_SPEC_CV_HANDLER, - ZEND_JMPNZ_SPEC_CONST_HANDLER, - ZEND_JMPNZ_SPEC_CONST_HANDLER, - ZEND_JMPNZ_SPEC_CONST_HANDLER, - ZEND_JMPNZ_SPEC_CONST_HANDLER, - ZEND_JMPNZ_SPEC_CONST_HANDLER, - ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_JMPNZ_SPEC_CV_HANDLER, - ZEND_JMPNZ_SPEC_CV_HANDLER, - ZEND_JMPNZ_SPEC_CV_HANDLER, - ZEND_JMPNZ_SPEC_CV_HANDLER, - ZEND_JMPNZ_SPEC_CV_HANDLER, - ZEND_JMPZNZ_SPEC_CONST_HANDLER, - ZEND_JMPZNZ_SPEC_CONST_HANDLER, - ZEND_JMPZNZ_SPEC_CONST_HANDLER, - ZEND_JMPZNZ_SPEC_CONST_HANDLER, - ZEND_JMPZNZ_SPEC_CONST_HANDLER, - ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, - ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_JMPZNZ_SPEC_CV_HANDLER, - ZEND_JMPZNZ_SPEC_CV_HANDLER, - ZEND_JMPZNZ_SPEC_CV_HANDLER, - ZEND_JMPZNZ_SPEC_CV_HANDLER, - ZEND_JMPZNZ_SPEC_CV_HANDLER, - ZEND_JMPZ_EX_SPEC_CONST_HANDLER, - ZEND_JMPZ_EX_SPEC_CONST_HANDLER, - ZEND_JMPZ_EX_SPEC_CONST_HANDLER, - ZEND_JMPZ_EX_SPEC_CONST_HANDLER, - ZEND_JMPZ_EX_SPEC_CONST_HANDLER, - ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_JMPZ_EX_SPEC_CV_HANDLER, - ZEND_JMPZ_EX_SPEC_CV_HANDLER, - ZEND_JMPZ_EX_SPEC_CV_HANDLER, - ZEND_JMPZ_EX_SPEC_CV_HANDLER, - ZEND_JMPZ_EX_SPEC_CV_HANDLER, - ZEND_JMPNZ_EX_SPEC_CONST_HANDLER, - ZEND_JMPNZ_EX_SPEC_CONST_HANDLER, - ZEND_JMPNZ_EX_SPEC_CONST_HANDLER, - ZEND_JMPNZ_EX_SPEC_CONST_HANDLER, - ZEND_JMPNZ_EX_SPEC_CONST_HANDLER, - ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_JMPNZ_EX_SPEC_CV_HANDLER, - ZEND_JMPNZ_EX_SPEC_CV_HANDLER, - ZEND_JMPNZ_EX_SPEC_CV_HANDLER, - ZEND_JMPNZ_EX_SPEC_CV_HANDLER, - ZEND_JMPNZ_EX_SPEC_CV_HANDLER, - ZEND_CASE_SPEC_CONST_CONST_HANDLER, - ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER, - ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CASE_SPEC_CONST_CV_HANDLER, - ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER, - ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CASE_SPEC_TMPVAR_CV_HANDLER, - ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER, - ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CASE_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CASE_SPEC_CV_CONST_HANDLER, - ZEND_CASE_SPEC_CV_TMPVAR_HANDLER, - ZEND_CASE_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CASE_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BOOL_SPEC_CONST_HANDLER, - ZEND_BOOL_SPEC_CONST_HANDLER, - ZEND_BOOL_SPEC_CONST_HANDLER, - ZEND_BOOL_SPEC_CONST_HANDLER, - ZEND_BOOL_SPEC_CONST_HANDLER, - ZEND_BOOL_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_SPEC_TMPVAR_HANDLER, - ZEND_BOOL_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BOOL_SPEC_CV_HANDLER, - ZEND_BOOL_SPEC_CV_HANDLER, - ZEND_BOOL_SPEC_CV_HANDLER, - ZEND_BOOL_SPEC_CV_HANDLER, - ZEND_BOOL_SPEC_CV_HANDLER, - ZEND_FAST_CONCAT_SPEC_CONST_CONST_HANDLER, - ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_HANDLER, - ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FAST_CONCAT_SPEC_CONST_CV_HANDLER, - ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER, - ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FAST_CONCAT_SPEC_CV_CONST_HANDLER, - ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HANDLER, - ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ROPE_INIT_SPEC_UNUSED_CONST_HANDLER, - ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ROPE_INIT_SPEC_UNUSED_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER, - ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER, - ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ROPE_END_SPEC_TMP_CONST_HANDLER, - ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER, - ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ROPE_END_SPEC_TMP_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_BEGIN_SILENCE_SPEC_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_END_SILENCE_SPEC_TMP_HANDLER, - ZEND_END_SILENCE_SPEC_TMP_HANDLER, - ZEND_END_SILENCE_SPEC_TMP_HANDLER, - ZEND_END_SILENCE_SPEC_TMP_HANDLER, - ZEND_END_SILENCE_SPEC_TMP_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_DO_FCALL_SPEC_HANDLER, - ZEND_INIT_FCALL_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_FCALL_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_FCALL_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_FCALL_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_FCALL_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_RETURN_SPEC_CONST_HANDLER, - ZEND_RETURN_SPEC_CONST_HANDLER, - ZEND_RETURN_SPEC_CONST_HANDLER, - ZEND_RETURN_SPEC_CONST_HANDLER, - ZEND_RETURN_SPEC_CONST_HANDLER, - ZEND_RETURN_SPEC_TMP_HANDLER, - ZEND_RETURN_SPEC_TMP_HANDLER, - ZEND_RETURN_SPEC_TMP_HANDLER, - ZEND_RETURN_SPEC_TMP_HANDLER, - ZEND_RETURN_SPEC_TMP_HANDLER, - ZEND_RETURN_SPEC_VAR_HANDLER, - ZEND_RETURN_SPEC_VAR_HANDLER, - ZEND_RETURN_SPEC_VAR_HANDLER, - ZEND_RETURN_SPEC_VAR_HANDLER, - ZEND_RETURN_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_RETURN_SPEC_CV_HANDLER, - ZEND_RETURN_SPEC_CV_HANDLER, - ZEND_RETURN_SPEC_CV_HANDLER, - ZEND_RETURN_SPEC_CV_HANDLER, - ZEND_RETURN_SPEC_CV_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_SPEC_HANDLER, - ZEND_RECV_INIT_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_RECV_INIT_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_RECV_INIT_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_RECV_INIT_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_RECV_INIT_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEND_VAL_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_SPEC_TMP_HANDLER, - ZEND_SEND_VAL_SPEC_TMP_HANDLER, - ZEND_SEND_VAL_SPEC_TMP_HANDLER, - ZEND_SEND_VAL_SPEC_TMP_HANDLER, - ZEND_SEND_VAL_SPEC_TMP_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEND_VAR_EX_SPEC_CV_HANDLER, - ZEND_SEND_VAR_EX_SPEC_CV_HANDLER, - ZEND_SEND_VAR_EX_SPEC_CV_HANDLER, - ZEND_SEND_VAR_EX_SPEC_CV_HANDLER, - ZEND_SEND_VAR_EX_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEND_REF_SPEC_VAR_HANDLER, - ZEND_SEND_REF_SPEC_VAR_HANDLER, - ZEND_SEND_REF_SPEC_VAR_HANDLER, - ZEND_SEND_REF_SPEC_VAR_HANDLER, - ZEND_SEND_REF_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEND_REF_SPEC_CV_HANDLER, - ZEND_SEND_REF_SPEC_CV_HANDLER, - ZEND_SEND_REF_SPEC_CV_HANDLER, - ZEND_SEND_REF_SPEC_CV_HANDLER, - ZEND_SEND_REF_SPEC_CV_HANDLER, - ZEND_NEW_SPEC_CONST_HANDLER, - ZEND_NEW_SPEC_CONST_HANDLER, - ZEND_NEW_SPEC_CONST_HANDLER, - ZEND_NEW_SPEC_CONST_HANDLER, - ZEND_NEW_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NEW_SPEC_VAR_HANDLER, - ZEND_NEW_SPEC_VAR_HANDLER, - ZEND_NEW_SPEC_VAR_HANDLER, - ZEND_NEW_SPEC_VAR_HANDLER, - ZEND_NEW_SPEC_VAR_HANDLER, - ZEND_NEW_SPEC_UNUSED_HANDLER, - ZEND_NEW_SPEC_UNUSED_HANDLER, - ZEND_NEW_SPEC_UNUSED_HANDLER, - ZEND_NEW_SPEC_UNUSED_HANDLER, - ZEND_NEW_SPEC_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FREE_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER, - ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER, - ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER, - ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER, - ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER, - ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER, - ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER, - ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER, - ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER, - ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER, - ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER, - ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER, - ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER, - ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER, - ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER, - ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER, - ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER, - ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER, - ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER, - ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER, - ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER, - ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER, - ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER, - ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER, - ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER, - ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER, - ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER, - ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER, - ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER, - ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER, - ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER, - ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER, - ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER, - ZEND_FE_RESET_R_SPEC_CONST_HANDLER, - ZEND_FE_RESET_R_SPEC_CONST_HANDLER, - ZEND_FE_RESET_R_SPEC_CONST_HANDLER, - ZEND_FE_RESET_R_SPEC_CONST_HANDLER, - ZEND_FE_RESET_R_SPEC_CONST_HANDLER, - ZEND_FE_RESET_R_SPEC_TMP_HANDLER, - ZEND_FE_RESET_R_SPEC_TMP_HANDLER, - ZEND_FE_RESET_R_SPEC_TMP_HANDLER, - ZEND_FE_RESET_R_SPEC_TMP_HANDLER, - ZEND_FE_RESET_R_SPEC_TMP_HANDLER, - ZEND_FE_RESET_R_SPEC_VAR_HANDLER, - ZEND_FE_RESET_R_SPEC_VAR_HANDLER, - ZEND_FE_RESET_R_SPEC_VAR_HANDLER, - ZEND_FE_RESET_R_SPEC_VAR_HANDLER, - ZEND_FE_RESET_R_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FE_RESET_R_SPEC_CV_HANDLER, - ZEND_FE_RESET_R_SPEC_CV_HANDLER, - ZEND_FE_RESET_R_SPEC_CV_HANDLER, - ZEND_FE_RESET_R_SPEC_CV_HANDLER, - ZEND_FE_RESET_R_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_EXIT_SPEC_CONST_HANDLER, - ZEND_EXIT_SPEC_CONST_HANDLER, - ZEND_EXIT_SPEC_CONST_HANDLER, - ZEND_EXIT_SPEC_CONST_HANDLER, - ZEND_EXIT_SPEC_CONST_HANDLER, - ZEND_EXIT_SPEC_TMPVAR_HANDLER, - ZEND_EXIT_SPEC_TMPVAR_HANDLER, - ZEND_EXIT_SPEC_TMPVAR_HANDLER, - ZEND_EXIT_SPEC_TMPVAR_HANDLER, - ZEND_EXIT_SPEC_TMPVAR_HANDLER, - ZEND_EXIT_SPEC_TMPVAR_HANDLER, - ZEND_EXIT_SPEC_TMPVAR_HANDLER, - ZEND_EXIT_SPEC_TMPVAR_HANDLER, - ZEND_EXIT_SPEC_TMPVAR_HANDLER, - ZEND_EXIT_SPEC_TMPVAR_HANDLER, - ZEND_EXIT_SPEC_UNUSED_HANDLER, - ZEND_EXIT_SPEC_UNUSED_HANDLER, - ZEND_EXIT_SPEC_UNUSED_HANDLER, - ZEND_EXIT_SPEC_UNUSED_HANDLER, - ZEND_EXIT_SPEC_UNUSED_HANDLER, - ZEND_EXIT_SPEC_CV_HANDLER, - ZEND_EXIT_SPEC_CV_HANDLER, - ZEND_EXIT_SPEC_CV_HANDLER, - ZEND_EXIT_SPEC_CV_HANDLER, - ZEND_EXIT_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER, - ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER, - ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER, - ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER, - ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER, - ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER, - ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER, - ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER, - ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER, - ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER, - ZEND_FETCH_LIST_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_LIST_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_LIST_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_LIST_SPEC_CV_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_STMT_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_FCALL_END_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_EXT_NOP_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_TICKS_SPEC_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_CATCH_SPEC_CONST_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_THROW_SPEC_CONST_HANDLER, - ZEND_THROW_SPEC_CONST_HANDLER, - ZEND_THROW_SPEC_CONST_HANDLER, - ZEND_THROW_SPEC_CONST_HANDLER, - ZEND_THROW_SPEC_CONST_HANDLER, - ZEND_THROW_SPEC_TMP_HANDLER, - ZEND_THROW_SPEC_TMP_HANDLER, - ZEND_THROW_SPEC_TMP_HANDLER, - ZEND_THROW_SPEC_TMP_HANDLER, - ZEND_THROW_SPEC_TMP_HANDLER, - ZEND_THROW_SPEC_VAR_HANDLER, - ZEND_THROW_SPEC_VAR_HANDLER, - ZEND_THROW_SPEC_VAR_HANDLER, - ZEND_THROW_SPEC_VAR_HANDLER, - ZEND_THROW_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_THROW_SPEC_CV_HANDLER, - ZEND_THROW_SPEC_CV_HANDLER, - ZEND_THROW_SPEC_CV_HANDLER, - ZEND_THROW_SPEC_CV_HANDLER, - ZEND_THROW_SPEC_CV_HANDLER, - ZEND_FETCH_CLASS_SPEC_CONST_HANDLER, - ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, - ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, - ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER, - ZEND_FETCH_CLASS_SPEC_CV_HANDLER, - ZEND_FETCH_CLASS_SPEC_CONST_HANDLER, - ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, - ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, - ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER, - ZEND_FETCH_CLASS_SPEC_CV_HANDLER, - ZEND_FETCH_CLASS_SPEC_CONST_HANDLER, - ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, - ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, - ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER, - ZEND_FETCH_CLASS_SPEC_CV_HANDLER, - ZEND_FETCH_CLASS_SPEC_CONST_HANDLER, - ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, - ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, - ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER, - ZEND_FETCH_CLASS_SPEC_CV_HANDLER, - ZEND_FETCH_CLASS_SPEC_CONST_HANDLER, - ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, - ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, - ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER, - ZEND_FETCH_CLASS_SPEC_CV_HANDLER, - ZEND_CLONE_SPEC_CONST_HANDLER, - ZEND_CLONE_SPEC_CONST_HANDLER, - ZEND_CLONE_SPEC_CONST_HANDLER, - ZEND_CLONE_SPEC_CONST_HANDLER, - ZEND_CLONE_SPEC_CONST_HANDLER, - ZEND_CLONE_SPEC_TMPVAR_HANDLER, - ZEND_CLONE_SPEC_TMPVAR_HANDLER, - ZEND_CLONE_SPEC_TMPVAR_HANDLER, - ZEND_CLONE_SPEC_TMPVAR_HANDLER, - ZEND_CLONE_SPEC_TMPVAR_HANDLER, - ZEND_CLONE_SPEC_TMPVAR_HANDLER, - ZEND_CLONE_SPEC_TMPVAR_HANDLER, - ZEND_CLONE_SPEC_TMPVAR_HANDLER, - ZEND_CLONE_SPEC_TMPVAR_HANDLER, - ZEND_CLONE_SPEC_TMPVAR_HANDLER, - ZEND_CLONE_SPEC_UNUSED_HANDLER, - ZEND_CLONE_SPEC_UNUSED_HANDLER, - ZEND_CLONE_SPEC_UNUSED_HANDLER, - ZEND_CLONE_SPEC_UNUSED_HANDLER, - ZEND_CLONE_SPEC_UNUSED_HANDLER, - ZEND_CLONE_SPEC_CV_HANDLER, - ZEND_CLONE_SPEC_CV_HANDLER, - ZEND_CLONE_SPEC_CV_HANDLER, - ZEND_CLONE_SPEC_CV_HANDLER, - ZEND_CLONE_SPEC_CV_HANDLER, - ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER, - ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER, - ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER, - ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER, - ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER, - ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER, - ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER, - ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER, - ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER, - ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER, - ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER, - ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER, - ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER, - ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER, - ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_RETURN_BY_REF_SPEC_CV_HANDLER, - ZEND_RETURN_BY_REF_SPEC_CV_HANDLER, - ZEND_RETURN_BY_REF_SPEC_CV_HANDLER, - ZEND_RETURN_BY_REF_SPEC_CV_HANDLER, - ZEND_RETURN_BY_REF_SPEC_CV_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_CONST_CONST_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_CONST_CV_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CV_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER, - ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER, - ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER, - ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER, - ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER, - ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER, - ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEND_VAR_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_SPEC_VAR_HANDLER, - ZEND_SEND_VAR_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEND_VAR_SPEC_CV_HANDLER, - ZEND_SEND_VAR_SPEC_CV_HANDLER, - ZEND_SEND_VAR_SPEC_CV_HANDLER, - ZEND_SEND_VAR_SPEC_CV_HANDLER, - ZEND_SEND_VAR_SPEC_CV_HANDLER, - ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER, - ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_SEND_ARRAY_SPEC_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEND_USER_SPEC_VAR_HANDLER, - ZEND_SEND_USER_SPEC_VAR_HANDLER, - ZEND_SEND_USER_SPEC_VAR_HANDLER, - ZEND_SEND_USER_SPEC_VAR_HANDLER, - ZEND_SEND_USER_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEND_USER_SPEC_CV_HANDLER, - ZEND_SEND_USER_SPEC_CV_HANDLER, - ZEND_SEND_USER_SPEC_CV_HANDLER, - ZEND_SEND_USER_SPEC_CV_HANDLER, - ZEND_SEND_USER_SPEC_CV_HANDLER, - ZEND_STRLEN_SPEC_CONST_HANDLER, - ZEND_STRLEN_SPEC_CONST_HANDLER, - ZEND_STRLEN_SPEC_CONST_HANDLER, - ZEND_STRLEN_SPEC_CONST_HANDLER, - ZEND_STRLEN_SPEC_CONST_HANDLER, - ZEND_STRLEN_SPEC_TMPVAR_HANDLER, - ZEND_STRLEN_SPEC_TMPVAR_HANDLER, - ZEND_STRLEN_SPEC_TMPVAR_HANDLER, - ZEND_STRLEN_SPEC_TMPVAR_HANDLER, - ZEND_STRLEN_SPEC_TMPVAR_HANDLER, - ZEND_STRLEN_SPEC_TMPVAR_HANDLER, - ZEND_STRLEN_SPEC_TMPVAR_HANDLER, - ZEND_STRLEN_SPEC_TMPVAR_HANDLER, - ZEND_STRLEN_SPEC_TMPVAR_HANDLER, - ZEND_STRLEN_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_STRLEN_SPEC_CV_HANDLER, - ZEND_STRLEN_SPEC_CV_HANDLER, - ZEND_STRLEN_SPEC_CV_HANDLER, - ZEND_STRLEN_SPEC_CV_HANDLER, - ZEND_STRLEN_SPEC_CV_HANDLER, - ZEND_DEFINED_SPEC_CONST_HANDLER, - ZEND_DEFINED_SPEC_CONST_HANDLER, - ZEND_DEFINED_SPEC_CONST_HANDLER, - ZEND_DEFINED_SPEC_CONST_HANDLER, - ZEND_DEFINED_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_TYPE_CHECK_SPEC_CONST_HANDLER, - ZEND_TYPE_CHECK_SPEC_CONST_HANDLER, - ZEND_TYPE_CHECK_SPEC_CONST_HANDLER, - ZEND_TYPE_CHECK_SPEC_CONST_HANDLER, - ZEND_TYPE_CHECK_SPEC_CONST_HANDLER, - ZEND_TYPE_CHECK_SPEC_TMP_HANDLER, - ZEND_TYPE_CHECK_SPEC_TMP_HANDLER, - ZEND_TYPE_CHECK_SPEC_TMP_HANDLER, - ZEND_TYPE_CHECK_SPEC_TMP_HANDLER, - ZEND_TYPE_CHECK_SPEC_TMP_HANDLER, - ZEND_TYPE_CHECK_SPEC_VAR_HANDLER, - ZEND_TYPE_CHECK_SPEC_VAR_HANDLER, - ZEND_TYPE_CHECK_SPEC_VAR_HANDLER, - ZEND_TYPE_CHECK_SPEC_VAR_HANDLER, - ZEND_TYPE_CHECK_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_TYPE_CHECK_SPEC_CV_HANDLER, - ZEND_TYPE_CHECK_SPEC_CV_HANDLER, - ZEND_TYPE_CHECK_SPEC_CV_HANDLER, - ZEND_TYPE_CHECK_SPEC_CV_HANDLER, - ZEND_TYPE_CHECK_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FE_RESET_RW_SPEC_CONST_HANDLER, - ZEND_FE_RESET_RW_SPEC_CONST_HANDLER, - ZEND_FE_RESET_RW_SPEC_CONST_HANDLER, - ZEND_FE_RESET_RW_SPEC_CONST_HANDLER, - ZEND_FE_RESET_RW_SPEC_CONST_HANDLER, - ZEND_FE_RESET_RW_SPEC_TMP_HANDLER, - ZEND_FE_RESET_RW_SPEC_TMP_HANDLER, - ZEND_FE_RESET_RW_SPEC_TMP_HANDLER, - ZEND_FE_RESET_RW_SPEC_TMP_HANDLER, - ZEND_FE_RESET_RW_SPEC_TMP_HANDLER, - ZEND_FE_RESET_RW_SPEC_VAR_HANDLER, - ZEND_FE_RESET_RW_SPEC_VAR_HANDLER, - ZEND_FE_RESET_RW_SPEC_VAR_HANDLER, - ZEND_FE_RESET_RW_SPEC_VAR_HANDLER, - ZEND_FE_RESET_RW_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FE_RESET_RW_SPEC_CV_HANDLER, - ZEND_FE_RESET_RW_SPEC_CV_HANDLER, - ZEND_FE_RESET_RW_SPEC_CV_HANDLER, - ZEND_FE_RESET_RW_SPEC_CV_HANDLER, - ZEND_FE_RESET_RW_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER, - ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, - ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_ICALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_UCALL_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_DO_FCALL_BY_NAME_SPEC_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_VAR_CV_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CV_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_PRE_DEC_OBJ_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER, - ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HANDLER, - ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_VAR_CV_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_UNUSED_CV_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POST_DEC_OBJ_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER, - ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER, - ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER, - ZEND_INSTANCEOF_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_DECLARE_CLASS_SPEC_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_DECLARE_FUNCTION_SPEC_HANDLER, - ZEND_YIELD_FROM_SPEC_CONST_HANDLER, - ZEND_YIELD_FROM_SPEC_CONST_HANDLER, - ZEND_YIELD_FROM_SPEC_CONST_HANDLER, - ZEND_YIELD_FROM_SPEC_CONST_HANDLER, - ZEND_YIELD_FROM_SPEC_CONST_HANDLER, - ZEND_YIELD_FROM_SPEC_TMP_HANDLER, - ZEND_YIELD_FROM_SPEC_TMP_HANDLER, - ZEND_YIELD_FROM_SPEC_TMP_HANDLER, - ZEND_YIELD_FROM_SPEC_TMP_HANDLER, - ZEND_YIELD_FROM_SPEC_TMP_HANDLER, - ZEND_YIELD_FROM_SPEC_VAR_HANDLER, - ZEND_YIELD_FROM_SPEC_VAR_HANDLER, - ZEND_YIELD_FROM_SPEC_VAR_HANDLER, - ZEND_YIELD_FROM_SPEC_VAR_HANDLER, - ZEND_YIELD_FROM_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_YIELD_FROM_SPEC_CV_HANDLER, - ZEND_YIELD_FROM_SPEC_CV_HANDLER, - ZEND_YIELD_FROM_SPEC_CV_HANDLER, - ZEND_YIELD_FROM_SPEC_CV_HANDLER, - ZEND_YIELD_FROM_SPEC_CV_HANDLER, - ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_USER_OPCODE_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_ASSERT_CHECK_SPEC_HANDLER, - ZEND_JMP_SET_SPEC_CONST_HANDLER, - ZEND_JMP_SET_SPEC_CONST_HANDLER, - ZEND_JMP_SET_SPEC_CONST_HANDLER, - ZEND_JMP_SET_SPEC_CONST_HANDLER, - ZEND_JMP_SET_SPEC_CONST_HANDLER, - ZEND_JMP_SET_SPEC_TMP_HANDLER, - ZEND_JMP_SET_SPEC_TMP_HANDLER, - ZEND_JMP_SET_SPEC_TMP_HANDLER, - ZEND_JMP_SET_SPEC_TMP_HANDLER, - ZEND_JMP_SET_SPEC_TMP_HANDLER, - ZEND_JMP_SET_SPEC_VAR_HANDLER, - ZEND_JMP_SET_SPEC_VAR_HANDLER, - ZEND_JMP_SET_SPEC_VAR_HANDLER, - ZEND_JMP_SET_SPEC_VAR_HANDLER, - ZEND_JMP_SET_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_JMP_SET_SPEC_CV_HANDLER, - ZEND_JMP_SET_SPEC_CV_HANDLER, - ZEND_JMP_SET_SPEC_CV_HANDLER, - ZEND_JMP_SET_SPEC_CV_HANDLER, - ZEND_JMP_SET_SPEC_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_ADD_TRAIT_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_BIND_TRAITS_SPEC_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, - ZEND_YIELD_SPEC_CONST_CONST_HANDLER, - ZEND_YIELD_SPEC_CONST_TMP_HANDLER, - ZEND_YIELD_SPEC_CONST_VAR_HANDLER, - ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER, - ZEND_YIELD_SPEC_CONST_CV_HANDLER, - ZEND_YIELD_SPEC_TMP_CONST_HANDLER, - ZEND_YIELD_SPEC_TMP_TMP_HANDLER, - ZEND_YIELD_SPEC_TMP_VAR_HANDLER, - ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER, - ZEND_YIELD_SPEC_TMP_CV_HANDLER, - ZEND_YIELD_SPEC_VAR_CONST_HANDLER, - ZEND_YIELD_SPEC_VAR_TMP_HANDLER, - ZEND_YIELD_SPEC_VAR_VAR_HANDLER, - ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER, - ZEND_YIELD_SPEC_VAR_CV_HANDLER, - ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER, - ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER, - ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER, - ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_YIELD_SPEC_UNUSED_CV_HANDLER, - ZEND_YIELD_SPEC_CV_CONST_HANDLER, - ZEND_YIELD_SPEC_CV_TMP_HANDLER, - ZEND_YIELD_SPEC_CV_VAR_HANDLER, - ZEND_YIELD_SPEC_CV_UNUSED_HANDLER, - ZEND_YIELD_SPEC_CV_CV_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER, - ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_CALL_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_FAST_RET_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_RECV_VARIADIC_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_SEND_UNPACK_SPEC_HANDLER, - ZEND_POW_SPEC_CONST_CONST_HANDLER, - ZEND_POW_SPEC_CONST_TMPVAR_HANDLER, - ZEND_POW_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POW_SPEC_CONST_CV_HANDLER, - ZEND_POW_SPEC_TMPVAR_CONST_HANDLER, - ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POW_SPEC_TMPVAR_CV_HANDLER, - ZEND_POW_SPEC_TMPVAR_CONST_HANDLER, - ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POW_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POW_SPEC_CV_CONST_HANDLER, - ZEND_POW_SPEC_CV_TMPVAR_HANDLER, - ZEND_POW_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_POW_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ASSIGN_POW_SPEC_VAR_CONST_HANDLER, - ZEND_ASSIGN_POW_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_POW_SPEC_VAR_TMPVAR_HANDLER, - ZEND_ASSIGN_POW_SPEC_VAR_UNUSED_HANDLER, - ZEND_ASSIGN_POW_SPEC_VAR_CV_HANDLER, - ZEND_ASSIGN_POW_SPEC_UNUSED_CONST_HANDLER, - ZEND_ASSIGN_POW_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_POW_SPEC_UNUSED_TMPVAR_HANDLER, - ZEND_ASSIGN_POW_SPEC_UNUSED_UNUSED_HANDLER, - ZEND_ASSIGN_POW_SPEC_UNUSED_CV_HANDLER, - ZEND_ASSIGN_POW_SPEC_CV_CONST_HANDLER, - ZEND_ASSIGN_POW_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_POW_SPEC_CV_TMPVAR_HANDLER, - ZEND_ASSIGN_POW_SPEC_CV_UNUSED_HANDLER, - ZEND_ASSIGN_POW_SPEC_CV_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_COALESCE_SPEC_CONST_HANDLER, - ZEND_COALESCE_SPEC_CONST_HANDLER, - ZEND_COALESCE_SPEC_CONST_HANDLER, - ZEND_COALESCE_SPEC_CONST_HANDLER, - ZEND_COALESCE_SPEC_CONST_HANDLER, - ZEND_COALESCE_SPEC_TMP_HANDLER, - ZEND_COALESCE_SPEC_TMP_HANDLER, - ZEND_COALESCE_SPEC_TMP_HANDLER, - ZEND_COALESCE_SPEC_TMP_HANDLER, - ZEND_COALESCE_SPEC_TMP_HANDLER, - ZEND_COALESCE_SPEC_VAR_HANDLER, - ZEND_COALESCE_SPEC_VAR_HANDLER, - ZEND_COALESCE_SPEC_VAR_HANDLER, - ZEND_COALESCE_SPEC_VAR_HANDLER, - ZEND_COALESCE_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_COALESCE_SPEC_CV_HANDLER, - ZEND_COALESCE_SPEC_CV_HANDLER, - ZEND_COALESCE_SPEC_CV_HANDLER, - ZEND_COALESCE_SPEC_CV_HANDLER, - ZEND_COALESCE_SPEC_CV_HANDLER, - ZEND_SPACESHIP_SPEC_CONST_CONST_HANDLER, - ZEND_SPACESHIP_SPEC_CONST_TMPVAR_HANDLER, - ZEND_SPACESHIP_SPEC_CONST_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SPACESHIP_SPEC_CONST_CV_HANDLER, - ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HANDLER, - ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER, - ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HANDLER, - ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SPACESHIP_SPEC_CV_CONST_HANDLER, - ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDLER, - ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_SPACESHIP_SPEC_CV_CV_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_CV_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_CV_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_R_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_CONST_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_CV_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_CV_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_W_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_CONST_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_CV_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_CV_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_RW_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_CONST_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_CV_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_CV_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_IS_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CONST_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CV_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CV_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CONST_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CV_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CV_VAR_HANDLER, - ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_CONST_VAR_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_VAR_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_VAR_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_CV_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_CV_VAR_HANDLER, - ZEND_UNSET_STATIC_PROP_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CONST_VAR_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CONST_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_VAR_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_VAR_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CV_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CV_VAR_HANDLER, - ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CV_UNUSED_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER, - ZEND_NULL_HANDLER - }; - zend_opcode_handlers = labels; + static const void *labels[] = { + ZEND_NOP_SPEC_HANDLER, + ZEND_ADD_SPEC_CONST_CONST_HANDLER, + ZEND_ADD_SPEC_CONST_TMPVAR_HANDLER, + ZEND_ADD_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ADD_SPEC_CONST_CV_HANDLER, + ZEND_ADD_SPEC_TMPVAR_CONST_HANDLER, + ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ADD_SPEC_TMPVAR_CV_HANDLER, + ZEND_ADD_SPEC_TMPVAR_CONST_HANDLER, + ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_ADD_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ADD_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ADD_SPEC_CV_CONST_HANDLER, + ZEND_ADD_SPEC_CV_TMPVAR_HANDLER, + ZEND_ADD_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ADD_SPEC_CV_CV_HANDLER, + ZEND_SUB_SPEC_CONST_CONST_HANDLER, + ZEND_SUB_SPEC_CONST_TMPVAR_HANDLER, + ZEND_SUB_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SUB_SPEC_CONST_CV_HANDLER, + ZEND_SUB_SPEC_TMPVAR_CONST_HANDLER, + ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SUB_SPEC_TMPVAR_CV_HANDLER, + ZEND_SUB_SPEC_TMPVAR_CONST_HANDLER, + ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_SUB_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SUB_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SUB_SPEC_CV_CONST_HANDLER, + ZEND_SUB_SPEC_CV_TMPVAR_HANDLER, + ZEND_SUB_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SUB_SPEC_CV_CV_HANDLER, + ZEND_MUL_SPEC_CONST_CONST_HANDLER, + ZEND_MUL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_MUL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MUL_SPEC_CONST_CV_HANDLER, + ZEND_MUL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MUL_SPEC_TMPVAR_CV_HANDLER, + ZEND_MUL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_MUL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MUL_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MUL_SPEC_CV_CONST_HANDLER, + ZEND_MUL_SPEC_CV_TMPVAR_HANDLER, + ZEND_MUL_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MUL_SPEC_CV_CV_HANDLER, + ZEND_DIV_SPEC_CONST_CONST_HANDLER, + ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER, + ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DIV_SPEC_CONST_CV_HANDLER, + ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER, + ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DIV_SPEC_TMPVAR_CV_HANDLER, + ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER, + ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DIV_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DIV_SPEC_CV_CONST_HANDLER, + ZEND_DIV_SPEC_CV_TMPVAR_HANDLER, + ZEND_DIV_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DIV_SPEC_CV_CV_HANDLER, + ZEND_MOD_SPEC_CONST_CONST_HANDLER, + ZEND_MOD_SPEC_CONST_TMPVAR_HANDLER, + ZEND_MOD_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MOD_SPEC_CONST_CV_HANDLER, + ZEND_MOD_SPEC_TMPVAR_CONST_HANDLER, + ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MOD_SPEC_TMPVAR_CV_HANDLER, + ZEND_MOD_SPEC_TMPVAR_CONST_HANDLER, + ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_MOD_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MOD_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MOD_SPEC_CV_CONST_HANDLER, + ZEND_MOD_SPEC_CV_TMPVAR_HANDLER, + ZEND_MOD_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_MOD_SPEC_CV_CV_HANDLER, + ZEND_SL_SPEC_CONST_CONST_HANDLER, + ZEND_SL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_SL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SL_SPEC_CONST_CV_HANDLER, + ZEND_SL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SL_SPEC_TMPVAR_CV_HANDLER, + ZEND_SL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SL_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SL_SPEC_CV_CONST_HANDLER, + ZEND_SL_SPEC_CV_TMPVAR_HANDLER, + ZEND_SL_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SL_SPEC_CV_CV_HANDLER, + ZEND_SR_SPEC_CONST_CONST_HANDLER, + ZEND_SR_SPEC_CONST_TMPVAR_HANDLER, + ZEND_SR_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SR_SPEC_CONST_CV_HANDLER, + ZEND_SR_SPEC_TMPVAR_CONST_HANDLER, + ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SR_SPEC_TMPVAR_CV_HANDLER, + ZEND_SR_SPEC_TMPVAR_CONST_HANDLER, + ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SR_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SR_SPEC_CV_CONST_HANDLER, + ZEND_SR_SPEC_CV_TMPVAR_HANDLER, + ZEND_SR_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SR_SPEC_CV_CV_HANDLER, + ZEND_CONCAT_SPEC_CONST_CONST_HANDLER, + ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDLER, + ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CONCAT_SPEC_CONST_CV_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CONCAT_SPEC_CV_CONST_HANDLER, + ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER, + ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CONCAT_SPEC_CV_CV_HANDLER, + ZEND_BW_OR_SPEC_CONST_CONST_HANDLER, + ZEND_BW_OR_SPEC_CONST_TMPVAR_HANDLER, + ZEND_BW_OR_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_OR_SPEC_CONST_CV_HANDLER, + ZEND_BW_OR_SPEC_TMPVAR_CONST_HANDLER, + ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_OR_SPEC_TMPVAR_CV_HANDLER, + ZEND_BW_OR_SPEC_TMPVAR_CONST_HANDLER, + ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_OR_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_OR_SPEC_CV_CONST_HANDLER, + ZEND_BW_OR_SPEC_CV_TMPVAR_HANDLER, + ZEND_BW_OR_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_OR_SPEC_CV_CV_HANDLER, + ZEND_BW_AND_SPEC_CONST_CONST_HANDLER, + ZEND_BW_AND_SPEC_CONST_TMPVAR_HANDLER, + ZEND_BW_AND_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_AND_SPEC_CONST_CV_HANDLER, + ZEND_BW_AND_SPEC_TMPVAR_CONST_HANDLER, + ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_AND_SPEC_TMPVAR_CV_HANDLER, + ZEND_BW_AND_SPEC_TMPVAR_CONST_HANDLER, + ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_AND_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_AND_SPEC_CV_CONST_HANDLER, + ZEND_BW_AND_SPEC_CV_TMPVAR_HANDLER, + ZEND_BW_AND_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_AND_SPEC_CV_CV_HANDLER, + ZEND_BW_XOR_SPEC_CONST_CONST_HANDLER, + ZEND_BW_XOR_SPEC_CONST_TMPVAR_HANDLER, + ZEND_BW_XOR_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_XOR_SPEC_CONST_CV_HANDLER, + ZEND_BW_XOR_SPEC_TMPVAR_CONST_HANDLER, + ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVAR_CV_HANDLER, + ZEND_BW_XOR_SPEC_TMPVAR_CONST_HANDLER, + ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_XOR_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_XOR_SPEC_CV_CONST_HANDLER, + ZEND_BW_XOR_SPEC_CV_TMPVAR_HANDLER, + ZEND_BW_XOR_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_XOR_SPEC_CV_CV_HANDLER, + ZEND_BW_NOT_SPEC_CONST_HANDLER, + ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, + ZEND_BW_NOT_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BW_NOT_SPEC_CV_HANDLER, + ZEND_BOOL_NOT_SPEC_CONST_HANDLER, + ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, + ZEND_BOOL_NOT_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BOOL_NOT_SPEC_CV_HANDLER, + ZEND_BOOL_XOR_SPEC_CONST_CONST_HANDLER, + ZEND_BOOL_XOR_SPEC_CONST_TMPVAR_HANDLER, + ZEND_BOOL_XOR_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BOOL_XOR_SPEC_CONST_CV_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_CV_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BOOL_XOR_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER, + ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLER, + ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CONST_CONST_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CONST_TMP_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CONST_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CONST_CV_HANDLER, + ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HANDLER, + ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HANDLER, + ZEND_IS_IDENTICAL_SPEC_TMP_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDLER, + ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HANDLER, + ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HANDLER, + ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CV_CONST_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CONST_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CONST_TMP_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CONST_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CV_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONST_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_TMP_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CV_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONST_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HANDLER, + ZEND_IS_EQUAL_SPEC_CONST_CONST_HANDLER, + ZEND_IS_EQUAL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_IS_EQUAL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_CV_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_EQUAL_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CV_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_CONST_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_TMPVAR_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_SMALLER_SPEC_CONST_CV_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVAR_CONST_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVAR_CV_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVAR_CONST_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_SMALLER_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_SMALLER_SPEC_CV_CONST_HANDLER, + ZEND_IS_SMALLER_SPEC_CV_TMPVAR_HANDLER, + ZEND_IS_SMALLER_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_SMALLER_SPEC_CV_CV_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CONST_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CONST_CV_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CV_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CONST_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMPVAR_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_IS_SMALLER_OR_EQUAL_SPEC_CV_CV_HANDLER, + ZEND_CAST_SPEC_CONST_HANDLER, + ZEND_CAST_SPEC_TMP_HANDLER, + ZEND_CAST_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CAST_SPEC_CV_HANDLER, + ZEND_QM_ASSIGN_SPEC_CONST_HANDLER, + ZEND_QM_ASSIGN_SPEC_TMP_HANDLER, + ZEND_QM_ASSIGN_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_QM_ASSIGN_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_ADD_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_ADD_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_ADD_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_ADD_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_ADD_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_ADD_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_ADD_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_ADD_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_ADD_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_ADD_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_ADD_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_ADD_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_ADD_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_ADD_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_ADD_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_SUB_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_SUB_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_SUB_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_SUB_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_SUB_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_SUB_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_SUB_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_SUB_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_SUB_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_SUB_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_SUB_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_SUB_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_SUB_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_SUB_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_SUB_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_MUL_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_MUL_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_MUL_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_MUL_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_MUL_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_MUL_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_MUL_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_MUL_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_MUL_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_MUL_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_MUL_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_MUL_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_MUL_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_MUL_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_MUL_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIV_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_DIV_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_DIV_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_DIV_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_DIV_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_DIV_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_DIV_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_DIV_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_DIV_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_DIV_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_DIV_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_DIV_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_DIV_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_DIV_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_DIV_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_MOD_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_MOD_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_MOD_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_MOD_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_MOD_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_MOD_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_MOD_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_MOD_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_MOD_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_MOD_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_MOD_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_MOD_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_MOD_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_MOD_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_MOD_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_SL_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_SL_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_SL_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_SL_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_SL_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_SL_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_SL_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_SL_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_SL_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_SL_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_SL_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_SL_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_SL_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_SL_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_SL_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_SR_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_SR_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_SR_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_SR_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_SR_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_SR_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_SR_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_SR_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_SR_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_SR_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_SR_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_SR_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_SR_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_SR_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_SR_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_CONCAT_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_BW_OR_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_BW_AND_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_BW_XOR_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_INC_SPEC_VAR_RETVAL_UNUSED_HANDLER, + ZEND_PRE_INC_SPEC_VAR_RETVAL_USED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_INC_SPEC_CV_RETVAL_UNUSED_HANDLER, + ZEND_PRE_INC_SPEC_CV_RETVAL_USED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_DEC_SPEC_VAR_RETVAL_UNUSED_HANDLER, + ZEND_PRE_DEC_SPEC_VAR_RETVAL_USED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_DEC_SPEC_CV_RETVAL_UNUSED_HANDLER, + ZEND_PRE_DEC_SPEC_CV_RETVAL_USED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_INC_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_INC_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_DEC_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_DEC_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_UNUSED_HANDLER, + ZEND_ASSIGN_SPEC_VAR_CONST_RETVAL_USED_HANDLER, + ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_UNUSED_HANDLER, + ZEND_ASSIGN_SPEC_VAR_TMP_RETVAL_USED_HANDLER, + ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_UNUSED_HANDLER, + ZEND_ASSIGN_SPEC_VAR_VAR_RETVAL_USED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_UNUSED_HANDLER, + ZEND_ASSIGN_SPEC_VAR_CV_RETVAL_USED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_UNUSED_HANDLER, + ZEND_ASSIGN_SPEC_CV_CONST_RETVAL_USED_HANDLER, + ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_UNUSED_HANDLER, + ZEND_ASSIGN_SPEC_CV_TMP_RETVAL_USED_HANDLER, + ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_UNUSED_HANDLER, + ZEND_ASSIGN_SPEC_CV_VAR_RETVAL_USED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_SPEC_CV_CV_RETVAL_UNUSED_HANDLER, + ZEND_ASSIGN_SPEC_CV_CV_RETVAL_USED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER, + ZEND_ECHO_SPEC_CONST_HANDLER, + ZEND_ECHO_SPEC_TMPVAR_HANDLER, + ZEND_ECHO_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ECHO_SPEC_CV_HANDLER, + ZEND_JMP_SPEC_HANDLER, + ZEND_JMPZ_SPEC_CONST_HANDLER, + ZEND_JMPZ_SPEC_TMPVAR_HANDLER, + ZEND_JMPZ_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_JMPZ_SPEC_CV_HANDLER, + ZEND_JMPNZ_SPEC_CONST_HANDLER, + ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, + ZEND_JMPNZ_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_JMPNZ_SPEC_CV_HANDLER, + ZEND_JMPZNZ_SPEC_CONST_HANDLER, + ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, + ZEND_JMPZNZ_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_JMPZNZ_SPEC_CV_HANDLER, + ZEND_JMPZ_EX_SPEC_CONST_HANDLER, + ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, + ZEND_JMPZ_EX_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_JMPZ_EX_SPEC_CV_HANDLER, + ZEND_JMPNZ_EX_SPEC_CONST_HANDLER, + ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, + ZEND_JMPNZ_EX_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_JMPNZ_EX_SPEC_CV_HANDLER, + ZEND_CASE_SPEC_CONST_CONST_HANDLER, + ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER, + ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CASE_SPEC_CONST_CV_HANDLER, + ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER, + ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CASE_SPEC_TMPVAR_CV_HANDLER, + ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER, + ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CASE_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CASE_SPEC_CV_CONST_HANDLER, + ZEND_CASE_SPEC_CV_TMPVAR_HANDLER, + ZEND_CASE_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CASE_SPEC_CV_CV_HANDLER, + ZEND_BOOL_SPEC_CONST_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, + ZEND_BOOL_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BOOL_SPEC_CV_HANDLER, + ZEND_FAST_CONCAT_SPEC_CONST_CONST_HANDLER, + ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_HANDLER, + ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FAST_CONCAT_SPEC_CONST_CV_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FAST_CONCAT_SPEC_CV_CONST_HANDLER, + ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HANDLER, + ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ROPE_INIT_SPEC_UNUSED_CONST_HANDLER, + ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ROPE_INIT_SPEC_UNUSED_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLER, + ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER, + ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ROPE_END_SPEC_TMP_CONST_HANDLER, + ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER, + ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ROPE_END_SPEC_TMP_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BEGIN_SILENCE_SPEC_HANDLER, + ZEND_NULL_HANDLER, + ZEND_END_SILENCE_SPEC_TMP_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_FCALL_BY_NAME_SPEC_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DO_FCALL_SPEC_RETVAL_UNUSED_HANDLER, + ZEND_DO_FCALL_SPEC_RETVAL_USED_HANDLER, + ZEND_INIT_FCALL_SPEC_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_RETURN_SPEC_CONST_HANDLER, + ZEND_RETURN_SPEC_TMP_HANDLER, + ZEND_RETURN_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_RETURN_SPEC_CV_HANDLER, + ZEND_RECV_SPEC_HANDLER, + ZEND_RECV_INIT_SPEC_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAL_SPEC_CONST_HANDLER, + ZEND_SEND_VAL_SPEC_TMP_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_VAR_HANDLER, + ZEND_SEND_VAR_EX_SPEC_VAR_QUICK_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_EX_SPEC_CV_HANDLER, + ZEND_SEND_VAR_EX_SPEC_CV_QUICK_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_REF_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_REF_SPEC_CV_HANDLER, + ZEND_NEW_SPEC_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NEW_SPEC_VAR_HANDLER, + ZEND_NEW_SPEC_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_NS_FCALL_BY_NAME_SPEC_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FREE_SPEC_TMPVAR_HANDLER, + ZEND_FREE_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_CONST_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_UNUSED_HANDLER, + ZEND_INIT_ARRAY_SPEC_CONST_CV_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_CONST_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_UNUSED_HANDLER, + ZEND_INIT_ARRAY_SPEC_TMP_CV_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_CONST_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_UNUSED_HANDLER, + ZEND_INIT_ARRAY_SPEC_VAR_CV_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_CONST_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_TMPVAR_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_UNUSED_HANDLER, + ZEND_INIT_ARRAY_SPEC_CV_CV_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CONST_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_UNUSED_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_CV_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CONST_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNUSED_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CONST_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNUSED_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONST_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPVAR_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUSED_HANDLER, + ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDLER, + ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER, + ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER, + ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HANDLER, + ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDLER, + ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLER, + ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER, + ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDLER, + ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER, + ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HANDLER, + ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDLER, + ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLER, + ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER, + ZEND_FE_RESET_R_SPEC_CONST_HANDLER, + ZEND_FE_RESET_R_SPEC_TMP_HANDLER, + ZEND_FE_RESET_R_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FE_RESET_R_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FE_FETCH_R_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_EXIT_SPEC_CONST_HANDLER, + ZEND_EXIT_SPEC_TMPVAR_HANDLER, + ZEND_EXIT_SPEC_TMPVAR_HANDLER, + ZEND_EXIT_SPEC_UNUSED_HANDLER, + ZEND_EXIT_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_R_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HANDLER, + ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_W_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER, + ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HANDLER, + ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CONST_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_IS_SPEC_CV_CV_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_FUNC_ARG_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UNUSED_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UNUSED_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNUSED_HANDLER, + ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CONST_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_CV_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CONST_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CONST_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED_CV_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CONST_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HANDLER, + ZEND_FETCH_LIST_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_LIST_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_LIST_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_LIST_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_EXT_STMT_SPEC_HANDLER, + ZEND_EXT_FCALL_BEGIN_SPEC_HANDLER, + ZEND_EXT_FCALL_END_SPEC_HANDLER, + ZEND_EXT_NOP_SPEC_HANDLER, + ZEND_TICKS_SPEC_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_NO_REF_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_CATCH_SPEC_CONST_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_THROW_SPEC_CONST_HANDLER, + ZEND_THROW_SPEC_TMP_HANDLER, + ZEND_THROW_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_THROW_SPEC_CV_HANDLER, + ZEND_FETCH_CLASS_SPEC_CONST_HANDLER, + ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, + ZEND_FETCH_CLASS_SPEC_TMPVAR_HANDLER, + ZEND_FETCH_CLASS_SPEC_UNUSED_HANDLER, + ZEND_FETCH_CLASS_SPEC_CV_HANDLER, + ZEND_CLONE_SPEC_CONST_HANDLER, + ZEND_CLONE_SPEC_TMPVAR_HANDLER, + ZEND_CLONE_SPEC_TMPVAR_HANDLER, + ZEND_CLONE_SPEC_UNUSED_HANDLER, + ZEND_CLONE_SPEC_CV_HANDLER, + ZEND_RETURN_BY_REF_SPEC_CONST_HANDLER, + ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER, + ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_RETURN_BY_REF_SPEC_CV_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_CONST_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CONST_CV_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CONST_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_CV_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_UNUSED_CV_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CV_CONST_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CONST_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_UNUSED_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_CONST_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CONST_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_TMPVAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_UNUSED_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_VAR_CV_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CV_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CV_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNUSED_CV_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CV_HANDLER, + ZEND_SEND_VAL_EX_SPEC_CONST_HANDLER, + ZEND_SEND_VAL_EX_SPEC_CONST_QUICK_HANDLER, + ZEND_SEND_VAL_EX_SPEC_TMP_HANDLER, + ZEND_SEND_VAL_EX_SPEC_TMP_QUICK_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_VAR_SPEC_CV_HANDLER, + ZEND_INIT_USER_CALL_SPEC_CONST_CONST_HANDLER, + ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_INIT_USER_CALL_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_USER_CALL_SPEC_CONST_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_ARRAY_SPEC_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_USER_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEND_USER_SPEC_CV_HANDLER, + ZEND_STRLEN_SPEC_CONST_HANDLER, + ZEND_STRLEN_SPEC_TMPVAR_HANDLER, + ZEND_STRLEN_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_STRLEN_SPEC_CV_HANDLER, + ZEND_DEFINED_SPEC_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_TYPE_CHECK_SPEC_CONST_HANDLER, + ZEND_TYPE_CHECK_SPEC_TMP_HANDLER, + ZEND_TYPE_CHECK_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_TYPE_CHECK_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FE_RESET_RW_SPEC_CONST_HANDLER, + ZEND_FE_RESET_RW_SPEC_TMP_HANDLER, + ZEND_FE_RESET_RW_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FE_RESET_RW_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, + ZEND_FE_FREE_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_DYNAMIC_CALL_SPEC_CONST_HANDLER, + ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, + ZEND_INIT_DYNAMIC_CALL_SPEC_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HANDLER, + ZEND_DO_ICALL_SPEC_RETVAL_UNUSED_HANDLER, + ZEND_DO_ICALL_SPEC_RETVAL_USED_HANDLER, + ZEND_DO_UCALL_SPEC_RETVAL_UNUSED_HANDLER, + ZEND_DO_UCALL_SPEC_RETVAL_USED_HANDLER, + ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_UNUSED_HANDLER, + ZEND_DO_FCALL_BY_NAME_SPEC_RETVAL_USED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_VAR_CONST_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_VAR_CV_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CV_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_CV_CONST_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_PRE_DEC_OBJ_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER, + ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER, + ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER, + ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HANDLER, + ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER, + ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_VAR_CONST_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_VAR_CV_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_UNUSED_CV_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_CV_CONST_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POST_DEC_OBJ_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_VAR_CV_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CONST_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_OBJ_SPEC_CV_CV_OP_DATA_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER, + ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER, + ZEND_INSTANCEOF_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DECLARE_CLASS_SPEC_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DECLARE_INHERITED_CLASS_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DECLARE_FUNCTION_SPEC_HANDLER, + ZEND_YIELD_FROM_SPEC_CONST_HANDLER, + ZEND_YIELD_FROM_SPEC_TMP_HANDLER, + ZEND_YIELD_FROM_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_YIELD_FROM_SPEC_CV_HANDLER, + ZEND_DECLARE_CONST_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ADD_INTERFACE_SPEC_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DECLARE_INHERITED_CLASS_DELAYED_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_VERIFY_ABSTRACT_CLASS_SPEC_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CONST_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_VAR_CV_OP_DATA_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CONST_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_OP_DATA_CV_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CONST_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_TMP_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_DIM_SPEC_CV_CV_OP_DATA_CV_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CONST_CV_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TMPVAR_CV_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UNUSED_CV_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CONST_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV_CV_HANDLER, + ZEND_HANDLE_EXCEPTION_SPEC_HANDLER, + ZEND_USER_OPCODE_SPEC_HANDLER, + ZEND_ASSERT_CHECK_SPEC_HANDLER, + ZEND_JMP_SET_SPEC_CONST_HANDLER, + ZEND_JMP_SET_SPEC_TMP_HANDLER, + ZEND_JMP_SET_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_JMP_SET_SPEC_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ADD_TRAIT_SPEC_HANDLER, + ZEND_BIND_TRAITS_SPEC_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SEPARATE_SPEC_VAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_CLASS_NAME_SPEC_HANDLER, + ZEND_CALL_TRAMPOLINE_SPEC_HANDLER, + ZEND_DISCARD_EXCEPTION_SPEC_HANDLER, + ZEND_YIELD_SPEC_CONST_CONST_HANDLER, + ZEND_YIELD_SPEC_CONST_TMP_HANDLER, + ZEND_YIELD_SPEC_CONST_VAR_HANDLER, + ZEND_YIELD_SPEC_CONST_UNUSED_HANDLER, + ZEND_YIELD_SPEC_CONST_CV_HANDLER, + ZEND_YIELD_SPEC_TMP_CONST_HANDLER, + ZEND_YIELD_SPEC_TMP_TMP_HANDLER, + ZEND_YIELD_SPEC_TMP_VAR_HANDLER, + ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER, + ZEND_YIELD_SPEC_TMP_CV_HANDLER, + ZEND_YIELD_SPEC_VAR_CONST_HANDLER, + ZEND_YIELD_SPEC_VAR_TMP_HANDLER, + ZEND_YIELD_SPEC_VAR_VAR_HANDLER, + ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER, + ZEND_YIELD_SPEC_VAR_CV_HANDLER, + ZEND_YIELD_SPEC_UNUSED_CONST_HANDLER, + ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER, + ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER, + ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_YIELD_SPEC_UNUSED_CV_HANDLER, + ZEND_YIELD_SPEC_CV_CONST_HANDLER, + ZEND_YIELD_SPEC_CV_TMP_HANDLER, + ZEND_YIELD_SPEC_CV_VAR_HANDLER, + ZEND_YIELD_SPEC_CV_UNUSED_HANDLER, + ZEND_YIELD_SPEC_CV_CV_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_CONST_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_TMP_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_GENERATOR_RETURN_SPEC_CV_HANDLER, + ZEND_FAST_CALL_SPEC_HANDLER, + ZEND_FAST_RET_SPEC_HANDLER, + ZEND_RECV_VARIADIC_SPEC_HANDLER, + ZEND_SEND_UNPACK_SPEC_HANDLER, + ZEND_POW_SPEC_CONST_CONST_HANDLER, + ZEND_POW_SPEC_CONST_TMPVAR_HANDLER, + ZEND_POW_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POW_SPEC_CONST_CV_HANDLER, + ZEND_POW_SPEC_TMPVAR_CONST_HANDLER, + ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POW_SPEC_TMPVAR_CV_HANDLER, + ZEND_POW_SPEC_TMPVAR_CONST_HANDLER, + ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POW_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POW_SPEC_CV_CONST_HANDLER, + ZEND_POW_SPEC_CV_TMPVAR_HANDLER, + ZEND_POW_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_POW_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ASSIGN_POW_SPEC_VAR_CONST_HANDLER, + ZEND_ASSIGN_POW_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_POW_SPEC_VAR_TMPVAR_HANDLER, + ZEND_ASSIGN_POW_SPEC_VAR_UNUSED_HANDLER, + ZEND_ASSIGN_POW_SPEC_VAR_CV_HANDLER, + ZEND_ASSIGN_POW_SPEC_UNUSED_CONST_HANDLER, + ZEND_ASSIGN_POW_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_POW_SPEC_UNUSED_TMPVAR_HANDLER, + ZEND_ASSIGN_POW_SPEC_UNUSED_UNUSED_HANDLER, + ZEND_ASSIGN_POW_SPEC_UNUSED_CV_HANDLER, + ZEND_ASSIGN_POW_SPEC_CV_CONST_HANDLER, + ZEND_ASSIGN_POW_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_POW_SPEC_CV_TMPVAR_HANDLER, + ZEND_ASSIGN_POW_SPEC_CV_UNUSED_HANDLER, + ZEND_ASSIGN_POW_SPEC_CV_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BIND_GLOBAL_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_COALESCE_SPEC_CONST_HANDLER, + ZEND_COALESCE_SPEC_TMP_HANDLER, + ZEND_COALESCE_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_COALESCE_SPEC_CV_HANDLER, + ZEND_SPACESHIP_SPEC_CONST_CONST_HANDLER, + ZEND_SPACESHIP_SPEC_CONST_TMPVAR_HANDLER, + ZEND_SPACESHIP_SPEC_CONST_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SPACESHIP_SPEC_CONST_CV_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SPACESHIP_SPEC_CV_CONST_HANDLER, + ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDLER, + ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_SPACESHIP_SPEC_CV_CV_HANDLER, + ZEND_DECLARE_ANON_CLASS_SPEC_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_VAR_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_R_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_CONST_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_W_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_CONST_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_RW_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_CONST_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_IS_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CONST_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CONST_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CV_VAR_HANDLER, + ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_CONST_VAR_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_VAR_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_VAR_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_CV_VAR_HANDLER, + ZEND_UNSET_STATIC_PROP_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CONST_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CONST_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CV_VAR_HANDLER, + ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CV_UNUSED_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BIND_LEXICAL_SPEC_TMP_CV_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_BIND_STATIC_SPEC_CV_CONST_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER, + ZEND_NULL_HANDLER + }; + static const uint32_t specs[] = { + 0, + 1 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 26 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 51 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 76 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 101 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 126 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 151 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 176 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 201 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 226 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 251 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 276 | SPEC_RULE_OP1, + 281 | SPEC_RULE_OP1, + 286 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 311 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 336 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 361 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 386 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 411 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 436 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 461 | SPEC_RULE_OP1, + 466 | SPEC_RULE_OP1, + 471 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 496 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 521 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 546 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 571 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 596 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 621 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 646 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 671 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 696 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 721 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 746 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL, + 756 | SPEC_RULE_OP1 | SPEC_RULE_RETVAL, + 766 | SPEC_RULE_OP1, + 771 | SPEC_RULE_OP1, + 776 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_RETVAL, + 826 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 851 | SPEC_RULE_OP1, + 2920, + 856, + 857 | SPEC_RULE_OP1, + 862 | SPEC_RULE_OP1, + 867 | SPEC_RULE_OP1, + 872 | SPEC_RULE_OP1, + 877 | SPEC_RULE_OP1, + 882 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2920, + 2920, + 2920, + 907 | SPEC_RULE_OP1, + 912 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 937 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 962 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 987 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1012, + 1013 | SPEC_RULE_OP1, + 1018 | SPEC_RULE_OP2, + 1023 | SPEC_RULE_RETVAL, + 1025 | SPEC_RULE_OP2, + 1030 | SPEC_RULE_OP1, + 1035, + 1036 | SPEC_RULE_OP2, + 1041 | SPEC_RULE_OP1, + 1046 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG, + 1056 | SPEC_RULE_OP1, + 1061 | SPEC_RULE_OP1, + 1066 | SPEC_RULE_OP2, + 1071 | SPEC_RULE_OP1, + 1076 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1101 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1126 | SPEC_RULE_OP1, + 1131 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1156 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1181 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1206 | SPEC_RULE_OP1, + 1211 | SPEC_RULE_OP1, + 1216 | SPEC_RULE_OP1, + 1221 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1246 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1271 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1296 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1321 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1346 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1371 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1396 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1421 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1446 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1471 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1496 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1521 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1546 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1571 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1596 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1621 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1646 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1671 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1696 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2920, + 1721, + 1722, + 1723, + 1724, + 1725, + 1726 | SPEC_RULE_OP1, + 1731 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1756 | SPEC_RULE_OP1, + 1761 | SPEC_RULE_OP2, + 1766 | SPEC_RULE_OP1, + 1771 | SPEC_RULE_OP1, + 1776 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1801 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1826 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1851 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1876 | SPEC_RULE_OP1 | SPEC_RULE_QUICK_ARG, + 1886 | SPEC_RULE_OP1, + 1891 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1916, + 1917 | SPEC_RULE_OP1, + 1922 | SPEC_RULE_OP1, + 1927 | SPEC_RULE_OP1, + 1932 | SPEC_RULE_OP1, + 1937 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 1962 | SPEC_RULE_OP1, + 1967 | SPEC_RULE_OP1, + 1972 | SPEC_RULE_OP1, + 1977 | SPEC_RULE_OP2, + 1982 | SPEC_RULE_RETVAL, + 1984 | SPEC_RULE_RETVAL, + 1986 | SPEC_RULE_RETVAL, + 1988 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2013 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2038 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2063 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2088 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_OP_DATA, + 2213, + 2214 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2239, + 2240 | SPEC_RULE_OP2, + 2245, + 2246 | SPEC_RULE_OP1, + 2251 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2276 | SPEC_RULE_OP2, + 2281 | SPEC_RULE_OP2, + 2286, + 2287 | SPEC_RULE_OP1 | SPEC_RULE_OP2 | SPEC_RULE_OP_DATA, + 2412 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2437, + 2438, + 2439, + 2440 | SPEC_RULE_OP1, + 2445 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2470, + 2471, + 2472 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2497, + 2498, + 2499, + 2500 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2525 | SPEC_RULE_OP1, + 2530, + 2531, + 2532, + 2533, + 2534 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2559 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2584 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2609 | SPEC_RULE_OP1, + 2614 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2639, + 2640 | SPEC_RULE_OP2, + 2645 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2670 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2695 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2720 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2745 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2770 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2795 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2820 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2845 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2870 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2895 | SPEC_RULE_OP1 | SPEC_RULE_OP2, + 2920 + }; + zend_opcode_handlers = labels; + zend_spec_handlers = specs; } static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op) { - static const int zend_vm_decode[] = { - _UNUSED_CODE, /* 0 */ - _CONST_CODE, /* 1 = IS_CONST */ - _TMP_CODE, /* 2 = IS_TMP_VAR */ - _UNUSED_CODE, /* 3 */ - _VAR_CODE, /* 4 = IS_VAR */ - _UNUSED_CODE, /* 5 */ - _UNUSED_CODE, /* 6 */ - _UNUSED_CODE, /* 7 */ - _UNUSED_CODE, /* 8 = IS_UNUSED */ - _UNUSED_CODE, /* 9 */ - _UNUSED_CODE, /* 10 */ - _UNUSED_CODE, /* 11 */ - _UNUSED_CODE, /* 12 */ - _UNUSED_CODE, /* 13 */ - _UNUSED_CODE, /* 14 */ - _UNUSED_CODE, /* 15 */ - _CV_CODE /* 16 = IS_CV */ - }; - return zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1_type] * 5 + zend_vm_decode[op->op2_type]]; + static const int zend_vm_decode[] = { + _UNUSED_CODE, /* 0 */ + _CONST_CODE, /* 1 = IS_CONST */ + _TMP_CODE, /* 2 = IS_TMP_VAR */ + _UNUSED_CODE, /* 3 */ + _VAR_CODE, /* 4 = IS_VAR */ + _UNUSED_CODE, /* 5 */ + _UNUSED_CODE, /* 6 */ + _UNUSED_CODE, /* 7 */ + _UNUSED_CODE, /* 8 = IS_UNUSED */ + _UNUSED_CODE, /* 9 */ + _UNUSED_CODE, /* 10 */ + _UNUSED_CODE, /* 11 */ + _UNUSED_CODE, /* 12 */ + _UNUSED_CODE, /* 13 */ + _UNUSED_CODE, /* 14 */ + _UNUSED_CODE, /* 15 */ + _CV_CODE /* 16 = IS_CV */ + }; + uint32_t spec = zend_spec_handlers[opcode]; + uint32_t offset = 0; + if (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type]; + if (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type]; + if (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type]; + if (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED); + if (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM); + return zend_opcode_handlers[(spec & SPEC_START_MASK) + offset]; } ZEND_API void zend_vm_set_opcode_handler(zend_op* op) diff --git a/Zend/zend_vm_execute.skl b/Zend/zend_vm_execute.skl index 7e223385ff..144a17920a 100644 --- a/Zend/zend_vm_execute.skl +++ b/Zend/zend_vm_execute.skl @@ -11,7 +11,7 @@ ZEND_API void {%EXECUTOR_NAME%}_ex(zend_execute_data *ex) LOAD_OPLINE(); while (1) { - {%ZEND_VM_CONTINUE_LABEL%} + {%ZEND_VM_CONTINUE_LABEL%} {%ZEND_VM_DISPATCH%} { {%INTERNAL_EXECUTOR%} } @@ -45,5 +45,5 @@ ZEND_API void zend_{%EXECUTOR_NAME%}(zend_op_array *op_array, zval *return_value void {%INITIALIZER_NAME%}(void) { - {%EXTERNAL_LABELS%} + {%EXTERNAL_LABELS%} } diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php index 5899199c1f..53b9910e65 100644 --- a/Zend/zend_vm_gen.php +++ b/Zend/zend_vm_gen.php @@ -55,31 +55,18 @@ define("ZEND_VM_KIND_SWITCH", 2); define("ZEND_VM_KIND_GOTO", 3); $vm_op_flags = array( - "ZEND_VM_OP1_SPEC" => 1<<0, - "ZEND_VM_OP1_CONST" => 1<<1, - "ZEND_VM_OP1_TMPVAR" => 1<<2, - "ZEND_VM_OP1_MASK" => 0xf0, - "ZEND_VM_OP1_NUM" => 0x10, - "ZEND_VM_OP1_JMP_ADDR" => 0x20, - "ZEND_VM_OP1_TRY_CATCH" => 0x30, - "ZEND_VM_OP1_LIVE_RANGE" => 0x40, - "ZEND_VM_OP1_THIS" => 0x50, - "ZEND_VM_OP1_NEXT" => 0x60, - "ZEND_VM_OP1_CLASS_FETCH" => 0x70, - "ZEND_VM_OP1_CONSTRUCTOR" => 0x80, - - "ZEND_VM_OP2_SPEC" => 1<<8, - "ZEND_VM_OP2_CONST" => 1<<9, - "ZEND_VM_OP2_TMPVAR" => 1<<10, - "ZEND_VM_OP2_MASK" => 0xf000, - "ZEND_VM_OP2_NUM" => 0x1000, - "ZEND_VM_OP2_JMP_ADDR" => 0x2000, - "ZEND_VM_OP2_TRY_CATCH" => 0x3000, - "ZEND_VM_OP2_LIVE_RANGE" => 0x4000, - "ZEND_VM_OP2_THIS" => 0x5000, - "ZEND_VM_OP2_NEXT" => 0x6000, - "ZEND_VM_OP2_CLASS_FETCH" => 0x7000, - "ZEND_VM_OP2_CONSTRUCTOR" => 0x8000, + "ZEND_VM_OP_SPEC" => 1<<0, + "ZEND_VM_OP_CONST" => 1<<1, + "ZEND_VM_OP_TMPVAR" => 1<<2, + "ZEND_VM_OP_MASK" => 0xf0, + "ZEND_VM_OP_NUM" => 0x10, + "ZEND_VM_OP_JMP_ADDR" => 0x20, + "ZEND_VM_OP_TRY_CATCH" => 0x30, + "ZEND_VM_OP_LIVE_RANGE" => 0x40, + "ZEND_VM_OP_THIS" => 0x50, + "ZEND_VM_OP_NEXT" => 0x60, + "ZEND_VM_OP_CLASS_FETCH" => 0x70, + "ZEND_VM_OP_CONSTRUCTOR" => 0x80, "ZEND_VM_EXT_VAR_FETCH" => 1<<16, "ZEND_VM_EXT_ISSET" => 1<<17, @@ -107,20 +94,20 @@ foreach ($vm_op_flags as $name => $val) { $vm_op_decode = array( "ANY" => 0, - "CONST" => ZEND_VM_OP1_SPEC | ZEND_VM_OP1_CONST, - "TMP" => ZEND_VM_OP1_SPEC, - "VAR" => ZEND_VM_OP1_SPEC, - "UNUSED" => ZEND_VM_OP1_SPEC, - "CV" => ZEND_VM_OP1_SPEC, - "TMPVAR" => ZEND_VM_OP1_SPEC | ZEND_VM_OP1_TMPVAR, - "NUM" => ZEND_VM_OP1_NUM, - "JMP_ADDR" => ZEND_VM_OP1_JMP_ADDR, - "TRY_CATCH" => ZEND_VM_OP1_TRY_CATCH, - "LIVE_RANGE" => ZEND_VM_OP1_LIVE_RANGE, - "THIS" => ZEND_VM_OP1_THIS, - "NEXT" => ZEND_VM_OP1_NEXT, - "CLASS_FETCH" => ZEND_VM_OP1_CLASS_FETCH, - "CONSTRUCTOR" => ZEND_VM_OP1_CONSTRUCTOR, + "CONST" => ZEND_VM_OP_SPEC | ZEND_VM_OP_CONST, + "TMP" => ZEND_VM_OP_SPEC, + "VAR" => ZEND_VM_OP_SPEC, + "UNUSED" => ZEND_VM_OP_SPEC, + "CV" => ZEND_VM_OP_SPEC, + "TMPVAR" => ZEND_VM_OP_SPEC | ZEND_VM_OP_TMPVAR, + "NUM" => ZEND_VM_OP_NUM, + "JMP_ADDR" => ZEND_VM_OP_JMP_ADDR, + "TRY_CATCH" => ZEND_VM_OP_TRY_CATCH, + "LIVE_RANGE" => ZEND_VM_OP_LIVE_RANGE, + "THIS" => ZEND_VM_OP_THIS, + "NEXT" => ZEND_VM_OP_NEXT, + "CLASS_FETCH" => ZEND_VM_OP_CLASS_FETCH, + "CONSTRUCTOR" => ZEND_VM_OP_CONSTRUCTOR, ); $vm_ext_decode = array( @@ -507,6 +494,56 @@ $op2_free_unfetched = array( "TMPVAR" => "zval_ptr_dtor_nogc(EX_VAR(opline->op2.var))", ); +$op_data_type = array( + "ANY" => "(opline+1)->op1_type", + "TMP" => "IS_TMP_VAR", + "VAR" => "IS_VAR", + "CONST" => "IS_CONST", + "UNUSED" => "IS_UNUSED", + "CV" => "IS_CV", + "TMPVAR" => "(IS_TMP_VAR|IS_VAR)", +); + +$op_data_get_zval_ptr = array( + "ANY" => "get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data, \\1)", + "TMP" => "_get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data)", + "VAR" => "_get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data)", + "CONST" => "EX_CONSTANT((opline+1)->op1)", + "UNUSED" => "NULL", + "CV" => "_get_zval_ptr_cv_\\1(execute_data, (opline+1)->op1.var)", + "TMPVAR" => "_get_zval_ptr_var((opline+1)->op1.var, execute_data, &free_op_data)", +); + +$op_data_get_zval_ptr_deref = array( + "ANY" => "get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data, \\1)", + "TMP" => "_get_zval_ptr_tmp((opline+1)->op1.var, execute_data, &free_op_data)", + "VAR" => "_get_zval_ptr_var_deref((opline+1)->op1.var, execute_data, &free_op_data)", + "CONST" => "EX_CONSTANT((opline+1)->op1)", + "UNUSED" => "NULL", + "CV" => "_get_zval_ptr_cv_deref_\\1(execute_data, (opline+1)->op1.var)", + "TMPVAR" => "???", +); + +$op_data_free_op = array( + "ANY" => "FREE_OP(free_op_data)", + "TMP" => "zval_ptr_dtor_nogc(free_op_data)", + "VAR" => "zval_ptr_dtor_nogc(free_op_data)", + "CONST" => "", + "UNUSED" => "", + "CV" => "", + "TMPVAR" => "zval_ptr_dtor_nogc(free_op_data)", +); + +$op_data_free_unfetched = array( + "ANY" => "FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var)", + "TMP" => "zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))", + "VAR" => "zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))", + "CONST" => "", + "UNUSED" => "", + "CV" => "", + "TMPVAR" => "zval_ptr_dtor_nogc(EX_VAR((opline+1)->op1.var))", +); + $list = array(); // list of opcode handlers and helpers in original order $opcodes = array(); // opcode handlers by code $helpers = array(); // opcode helpers by name @@ -569,7 +606,7 @@ function opcode_name($name, $spec, $op1, $op2) { } // Generates code for opcode handler or helper -function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { +function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name, $extra_spec=null) { global $op1_type, $op2_type, $op1_get_zval_ptr, $op2_get_zval_ptr, $op1_get_zval_ptr_deref, $op2_get_zval_ptr_deref, $op1_get_zval_ptr_undef, $op2_get_zval_ptr_undef, @@ -582,7 +619,9 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { $op1_get_obj_zval_ptr_ptr_undef, $op2_get_obj_zval_ptr_ptr_undef, $op1_free, $op2_free, $op1_free_unfetched, $op2_free_unfetched, $op1_free_op, $op2_free_op, $op1_free_op_if_var, $op2_free_op_if_var, - $op1_free_op_var_ptr, $op2_free_op_var_ptr, $prefix; + $op1_free_op_var_ptr, $op2_free_op_var_ptr, $prefix, + $op_data_type, $op_data_get_zval_ptr, $op_data_get_zval_ptr_deref, + $op_data_free_op, $op_data_free_unfetched; // Specializing $code = preg_replace( @@ -628,7 +667,14 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { "/^#(\s*)if\s+1\s*\\|\\|.*[^\\\\]$/m", "/^#(\s*)if\s+0\s*&&.*[^\\\\]$/m", "/^#(\s*)ifdef\s+ZEND_VM_EXPORT\s*\n/m", - "/^#(\s*)ifndef\s+ZEND_VM_EXPORT\s*\n/m" + "/^#(\s*)ifndef\s+ZEND_VM_EXPORT\s*\n/m", + "/OP_DATA_TYPE/", + "/GET_OP_DATA_ZVAL_PTR\(([^)]*)\)/", + "/GET_OP_DATA_ZVAL_PTR_DEREF\(([^)]*)\)/", + "/FREE_OP_DATA\(\)/", + "/FREE_UNFETCHED_OP_DATA\(\)/", + "/RETURN_VALUE_USED\(opline\)/", + "/arg_num <= MAX_ARG_FLAG_NUM/", ), array( $op1_type[$op1], @@ -667,12 +713,19 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { ($op1!="ANY"||$op2!="ANY")?"#\\1if 0\n":"#\\1if 1\n", ($op1!="ANY"||$op2!="ANY")?"0":"1", ($op1!="ANY"||$op2!="ANY")?"1":"0", - "\\1".(($spec && $kind != ZEND_VM_KIND_CALL)?("_SPEC".$prefix[$op1].$prefix[$op2]):""), - "goto \\1".(($spec && $kind != ZEND_VM_KIND_CALL)?("_SPEC".$prefix[$op1].$prefix[$op2]):""), + "\\1".(($spec && $kind != ZEND_VM_KIND_CALL)?("_SPEC".$prefix[$op1].$prefix[$op2].extra_spec_name($extra_spec)):""), + "goto \\1".(($spec && $kind != ZEND_VM_KIND_CALL)?("_SPEC".$prefix[$op1].$prefix[$op2].extra_spec_name($extra_spec)):""), "#\\1if 1", "#\\1if 0", $export?"#\\1if 1\n":"#\\1if 0\n", - $export?"#\\1if 0\n":"#\\1if 1\n" + $export?"#\\1if 0\n":"#\\1if 1\n", + $op_data_type[isset($extra_spec['op_data']) ? $extra_spec['op_data'] : "ANY"], + $op_data_get_zval_ptr[isset($extra_spec['op_data']) ? $extra_spec['op_data'] : "ANY"], + $op_data_get_zval_ptr_deref[isset($extra_spec['op_data']) ? $extra_spec['op_data'] : "ANY"], + $op_data_free_op[isset($extra_spec['op_data']) ? $extra_spec['op_data'] : "ANY"], + $op_data_free_unfetched[isset($extra_spec['op_data']) ? $extra_spec['op_data'] : "ANY"], + isset($extra_spec['retval']) ? $extra_spec['retval'] : "RETURN_VALUE_USED(opline)", + isset($extra_spec['quick_arg']) ? $extra_spec['quick_arg'] : "arg_num <= MAX_ARG_FLAG_NUM", ), $code); @@ -764,6 +817,7 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { } $del_free_op1 = (strpos($code, "free_op1") === false); $del_free_op2 = (strpos($code, "free_op2") === false); + $del_free_op_data = (strpos($code, "free_op_data") === false); $n = 0; foreach ($matches as $match) { $dcl = $match[0]; @@ -778,6 +832,11 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { $dcl = preg_replace("/free_op2\s*;/", ";", $dcl); $changed = 1; } + if ($del_free_op_data && strpos($dcl, "free_op_data") !== false) { + $dcl = preg_replace("/free_op_data\s*,\s*/", "", $dcl); + $dcl = preg_replace("/free_op_data\s*;/", ";", $dcl); + $changed = 1; + } if ($changed) { $dcl = preg_replace("/,\s*;/", ";", $dcl); $dcl = preg_replace("/zend_free_op\s*;/", "", $dcl); @@ -797,7 +856,7 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) { } // Generates opcode handler -function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno) { +function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno, $extra_spec = null, &$switch_labels = array()) { global $definition_file, $prefix, $typecode, $opnames; if (ZEND_VM_LINES) { @@ -805,30 +864,33 @@ function gen_handler($f, $spec, $kind, $name, $op1, $op2, $use, $code, $lineno) } // Generate opcode handler's entry point according to selected threading model + $spec_name = $name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].($spec?extra_spec_name($extra_spec):""); switch($kind) { case ZEND_VM_KIND_CALL: - out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); + out($f,"static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL {$spec_name}_HANDLER(ZEND_OPCODE_HANDLER_ARGS)\n"); break; case ZEND_VM_KIND_SWITCH: if ($spec) { - out($f,"case ".((string)($opnames[$name]*25+($typecode[$op1=="TMPVAR"?"TMP":$op1]*5)+$typecode[$op2=="TMPVAR"?"TMP":$op2])).": /*".$name."_SPEC".$prefix[$op1].$prefix[$op2]."_HANDLER*/"); + $cur = $switch_labels ? end($switch_labels) + 1 : 0; + out($f,"case $cur: /* $spec_name */"); + $switch_labels[$spec_name] = $cur; } else { out($f,"case ".$name.":"); } if ($use) { // This handler is used by other handlers. We will add label to call it. - out($f," ".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_LABEL:\n"); + out($f," {$spec_name}_LABEL:\n"); } else { out($f,"\n"); } break; case ZEND_VM_KIND_GOTO: - out($f,$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2]."_HANDLER: ZEND_VM_GUARD(".$name.($spec?"_SPEC":"").$prefix[$op1].$prefix[$op2].");\n"); + out($f,"{$spec_name}_HANDLER: ZEND_VM_GUARD($spec_name);\n"); break; } // Generate opcode handler's code - gen_code($f, $spec, $kind, 0, $code, $op1, $op2, $name); + gen_code($f, $spec, $kind, 0, $code, $op1, $op2, $name, $extra_spec); } // Generates helper @@ -870,60 +932,57 @@ function gen_helper($f, $spec, $kind, $name, $op1, $op2, $param, $code, $lineno, } // Generates array of opcode handlers (specialized or unspecialized) -function gen_labels($f, $spec, $kind, $prolog) { - global $opcodes, $op_types, $prefix, $typecode; +function gen_labels($f, $spec, $kind, $prolog, &$specs, $switch_labels = array()) { + global $opcodes, $op_types, $prefix; $next = 0; + $label = 0; if ($spec) { // Emit labels for specialized executor // For each opcode in opcode number order foreach($opcodes as $num => $dsc) { - while ($next != $num) { - // If some opcode numbers are not used then fill hole with pointers - // to handler of undefined opcode - $op1t = $op_types; - // For each op1.op_type except ANY - foreach($op1t as $op1) { - if ($op1 != "ANY") { - $op2t = $op_types; - // For each op2.op_type except ANY - foreach($op2t as $op2) { - if ($op2 != "ANY") { - // Emit pointer to handler of undefined opcode - switch ($kind) { - case ZEND_VM_KIND_CALL: - out($f,$prolog."ZEND_NULL_HANDLER,\n"); - break; - case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(void*)(uintptr_t)-1,\n"); - break; - case ZEND_VM_KIND_GOTO: - out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n"); - break; + $specs[$num] = "$label"; + $spec_op1 = $spec_op2 = $spec_extra = false; + $next = $num + 1; + $diff = array_diff_key(array_flip($op_types), isset($dsc["op1"]) ? $dsc["op1"] : array()); + if ((count($diff) == count($op_types) - 1 ? isset($diff["ANY"]) : count($diff) != count($op_types)) || isset($dsc["op1"]["TMPVAR"])) { + $spec_op1 = true; + $specs[$num] .= " | SPEC_RULE_OP1"; + } + $diff = array_diff_key(array_flip($op_types), isset($dsc["op2"]) ? $dsc["op2"] : array()); + if ((count($diff) == count($op_types) - 1 ? isset($diff["ANY"]) : count($diff) != count($op_types)) || isset($dsc["op2"]["TMPVAR"])) { + $spec_op2 = true; + $specs[$num] .= " | SPEC_RULE_OP2"; + } + $spec_extra = call_user_func_array("array_merge", extra_spec_handler($dsc) ?: array(array())); + $flags = extra_spec_flags($spec_extra); + if ($flags) { + $specs[$num] .= " | ".implode("|", $flags); + } + + $foreach_op1 = function($do) use ($dsc, $op_types) { + return function() use ($do, $dsc, $op_types) { + // For each op1.op_type except ANY + foreach($op_types as $op1) { + if ($op1 != "ANY") { + if (!isset($dsc["op1"][$op1])) { + if (($op1 == "TMP" || $op1 == "VAR") && isset($dsc["op1"]["TMPVAR"])) { + $op1 = "TMPVAR"; + } else { + // Try to use unspecialized handler + $op1 = "ANY"; } } + $do($op1, "ANY"); } } - } - $next++; - } - $next = $num + 1; - $op1t = $op_types; - // For each op1.op_type except ANY - foreach($op1t as $op1) { - if ($op1 != "ANY") { - if (!isset($dsc["op1"][$op1])) { - if (($op1 == "TMP" || $op1 == "VAR") && isset($dsc["op1"]["TMPVAR"])) { - $op1 = "TMPVAR"; - } else { - // Try to use unspecialized handler - $op1 = "ANY"; - } - } - $op2t = $op_types; + }; + }; + $foreach_op2 = function($do) use ($dsc, $op_types) { + return function($op1) use ($do, $dsc, $op_types) { // For each op2.op_type except ANY - foreach($op2t as $op2) { + foreach($op_types as $op2) { if ($op2 != "ANY") { if (!isset($dsc["op2"][$op2])) { if (($op2 == "TMP" || $op2 == "VAR") && isset($dsc["op2"]["TMPVAR"])) { @@ -933,39 +992,97 @@ function gen_labels($f, $spec, $kind, $prolog) { $op2 = "ANY"; } } - // Check if specialized handler is defined - if (isset($dsc["op1"][$op1]) && - isset($dsc["op2"][$op2])) { - // Emit pointer to specialized handler - switch ($kind) { - case ZEND_VM_KIND_CALL: - out($f,$prolog.$dsc["op"]."_SPEC".$prefix[$op1].$prefix[$op2]."_HANDLER,\n"); - break; - case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(void*)(uintptr_t)".((string)($num*25+$typecode[$op1=="TMPVAR"?"TMP":$op1]*5+$typecode[$op2=="TMPVAR"?"TMP":$op2])).",\n"); - break; - case ZEND_VM_KIND_GOTO: - out($f,$prolog."(void*)&&".$dsc["op"]."_SPEC".$prefix[$op1].$prefix[$op2]."_HANDLER,\n"); - break; - } - } else { - // Emit pinter to handler of undefined opcode - switch ($kind) { - case ZEND_VM_KIND_CALL: - out($f,$prolog."ZEND_NULL_HANDLER,\n"); - break; - case ZEND_VM_KIND_SWITCH: - out($f,$prolog."(void*)(uintptr_t)-1,\n"); - break; - case ZEND_VM_KIND_GOTO: - out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n"); - break; + $do($op1, $op2); + } + } + }; + }; + $foreach_op_data = function($do) use ($dsc, $op_types) { + return function($op1, $op2, $extra_spec = array()) use ($do, $dsc, $op_types) { + // For each op_data.op_type except ANY + foreach($op_types as $op_data) { + if ($op_data != "ANY") { + if (!isset($dsc["spec"]["op_data"][$op_data])) { + if (($op_data == "TMP" || $op_data == "VAR") && isset($dsc["spec"]["op_data"]["TMPVAR"])) { + $op_data = "TMPVAR"; + } else { + // Try to use unspecialized handler + $op_data = "ANY"; } } + $do($op1, $op2, array("op_data" => $op_data) + $extra_spec); } } + }; + }; + $foreach_extra_spec = function($do, $spec) use ($dsc) { + return function($op1, $op2, $extra_spec = array()) use ($do, $spec, $dsc) { + foreach ($dsc["spec"][$spec] as $val) { + $do($op1, $op2, array($spec => $val) + $extra_spec); + } + }; + }; + $generate = function ($op1, $op2, $extra_spec = array()) use ($f, $kind, $dsc, $prefix, $prolog, $num, $switch_labels, &$label) { + global $typecode; + + // Check if specialized handler is defined + /* TODO: figure out better way to signal "specialized and not defined" than an extra lookup */ + if (isset($dsc["op1"][$op1]) && + isset($dsc["op2"][$op2]) && + (!isset($extra_spec["op_data"]) || isset($dsc["spec"]["op_data"][$extra_spec["op_data"]]))) { + // Emit pointer to specialized handler + $spec_name = $dsc["op"]."_SPEC".$prefix[$op1].$prefix[$op2].extra_spec_name($extra_spec); + switch ($kind) { + case ZEND_VM_KIND_CALL: + out($f,"$prolog{$spec_name}_HANDLER,\n"); + $label++; + break; + case ZEND_VM_KIND_SWITCH: + out($f,$prolog."(void*)(uintptr_t)$switch_labels[$spec_name],\n"); + $label++; + break; + case ZEND_VM_KIND_GOTO: + out($f,$prolog."(void*)&&{$spec_name}_HANDLER,\n"); + $label++; + break; + } + } else { + // Emit pointer to handler of undefined opcode + switch ($kind) { + case ZEND_VM_KIND_CALL: + out($f,$prolog."ZEND_NULL_HANDLER,\n"); + $label++; + break; + case ZEND_VM_KIND_SWITCH: + out($f,$prolog."(void*)(uintptr_t)-1,\n"); + $label++; + break; + case ZEND_VM_KIND_GOTO: + out($f,$prolog."(void*)&&ZEND_NULL_HANDLER,\n"); + $label++; + break; + } } + }; + + $do = $generate; + if ($spec_extra) { + foreach ($spec_extra as $extra => $devnull) { + if ($extra == "op_data") { + $do = $foreach_op_data($do); + } else { + $do = $foreach_extra_spec($do, $extra); + } + } + } + if ($spec_op2) { + $do = $foreach_op2($do); } + if ($spec_op1) { + $do = $foreach_op1($do); + } + + $do("ANY", "ANY"); } } else { // Emit labels for unspecialized executor @@ -1032,6 +1149,21 @@ function gen_labels($f, $spec, $kind, $prolog) { out($f,$prolog."(void*)&&ZEND_NULL_HANDLER\n"); break; } + $specs[$num + 1] = "$label"; +} + +// Generates specialized offsets +function gen_specs($f, $spec, $kind, $prolog, $specs) { + $lastdef = array_pop($specs); + $last = 0; + foreach ($specs as $num => $def) { + while (++$last < $num) { + out($f, "$prolog$lastdef,\n"); + } + $last = $num; + out($f, "$prolog$def,\n"); + } + out($f, "$prolog$lastdef\n"); } // Generates handler for undefined opcodes (CALL threading model) @@ -1052,8 +1184,77 @@ function gen_null_handler($f) { } } +function extra_spec_name($extra_spec) { + global $prefix; + + $s = ""; + if (isset($extra_spec["op_data"])) { + $s .= "_OP_DATA" . $prefix[$extra_spec["op_data"]]; + } + if (isset($extra_spec["retval"])) { + $s .= "_RETVAL_".($extra_spec["retval"] ? "USED" : "UNUSED"); + } + if (isset($extra_spec["quick_arg"])) { + if ($extra_spec["quick_arg"]) { + $s .= "_QUICK"; + } + } + return $s; +} + +function extra_spec_flags($extra_spec) { + $s = array(); + if (isset($extra_spec["op_data"])) { + $s[] = "SPEC_RULE_OP_DATA"; + } + if (isset($extra_spec["retval"])) { + $s[] = "SPEC_RULE_RETVAL"; + } + if (isset($extra_spec["quick_arg"])) { + $s[] = "SPEC_RULE_QUICK_ARG"; + } + return $s; +} + +function extra_spec_handler($dsc) { + global $op_types_ex; + + if (!isset($dsc["spec"])) { + return array(array()); + } + $specs = $dsc["spec"]; + + if (isset($specs["op_data"])) { + $op_data_specs = $specs["op_data"]; + $specs["op_data"] = array(); + foreach($op_types_ex as $op_data) { + if (isset($dsc["spec"]["op_data"][$op_data])) { + $specs["op_data"][] = $op_data; + } + } + } + + $f = function($specs) use (&$f) { + $spec = key($specs); + $top = array_shift($specs); + if ($specs) { + $next = $f($specs); + } else { + $next = array(array()); + } + $ret = array(); + foreach ($next as $existing) { + foreach ($top as $mode) { + $ret[] = array($spec => $mode) + $existing; + } + } + return $ret; + }; + return $f($specs); +} + // Generates all opcode handlers and helpers (specialized or unspecilaized) -function gen_executor_code($f, $spec, $kind, $prolog) { +function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array()) { global $list, $opcodes, $helpers, $op_types_ex; if ($spec) { @@ -1068,11 +1269,13 @@ function gen_executor_code($f, $spec, $kind, $prolog) { foreach ($list as $lineno => $dsc) { if (isset($dsc["handler"])) { $num = $dsc["handler"]; - // Check if handler accepts such types of operands (op1 and op2) - if (isset($opcodes[$num]["op1"][$op1]) && - isset($opcodes[$num]["op2"][$op2])) { - // Generate handler code - gen_handler($f, 1, $kind, $opcodes[$num]["op"], $op1, $op2, isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno); + foreach (extra_spec_handler($opcodes[$num]) as $extra_spec) { + // Check if handler accepts such types of operands (op1 and op2) + if (isset($opcodes[$num]["op1"][$op1]) && + isset($opcodes[$num]["op2"][$op2])) { + // Generate handler code + gen_handler($f, 1, $kind, $opcodes[$num]["op"], $op1, $op2, isset($opcodes[$num]["use"]), $opcodes[$num]["code"], $lineno, $extra_spec, $switch_labels); + } } } else if (isset($dsc["helper"])) { $num = $dsc["helper"]; @@ -1142,13 +1345,22 @@ function skip_blanks($f, $prolog, $epilog) { function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) { global $params, $skeleton_file, $line_no; - $lineno = 0; + $switch_labels = array(); + $lineno = 0; foreach ($skl as $line) { // Skeleton file contains special markers in form %NAME% those are // substituted by custom code if (preg_match("/(.*)[{][%]([A-Z_]*)[%][}](.*)/", $line, $m)) { switch ($m[2]) { case "DEFINES": + out($f,"#define SPEC_START_MASK 0x0000ffff\n"); + out($f,"#define SPEC_RULE_OP1 0x00010000\n"); + out($f,"#define SPEC_RULE_OP2 0x00020000\n"); + out($f,"#define SPEC_RULE_OP_DATA 0x00040000\n"); + out($f,"#define SPEC_RULE_RETVAL 0x00080000\n"); + out($f,"#define SPEC_RULE_QUICK_ARG 0x00100000\n"); + out($f,"\n"); + out($f,"static const uint32_t *zend_spec_handlers;\n"); out($f,"static const void **zend_opcode_handlers;\n"); out($f,"static const void *zend_vm_get_opcode_handler(zend_uchar opcode, const zend_op* op);\n\n"); switch ($kind) { @@ -1334,9 +1546,13 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) $prolog = $m[1]; out($f,$prolog."if (UNEXPECTED(execute_data == NULL)) {\n"); out($f,$prolog."\tstatic const void* labels[] = {\n"); - gen_labels($f, $spec, $kind, $prolog."\t\t"); + gen_labels($f, $spec, $kind, $prolog."\t\t", $specs); out($f,$prolog."\t};\n"); - out($f,$prolog."\tzend_opcode_handlers = (const void **)labels;\n"); + out($f,$prolog."static const uint32_t specs[] = {\n"); + gen_specs($f, $spec, $kind, $prolog."\t", $specs); + out($f,$prolog."};\n"); + out($f,$prolog."\tzend_opcode_handlers = (const void **) labels;\n"); + out($f,$prolog."\tzend_spec_handlers = (const uint32_t *) specs;\n"); out($f,$prolog."\treturn;\n"); out($f,$prolog."}\n"); } else { @@ -1397,7 +1613,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) "#endif\n"); } else { // Emit executor code - gen_executor_code($f, $spec, $kind, $m[1]); + gen_executor_code($f, $spec, $kind, $m[1], $switch_labels); } break; case "EXTERNAL_EXECUTOR": @@ -1418,9 +1634,13 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name) out($f,$prolog.$executor_name."_ex(NULL);\n"); } else { out($f,$prolog."static const void *labels[] = {\n"); - gen_labels($f, $spec, $kind, $prolog."\t"); + gen_labels($f, $spec, $kind, $prolog."\t", $specs, $switch_labels); + out($f,$prolog."};\n"); + out($f,$prolog."static const uint32_t specs[] = {\n"); + gen_specs($f, $spec, $kind, $prolog."\t", $specs); out($f,$prolog."};\n"); out($f,$prolog."zend_opcode_handlers = labels;\n"); + out($f,$prolog."zend_spec_handlers = specs;\n"); } break; default: @@ -1445,7 +1665,7 @@ function parse_operand_spec($def, $lineno, $str, &$flags) { die("ERROR ($def:$lineno): Wrong operand type '$str'\n"); } } - if (!($flags & ZEND_VM_OP1_SPEC)) { + if (!($flags & ZEND_VM_OP_SPEC)) { if (count($a) != 1) { die("ERROR ($def:$lineno): Wrong operand type '$str'\n"); } @@ -1469,6 +1689,37 @@ function parse_ext_spec($def, $lineno, $str) { return $flags; } +function parse_spec_rules($def, $lineno, $str) { + $ret = array(); + $a = explode(",", $str); + foreach($a as $rule) { + $n = strpos($rule, "="); + if ($n !== false) { + $id = trim(substr($rule, 0, $n)); + $val = trim(substr($rule, $n+1)); + switch ($id) { + case "OP_DATA": + $ret["op_data"] = parse_operand_spec($def, $lineno, $val, $devnull); + break; + default: + die("ERROR ($def:$lineno): Wrong specialization rules '$str'\n"); + } + } else { + switch ($rule) { + case "RETVAL": + $ret["retval"] = array(0, 1); + break; + case "QUICK_ARG": + $ret["quick_arg"] = array(0, 1); + break; + default: + die("ERROR ($def:$lineno): Wrong specialization rules '$str'\n"); + } + } + } + return $ret; +} + function gen_vm($def, $skel) { global $definition_file, $skeleton_file, $executor_file, $op_types, $list, $opcodes, $helpers, $params, $opnames, @@ -1502,7 +1753,7 @@ function gen_vm($def, $skel) { if (strpos($line,"ZEND_VM_HANDLER(") === 0) { // Parsing opcode handler's definition if (preg_match( - "/^ZEND_VM_HANDLER\(\s*([0-9]+)\s*,\s*([A-Z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?\)/", + "/^ZEND_VM_HANDLER\(\s*([0-9]+)\s*,\s*([A-Z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?(,\s*SPEC\(([A-Z_|=,]+)\)\s*)?\)/", $line, $m) == 0) { die("ERROR ($def:$lineno): Invalid ZEND_VM_HANDLER definition.\n"); @@ -1513,7 +1764,7 @@ function gen_vm($def, $skel) { $op1 = parse_operand_spec($def, $lineno, $m[3], $flags1); $op2 = parse_operand_spec($def, $lineno, $m[4], $flags2); $flags = $flags1 | ($flags2 << 8); - if (isset($m[6])) { + if (!empty($m[6])) { $flags |= parse_ext_spec($def, $lineno, $m[6]); } @@ -1530,6 +1781,9 @@ function gen_vm($def, $skel) { die("ERROR ($def:$lineno): Opcode with name '$op' is already defined.\n"); } $opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags); + if (isset($m[8])) { + $opcodes[$code]["spec"] = parse_spec_rules($def, $lineno, $m[8]); + } $opnames[$op] = $code; $handler = $code; $helper = null; @@ -1649,6 +1903,8 @@ function gen_vm($def, $skel) { foreach($vm_op_flags as $name => $val) { fprintf($f, "#define %-24s 0x%08x\n", $name, $val); } + fputs($f, "#define ZEND_VM_OP1_FLAGS(flags) (flags & 0xff)\n"); + fputs($f, "#define ZEND_VM_OP2_FLAGS(flags) ((flags >> 8) & 0xff)\n"); fputs($f, "\n"); fputs($f, "BEGIN_EXTERN_C()\n\n"); fputs($f, "ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);\n"); @@ -1751,26 +2007,33 @@ function gen_vm($def, $skel) { if (!ZEND_VM_SPEC) { out($f, "\treturn zend_opcode_handlers[opcode];\n"); } else { - out($f, "\t\tstatic const int zend_vm_decode[] = {\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 0 */\n"); - out($f, "\t\t\t_CONST_CODE, /* 1 = IS_CONST */\n"); - out($f, "\t\t\t_TMP_CODE, /* 2 = IS_TMP_VAR */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 3 */\n"); - out($f, "\t\t\t_VAR_CODE, /* 4 = IS_VAR */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 5 */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 6 */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 7 */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 8 = IS_UNUSED */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 9 */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 10 */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 11 */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 12 */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 13 */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 14 */\n"); - out($f, "\t\t\t_UNUSED_CODE, /* 15 */\n"); - out($f, "\t\t\t_CV_CODE /* 16 = IS_CV */\n"); - out($f, "\t\t};\n"); - out($f, "\t\treturn zend_opcode_handlers[opcode * 25 + zend_vm_decode[op->op1_type] * 5 + zend_vm_decode[op->op2_type]];\n"); + out($f, "\tstatic const int zend_vm_decode[] = {\n"); + out($f, "\t\t_UNUSED_CODE, /* 0 */\n"); + out($f, "\t\t_CONST_CODE, /* 1 = IS_CONST */\n"); + out($f, "\t\t_TMP_CODE, /* 2 = IS_TMP_VAR */\n"); + out($f, "\t\t_UNUSED_CODE, /* 3 */\n"); + out($f, "\t\t_VAR_CODE, /* 4 = IS_VAR */\n"); + out($f, "\t\t_UNUSED_CODE, /* 5 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 6 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 7 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 8 = IS_UNUSED */\n"); + out($f, "\t\t_UNUSED_CODE, /* 9 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 10 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 11 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 12 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 13 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 14 */\n"); + out($f, "\t\t_UNUSED_CODE, /* 15 */\n"); + out($f, "\t\t_CV_CODE /* 16 = IS_CV */\n"); + out($f, "\t};\n"); + out($f, "\tuint32_t spec = zend_spec_handlers[opcode];\n"); + out($f, "\tuint32_t offset = 0;\n"); + out($f, "\tif (spec & SPEC_RULE_OP1) offset = offset * 5 + zend_vm_decode[op->op1_type];\n"); + out($f, "\tif (spec & SPEC_RULE_OP2) offset = offset * 5 + zend_vm_decode[op->op2_type];\n"); + out($f, "\tif (spec & SPEC_RULE_OP_DATA) offset = offset * 5 + zend_vm_decode[(op + 1)->op1_type];\n"); + out($f, "\tif (spec & SPEC_RULE_RETVAL) offset = offset * 2 + (op->result_type != IS_UNUSED);\n"); + out($f, "\tif (spec & SPEC_RULE_QUICK_ARG) offset = offset * 2 + (op->op2.num < MAX_ARG_FLAG_NUM);\n"); + out($f, "\treturn zend_opcode_handlers[(spec & SPEC_START_MASK) + offset];\n"); } out($f, "}\n\n"); diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c index a2ed83ee9e..37ba8d411b 100644 --- a/Zend/zend_vm_opcodes.c +++ b/Zend/zend_vm_opcodes.c @@ -21,7 +21,7 @@ #include <stdio.h> #include <zend.h> -static const char *zend_vm_opcodes_names[183] = { +static const char *zend_vm_opcodes_names[184] = { "ZEND_NOP", "ZEND_ADD", "ZEND_SUB", @@ -205,9 +205,10 @@ static const char *zend_vm_opcodes_names[183] = { "ZEND_ISSET_ISEMPTY_STATIC_PROP", "ZEND_FETCH_CLASS_CONSTANT", "ZEND_BIND_LEXICAL", + "ZEND_BIND_STATIC", }; -static uint32_t zend_vm_opcodes_flags[183] = { +static uint32_t zend_vm_opcodes_flags[184] = { 0x00000000, 0x00000707, 0x00000707, @@ -269,7 +270,7 @@ static uint32_t zend_vm_opcodes_flags[183] = { 0x00000001, 0x01000300, 0x00000000, - 0x01000300, + 0x01000310, 0x00000003, 0x00000010, 0x00000310, @@ -391,6 +392,7 @@ static uint32_t zend_vm_opcodes_flags[183] = { 0x00027307, 0x00000373, 0x00100101, + 0x00100301, }; ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) { diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h index bb677134c6..768dbb87c8 100644 --- a/Zend/zend_vm_opcodes.h +++ b/Zend/zend_vm_opcodes.h @@ -28,30 +28,18 @@ #define ZEND_VM_KIND_GOTO 3 #define ZEND_VM_KIND ZEND_VM_KIND_CALL -#define ZEND_VM_OP1_SPEC 0x00000001 -#define ZEND_VM_OP1_CONST 0x00000002 -#define ZEND_VM_OP1_TMPVAR 0x00000004 -#define ZEND_VM_OP1_MASK 0x000000f0 -#define ZEND_VM_OP1_NUM 0x00000010 -#define ZEND_VM_OP1_JMP_ADDR 0x00000020 -#define ZEND_VM_OP1_TRY_CATCH 0x00000030 -#define ZEND_VM_OP1_LIVE_RANGE 0x00000040 -#define ZEND_VM_OP1_THIS 0x00000050 -#define ZEND_VM_OP1_NEXT 0x00000060 -#define ZEND_VM_OP1_CLASS_FETCH 0x00000070 -#define ZEND_VM_OP1_CONSTRUCTOR 0x00000080 -#define ZEND_VM_OP2_SPEC 0x00000100 -#define ZEND_VM_OP2_CONST 0x00000200 -#define ZEND_VM_OP2_TMPVAR 0x00000400 -#define ZEND_VM_OP2_MASK 0x0000f000 -#define ZEND_VM_OP2_NUM 0x00001000 -#define ZEND_VM_OP2_JMP_ADDR 0x00002000 -#define ZEND_VM_OP2_TRY_CATCH 0x00003000 -#define ZEND_VM_OP2_LIVE_RANGE 0x00004000 -#define ZEND_VM_OP2_THIS 0x00005000 -#define ZEND_VM_OP2_NEXT 0x00006000 -#define ZEND_VM_OP2_CLASS_FETCH 0x00007000 -#define ZEND_VM_OP2_CONSTRUCTOR 0x00008000 +#define ZEND_VM_OP_SPEC 0x00000001 +#define ZEND_VM_OP_CONST 0x00000002 +#define ZEND_VM_OP_TMPVAR 0x00000004 +#define ZEND_VM_OP_MASK 0x000000f0 +#define ZEND_VM_OP_NUM 0x00000010 +#define ZEND_VM_OP_JMP_ADDR 0x00000020 +#define ZEND_VM_OP_TRY_CATCH 0x00000030 +#define ZEND_VM_OP_LIVE_RANGE 0x00000040 +#define ZEND_VM_OP_THIS 0x00000050 +#define ZEND_VM_OP_NEXT 0x00000060 +#define ZEND_VM_OP_CLASS_FETCH 0x00000070 +#define ZEND_VM_OP_CONSTRUCTOR 0x00000080 #define ZEND_VM_EXT_VAR_FETCH 0x00010000 #define ZEND_VM_EXT_ISSET 0x00020000 #define ZEND_VM_EXT_ARG_NUM 0x00040000 @@ -69,6 +57,8 @@ #define ZEND_VM_EXT_FAST_RET 0x0a000000 #define ZEND_VM_EXT_SRC 0x0b000000 #define ZEND_VM_EXT_SEND 0x0c000000 +#define ZEND_VM_OP1_FLAGS(flags) (flags & 0xff) +#define ZEND_VM_OP2_FLAGS(flags) ((flags >> 8) & 0xff) BEGIN_EXTERN_C() @@ -255,7 +245,8 @@ END_EXTERN_C() #define ZEND_ISSET_ISEMPTY_STATIC_PROP 180 #define ZEND_FETCH_CLASS_CONSTANT 181 #define ZEND_BIND_LEXICAL 182 +#define ZEND_BIND_STATIC 183 -#define ZEND_VM_LAST_OPCODE 182 +#define ZEND_VM_LAST_OPCODE 183 #endif diff --git a/acinclude.m4 b/acinclude.m4 index e828de1fd6..70b1a79894 100644 --- a/acinclude.m4 +++ b/acinclude.m4 @@ -2685,20 +2685,21 @@ EOF else CONFIGURE_COMMAND="$CONFIGURE_COMMAND [$]0" fi - for arg in $ac_configure_args; do - if test `expr -- $arg : "'.*"` = 0; then - if test `expr -- $arg : "-.*"` = 0 && test `expr -- $arg : ".*=.*"` = 0; then - continue; - fi - echo "'[$]arg' \\" >> $1 - CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS '[$]arg'" - else - if test `expr -- $arg : "'-.*"` = 0 && test `expr -- $arg : "'.*=.*"` = 0; then - continue; - fi - echo "[$]arg \\" >> $1 - CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS [$]arg" - fi + CONFIGURE_ARGS="$ac_configure_args" + while test "X$CONFIGURE_ARGS" != "X"; + do + if CURRENT_ARG=`expr "X$CONFIGURE_ARGS" : "X *\('[[^']]*'\)"` + then + CONFIGURE_ARGS=`expr "X$CONFIGURE_ARGS" : "X *'[[^']]*' \(.*\)"` + elif CURRENT_ARG=`expr "X$CONFIGURE_ARGS" : "X *\([[^ ]]*\)"` + then + CONFIGURE_ARGS=`expr "X$CONFIGURE_ARGS" : "X *[[^ ]]* \(.*\)"` + CURRENT_ARG="'$CURRENT_ARG'" + else + break + fi + $as_echo "$CURRENT_ARG \\" >>$1 + CONFIGURE_OPTIONS="$CONFIGURE_OPTIONS $CURRENT_ARG" done echo '"[$]@"' >> $1 chmod +x $1 diff --git a/ext/curl/config.w32 b/ext/curl/config.w32 index 965721318e..8ea5f6524c 100644 --- a/ext/curl/config.w32 +++ b/ext/curl/config.w32 @@ -13,7 +13,7 @@ if (PHP_CURL != "no") { && (((PHP_ZLIB=="no") && (CHECK_LIB("zlib_a.lib;zlib.lib", "curl", PHP_CURL))) || (PHP_ZLIB_SHARED && CHECK_LIB("zlib.lib", "curl", PHP_CURL)) || (PHP_ZLIB == "yes" && (!PHP_ZLIB_SHARED))) ) { - EXTENSION("curl", "interface.c multi.c share.c curl_file.c", true); + EXTENSION("curl", "interface.c multi.c share.c curl_file.c"); AC_DEFINE('HAVE_CURL', 1, 'Have cURL library'); AC_DEFINE('HAVE_CURL_SSL', 1, 'Have SSL suppurt in cURL'); AC_DEFINE('HAVE_CURL_EASY_STRERROR', 1, 'Have curl_easy_strerror in cURL'); diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 47b3b6fc41..564d9fcb1c 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -157,7 +157,8 @@ static void _php_curl_close(zend_resource *rsrc); #define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s) - 1, (zend_long) v); #define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s) - 1, (double) v); #define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s) - 1, (char *) (v ? v : "")); -#define CAASTR(s, v) add_assoc_str_ex(return_value, s, sizeof(s) - 1, v ? v : ZSTR_EMPTY_ALLOC()); +#define CAASTR(s, v) add_assoc_str_ex(return_value, s, sizeof(s) - 1, \ + v ? zend_string_copy(v) : ZSTR_EMPTY_ALLOC()); #define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s) -1 , (zval *) v); #if defined(PHP_WIN32) || defined(__GNUC__) @@ -1751,7 +1752,7 @@ static php_curl *alloc_curl_handle() memset(&ch->err, 0, sizeof(struct _php_curl_error)); zend_llist_init(&ch->to_free->str, sizeof(char *), (llist_dtor_func_t)curl_free_string, 0); - zend_llist_init(&ch->to_free->post, sizeof(struct HttpPost), (llist_dtor_func_t)curl_free_post, 0); + zend_llist_init(&ch->to_free->post, sizeof(struct HttpPost *), (llist_dtor_func_t)curl_free_post, 0); ch->to_free->slist = emalloc(sizeof(HashTable)); zend_hash_init(ch->to_free->slist, 4, NULL, curl_free_slist, 0); @@ -2475,7 +2476,11 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{ } } ZEND_HASH_FOREACH_END(); - zend_hash_index_update_ptr(ch->to_free->slist, option, slist); + if ((*ch->clone) == 1) { + zend_hash_index_update_ptr(ch->to_free->slist, option, slist); + } else { + zend_hash_next_index_insert_ptr(ch->to_free->slist, slist); + } error = curl_easy_setopt(ch->cp, option, slist); @@ -3032,7 +3037,7 @@ PHP_FUNCTION(curl_getinfo) } #endif if (ch->header.str) { - CAASTR("request_header", zend_string_copy(ch->header.str)); + CAASTR("request_header", ch->header.str); } } else { switch (option) { diff --git a/ext/curl/tests/bug64267.phpt b/ext/curl/tests/bug64267.phpt index 5d5330fef3..ca1fe4b368 100644 --- a/ext/curl/tests/bug64267.phpt +++ b/ext/curl/tests/bug64267.phpt @@ -2,6 +2,7 @@ Bug #64267 (CURLOPT_INFILE doesn't allow reset) --SKIPIF-- <?php +if (getenv("SKIP_ONLINE_TESTS")) die("skip online test"); extension_loaded("curl") or die("skip need ext/curl"); ?> --FILE-- diff --git a/ext/curl/tests/bug71523.phpt b/ext/curl/tests/bug71523.phpt new file mode 100644 index 0000000000..24aa83c620 --- /dev/null +++ b/ext/curl/tests/bug71523.phpt @@ -0,0 +1,31 @@ +--TEST-- +Bug #71523 (Copied handle with new option CURLOPT_HTTPHEADER crashes while curl_multi_exec) +--SKIPIF-- +<?php +if (!extension_loaded("curl")) { + exit("skip curl extension not loaded"); +} +if (getenv("SKIP_ONLINE_TESTS")) { + die("skip online test"); +} +?> +--FILE-- +<?php + +$base = curl_init('http://www.google.com/'); +curl_setopt($base, CURLOPT_RETURNTRANSFER, true); +$mh = curl_multi_init(); + +for ($i = 0; $i < 2; ++$i) { + $ch = curl_copy_handle($base); + curl_setopt($ch, CURLOPT_HTTPHEADER, ['Foo: Bar']); + curl_multi_add_handle($mh, $ch); +} + +do { + curl_multi_exec($mh, $active); +} while ($active); +?> +okey +--EXPECTF-- +okey diff --git a/ext/date/lib/interval.c b/ext/date/lib/interval.c index 6a3403fc3e..9c1cc3b273 100644 --- a/ext/date/lib/interval.c +++ b/ext/date/lib/interval.c @@ -70,7 +70,7 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two) rt->i += dst_m_corr; } - rt->days = abs(floor((one->sse - two->sse - (dst_h_corr * 3600) - (dst_m_corr * 60)) / 86400)); + rt->days = fabs(floor((one->sse - two->sse - (dst_h_corr * 3600) - (dst_m_corr * 60)) / 86400)); timelib_do_rel_normalize(rt->invert ? one : two, rt); diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re index 3ff00bec3e..3d4cf6bb61 100644 --- a/ext/date/lib/parse_date.re +++ b/ext/date/lib/parse_date.re @@ -1812,6 +1812,11 @@ timelib_time* timelib_strtotime(char *s, size_t len, struct timelib_error_contai { \ add_pbf_error(s, "Unexpected data found.", string, begin); \ } +#define TIMELIB_CHECK_SIGNED_NUMBER \ + if (strchr("-0123456789", *ptr) == NULL) \ + { \ + add_pbf_error(s, "Unexpected data found.", string, begin); \ + } static void timelib_time_reset_fields(timelib_time *time) { @@ -2016,7 +2021,7 @@ timelib_time *timelib_parse_from_format(char *format, char *string, size_t len, timelib_eat_spaces((char **) &ptr); break; case 'U': /* epoch seconds */ - TIMELIB_CHECK_NUMBER; + TIMELIB_CHECK_SIGNED_NUMBER; TIMELIB_HAVE_RELATIVE(); tmp = timelib_get_unsigned_nr((char **) &ptr, 24); s->time->y = 1970; diff --git a/ext/date/lib/timelib.c b/ext/date/lib/timelib.c index 73cdfa2d85..b938d9f998 100644 --- a/ext/date/lib/timelib.c +++ b/ext/date/lib/timelib.c @@ -65,6 +65,23 @@ timelib_time* timelib_time_clone(timelib_time *orig) return tmp; } +int timelib_time_compare(timelib_time *t1, timelib_time *t2) +{ + if (t1->sse == t2->sse) { + if (t1->f == t2->f) { + return 0; + } + + if (t1->sse < 0) { + return (t1->f < t2->f) ? 1 : -1; + } else { + return (t1->f < t2->f) ? -1 : 1; + } + } + + return (t1->sse < t2->sse) ? -1 : 1; +} + timelib_rel_time* timelib_rel_time_clone(timelib_rel_time *rel) { timelib_rel_time *tmp = timelib_rel_time_ctor(); diff --git a/ext/date/lib/timelib.h b/ext/date/lib/timelib.h index 125b8b21ad..fe1069bdde 100644 --- a/ext/date/lib/timelib.h +++ b/ext/date/lib/timelib.h @@ -138,6 +138,7 @@ timelib_time* timelib_time_ctor(void); void timelib_time_set_option(timelib_time* tm, int option, void* option_value); void timelib_time_dtor(timelib_time* t); timelib_time* timelib_time_clone(timelib_time* orig); +int timelib_time_compare(timelib_time *t1, timelib_time *t2); timelib_time_offset* timelib_time_offset_ctor(void); void timelib_time_offset_dtor(timelib_time_offset* t); diff --git a/ext/date/lib/timezonedb.h b/ext/date/lib/timezonedb.h index ed56507cb3..df521607a3 100644 --- a/ext/date/lib/timezonedb.h +++ b/ext/date/lib/timezonedb.h @@ -98,502 +98,502 @@ const timelib_tzdb_index_entry timezonedb_idx_builtin[584] = { { "America/Catamarca" , FOR_V2(0x00F876, 0x0064F3) }, { "America/Cayenne" , FOR_V2(0x00FCEB, 0x0066B2) }, { "America/Cayman" , FOR_V2(0x00FDBF, 0x006719) }, - { "America/Chicago" , FOR_V2(0x010128, 0x006867) }, - { "America/Chihuahua" , FOR_V2(0x010F41, 0x006D97) }, - { "America/Coral_Harbour" , FOR_V2(0x011574, 0x00700F) }, - { "America/Cordoba" , FOR_V2(0x0116D9, 0x0070B2) }, - { "America/Costa_Rica" , FOR_V2(0x011B4E, 0x007271) }, - { "America/Creston" , FOR_V2(0x011CAF, 0x00730C) }, - { "America/Cuiaba" , FOR_V2(0x011DD6, 0x0073B1) }, - { "America/Curacao" , FOR_V2(0x0125B0, 0x007694) }, - { "America/Danmarkshavn" , FOR_V2(0x01268C, 0x0076FF) }, - { "America/Dawson" , FOR_V2(0x012983, 0x007848) }, - { "America/Dawson_Creek" , FOR_V2(0x0131D6, 0x007B76) }, - { "America/Denver" , FOR_V2(0x01364E, 0x007D61) }, - { "America/Detroit" , FOR_V2(0x013FFC, 0x0080F8) }, - { "America/Dominica" , FOR_V2(0x0148D8, 0x00845C) }, - { "America/Edmonton" , FOR_V2(0x01498E, 0x0084B6) }, - { "America/Eirunepe" , FOR_V2(0x01533E, 0x008873) }, - { "America/El_Salvador" , FOR_V2(0x015600, 0x008998) }, - { "America/Ensenada" , FOR_V2(0x015706, 0x008A12) }, - { "America/Fort_Nelson" , FOR_V2(0x016046, 0x008D80) }, - { "America/Fort_Wayne" , FOR_V2(0x016951, 0x009101) }, - { "America/Fortaleza" , FOR_V2(0x016FE8, 0x00937C) }, - { "America/Glace_Bay" , FOR_V2(0x0172EA, 0x0094BF) }, - { "America/Godthab" , FOR_V2(0x017BBD, 0x00981D) }, - { "America/Goose_Bay" , FOR_V2(0x01832C, 0x009AE6) }, - { "America/Grand_Turk" , FOR_V2(0x018FF4, 0x009FBC) }, - { "America/Grenada" , FOR_V2(0x019507, 0x00A1AC) }, - { "America/Guadeloupe" , FOR_V2(0x0195BD, 0x00A206) }, - { "America/Guatemala" , FOR_V2(0x019673, 0x00A260) }, - { "America/Guayaquil" , FOR_V2(0x0197B1, 0x00A2EE) }, - { "America/Guyana" , FOR_V2(0x019890, 0x00A35C) }, - { "America/Halifax" , FOR_V2(0x0199AA, 0x00A3E2) }, - { "America/Havana" , FOR_V2(0x01A750, 0x00A8FB) }, - { "America/Hermosillo" , FOR_V2(0x01B0E1, 0x00AC7F) }, - { "America/Indiana/Indianapolis" , FOR_V2(0x01B2D2, 0x00AD6A) }, - { "America/Indiana/Knox" , FOR_V2(0x01B990, 0x00B00C) }, - { "America/Indiana/Marengo" , FOR_V2(0x01C347, 0x00B3BC) }, - { "America/Indiana/Petersburg" , FOR_V2(0x01CA3E, 0x00B673) }, - { "America/Indiana/Tell_City" , FOR_V2(0x01D1E7, 0x00B967) }, - { "America/Indiana/Vevay" , FOR_V2(0x01D8DF, 0x00BC21) }, - { "America/Indiana/Vincennes" , FOR_V2(0x01DEA5, 0x00BE6D) }, - { "America/Indiana/Winamac" , FOR_V2(0x01E598, 0x00C132) }, - { "America/Indianapolis" , FOR_V2(0x01ECC6, 0x00C3FC) }, - { "America/Inuvik" , FOR_V2(0x01F35D, 0x00C677) }, - { "America/Iqaluit" , FOR_V2(0x01FB1B, 0x00C973) }, - { "America/Jamaica" , FOR_V2(0x020351, 0x00CCAA) }, - { "America/Jujuy" , FOR_V2(0x020558, 0x00CD80) }, - { "America/Juneau" , FOR_V2(0x0209DD, 0x00CF4B) }, - { "America/Kentucky/Louisville" , FOR_V2(0x021341, 0x00D2DA) }, - { "America/Kentucky/Monticello" , FOR_V2(0x021E53, 0x00D709) }, - { "America/Knox_IN" , FOR_V2(0x0227BE, 0x00DA9F) }, - { "America/Kralendijk" , FOR_V2(0x02314F, 0x00DE29) }, - { "America/La_Paz" , FOR_V2(0x02322B, 0x00DE94) }, - { "America/Lima" , FOR_V2(0x02332A, 0x00DF0C) }, - { "America/Los_Angeles" , FOR_V2(0x0234D7, 0x00DFC1) }, - { "America/Louisville" , FOR_V2(0x02400C, 0x00E3E3) }, - { "America/Lower_Princes" , FOR_V2(0x024AF5, 0x00E7E9) }, - { "America/Maceio" , FOR_V2(0x024BD1, 0x00E854) }, - { "America/Managua" , FOR_V2(0x024EE1, 0x00E993) }, - { "America/Manaus" , FOR_V2(0x0250BC, 0x00EA5F) }, - { "America/Marigot" , FOR_V2(0x02533A, 0x00EB66) }, - { "America/Martinique" , FOR_V2(0x0253F0, 0x00EBC0) }, - { "America/Matamoros" , FOR_V2(0x0254FD, 0x00EC3D) }, - { "America/Mazatlan" , FOR_V2(0x025ADB, 0x00EE9B) }, - { "America/Mendoza" , FOR_V2(0x02612B, 0x00F115) }, - { "America/Menominee" , FOR_V2(0x0265CC, 0x00F2EA) }, - { "America/Merida" , FOR_V2(0x026F0A, 0x00F684) }, - { "America/Metlakatla" , FOR_V2(0x0274E6, 0x00F8CC) }, - { "America/Mexico_City" , FOR_V2(0x0277EC, 0x00FA18) }, - { "America/Miquelon" , FOR_V2(0x027E67, 0x00FC98) }, - { "America/Moncton" , FOR_V2(0x028507, 0x00FF0F) }, - { "America/Monterrey" , FOR_V2(0x02918B, 0x0103B7) }, - { "America/Montevideo" , FOR_V2(0x029773, 0x01061F) }, - { "America/Montreal" , FOR_V2(0x029D66, 0x010869) }, - { "America/Montserrat" , FOR_V2(0x02AB21, 0x010D6A) }, - { "America/Nassau" , FOR_V2(0x02ABD7, 0x010DC4) }, - { "America/New_York" , FOR_V2(0x02B4CF, 0x01110E) }, - { "America/Nipigon" , FOR_V2(0x02C2C0, 0x01162A) }, - { "America/Nome" , FOR_V2(0x02CB6A, 0x01198C) }, - { "America/Noronha" , FOR_V2(0x02D4D7, 0x011D1B) }, - { "America/North_Dakota/Beulah" , FOR_V2(0x02D7CB, 0x011E50) }, - { "America/North_Dakota/Center" , FOR_V2(0x02E157, 0x0121F5) }, - { "America/North_Dakota/New_Salem" , FOR_V2(0x02EAE3, 0x01259A) }, - { "America/Ojinaga" , FOR_V2(0x02F484, 0x012954) }, - { "America/Panama" , FOR_V2(0x02FAAD, 0x012BC2) }, - { "America/Pangnirtung" , FOR_V2(0x02FB84, 0x012C28) }, - { "America/Paramaribo" , FOR_V2(0x0303EF, 0x012F73) }, - { "America/Phoenix" , FOR_V2(0x03052F, 0x01300A) }, - { "America/Port-au-Prince" , FOR_V2(0x0306CC, 0x0130D9) }, - { "America/Port_of_Spain" , FOR_V2(0x030CA3, 0x01330A) }, - { "America/Porto_Acre" , FOR_V2(0x030D59, 0x013364) }, - { "America/Porto_Velho" , FOR_V2(0x030FF5, 0x013475) }, - { "America/Puerto_Rico" , FOR_V2(0x031255, 0x013570) }, - { "America/Rainy_River" , FOR_V2(0x031360, 0x0135EC) }, - { "America/Rankin_Inlet" , FOR_V2(0x031BF1, 0x013935) }, - { "America/Recife" , FOR_V2(0x0323A5, 0x013C28) }, - { "America/Regina" , FOR_V2(0x032693, 0x013D57) }, - { "America/Resolute" , FOR_V2(0x032AB6, 0x013F1A) }, - { "America/Rio_Branco" , FOR_V2(0x03326C, 0x01420F) }, - { "America/Rosario" , FOR_V2(0x03350C, 0x014324) }, - { "America/Santa_Isabel" , FOR_V2(0x033981, 0x0144E3) }, - { "America/Santarem" , FOR_V2(0x0342FB, 0x01488B) }, - { "America/Santiago" , FOR_V2(0x03457F, 0x014995) }, - { "America/Santo_Domingo" , FOR_V2(0x034D0A, 0x014C78) }, - { "America/Sao_Paulo" , FOR_V2(0x034EFF, 0x014D4F) }, - { "America/Scoresbysund" , FOR_V2(0x03571C, 0x015063) }, - { "America/Shiprock" , FOR_V2(0x035ECC, 0x015356) }, - { "America/Sitka" , FOR_V2(0x03686D, 0x0156E0) }, - { "America/St_Barthelemy" , FOR_V2(0x0371CF, 0x015A6D) }, - { "America/St_Johns" , FOR_V2(0x037285, 0x015AC7) }, - { "America/St_Kitts" , FOR_V2(0x038109, 0x016033) }, - { "America/St_Lucia" , FOR_V2(0x0381BF, 0x01608D) }, - { "America/St_Thomas" , FOR_V2(0x038275, 0x0160E7) }, - { "America/St_Vincent" , FOR_V2(0x03832B, 0x016141) }, - { "America/Swift_Current" , FOR_V2(0x0383E1, 0x01619B) }, - { "America/Tegucigalpa" , FOR_V2(0x038659, 0x0162C1) }, - { "America/Thule" , FOR_V2(0x03877B, 0x016345) }, - { "America/Thunder_Bay" , FOR_V2(0x038D8F, 0x016591) }, - { "America/Tijuana" , FOR_V2(0x039661, 0x0168EB) }, - { "America/Toronto" , FOR_V2(0x039FD1, 0x016C89) }, - { "America/Tortola" , FOR_V2(0x03ADBC, 0x0171BA) }, - { "America/Vancouver" , FOR_V2(0x03AE72, 0x017214) }, - { "America/Virgin" , FOR_V2(0x03B9F7, 0x017662) }, - { "America/Whitehorse" , FOR_V2(0x03BAAD, 0x0176BC) }, - { "America/Winnipeg" , FOR_V2(0x03C300, 0x0179EA) }, - { "America/Yakutat" , FOR_V2(0x03CE7D, 0x017E3B) }, - { "America/Yellowknife" , FOR_V2(0x03D7B6, 0x0181B7) }, - { "Antarctica/Casey" , FOR_V2(0x03DFAB, 0x0184CC) }, - { "Antarctica/Davis" , FOR_V2(0x03E0E6, 0x01856F) }, - { "Antarctica/DumontDUrville" , FOR_V2(0x03E231, 0x018615) }, - { "Antarctica/Macquarie" , FOR_V2(0x03E345, 0x0186AB) }, - { "Antarctica/Mawson" , FOR_V2(0x03E95B, 0x018905) }, - { "Antarctica/McMurdo" , FOR_V2(0x03EA4C, 0x018986) }, - { "Antarctica/Palmer" , FOR_V2(0x03F421, 0x018D42) }, - { "Antarctica/Rothera" , FOR_V2(0x03F9D2, 0x018F8A) }, - { "Antarctica/South_Pole" , FOR_V2(0x03FAAB, 0x019005) }, - { "Antarctica/Syowa" , FOR_V2(0x040453, 0x019394) }, - { "Antarctica/Troll" , FOR_V2(0x040525, 0x019407) }, - { "Antarctica/Vostok" , FOR_V2(0x0409D8, 0x0195DE) }, - { "Arctic/Longyearbyen" , FOR_V2(0x040AAD, 0x019654) }, - { "Asia/Aden" , FOR_V2(0x041384, 0x019997) }, - { "Asia/Almaty" , FOR_V2(0x04143B, 0x0199F1) }, - { "Asia/Amman" , FOR_V2(0x0417FD, 0x019B75) }, - { "Asia/Anadyr" , FOR_V2(0x041F5E, 0x019E30) }, - { "Asia/Aqtau" , FOR_V2(0x04244A, 0x01A03F) }, - { "Asia/Aqtobe" , FOR_V2(0x0428FD, 0x01A24B) }, - { "Asia/Ashgabat" , FOR_V2(0x042D34, 0x01A408) }, - { "Asia/Ashkhabad" , FOR_V2(0x042FDF, 0x01A52A) }, - { "Asia/Baghdad" , FOR_V2(0x04328A, 0x01A64C) }, - { "Asia/Bahrain" , FOR_V2(0x043672, 0x01A7D2) }, - { "Asia/Baku" , FOR_V2(0x04374F, 0x01A83D) }, - { "Asia/Bangkok" , FOR_V2(0x043EFF, 0x01AB2A) }, - { "Asia/Beirut" , FOR_V2(0x043FD7, 0x01AB90) }, - { "Asia/Bishkek" , FOR_V2(0x044862, 0x01AEAE) }, - { "Asia/Brunei" , FOR_V2(0x044C93, 0x01B05F) }, - { "Asia/Calcutta" , FOR_V2(0x044D68, 0x01B0C6) }, - { "Asia/Chita" , FOR_V2(0x044E97, 0x01B150) }, - { "Asia/Choibalsan" , FOR_V2(0x0453AB, 0x01B372) }, - { "Asia/Chongqing" , FOR_V2(0x0459FA, 0x01B5DE) }, - { "Asia/Chungking" , FOR_V2(0x045BA4, 0x01B68F) }, - { "Asia/Colombo" , FOR_V2(0x045D4E, 0x01B740) }, - { "Asia/Dacca" , FOR_V2(0x045EDF, 0x01B7F5) }, - { "Asia/Damascus" , FOR_V2(0x046071, 0x01B8AC) }, - { "Asia/Dhaka" , FOR_V2(0x04698D, 0x01BC01) }, - { "Asia/Dili" , FOR_V2(0x046B1F, 0x01BCB8) }, - { "Asia/Dubai" , FOR_V2(0x046C60, 0x01BD4F) }, - { "Asia/Dushanbe" , FOR_V2(0x046D17, 0x01BDA9) }, - { "Asia/Gaza" , FOR_V2(0x046F86, 0x01BEB1) }, - { "Asia/Harbin" , FOR_V2(0x0478A6, 0x01C215) }, - { "Asia/Hebron" , FOR_V2(0x047A50, 0x01C2C6) }, - { "Asia/Ho_Chi_Minh" , FOR_V2(0x04838B, 0x01C633) }, - { "Asia/Hong_Kong" , FOR_V2(0x04850C, 0x01C6E2) }, - { "Asia/Hovd" , FOR_V2(0x0489BD, 0x01C8B1) }, - { "Asia/Irkutsk" , FOR_V2(0x048FDD, 0x01CB14) }, - { "Asia/Istanbul" , FOR_V2(0x0494EB, 0x01CD20) }, - { "Asia/Jakarta" , FOR_V2(0x049FB2, 0x01D11E) }, - { "Asia/Jayapura" , FOR_V2(0x04A13E, 0x01D1D9) }, - { "Asia/Jerusalem" , FOR_V2(0x04A26C, 0x01D283) }, - { "Asia/Kabul" , FOR_V2(0x04AB51, 0x01D5CB) }, - { "Asia/Kamchatka" , FOR_V2(0x04AC24, 0x01D62D) }, - { "Asia/Karachi" , FOR_V2(0x04B0FF, 0x01D833) }, - { "Asia/Kashgar" , FOR_V2(0x04B29E, 0x01D8ED) }, - { "Asia/Kathmandu" , FOR_V2(0x04B355, 0x01D947) }, - { "Asia/Katmandu" , FOR_V2(0x04B435, 0x01D9B2) }, - { "Asia/Khandyga" , FOR_V2(0x04B515, 0x01DA1D) }, - { "Asia/Kolkata" , FOR_V2(0x04BA6E, 0x01DC54) }, - { "Asia/Krasnoyarsk" , FOR_V2(0x04BB9D, 0x01DCDE) }, - { "Asia/Kuala_Lumpur" , FOR_V2(0x04C08C, 0x01DEE0) }, - { "Asia/Kuching" , FOR_V2(0x04C239, 0x01DFAE) }, - { "Asia/Kuwait" , FOR_V2(0x04C45B, 0x01E0A1) }, - { "Asia/Macao" , FOR_V2(0x04C512, 0x01E0FB) }, - { "Asia/Macau" , FOR_V2(0x04C839, 0x01E23B) }, - { "Asia/Magadan" , FOR_V2(0x04CB60, 0x01E37B) }, - { "Asia/Makassar" , FOR_V2(0x04D067, 0x01E594) }, - { "Asia/Manila" , FOR_V2(0x04D1D3, 0x01E666) }, - { "Asia/Muscat" , FOR_V2(0x04D348, 0x01E704) }, - { "Asia/Nicosia" , FOR_V2(0x04D3FF, 0x01E75E) }, - { "Asia/Novokuznetsk" , FOR_V2(0x04DBEB, 0x01EA4B) }, - { "Asia/Novosibirsk" , FOR_V2(0x04E108, 0x01EC70) }, - { "Asia/Omsk" , FOR_V2(0x04E5E3, 0x01EE65) }, - { "Asia/Oral" , FOR_V2(0x04EAD1, 0x01F066) }, - { "Asia/Phnom_Penh" , FOR_V2(0x04EF38, 0x01F23B) }, - { "Asia/Pontianak" , FOR_V2(0x04F010, 0x01F2A1) }, - { "Asia/Pyongyang" , FOR_V2(0x04F1A8, 0x01F368) }, - { "Asia/Qatar" , FOR_V2(0x04F2EC, 0x01F3FF) }, - { "Asia/Qyzylorda" , FOR_V2(0x04F3C9, 0x01F46A) }, - { "Asia/Rangoon" , FOR_V2(0x04F82F, 0x01F645) }, - { "Asia/Riyadh" , FOR_V2(0x04F958, 0x01F6CE) }, - { "Asia/Saigon" , FOR_V2(0x04FA0F, 0x01F728) }, - { "Asia/Sakhalin" , FOR_V2(0x04FB90, 0x01F7D7) }, - { "Asia/Samarkand" , FOR_V2(0x050082, 0x01F9D9) }, - { "Asia/Seoul" , FOR_V2(0x050350, 0x01FB14) }, - { "Asia/Shanghai" , FOR_V2(0x050597, 0x01FC0C) }, - { "Asia/Singapore" , FOR_V2(0x05074D, 0x01FCC9) }, - { "Asia/Srednekolymsk" , FOR_V2(0x050905, 0x01FD91) }, - { "Asia/Taipei" , FOR_V2(0x050E05, 0x01FF9E) }, - { "Asia/Tashkent" , FOR_V2(0x051131, 0x0200E0) }, - { "Asia/Tbilisi" , FOR_V2(0x0513F5, 0x020216) }, - { "Asia/Tehran" , FOR_V2(0x051877, 0x0203E9) }, - { "Asia/Tel_Aviv" , FOR_V2(0x051F00, 0x020664) }, - { "Asia/Thimbu" , FOR_V2(0x0527E5, 0x0209AC) }, - { "Asia/Thimphu" , FOR_V2(0x0528C2, 0x020A17) }, - { "Asia/Tokyo" , FOR_V2(0x05299F, 0x020A82) }, - { "Asia/Ujung_Pandang" , FOR_V2(0x052B0E, 0x020B19) }, - { "Asia/Ulaanbaatar" , FOR_V2(0x052C32, 0x020BA3) }, - { "Asia/Ulan_Bator" , FOR_V2(0x053235, 0x020DE9) }, - { "Asia/Urumqi" , FOR_V2(0x05382A, 0x021021) }, - { "Asia/Ust-Nera" , FOR_V2(0x0538EE, 0x021088) }, - { "Asia/Vientiane" , FOR_V2(0x053E1E, 0x0212A7) }, - { "Asia/Vladivostok" , FOR_V2(0x053EF6, 0x02130D) }, - { "Asia/Yakutsk" , FOR_V2(0x0543E3, 0x02150C) }, - { "Asia/Yekaterinburg" , FOR_V2(0x0548CF, 0x02170B) }, - { "Asia/Yerevan" , FOR_V2(0x054E22, 0x021939) }, - { "Atlantic/Azores" , FOR_V2(0x05532B, 0x021B3E) }, - { "Atlantic/Bermuda" , FOR_V2(0x0560DD, 0x022052) }, - { "Atlantic/Canary" , FOR_V2(0x0568BD, 0x022338) }, - { "Atlantic/Cape_Verde" , FOR_V2(0x057050, 0x022613) }, - { "Atlantic/Faeroe" , FOR_V2(0x05715A, 0x022691) }, - { "Atlantic/Faroe" , FOR_V2(0x05788B, 0x02293A) }, - { "Atlantic/Jan_Mayen" , FOR_V2(0x057FBC, 0x022BE3) }, - { "Atlantic/Madeira" , FOR_V2(0x058893, 0x022F26) }, - { "Atlantic/Reykjavik" , FOR_V2(0x059644, 0x023440) }, - { "Atlantic/South_Georgia" , FOR_V2(0x059AF6, 0x023612) }, - { "Atlantic/St_Helena" , FOR_V2(0x059B96, 0x023656) }, - { "Atlantic/Stanley" , FOR_V2(0x059C4C, 0x0236B0) }, - { "Australia/ACT" , FOR_V2(0x05A136, 0x023897) }, - { "Australia/Adelaide" , FOR_V2(0x05A9F1, 0x023BCB) }, - { "Australia/Brisbane" , FOR_V2(0x05B2CA, 0x023F0A) }, - { "Australia/Broken_Hill" , FOR_V2(0x05B4B5, 0x023FE8) }, - { "Australia/Canberra" , FOR_V2(0x05BDBF, 0x024339) }, - { "Australia/Currie" , FOR_V2(0x05C67A, 0x02466D) }, - { "Australia/Darwin" , FOR_V2(0x05CF4B, 0x0249B7) }, - { "Australia/Eucla" , FOR_V2(0x05D0AC, 0x024A50) }, - { "Australia/Hobart" , FOR_V2(0x05D2BD, 0x024B3D) }, - { "Australia/LHI" , FOR_V2(0x05DC01, 0x024EB2) }, - { "Australia/Lindeman" , FOR_V2(0x05E350, 0x025164) }, - { "Australia/Lord_Howe" , FOR_V2(0x05E582, 0x02525C) }, - { "Australia/Melbourne" , FOR_V2(0x05ECE1, 0x02551E) }, - { "Australia/North" , FOR_V2(0x05F5A4, 0x02585A) }, - { "Australia/NSW" , FOR_V2(0x05F6F3, 0x0258E1) }, - { "Australia/Perth" , FOR_V2(0x05FFAE, 0x025C15) }, - { "Australia/Queensland" , FOR_V2(0x0601BB, 0x025D04) }, - { "Australia/South" , FOR_V2(0x06038B, 0x025DC7) }, - { "Australia/Sydney" , FOR_V2(0x060C55, 0x0260F7) }, - { "Australia/Tasmania" , FOR_V2(0x061530, 0x02644B) }, - { "Australia/Victoria" , FOR_V2(0x061E5B, 0x0267A7) }, - { "Australia/West" , FOR_V2(0x062716, 0x026ADB) }, - { "Australia/Yancowinna" , FOR_V2(0x062901, 0x026BA8) }, - { "Brazil/Acre" , FOR_V2(0x0631EF, 0x026EDD) }, - { "Brazil/DeNoronha" , FOR_V2(0x06348B, 0x026FEE) }, - { "Brazil/East" , FOR_V2(0x06376F, 0x027113) }, - { "Brazil/West" , FOR_V2(0x063F5A, 0x0273F5) }, - { "Canada/Atlantic" , FOR_V2(0x0641CE, 0x0274F2) }, - { "Canada/Central" , FOR_V2(0x064F48, 0x0279DF) }, - { "Canada/East-Saskatchewan" , FOR_V2(0x065A9F, 0x027E0A) }, - { "Canada/Eastern" , FOR_V2(0x065E8D, 0x027F98) }, - { "Canada/Mountain" , FOR_V2(0x066C48, 0x028499) }, - { "Canada/Newfoundland" , FOR_V2(0x0675B6, 0x028814) }, - { "Canada/Pacific" , FOR_V2(0x068412, 0x028D58) }, - { "Canada/Saskatchewan" , FOR_V2(0x068F73, 0x029182) }, - { "Canada/Yukon" , FOR_V2(0x069361, 0x029310) }, - { "CET" , FOR_V2(0x069B9A, 0x029624) }, - { "Chile/Continental" , FOR_V2(0x06A3DC, 0x02992D) }, - { "Chile/EasterIsland" , FOR_V2(0x06AB59, 0x029C02) }, - { "CST6CDT" , FOR_V2(0x06B1B3, 0x029E6D) }, - { "Cuba" , FOR_V2(0x06BAB5, 0x02A1BE) }, - { "EET" , FOR_V2(0x06C446, 0x02A542) }, - { "Egypt" , FOR_V2(0x06CBA6, 0x02A7F5) }, - { "Eire" , FOR_V2(0x06D366, 0x02AAD5) }, - { "EST" , FOR_V2(0x06E159, 0x02AFF7) }, - { "EST5EDT" , FOR_V2(0x06E1E4, 0x02B03B) }, - { "Etc/GMT" , FOR_V2(0x06EAE6, 0x02B38C) }, - { "Etc/GMT+0" , FOR_V2(0x06EB71, 0x02B3D0) }, - { "Etc/GMT+1" , FOR_V2(0x06EBFC, 0x02B414) }, - { "Etc/GMT+10" , FOR_V2(0x06EC8F, 0x02B45A) }, - { "Etc/GMT+11" , FOR_V2(0x06ED26, 0x02B4A1) }, - { "Etc/GMT+12" , FOR_V2(0x06EDBD, 0x02B4E8) }, - { "Etc/GMT+2" , FOR_V2(0x06EE54, 0x02B52F) }, - { "Etc/GMT+3" , FOR_V2(0x06EEE7, 0x02B575) }, - { "Etc/GMT+4" , FOR_V2(0x06EF7A, 0x02B5BB) }, - { "Etc/GMT+5" , FOR_V2(0x06F00D, 0x02B601) }, - { "Etc/GMT+6" , FOR_V2(0x06F0A0, 0x02B647) }, - { "Etc/GMT+7" , FOR_V2(0x06F133, 0x02B68D) }, - { "Etc/GMT+8" , FOR_V2(0x06F1C6, 0x02B6D3) }, - { "Etc/GMT+9" , FOR_V2(0x06F259, 0x02B719) }, - { "Etc/GMT-0" , FOR_V2(0x06F2EC, 0x02B75F) }, - { "Etc/GMT-1" , FOR_V2(0x06F377, 0x02B7A3) }, - { "Etc/GMT-10" , FOR_V2(0x06F40B, 0x02B7E9) }, - { "Etc/GMT-11" , FOR_V2(0x06F4A3, 0x02B830) }, - { "Etc/GMT-12" , FOR_V2(0x06F53B, 0x02B877) }, - { "Etc/GMT-13" , FOR_V2(0x06F5D3, 0x02B8BE) }, - { "Etc/GMT-14" , FOR_V2(0x06F66B, 0x02B905) }, - { "Etc/GMT-2" , FOR_V2(0x06F703, 0x02B94C) }, - { "Etc/GMT-3" , FOR_V2(0x06F797, 0x02B992) }, - { "Etc/GMT-4" , FOR_V2(0x06F82B, 0x02B9D8) }, - { "Etc/GMT-5" , FOR_V2(0x06F8BF, 0x02BA1E) }, - { "Etc/GMT-6" , FOR_V2(0x06F953, 0x02BA64) }, - { "Etc/GMT-7" , FOR_V2(0x06F9E7, 0x02BAAA) }, - { "Etc/GMT-8" , FOR_V2(0x06FA7B, 0x02BAF0) }, - { "Etc/GMT-9" , FOR_V2(0x06FB0F, 0x02BB36) }, - { "Etc/GMT0" , FOR_V2(0x06FBA3, 0x02BB7C) }, - { "Etc/Greenwich" , FOR_V2(0x06FC2E, 0x02BBC0) }, - { "Etc/UCT" , FOR_V2(0x06FCB9, 0x02BC04) }, - { "Etc/Universal" , FOR_V2(0x06FD44, 0x02BC48) }, - { "Etc/UTC" , FOR_V2(0x06FDCF, 0x02BC8C) }, - { "Etc/Zulu" , FOR_V2(0x06FE5A, 0x02BCD0) }, - { "Europe/Amsterdam" , FOR_V2(0x06FEE5, 0x02BD14) }, - { "Europe/Andorra" , FOR_V2(0x070A70, 0x02C163) }, - { "Europe/Athens" , FOR_V2(0x071153, 0x02C3F0) }, - { "Europe/Belfast" , FOR_V2(0x071A3E, 0x02C744) }, - { "Europe/Belgrade" , FOR_V2(0x0728B1, 0x02CC8C) }, - { "Europe/Berlin" , FOR_V2(0x073062, 0x02CF66) }, - { "Europe/Bratislava" , FOR_V2(0x07399B, 0x02D2DB) }, - { "Europe/Brussels" , FOR_V2(0x074287, 0x02D61E) }, - { "Europe/Bucharest" , FOR_V2(0x074E2D, 0x02DA66) }, - { "Europe/Budapest" , FOR_V2(0x0756E6, 0x02DDA1) }, - { "Europe/Busingen" , FOR_V2(0x076057, 0x02E11B) }, - { "Europe/Chisinau" , FOR_V2(0x0767E9, 0x02E3E3) }, - { "Europe/Copenhagen" , FOR_V2(0x077174, 0x02E782) }, - { "Europe/Dublin" , FOR_V2(0x0779F0, 0x02EA9D) }, - { "Europe/Gibraltar" , FOR_V2(0x0787E3, 0x02EFBF) }, - { "Europe/Guernsey" , FOR_V2(0x0793E4, 0x02F427) }, - { "Europe/Helsinki" , FOR_V2(0x07A257, 0x02F96F) }, - { "Europe/Isle_of_Man" , FOR_V2(0x07A9D8, 0x02FC36) }, - { "Europe/Istanbul" , FOR_V2(0x07B84B, 0x03017E) }, - { "Europe/Jersey" , FOR_V2(0x07C312, 0x03057C) }, - { "Europe/Kaliningrad" , FOR_V2(0x07D185, 0x030AC4) }, - { "Europe/Kiev" , FOR_V2(0x07D7B6, 0x030D48) }, - { "Europe/Lisbon" , FOR_V2(0x07E001, 0x031075) }, - { "Europe/Ljubljana" , FOR_V2(0x07ED92, 0x03157E) }, - { "Europe/London" , FOR_V2(0x07F543, 0x031858) }, - { "Europe/Luxembourg" , FOR_V2(0x0803B6, 0x031DA0) }, - { "Europe/Madrid" , FOR_V2(0x080F60, 0x0321FB) }, - { "Europe/Malta" , FOR_V2(0x0819AF, 0x0325D2) }, - { "Europe/Mariehamn" , FOR_V2(0x082400, 0x03299C) }, - { "Europe/Minsk" , FOR_V2(0x082B81, 0x032C63) }, - { "Europe/Monaco" , FOR_V2(0x0830E5, 0x032E87) }, - { "Europe/Moscow" , FOR_V2(0x083C7A, 0x0332D3) }, - { "Europe/Nicosia" , FOR_V2(0x084295, 0x03354E) }, - { "Europe/Oslo" , FOR_V2(0x084A81, 0x03383B) }, - { "Europe/Paris" , FOR_V2(0x085358, 0x033B7E) }, - { "Europe/Podgorica" , FOR_V2(0x085EFF, 0x033FD5) }, - { "Europe/Prague" , FOR_V2(0x0866B0, 0x0342AF) }, - { "Europe/Riga" , FOR_V2(0x086F9C, 0x0345F2) }, - { "Europe/Rome" , FOR_V2(0x087863, 0x034948) }, - { "Europe/Samara" , FOR_V2(0x0882E5, 0x034D1C) }, - { "Europe/San_Marino" , FOR_V2(0x08889C, 0x034F92) }, - { "Europe/Sarajevo" , FOR_V2(0x08931E, 0x035366) }, - { "Europe/Simferopol" , FOR_V2(0x089ACF, 0x035640) }, - { "Europe/Skopje" , FOR_V2(0x08A0BF, 0x0358A5) }, - { "Europe/Sofia" , FOR_V2(0x08A870, 0x035B7F) }, - { "Europe/Stockholm" , FOR_V2(0x08B0CE, 0x035E98) }, - { "Europe/Tallinn" , FOR_V2(0x08B858, 0x036158) }, - { "Europe/Tirane" , FOR_V2(0x08C0EF, 0x03649E) }, - { "Europe/Tiraspol" , FOR_V2(0x08C92D, 0x0367A9) }, - { "Europe/Uzhgorod" , FOR_V2(0x08D2B8, 0x036B48) }, - { "Europe/Vaduz" , FOR_V2(0x08DB03, 0x036E70) }, - { "Europe/Vatican" , FOR_V2(0x08E28D, 0x037130) }, - { "Europe/Vienna" , FOR_V2(0x08ED0F, 0x037504) }, - { "Europe/Vilnius" , FOR_V2(0x08F5D8, 0x037842) }, - { "Europe/Volgograd" , FOR_V2(0x08FE7B, 0x037B92) }, - { "Europe/Warsaw" , FOR_V2(0x0903CB, 0x037DC4) }, - { "Europe/Zagreb" , FOR_V2(0x090E68, 0x0381B6) }, - { "Europe/Zaporozhye" , FOR_V2(0x091619, 0x038490) }, - { "Europe/Zurich" , FOR_V2(0x091E92, 0x0387E2) }, - { "Factory" , FOR_V2(0x09261C, 0x038AA2) }, - { "GB" , FOR_V2(0x092730, 0x038B13) }, - { "GB-Eire" , FOR_V2(0x0935A3, 0x03905B) }, - { "GMT" , FOR_V2(0x094416, 0x0395A3) }, - { "GMT+0" , FOR_V2(0x0944A1, 0x0395E7) }, - { "GMT-0" , FOR_V2(0x09452C, 0x03962B) }, - { "GMT0" , FOR_V2(0x0945B7, 0x03966F) }, - { "Greenwich" , FOR_V2(0x094642, 0x0396B3) }, - { "Hongkong" , FOR_V2(0x0946CD, 0x0396F7) }, - { "HST" , FOR_V2(0x094B7E, 0x0398C6) }, - { "Iceland" , FOR_V2(0x094C0A, 0x03990A) }, - { "Indian/Antananarivo" , FOR_V2(0x0950BC, 0x039ADC) }, - { "Indian/Chagos" , FOR_V2(0x0951E3, 0x039B68) }, - { "Indian/Christmas" , FOR_V2(0x0952B8, 0x039BCF) }, - { "Indian/Cocos" , FOR_V2(0x095359, 0x039C13) }, - { "Indian/Comoro" , FOR_V2(0x0953FD, 0x039C57) }, - { "Indian/Kerguelen" , FOR_V2(0x095524, 0x039CE3) }, - { "Indian/Mahe" , FOR_V2(0x0955DB, 0x039D3D) }, - { "Indian/Maldives" , FOR_V2(0x095692, 0x039D97) }, - { "Indian/Mauritius" , FOR_V2(0x09576A, 0x039DFD) }, - { "Indian/Mayotte" , FOR_V2(0x095873, 0x039E78) }, - { "Indian/Reunion" , FOR_V2(0x09599A, 0x039F04) }, - { "Iran" , FOR_V2(0x095A51, 0x039F5E) }, - { "Israel" , FOR_V2(0x0960DA, 0x03A1D9) }, - { "Jamaica" , FOR_V2(0x0969BF, 0x03A521) }, - { "Japan" , FOR_V2(0x096BC6, 0x03A5F7) }, - { "Kwajalein" , FOR_V2(0x096D35, 0x03A68E) }, - { "Libya" , FOR_V2(0x096E2E, 0x03A702) }, - { "MET" , FOR_V2(0x0970C9, 0x03A810) }, - { "Mexico/BajaNorte" , FOR_V2(0x09790B, 0x03AB19) }, - { "Mexico/BajaSur" , FOR_V2(0x09824B, 0x03AE87) }, - { "Mexico/General" , FOR_V2(0x098873, 0x03B0D9) }, - { "MST" , FOR_V2(0x098ED1, 0x03B33C) }, - { "MST7MDT" , FOR_V2(0x098F5C, 0x03B380) }, - { "Navajo" , FOR_V2(0x09985E, 0x03B6D1) }, - { "NZ" , FOR_V2(0x09A1FF, 0x03BA5B) }, - { "NZ-CHAT" , FOR_V2(0x09ABA7, 0x03BDEA) }, - { "Pacific/Apia" , FOR_V2(0x09B3BC, 0x03C0DF) }, - { "Pacific/Auckland" , FOR_V2(0x09B816, 0x03C288) }, - { "Pacific/Bougainville" , FOR_V2(0x09C1CC, 0x03C625) }, - { "Pacific/Chatham" , FOR_V2(0x09C2FC, 0x03C6AE) }, - { "Pacific/Chuuk" , FOR_V2(0x09CB20, 0x03C9B2) }, - { "Pacific/Easter" , FOR_V2(0x09CBD9, 0x03CA0B) }, - { "Pacific/Efate" , FOR_V2(0x09D240, 0x03CC83) }, - { "Pacific/Enderbury" , FOR_V2(0x09D42A, 0x03CD4E) }, - { "Pacific/Fakaofo" , FOR_V2(0x09D52B, 0x03CDCD) }, - { "Pacific/Fiji" , FOR_V2(0x09D5FC, 0x03CE2F) }, - { "Pacific/Funafuti" , FOR_V2(0x09DA39, 0x03CFC7) }, - { "Pacific/Galapagos" , FOR_V2(0x09DADB, 0x03D00B) }, - { "Pacific/Gambier" , FOR_V2(0x09DBCB, 0x03D088) }, - { "Pacific/Guadalcanal" , FOR_V2(0x09DC93, 0x03D0F2) }, - { "Pacific/Guam" , FOR_V2(0x09DD4B, 0x03D14C) }, - { "Pacific/Honolulu" , FOR_V2(0x09DE38, 0x03D1B3) }, - { "Pacific/Johnston" , FOR_V2(0x09DF5E, 0x03D23B) }, - { "Pacific/Kiritimati" , FOR_V2(0x09E08C, 0x03D2CB) }, - { "Pacific/Kosrae" , FOR_V2(0x09E18A, 0x03D347) }, - { "Pacific/Kwajalein" , FOR_V2(0x09E282, 0x03D3BD) }, - { "Pacific/Majuro" , FOR_V2(0x09E384, 0x03D43A) }, - { "Pacific/Marquesas" , FOR_V2(0x09E463, 0x03D4AA) }, - { "Pacific/Midway" , FOR_V2(0x09E530, 0x03D516) }, - { "Pacific/Nauru" , FOR_V2(0x09E65A, 0x03D5A8) }, - { "Pacific/Niue" , FOR_V2(0x09E764, 0x03D625) }, - { "Pacific/Norfolk" , FOR_V2(0x09E852, 0x03D694) }, - { "Pacific/Noumea" , FOR_V2(0x09E97F, 0x03D71E) }, - { "Pacific/Pago_Pago" , FOR_V2(0x09EAC5, 0x03D7B3) }, - { "Pacific/Palau" , FOR_V2(0x09EBE1, 0x03D837) }, - { "Pacific/Pitcairn" , FOR_V2(0x09EC82, 0x03D87B) }, - { "Pacific/Pohnpei" , FOR_V2(0x09ED59, 0x03D8E1) }, - { "Pacific/Ponape" , FOR_V2(0x09EE0E, 0x03D936) }, - { "Pacific/Port_Moresby" , FOR_V2(0x09EEB3, 0x03D97B) }, - { "Pacific/Rarotonga" , FOR_V2(0x09EF79, 0x03D9CD) }, - { "Pacific/Saipan" , FOR_V2(0x09F1C3, 0x03DABA) }, - { "Pacific/Samoa" , FOR_V2(0x09F2B0, 0x03DB21) }, - { "Pacific/Tahiti" , FOR_V2(0x09F3CC, 0x03DBA5) }, - { "Pacific/Tarawa" , FOR_V2(0x09F495, 0x03DC0F) }, - { "Pacific/Tongatapu" , FOR_V2(0x09F549, 0x03DC63) }, - { "Pacific/Truk" , FOR_V2(0x09F6A8, 0x03DD00) }, - { "Pacific/Wake" , FOR_V2(0x09F74D, 0x03DD45) }, - { "Pacific/Wallis" , FOR_V2(0x09F7FD, 0x03DD95) }, - { "Pacific/Yap" , FOR_V2(0x09F89F, 0x03DDD9) }, - { "Poland" , FOR_V2(0x09F944, 0x03DE1E) }, - { "Portugal" , FOR_V2(0x0A03E1, 0x03E210) }, - { "PRC" , FOR_V2(0x0A116A, 0x03E711) }, - { "PST8PDT" , FOR_V2(0x0A1314, 0x03E7C2) }, - { "ROC" , FOR_V2(0x0A1C16, 0x03EB13) }, - { "ROK" , FOR_V2(0x0A1F42, 0x03EC55) }, - { "Singapore" , FOR_V2(0x0A2189, 0x03ED4D) }, - { "Turkey" , FOR_V2(0x0A2341, 0x03EE15) }, - { "UCT" , FOR_V2(0x0A2E08, 0x03F213) }, - { "Universal" , FOR_V2(0x0A2E93, 0x03F257) }, - { "US/Alaska" , FOR_V2(0x0A2F1E, 0x03F29B) }, - { "US/Aleutian" , FOR_V2(0x0A387A, 0x03F615) }, - { "US/Arizona" , FOR_V2(0x0A41C3, 0x03F986) }, - { "US/Central" , FOR_V2(0x0A4330, 0x03FA25) }, - { "US/East-Indiana" , FOR_V2(0x0A513D, 0x03FF49) }, - { "US/Eastern" , FOR_V2(0x0A57D4, 0x0401C4) }, - { "US/Hawaii" , FOR_V2(0x0A65B9, 0x0406D4) }, - { "US/Indiana-Starke" , FOR_V2(0x0A66D9, 0x040756) }, - { "US/Michigan" , FOR_V2(0x0A706A, 0x040AE0) }, - { "US/Mountain" , FOR_V2(0x0A791E, 0x040E1C) }, - { "US/Pacific" , FOR_V2(0x0A82BF, 0x0411A6) }, - { "US/Pacific-New" , FOR_V2(0x0A8DE8, 0x0415BC) }, - { "US/Samoa" , FOR_V2(0x0A9911, 0x0419D2) }, - { "UTC" , FOR_V2(0x0A9A2D, 0x041A56) }, - { "W-SU" , FOR_V2(0x0A9AB8, 0x041A9A) }, - { "WET" , FOR_V2(0x0AA0BC, 0x041CFE) }, - { "Zulu" , FOR_V2(0x0AA819, 0x041FB1) }, + { "America/Chicago" , FOR_V2(0x00FE96, 0x00677F) }, + { "America/Chihuahua" , FOR_V2(0x010CAF, 0x006CAF) }, + { "America/Coral_Harbour" , FOR_V2(0x0112E2, 0x006F27) }, + { "America/Cordoba" , FOR_V2(0x011447, 0x006FCA) }, + { "America/Costa_Rica" , FOR_V2(0x0118BC, 0x007189) }, + { "America/Creston" , FOR_V2(0x011A1D, 0x007224) }, + { "America/Cuiaba" , FOR_V2(0x011B44, 0x0072C9) }, + { "America/Curacao" , FOR_V2(0x01231E, 0x0075AC) }, + { "America/Danmarkshavn" , FOR_V2(0x0123FA, 0x007617) }, + { "America/Dawson" , FOR_V2(0x0126F1, 0x007760) }, + { "America/Dawson_Creek" , FOR_V2(0x012F44, 0x007A8E) }, + { "America/Denver" , FOR_V2(0x0133BC, 0x007C79) }, + { "America/Detroit" , FOR_V2(0x013D6A, 0x008010) }, + { "America/Dominica" , FOR_V2(0x014646, 0x008374) }, + { "America/Edmonton" , FOR_V2(0x0146FC, 0x0083CE) }, + { "America/Eirunepe" , FOR_V2(0x0150AC, 0x00878B) }, + { "America/El_Salvador" , FOR_V2(0x01536E, 0x0088B0) }, + { "America/Ensenada" , FOR_V2(0x015474, 0x00892A) }, + { "America/Fort_Nelson" , FOR_V2(0x015DB4, 0x008C98) }, + { "America/Fort_Wayne" , FOR_V2(0x0166BF, 0x009019) }, + { "America/Fortaleza" , FOR_V2(0x016D56, 0x009294) }, + { "America/Glace_Bay" , FOR_V2(0x017058, 0x0093D7) }, + { "America/Godthab" , FOR_V2(0x01792B, 0x009735) }, + { "America/Goose_Bay" , FOR_V2(0x01809A, 0x0099FE) }, + { "America/Grand_Turk" , FOR_V2(0x018D62, 0x009ED4) }, + { "America/Grenada" , FOR_V2(0x019275, 0x00A0C4) }, + { "America/Guadeloupe" , FOR_V2(0x01932B, 0x00A11E) }, + { "America/Guatemala" , FOR_V2(0x0193E1, 0x00A178) }, + { "America/Guayaquil" , FOR_V2(0x01951F, 0x00A206) }, + { "America/Guyana" , FOR_V2(0x0195FE, 0x00A274) }, + { "America/Halifax" , FOR_V2(0x019718, 0x00A2FA) }, + { "America/Havana" , FOR_V2(0x01A4BE, 0x00A813) }, + { "America/Hermosillo" , FOR_V2(0x01AE4F, 0x00AB97) }, + { "America/Indiana/Indianapolis" , FOR_V2(0x01B040, 0x00AC82) }, + { "America/Indiana/Knox" , FOR_V2(0x01B6FE, 0x00AF24) }, + { "America/Indiana/Marengo" , FOR_V2(0x01C0B5, 0x00B2D4) }, + { "America/Indiana/Petersburg" , FOR_V2(0x01C7AC, 0x00B58B) }, + { "America/Indiana/Tell_City" , FOR_V2(0x01CF55, 0x00B87F) }, + { "America/Indiana/Vevay" , FOR_V2(0x01D64D, 0x00BB39) }, + { "America/Indiana/Vincennes" , FOR_V2(0x01DC13, 0x00BD85) }, + { "America/Indiana/Winamac" , FOR_V2(0x01E306, 0x00C04A) }, + { "America/Indianapolis" , FOR_V2(0x01EA34, 0x00C314) }, + { "America/Inuvik" , FOR_V2(0x01F0CB, 0x00C58F) }, + { "America/Iqaluit" , FOR_V2(0x01F889, 0x00C88B) }, + { "America/Jamaica" , FOR_V2(0x0200BF, 0x00CBC2) }, + { "America/Jujuy" , FOR_V2(0x0202C6, 0x00CC98) }, + { "America/Juneau" , FOR_V2(0x02074B, 0x00CE63) }, + { "America/Kentucky/Louisville" , FOR_V2(0x0210AF, 0x00D1F2) }, + { "America/Kentucky/Monticello" , FOR_V2(0x021BC1, 0x00D621) }, + { "America/Knox_IN" , FOR_V2(0x02252C, 0x00D9B7) }, + { "America/Kralendijk" , FOR_V2(0x022EBD, 0x00DD41) }, + { "America/La_Paz" , FOR_V2(0x022F99, 0x00DDAC) }, + { "America/Lima" , FOR_V2(0x023098, 0x00DE24) }, + { "America/Los_Angeles" , FOR_V2(0x023245, 0x00DED9) }, + { "America/Louisville" , FOR_V2(0x023D7A, 0x00E2FB) }, + { "America/Lower_Princes" , FOR_V2(0x024863, 0x00E701) }, + { "America/Maceio" , FOR_V2(0x02493F, 0x00E76C) }, + { "America/Managua" , FOR_V2(0x024C4F, 0x00E8AB) }, + { "America/Manaus" , FOR_V2(0x024E2A, 0x00E977) }, + { "America/Marigot" , FOR_V2(0x0250A8, 0x00EA7E) }, + { "America/Martinique" , FOR_V2(0x02515E, 0x00EAD8) }, + { "America/Matamoros" , FOR_V2(0x02526B, 0x00EB55) }, + { "America/Mazatlan" , FOR_V2(0x025849, 0x00EDB3) }, + { "America/Mendoza" , FOR_V2(0x025E99, 0x00F02D) }, + { "America/Menominee" , FOR_V2(0x02633A, 0x00F202) }, + { "America/Merida" , FOR_V2(0x026C78, 0x00F59C) }, + { "America/Metlakatla" , FOR_V2(0x027254, 0x00F7E4) }, + { "America/Mexico_City" , FOR_V2(0x027806, 0x00FA19) }, + { "America/Miquelon" , FOR_V2(0x027E81, 0x00FC99) }, + { "America/Moncton" , FOR_V2(0x028521, 0x00FF10) }, + { "America/Monterrey" , FOR_V2(0x0291A5, 0x0103B8) }, + { "America/Montevideo" , FOR_V2(0x02978D, 0x010620) }, + { "America/Montreal" , FOR_V2(0x029D80, 0x01086A) }, + { "America/Montserrat" , FOR_V2(0x02AB3B, 0x010D6B) }, + { "America/Nassau" , FOR_V2(0x02ABF1, 0x010DC5) }, + { "America/New_York" , FOR_V2(0x02B4E9, 0x01110F) }, + { "America/Nipigon" , FOR_V2(0x02C2DA, 0x01162B) }, + { "America/Nome" , FOR_V2(0x02CB84, 0x01198D) }, + { "America/Noronha" , FOR_V2(0x02D4F1, 0x011D1C) }, + { "America/North_Dakota/Beulah" , FOR_V2(0x02D7E5, 0x011E51) }, + { "America/North_Dakota/Center" , FOR_V2(0x02E171, 0x0121F6) }, + { "America/North_Dakota/New_Salem" , FOR_V2(0x02EAFD, 0x01259B) }, + { "America/Ojinaga" , FOR_V2(0x02F49E, 0x012955) }, + { "America/Panama" , FOR_V2(0x02FAC7, 0x012BC3) }, + { "America/Pangnirtung" , FOR_V2(0x02FB9E, 0x012C29) }, + { "America/Paramaribo" , FOR_V2(0x030409, 0x012F74) }, + { "America/Phoenix" , FOR_V2(0x030549, 0x01300B) }, + { "America/Port-au-Prince" , FOR_V2(0x0306E6, 0x0130DA) }, + { "America/Port_of_Spain" , FOR_V2(0x030CBD, 0x01330B) }, + { "America/Porto_Acre" , FOR_V2(0x030D73, 0x013365) }, + { "America/Porto_Velho" , FOR_V2(0x03100F, 0x013476) }, + { "America/Puerto_Rico" , FOR_V2(0x03126F, 0x013571) }, + { "America/Rainy_River" , FOR_V2(0x03137A, 0x0135ED) }, + { "America/Rankin_Inlet" , FOR_V2(0x031C0B, 0x013936) }, + { "America/Recife" , FOR_V2(0x0323BF, 0x013C29) }, + { "America/Regina" , FOR_V2(0x0326AD, 0x013D58) }, + { "America/Resolute" , FOR_V2(0x032AD0, 0x013F1B) }, + { "America/Rio_Branco" , FOR_V2(0x033286, 0x014210) }, + { "America/Rosario" , FOR_V2(0x033526, 0x014325) }, + { "America/Santa_Isabel" , FOR_V2(0x03399B, 0x0144E4) }, + { "America/Santarem" , FOR_V2(0x0342DB, 0x014852) }, + { "America/Santiago" , FOR_V2(0x03455F, 0x01495C) }, + { "America/Santo_Domingo" , FOR_V2(0x034CEA, 0x014C3F) }, + { "America/Sao_Paulo" , FOR_V2(0x034EDF, 0x014D16) }, + { "America/Scoresbysund" , FOR_V2(0x0356FC, 0x01502A) }, + { "America/Shiprock" , FOR_V2(0x035EAC, 0x01531D) }, + { "America/Sitka" , FOR_V2(0x03684D, 0x0156A7) }, + { "America/St_Barthelemy" , FOR_V2(0x0371AF, 0x015A34) }, + { "America/St_Johns" , FOR_V2(0x037265, 0x015A8E) }, + { "America/St_Kitts" , FOR_V2(0x0380E9, 0x015FFA) }, + { "America/St_Lucia" , FOR_V2(0x03819F, 0x016054) }, + { "America/St_Thomas" , FOR_V2(0x038255, 0x0160AE) }, + { "America/St_Vincent" , FOR_V2(0x03830B, 0x016108) }, + { "America/Swift_Current" , FOR_V2(0x0383C1, 0x016162) }, + { "America/Tegucigalpa" , FOR_V2(0x038639, 0x016288) }, + { "America/Thule" , FOR_V2(0x03875B, 0x01630C) }, + { "America/Thunder_Bay" , FOR_V2(0x038D6F, 0x016558) }, + { "America/Tijuana" , FOR_V2(0x039641, 0x0168B2) }, + { "America/Toronto" , FOR_V2(0x039FA8, 0x016C47) }, + { "America/Tortola" , FOR_V2(0x03AD93, 0x017178) }, + { "America/Vancouver" , FOR_V2(0x03AE49, 0x0171D2) }, + { "America/Virgin" , FOR_V2(0x03B9CE, 0x017620) }, + { "America/Whitehorse" , FOR_V2(0x03BA84, 0x01767A) }, + { "America/Winnipeg" , FOR_V2(0x03C2D7, 0x0179A8) }, + { "America/Yakutat" , FOR_V2(0x03CE54, 0x017DF9) }, + { "America/Yellowknife" , FOR_V2(0x03D78D, 0x018175) }, + { "Antarctica/Casey" , FOR_V2(0x03DF82, 0x01848A) }, + { "Antarctica/Davis" , FOR_V2(0x03E0BD, 0x01852D) }, + { "Antarctica/DumontDUrville" , FOR_V2(0x03E208, 0x0185D3) }, + { "Antarctica/Macquarie" , FOR_V2(0x03E31C, 0x018669) }, + { "Antarctica/Mawson" , FOR_V2(0x03E932, 0x0188C3) }, + { "Antarctica/McMurdo" , FOR_V2(0x03EA23, 0x018944) }, + { "Antarctica/Palmer" , FOR_V2(0x03F3F8, 0x018D00) }, + { "Antarctica/Rothera" , FOR_V2(0x03F9A9, 0x018F48) }, + { "Antarctica/South_Pole" , FOR_V2(0x03FA82, 0x018FC3) }, + { "Antarctica/Syowa" , FOR_V2(0x04042A, 0x019352) }, + { "Antarctica/Troll" , FOR_V2(0x0404FC, 0x0193C5) }, + { "Antarctica/Vostok" , FOR_V2(0x0409AF, 0x01959C) }, + { "Arctic/Longyearbyen" , FOR_V2(0x040A84, 0x019612) }, + { "Asia/Aden" , FOR_V2(0x04135B, 0x019955) }, + { "Asia/Almaty" , FOR_V2(0x041412, 0x0199AF) }, + { "Asia/Amman" , FOR_V2(0x0417D4, 0x019B33) }, + { "Asia/Anadyr" , FOR_V2(0x041F35, 0x019DEE) }, + { "Asia/Aqtau" , FOR_V2(0x042421, 0x019FFD) }, + { "Asia/Aqtobe" , FOR_V2(0x0428D4, 0x01A209) }, + { "Asia/Ashgabat" , FOR_V2(0x042D0B, 0x01A3C6) }, + { "Asia/Ashkhabad" , FOR_V2(0x042FB6, 0x01A4E8) }, + { "Asia/Baghdad" , FOR_V2(0x043261, 0x01A60A) }, + { "Asia/Bahrain" , FOR_V2(0x043649, 0x01A790) }, + { "Asia/Baku" , FOR_V2(0x043726, 0x01A7FB) }, + { "Asia/Bangkok" , FOR_V2(0x043ED6, 0x01AAE8) }, + { "Asia/Beirut" , FOR_V2(0x043FAE, 0x01AB4E) }, + { "Asia/Bishkek" , FOR_V2(0x044839, 0x01AE6C) }, + { "Asia/Brunei" , FOR_V2(0x044C6A, 0x01B01D) }, + { "Asia/Calcutta" , FOR_V2(0x044D3F, 0x01B084) }, + { "Asia/Chita" , FOR_V2(0x044E6E, 0x01B10E) }, + { "Asia/Choibalsan" , FOR_V2(0x0453A0, 0x01B33D) }, + { "Asia/Chongqing" , FOR_V2(0x0459EF, 0x01B5A9) }, + { "Asia/Chungking" , FOR_V2(0x045B99, 0x01B65A) }, + { "Asia/Colombo" , FOR_V2(0x045D43, 0x01B70B) }, + { "Asia/Dacca" , FOR_V2(0x045ED4, 0x01B7C0) }, + { "Asia/Damascus" , FOR_V2(0x046066, 0x01B877) }, + { "Asia/Dhaka" , FOR_V2(0x046982, 0x01BBCC) }, + { "Asia/Dili" , FOR_V2(0x046B14, 0x01BC83) }, + { "Asia/Dubai" , FOR_V2(0x046C55, 0x01BD1A) }, + { "Asia/Dushanbe" , FOR_V2(0x046D0C, 0x01BD74) }, + { "Asia/Gaza" , FOR_V2(0x046F7B, 0x01BE7C) }, + { "Asia/Harbin" , FOR_V2(0x04789B, 0x01C1E0) }, + { "Asia/Hebron" , FOR_V2(0x047A45, 0x01C291) }, + { "Asia/Ho_Chi_Minh" , FOR_V2(0x048380, 0x01C5FE) }, + { "Asia/Hong_Kong" , FOR_V2(0x048501, 0x01C6AD) }, + { "Asia/Hovd" , FOR_V2(0x0489B2, 0x01C87C) }, + { "Asia/Irkutsk" , FOR_V2(0x048FD2, 0x01CADF) }, + { "Asia/Istanbul" , FOR_V2(0x0494E0, 0x01CCEB) }, + { "Asia/Jakarta" , FOR_V2(0x049FA7, 0x01D0E9) }, + { "Asia/Jayapura" , FOR_V2(0x04A133, 0x01D1A4) }, + { "Asia/Jerusalem" , FOR_V2(0x04A261, 0x01D24E) }, + { "Asia/Kabul" , FOR_V2(0x04AB46, 0x01D596) }, + { "Asia/Kamchatka" , FOR_V2(0x04AC19, 0x01D5F8) }, + { "Asia/Karachi" , FOR_V2(0x04B0F4, 0x01D7FE) }, + { "Asia/Kashgar" , FOR_V2(0x04B293, 0x01D8B8) }, + { "Asia/Kathmandu" , FOR_V2(0x04B34A, 0x01D912) }, + { "Asia/Katmandu" , FOR_V2(0x04B42A, 0x01D97D) }, + { "Asia/Khandyga" , FOR_V2(0x04B50A, 0x01D9E8) }, + { "Asia/Kolkata" , FOR_V2(0x04BA63, 0x01DC1F) }, + { "Asia/Krasnoyarsk" , FOR_V2(0x04BB92, 0x01DCA9) }, + { "Asia/Kuala_Lumpur" , FOR_V2(0x04C081, 0x01DEAB) }, + { "Asia/Kuching" , FOR_V2(0x04C22E, 0x01DF79) }, + { "Asia/Kuwait" , FOR_V2(0x04C450, 0x01E06C) }, + { "Asia/Macao" , FOR_V2(0x04C507, 0x01E0C6) }, + { "Asia/Macau" , FOR_V2(0x04C82E, 0x01E206) }, + { "Asia/Magadan" , FOR_V2(0x04CB55, 0x01E346) }, + { "Asia/Makassar" , FOR_V2(0x04D05C, 0x01E55F) }, + { "Asia/Manila" , FOR_V2(0x04D1C8, 0x01E631) }, + { "Asia/Muscat" , FOR_V2(0x04D33D, 0x01E6CF) }, + { "Asia/Nicosia" , FOR_V2(0x04D3F4, 0x01E729) }, + { "Asia/Novokuznetsk" , FOR_V2(0x04DBE0, 0x01EA16) }, + { "Asia/Novosibirsk" , FOR_V2(0x04E0FD, 0x01EC3B) }, + { "Asia/Omsk" , FOR_V2(0x04E5D8, 0x01EE30) }, + { "Asia/Oral" , FOR_V2(0x04EAC6, 0x01F031) }, + { "Asia/Phnom_Penh" , FOR_V2(0x04EF2D, 0x01F206) }, + { "Asia/Pontianak" , FOR_V2(0x04F005, 0x01F26C) }, + { "Asia/Pyongyang" , FOR_V2(0x04F19D, 0x01F333) }, + { "Asia/Qatar" , FOR_V2(0x04F2E1, 0x01F3CA) }, + { "Asia/Qyzylorda" , FOR_V2(0x04F3BE, 0x01F435) }, + { "Asia/Rangoon" , FOR_V2(0x04F824, 0x01F610) }, + { "Asia/Riyadh" , FOR_V2(0x04F94D, 0x01F699) }, + { "Asia/Saigon" , FOR_V2(0x04FA04, 0x01F6F3) }, + { "Asia/Sakhalin" , FOR_V2(0x04FB85, 0x01F7A2) }, + { "Asia/Samarkand" , FOR_V2(0x050077, 0x01F9A4) }, + { "Asia/Seoul" , FOR_V2(0x050345, 0x01FADF) }, + { "Asia/Shanghai" , FOR_V2(0x05058C, 0x01FBD7) }, + { "Asia/Singapore" , FOR_V2(0x050742, 0x01FC94) }, + { "Asia/Srednekolymsk" , FOR_V2(0x0508FA, 0x01FD5C) }, + { "Asia/Taipei" , FOR_V2(0x050DFA, 0x01FF69) }, + { "Asia/Tashkent" , FOR_V2(0x051126, 0x0200AB) }, + { "Asia/Tbilisi" , FOR_V2(0x0513EA, 0x0201E1) }, + { "Asia/Tehran" , FOR_V2(0x05186C, 0x0203B4) }, + { "Asia/Tel_Aviv" , FOR_V2(0x051F06, 0x02062F) }, + { "Asia/Thimbu" , FOR_V2(0x0527EB, 0x020977) }, + { "Asia/Thimphu" , FOR_V2(0x0528C8, 0x0209E2) }, + { "Asia/Tokyo" , FOR_V2(0x0529A5, 0x020A4D) }, + { "Asia/Ujung_Pandang" , FOR_V2(0x052B14, 0x020AE4) }, + { "Asia/Ulaanbaatar" , FOR_V2(0x052C38, 0x020B6E) }, + { "Asia/Ulan_Bator" , FOR_V2(0x05323B, 0x020DB4) }, + { "Asia/Urumqi" , FOR_V2(0x053830, 0x020FEC) }, + { "Asia/Ust-Nera" , FOR_V2(0x0538F4, 0x021053) }, + { "Asia/Vientiane" , FOR_V2(0x053E24, 0x021272) }, + { "Asia/Vladivostok" , FOR_V2(0x053EFC, 0x0212D8) }, + { "Asia/Yakutsk" , FOR_V2(0x0543E9, 0x0214D7) }, + { "Asia/Yekaterinburg" , FOR_V2(0x0548D5, 0x0216D6) }, + { "Asia/Yerevan" , FOR_V2(0x054E28, 0x021904) }, + { "Atlantic/Azores" , FOR_V2(0x055331, 0x021B09) }, + { "Atlantic/Bermuda" , FOR_V2(0x0560E3, 0x02201D) }, + { "Atlantic/Canary" , FOR_V2(0x0568C3, 0x022303) }, + { "Atlantic/Cape_Verde" , FOR_V2(0x057056, 0x0225DE) }, + { "Atlantic/Faeroe" , FOR_V2(0x057160, 0x02265C) }, + { "Atlantic/Faroe" , FOR_V2(0x057891, 0x022905) }, + { "Atlantic/Jan_Mayen" , FOR_V2(0x057FC2, 0x022BAE) }, + { "Atlantic/Madeira" , FOR_V2(0x058899, 0x022EF1) }, + { "Atlantic/Reykjavik" , FOR_V2(0x05964A, 0x02340B) }, + { "Atlantic/South_Georgia" , FOR_V2(0x059AFC, 0x0235DD) }, + { "Atlantic/St_Helena" , FOR_V2(0x059B9C, 0x023621) }, + { "Atlantic/Stanley" , FOR_V2(0x059C52, 0x02367B) }, + { "Australia/ACT" , FOR_V2(0x05A13C, 0x023862) }, + { "Australia/Adelaide" , FOR_V2(0x05A9F7, 0x023B96) }, + { "Australia/Brisbane" , FOR_V2(0x05B2D0, 0x023ED5) }, + { "Australia/Broken_Hill" , FOR_V2(0x05B4BB, 0x023FB3) }, + { "Australia/Canberra" , FOR_V2(0x05BDC5, 0x024304) }, + { "Australia/Currie" , FOR_V2(0x05C680, 0x024638) }, + { "Australia/Darwin" , FOR_V2(0x05CF51, 0x024982) }, + { "Australia/Eucla" , FOR_V2(0x05D0B2, 0x024A1B) }, + { "Australia/Hobart" , FOR_V2(0x05D2C3, 0x024B08) }, + { "Australia/LHI" , FOR_V2(0x05DC07, 0x024E7D) }, + { "Australia/Lindeman" , FOR_V2(0x05E356, 0x02512F) }, + { "Australia/Lord_Howe" , FOR_V2(0x05E588, 0x025227) }, + { "Australia/Melbourne" , FOR_V2(0x05ECE7, 0x0254E9) }, + { "Australia/North" , FOR_V2(0x05F5AA, 0x025825) }, + { "Australia/NSW" , FOR_V2(0x05F6F9, 0x0258AC) }, + { "Australia/Perth" , FOR_V2(0x05FFB4, 0x025BE0) }, + { "Australia/Queensland" , FOR_V2(0x0601C1, 0x025CCF) }, + { "Australia/South" , FOR_V2(0x060391, 0x025D92) }, + { "Australia/Sydney" , FOR_V2(0x060C5B, 0x0260C2) }, + { "Australia/Tasmania" , FOR_V2(0x061536, 0x026416) }, + { "Australia/Victoria" , FOR_V2(0x061E61, 0x026772) }, + { "Australia/West" , FOR_V2(0x06271C, 0x026AA6) }, + { "Australia/Yancowinna" , FOR_V2(0x062907, 0x026B73) }, + { "Brazil/Acre" , FOR_V2(0x0631F5, 0x026EA8) }, + { "Brazil/DeNoronha" , FOR_V2(0x063491, 0x026FB9) }, + { "Brazil/East" , FOR_V2(0x063775, 0x0270DE) }, + { "Brazil/West" , FOR_V2(0x063F60, 0x0273C0) }, + { "Canada/Atlantic" , FOR_V2(0x0641D4, 0x0274BD) }, + { "Canada/Central" , FOR_V2(0x064F4E, 0x0279AA) }, + { "Canada/East-Saskatchewan" , FOR_V2(0x065AA5, 0x027DD5) }, + { "Canada/Eastern" , FOR_V2(0x065E93, 0x027F63) }, + { "Canada/Mountain" , FOR_V2(0x066C4E, 0x028464) }, + { "Canada/Newfoundland" , FOR_V2(0x0675BC, 0x0287DF) }, + { "Canada/Pacific" , FOR_V2(0x068418, 0x028D23) }, + { "Canada/Saskatchewan" , FOR_V2(0x068F79, 0x02914D) }, + { "Canada/Yukon" , FOR_V2(0x069367, 0x0292DB) }, + { "CET" , FOR_V2(0x069BA0, 0x0295EF) }, + { "Chile/Continental" , FOR_V2(0x06A3E2, 0x0298F8) }, + { "Chile/EasterIsland" , FOR_V2(0x06AB5F, 0x029BCD) }, + { "CST6CDT" , FOR_V2(0x06B1B9, 0x029E38) }, + { "Cuba" , FOR_V2(0x06BABB, 0x02A189) }, + { "EET" , FOR_V2(0x06C44C, 0x02A50D) }, + { "Egypt" , FOR_V2(0x06CBAC, 0x02A7C0) }, + { "Eire" , FOR_V2(0x06D36C, 0x02AAA0) }, + { "EST" , FOR_V2(0x06E15F, 0x02AFC2) }, + { "EST5EDT" , FOR_V2(0x06E1EA, 0x02B006) }, + { "Etc/GMT" , FOR_V2(0x06EAEC, 0x02B357) }, + { "Etc/GMT+0" , FOR_V2(0x06EB77, 0x02B39B) }, + { "Etc/GMT+1" , FOR_V2(0x06EC02, 0x02B3DF) }, + { "Etc/GMT+10" , FOR_V2(0x06EC95, 0x02B425) }, + { "Etc/GMT+11" , FOR_V2(0x06ED2C, 0x02B46C) }, + { "Etc/GMT+12" , FOR_V2(0x06EDC3, 0x02B4B3) }, + { "Etc/GMT+2" , FOR_V2(0x06EE5A, 0x02B4FA) }, + { "Etc/GMT+3" , FOR_V2(0x06EEED, 0x02B540) }, + { "Etc/GMT+4" , FOR_V2(0x06EF80, 0x02B586) }, + { "Etc/GMT+5" , FOR_V2(0x06F013, 0x02B5CC) }, + { "Etc/GMT+6" , FOR_V2(0x06F0A6, 0x02B612) }, + { "Etc/GMT+7" , FOR_V2(0x06F139, 0x02B658) }, + { "Etc/GMT+8" , FOR_V2(0x06F1CC, 0x02B69E) }, + { "Etc/GMT+9" , FOR_V2(0x06F25F, 0x02B6E4) }, + { "Etc/GMT-0" , FOR_V2(0x06F2F2, 0x02B72A) }, + { "Etc/GMT-1" , FOR_V2(0x06F37D, 0x02B76E) }, + { "Etc/GMT-10" , FOR_V2(0x06F411, 0x02B7B4) }, + { "Etc/GMT-11" , FOR_V2(0x06F4A9, 0x02B7FB) }, + { "Etc/GMT-12" , FOR_V2(0x06F541, 0x02B842) }, + { "Etc/GMT-13" , FOR_V2(0x06F5D9, 0x02B889) }, + { "Etc/GMT-14" , FOR_V2(0x06F671, 0x02B8D0) }, + { "Etc/GMT-2" , FOR_V2(0x06F709, 0x02B917) }, + { "Etc/GMT-3" , FOR_V2(0x06F79D, 0x02B95D) }, + { "Etc/GMT-4" , FOR_V2(0x06F831, 0x02B9A3) }, + { "Etc/GMT-5" , FOR_V2(0x06F8C5, 0x02B9E9) }, + { "Etc/GMT-6" , FOR_V2(0x06F959, 0x02BA2F) }, + { "Etc/GMT-7" , FOR_V2(0x06F9ED, 0x02BA75) }, + { "Etc/GMT-8" , FOR_V2(0x06FA81, 0x02BABB) }, + { "Etc/GMT-9" , FOR_V2(0x06FB15, 0x02BB01) }, + { "Etc/GMT0" , FOR_V2(0x06FBA9, 0x02BB47) }, + { "Etc/Greenwich" , FOR_V2(0x06FC34, 0x02BB8B) }, + { "Etc/UCT" , FOR_V2(0x06FCBF, 0x02BBCF) }, + { "Etc/Universal" , FOR_V2(0x06FD4A, 0x02BC13) }, + { "Etc/UTC" , FOR_V2(0x06FDD5, 0x02BC57) }, + { "Etc/Zulu" , FOR_V2(0x06FE60, 0x02BC9B) }, + { "Europe/Amsterdam" , FOR_V2(0x06FEEB, 0x02BCDF) }, + { "Europe/Andorra" , FOR_V2(0x070A76, 0x02C12E) }, + { "Europe/Athens" , FOR_V2(0x071159, 0x02C3BB) }, + { "Europe/Belfast" , FOR_V2(0x071A44, 0x02C70F) }, + { "Europe/Belgrade" , FOR_V2(0x0728B7, 0x02CC57) }, + { "Europe/Berlin" , FOR_V2(0x073068, 0x02CF31) }, + { "Europe/Bratislava" , FOR_V2(0x0739A1, 0x02D2A6) }, + { "Europe/Brussels" , FOR_V2(0x07428D, 0x02D5E9) }, + { "Europe/Bucharest" , FOR_V2(0x074E33, 0x02DA31) }, + { "Europe/Budapest" , FOR_V2(0x0756EC, 0x02DD6C) }, + { "Europe/Busingen" , FOR_V2(0x07605D, 0x02E0E6) }, + { "Europe/Chisinau" , FOR_V2(0x0767EF, 0x02E3AE) }, + { "Europe/Copenhagen" , FOR_V2(0x07717A, 0x02E74D) }, + { "Europe/Dublin" , FOR_V2(0x0779F6, 0x02EA68) }, + { "Europe/Gibraltar" , FOR_V2(0x0787E9, 0x02EF8A) }, + { "Europe/Guernsey" , FOR_V2(0x0793EA, 0x02F3F2) }, + { "Europe/Helsinki" , FOR_V2(0x07A25D, 0x02F93A) }, + { "Europe/Isle_of_Man" , FOR_V2(0x07A9DE, 0x02FC01) }, + { "Europe/Istanbul" , FOR_V2(0x07B851, 0x030149) }, + { "Europe/Jersey" , FOR_V2(0x07C318, 0x030547) }, + { "Europe/Kaliningrad" , FOR_V2(0x07D18B, 0x030A8F) }, + { "Europe/Kiev" , FOR_V2(0x07D7BC, 0x030D13) }, + { "Europe/Lisbon" , FOR_V2(0x07E007, 0x031040) }, + { "Europe/Ljubljana" , FOR_V2(0x07ED98, 0x031549) }, + { "Europe/London" , FOR_V2(0x07F549, 0x031823) }, + { "Europe/Luxembourg" , FOR_V2(0x0803BC, 0x031D6B) }, + { "Europe/Madrid" , FOR_V2(0x080F66, 0x0321C6) }, + { "Europe/Malta" , FOR_V2(0x0819B5, 0x03259D) }, + { "Europe/Mariehamn" , FOR_V2(0x082406, 0x032967) }, + { "Europe/Minsk" , FOR_V2(0x082B87, 0x032C2E) }, + { "Europe/Monaco" , FOR_V2(0x0830EB, 0x032E52) }, + { "Europe/Moscow" , FOR_V2(0x083C80, 0x03329E) }, + { "Europe/Nicosia" , FOR_V2(0x08429B, 0x033519) }, + { "Europe/Oslo" , FOR_V2(0x084A87, 0x033806) }, + { "Europe/Paris" , FOR_V2(0x08535E, 0x033B49) }, + { "Europe/Podgorica" , FOR_V2(0x085F05, 0x033FA0) }, + { "Europe/Prague" , FOR_V2(0x0866B6, 0x03427A) }, + { "Europe/Riga" , FOR_V2(0x086FA2, 0x0345BD) }, + { "Europe/Rome" , FOR_V2(0x087869, 0x034913) }, + { "Europe/Samara" , FOR_V2(0x0882EB, 0x034CE7) }, + { "Europe/San_Marino" , FOR_V2(0x0888A2, 0x034F5D) }, + { "Europe/Sarajevo" , FOR_V2(0x089324, 0x035331) }, + { "Europe/Simferopol" , FOR_V2(0x089AD5, 0x03560B) }, + { "Europe/Skopje" , FOR_V2(0x08A0C5, 0x035870) }, + { "Europe/Sofia" , FOR_V2(0x08A876, 0x035B4A) }, + { "Europe/Stockholm" , FOR_V2(0x08B0D4, 0x035E63) }, + { "Europe/Tallinn" , FOR_V2(0x08B85E, 0x036123) }, + { "Europe/Tirane" , FOR_V2(0x08C0F5, 0x036469) }, + { "Europe/Tiraspol" , FOR_V2(0x08C933, 0x036774) }, + { "Europe/Uzhgorod" , FOR_V2(0x08D2BE, 0x036B13) }, + { "Europe/Vaduz" , FOR_V2(0x08DB09, 0x036E3B) }, + { "Europe/Vatican" , FOR_V2(0x08E293, 0x0370FB) }, + { "Europe/Vienna" , FOR_V2(0x08ED15, 0x0374CF) }, + { "Europe/Vilnius" , FOR_V2(0x08F5DE, 0x03780D) }, + { "Europe/Volgograd" , FOR_V2(0x08FE81, 0x037B5D) }, + { "Europe/Warsaw" , FOR_V2(0x0903D1, 0x037D8F) }, + { "Europe/Zagreb" , FOR_V2(0x090E6E, 0x038181) }, + { "Europe/Zaporozhye" , FOR_V2(0x09161F, 0x03845B) }, + { "Europe/Zurich" , FOR_V2(0x091E98, 0x0387AD) }, + { "Factory" , FOR_V2(0x092622, 0x038A6D) }, + { "GB" , FOR_V2(0x092736, 0x038ADE) }, + { "GB-Eire" , FOR_V2(0x0935A9, 0x039026) }, + { "GMT" , FOR_V2(0x09441C, 0x03956E) }, + { "GMT+0" , FOR_V2(0x0944A7, 0x0395B2) }, + { "GMT-0" , FOR_V2(0x094532, 0x0395F6) }, + { "GMT0" , FOR_V2(0x0945BD, 0x03963A) }, + { "Greenwich" , FOR_V2(0x094648, 0x03967E) }, + { "Hongkong" , FOR_V2(0x0946D3, 0x0396C2) }, + { "HST" , FOR_V2(0x094B84, 0x039891) }, + { "Iceland" , FOR_V2(0x094C10, 0x0398D5) }, + { "Indian/Antananarivo" , FOR_V2(0x0950C2, 0x039AA7) }, + { "Indian/Chagos" , FOR_V2(0x0951E9, 0x039B33) }, + { "Indian/Christmas" , FOR_V2(0x0952BE, 0x039B9A) }, + { "Indian/Cocos" , FOR_V2(0x09535F, 0x039BDE) }, + { "Indian/Comoro" , FOR_V2(0x095403, 0x039C22) }, + { "Indian/Kerguelen" , FOR_V2(0x09552A, 0x039CAE) }, + { "Indian/Mahe" , FOR_V2(0x0955E1, 0x039D08) }, + { "Indian/Maldives" , FOR_V2(0x095698, 0x039D62) }, + { "Indian/Mauritius" , FOR_V2(0x095770, 0x039DC8) }, + { "Indian/Mayotte" , FOR_V2(0x095879, 0x039E43) }, + { "Indian/Reunion" , FOR_V2(0x0959A0, 0x039ECF) }, + { "Iran" , FOR_V2(0x095A57, 0x039F29) }, + { "Israel" , FOR_V2(0x0960F1, 0x03A1A4) }, + { "Jamaica" , FOR_V2(0x0969D6, 0x03A4EC) }, + { "Japan" , FOR_V2(0x096BDD, 0x03A5C2) }, + { "Kwajalein" , FOR_V2(0x096D4C, 0x03A659) }, + { "Libya" , FOR_V2(0x096E45, 0x03A6CD) }, + { "MET" , FOR_V2(0x0970E0, 0x03A7DB) }, + { "Mexico/BajaNorte" , FOR_V2(0x097922, 0x03AAE4) }, + { "Mexico/BajaSur" , FOR_V2(0x098262, 0x03AE52) }, + { "Mexico/General" , FOR_V2(0x09888A, 0x03B0A4) }, + { "MST" , FOR_V2(0x098EE8, 0x03B307) }, + { "MST7MDT" , FOR_V2(0x098F73, 0x03B34B) }, + { "Navajo" , FOR_V2(0x099875, 0x03B69C) }, + { "NZ" , FOR_V2(0x09A216, 0x03BA26) }, + { "NZ-CHAT" , FOR_V2(0x09ABBE, 0x03BDB5) }, + { "Pacific/Apia" , FOR_V2(0x09B3D3, 0x03C0AA) }, + { "Pacific/Auckland" , FOR_V2(0x09B82D, 0x03C253) }, + { "Pacific/Bougainville" , FOR_V2(0x09C1E3, 0x03C5F0) }, + { "Pacific/Chatham" , FOR_V2(0x09C313, 0x03C679) }, + { "Pacific/Chuuk" , FOR_V2(0x09CB37, 0x03C97D) }, + { "Pacific/Easter" , FOR_V2(0x09CBF0, 0x03C9D6) }, + { "Pacific/Efate" , FOR_V2(0x09D257, 0x03CC4E) }, + { "Pacific/Enderbury" , FOR_V2(0x09D441, 0x03CD19) }, + { "Pacific/Fakaofo" , FOR_V2(0x09D542, 0x03CD98) }, + { "Pacific/Fiji" , FOR_V2(0x09D613, 0x03CDFA) }, + { "Pacific/Funafuti" , FOR_V2(0x09DA50, 0x03CF92) }, + { "Pacific/Galapagos" , FOR_V2(0x09DAF2, 0x03CFD6) }, + { "Pacific/Gambier" , FOR_V2(0x09DBE2, 0x03D053) }, + { "Pacific/Guadalcanal" , FOR_V2(0x09DCAA, 0x03D0BD) }, + { "Pacific/Guam" , FOR_V2(0x09DD62, 0x03D117) }, + { "Pacific/Honolulu" , FOR_V2(0x09DE4F, 0x03D17E) }, + { "Pacific/Johnston" , FOR_V2(0x09DF75, 0x03D206) }, + { "Pacific/Kiritimati" , FOR_V2(0x09E0A3, 0x03D296) }, + { "Pacific/Kosrae" , FOR_V2(0x09E1A1, 0x03D312) }, + { "Pacific/Kwajalein" , FOR_V2(0x09E299, 0x03D388) }, + { "Pacific/Majuro" , FOR_V2(0x09E39B, 0x03D405) }, + { "Pacific/Marquesas" , FOR_V2(0x09E47A, 0x03D475) }, + { "Pacific/Midway" , FOR_V2(0x09E547, 0x03D4E1) }, + { "Pacific/Nauru" , FOR_V2(0x09E671, 0x03D573) }, + { "Pacific/Niue" , FOR_V2(0x09E77B, 0x03D5F0) }, + { "Pacific/Norfolk" , FOR_V2(0x09E869, 0x03D65F) }, + { "Pacific/Noumea" , FOR_V2(0x09E996, 0x03D6E9) }, + { "Pacific/Pago_Pago" , FOR_V2(0x09EADC, 0x03D77E) }, + { "Pacific/Palau" , FOR_V2(0x09EBF8, 0x03D802) }, + { "Pacific/Pitcairn" , FOR_V2(0x09EC99, 0x03D846) }, + { "Pacific/Pohnpei" , FOR_V2(0x09ED70, 0x03D8AC) }, + { "Pacific/Ponape" , FOR_V2(0x09EE25, 0x03D901) }, + { "Pacific/Port_Moresby" , FOR_V2(0x09EECA, 0x03D946) }, + { "Pacific/Rarotonga" , FOR_V2(0x09EF90, 0x03D998) }, + { "Pacific/Saipan" , FOR_V2(0x09F1DA, 0x03DA85) }, + { "Pacific/Samoa" , FOR_V2(0x09F2C7, 0x03DAEC) }, + { "Pacific/Tahiti" , FOR_V2(0x09F3E3, 0x03DB70) }, + { "Pacific/Tarawa" , FOR_V2(0x09F4AC, 0x03DBDA) }, + { "Pacific/Tongatapu" , FOR_V2(0x09F560, 0x03DC2E) }, + { "Pacific/Truk" , FOR_V2(0x09F6BF, 0x03DCCB) }, + { "Pacific/Wake" , FOR_V2(0x09F764, 0x03DD10) }, + { "Pacific/Wallis" , FOR_V2(0x09F814, 0x03DD60) }, + { "Pacific/Yap" , FOR_V2(0x09F8B6, 0x03DDA4) }, + { "Poland" , FOR_V2(0x09F95B, 0x03DDE9) }, + { "Portugal" , FOR_V2(0x0A03F8, 0x03E1DB) }, + { "PRC" , FOR_V2(0x0A1181, 0x03E6DC) }, + { "PST8PDT" , FOR_V2(0x0A132B, 0x03E78D) }, + { "ROC" , FOR_V2(0x0A1C2D, 0x03EADE) }, + { "ROK" , FOR_V2(0x0A1F59, 0x03EC20) }, + { "Singapore" , FOR_V2(0x0A21A0, 0x03ED18) }, + { "Turkey" , FOR_V2(0x0A2358, 0x03EDE0) }, + { "UCT" , FOR_V2(0x0A2E1F, 0x03F1DE) }, + { "Universal" , FOR_V2(0x0A2EAA, 0x03F222) }, + { "US/Alaska" , FOR_V2(0x0A2F35, 0x03F266) }, + { "US/Aleutian" , FOR_V2(0x0A3891, 0x03F5E0) }, + { "US/Arizona" , FOR_V2(0x0A41DA, 0x03F951) }, + { "US/Central" , FOR_V2(0x0A4347, 0x03F9F0) }, + { "US/East-Indiana" , FOR_V2(0x0A5154, 0x03FF14) }, + { "US/Eastern" , FOR_V2(0x0A57EB, 0x04018F) }, + { "US/Hawaii" , FOR_V2(0x0A65D0, 0x04069F) }, + { "US/Indiana-Starke" , FOR_V2(0x0A66F0, 0x040721) }, + { "US/Michigan" , FOR_V2(0x0A7081, 0x040AAB) }, + { "US/Mountain" , FOR_V2(0x0A7935, 0x040DE7) }, + { "US/Pacific" , FOR_V2(0x0A82D6, 0x041171) }, + { "US/Pacific-New" , FOR_V2(0x0A8DFF, 0x041587) }, + { "US/Samoa" , FOR_V2(0x0A9928, 0x04199D) }, + { "UTC" , FOR_V2(0x0A9A44, 0x041A21) }, + { "W-SU" , FOR_V2(0x0A9ACF, 0x041A65) }, + { "WET" , FOR_V2(0x0AA0D3, 0x041CC9) }, + { "Zulu" , FOR_V2(0x0AA830, 0x041F7C) }, }; #ifdef TIMELIB_SUPPORTS_V2DATA -const unsigned char timelib_timezone_db_data_builtin[698532] = { +const unsigned char timelib_timezone_db_data_builtin[698555] = { #else -const unsigned char timelib_timezone_db_data_builtin[270325] = { +const unsigned char timelib_timezone_db_data_builtin[270272] = { #endif @@ -5125,61 +5125,20 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { /* America/Cayman */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x4B, 0x59, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x2E, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0x80, 0x00, 0x00, 0x00, -0x93, 0x0F, 0xB4, 0xFF, 0x56, 0xE5, 0x0F, 0xF0, 0x58, 0x1E, 0xC6, 0xE0, 0x58, 0xC4, 0xF1, 0xF0, -0x59, 0xFE, 0xA8, 0xE0, 0x5A, 0xA4, 0xD3, 0xF0, 0x5B, 0xDE, 0x8A, 0xE0, 0x5C, 0x84, 0xB5, 0xF0, -0x5D, 0xBE, 0x6C, 0xE0, 0x5E, 0x64, 0x97, 0xF0, 0x5F, 0x9E, 0x4E, 0xE0, 0x60, 0x4D, 0xB4, 0x70, -0x61, 0x87, 0x6B, 0x60, 0x62, 0x2D, 0x96, 0x70, 0x63, 0x67, 0x4D, 0x60, 0x64, 0x0D, 0x78, 0x70, -0x65, 0x47, 0x2F, 0x60, 0x65, 0xED, 0x5A, 0x70, 0x67, 0x27, 0x11, 0x60, 0x67, 0xCD, 0x3C, 0x70, -0x69, 0x06, 0xF3, 0x60, 0x69, 0xAD, 0x1E, 0x70, 0x6A, 0xE6, 0xD5, 0x60, 0x6B, 0x96, 0x3A, 0xF0, -0x6C, 0xCF, 0xF1, 0xE0, 0x6D, 0x76, 0x1C, 0xF0, 0x6E, 0xAF, 0xD3, 0xE0, 0x6F, 0x55, 0xFE, 0xF0, -0x70, 0x8F, 0xB5, 0xE0, 0x71, 0x35, 0xE0, 0xF0, 0x72, 0x6F, 0x97, 0xE0, 0x73, 0x15, 0xC2, 0xF0, -0x74, 0x4F, 0x79, 0xE0, 0x74, 0xFE, 0xDF, 0x70, 0x76, 0x38, 0x96, 0x60, 0x76, 0xDE, 0xC1, 0x70, -0x78, 0x18, 0x78, 0x60, 0x78, 0xBE, 0xA3, 0x70, 0x79, 0xF8, 0x5A, 0x60, 0x7A, 0x9E, 0x85, 0x70, -0x7B, 0xD8, 0x3C, 0x60, 0x7C, 0x7E, 0x67, 0x70, 0x7D, 0xB8, 0x1E, 0x60, 0x7E, 0x5E, 0x49, 0x70, -0x7F, 0x98, 0x00, 0x60, 0x01, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, -0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, -0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, -0x03, 0x02, 0xFF, 0xFF, 0xB3, 0xB4, 0x00, 0x00, 0xFF, 0xFF, 0xB8, 0x01, 0x00, 0x04, 0xFF, 0xFF, -0xB9, 0xB0, 0x00, 0x08, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x0C, 0x4C, 0x4D, 0x54, 0x00, 0x4B, 0x4D, -0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, 0x44, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0x80, 0x00, 0x00, 0x00, +0x8B, 0xF4, 0x61, 0xE8, 0x01, 0x02, 0xFF, 0xFF, 0xB5, 0x70, 0x00, 0x00, 0xFF, 0xFF, 0xB5, 0x18, +0x00, 0x04, 0xFF, 0xFF, 0xB9, 0xB0, 0x00, 0x08, 0x4C, 0x4D, 0x54, 0x00, 0x43, 0x4D, 0x54, 0x00, +0x45, 0x53, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, #ifdef TIMELIB_SUPPORTS_V2DATA 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x2F, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x10, 0xF8, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x69, 0x87, 0x27, 0xCC, 0xFF, 0xFF, 0xFF, 0xFF, -0x93, 0x0F, 0xB4, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x56, 0xE5, 0x0F, 0xF0, 0x00, 0x00, 0x00, 0x00, -0x58, 0x1E, 0xC6, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x58, 0xC4, 0xF1, 0xF0, 0x00, 0x00, 0x00, 0x00, -0x59, 0xFE, 0xA8, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xA4, 0xD3, 0xF0, 0x00, 0x00, 0x00, 0x00, -0x5B, 0xDE, 0x8A, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x84, 0xB5, 0xF0, 0x00, 0x00, 0x00, 0x00, -0x5D, 0xBE, 0x6C, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x64, 0x97, 0xF0, 0x00, 0x00, 0x00, 0x00, -0x5F, 0x9E, 0x4E, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x60, 0x4D, 0xB4, 0x70, 0x00, 0x00, 0x00, 0x00, -0x61, 0x87, 0x6B, 0x60, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2D, 0x96, 0x70, 0x00, 0x00, 0x00, 0x00, -0x63, 0x67, 0x4D, 0x60, 0x00, 0x00, 0x00, 0x00, 0x64, 0x0D, 0x78, 0x70, 0x00, 0x00, 0x00, 0x00, -0x65, 0x47, 0x2F, 0x60, 0x00, 0x00, 0x00, 0x00, 0x65, 0xED, 0x5A, 0x70, 0x00, 0x00, 0x00, 0x00, -0x67, 0x27, 0x11, 0x60, 0x00, 0x00, 0x00, 0x00, 0x67, 0xCD, 0x3C, 0x70, 0x00, 0x00, 0x00, 0x00, -0x69, 0x06, 0xF3, 0x60, 0x00, 0x00, 0x00, 0x00, 0x69, 0xAD, 0x1E, 0x70, 0x00, 0x00, 0x00, 0x00, -0x6A, 0xE6, 0xD5, 0x60, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x96, 0x3A, 0xF0, 0x00, 0x00, 0x00, 0x00, -0x6C, 0xCF, 0xF1, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x76, 0x1C, 0xF0, 0x00, 0x00, 0x00, 0x00, -0x6E, 0xAF, 0xD3, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x55, 0xFE, 0xF0, 0x00, 0x00, 0x00, 0x00, -0x70, 0x8F, 0xB5, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x71, 0x35, 0xE0, 0xF0, 0x00, 0x00, 0x00, 0x00, -0x72, 0x6F, 0x97, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xC2, 0xF0, 0x00, 0x00, 0x00, 0x00, -0x74, 0x4F, 0x79, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x74, 0xFE, 0xDF, 0x70, 0x00, 0x00, 0x00, 0x00, -0x76, 0x38, 0x96, 0x60, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDE, 0xC1, 0x70, 0x00, 0x00, 0x00, 0x00, -0x78, 0x18, 0x78, 0x60, 0x00, 0x00, 0x00, 0x00, 0x78, 0xBE, 0xA3, 0x70, 0x00, 0x00, 0x00, 0x00, -0x79, 0xF8, 0x5A, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x9E, 0x85, 0x70, 0x00, 0x00, 0x00, 0x00, -0x7B, 0xD8, 0x3C, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x67, 0x70, 0x00, 0x00, 0x00, 0x00, -0x7D, 0xB8, 0x1E, 0x60, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5E, 0x49, 0x70, 0x00, 0x00, 0x00, 0x00, -0x7F, 0x98, 0x00, 0x60, 0x00, 0x01, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, -0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, -0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, -0x02, 0x03, 0x02, 0xFF, 0xFF, 0xB3, 0xB4, 0x00, 0x00, 0xFF, 0xFF, 0xB8, 0x01, 0x00, 0x04, 0xFF, -0xFF, 0xB9, 0xB0, 0x00, 0x08, 0xFF, 0xFF, 0xC7, 0xC0, 0x01, 0x0C, 0x4C, 0x4D, 0x54, 0x00, 0x4B, -0x4D, 0x54, 0x00, 0x45, 0x53, 0x54, 0x00, 0x45, 0x44, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x0A, 0x45, 0x53, 0x54, 0x35, 0x45, 0x44, 0x54, 0x2C, 0x4D, 0x33, 0x2E, 0x32, -0x2E, 0x30, 0x2C, 0x4D, 0x31, 0x31, 0x2E, 0x31, 0x2E, 0x30, 0x0A, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x0C, 0xF8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x69, 0x87, 0x26, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, +0x8B, 0xF4, 0x61, 0xE8, 0x00, 0x01, 0x02, 0xFF, 0xFF, 0xB5, 0x70, 0x00, 0x00, 0xFF, 0xFF, 0xB5, +0x18, 0x00, 0x04, 0xFF, 0xFF, 0xB9, 0xB0, 0x00, 0x08, 0x4C, 0x4D, 0x54, 0x00, 0x43, 0x4D, 0x54, +0x00, 0x45, 0x53, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x45, 0x53, 0x54, 0x35, +0x0A, #endif 0x00, 0xA6, 0xC7, 0x50, 0x00, 0x96, 0x7A, 0x22, 0x00, 0x00, 0x00, 0x00, @@ -11486,8 +11445,8 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { /* America/Metlakatla */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x55, 0x53, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x22, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x4F, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x1E, 0x80, 0x00, 0x00, 0x00, 0xCB, 0x89, 0x1A, 0xA0, 0xD2, 0x23, 0xF4, 0x70, 0xD2, 0x61, 0x26, 0x10, 0xFE, 0xB8, 0x47, 0x20, 0xFF, 0xA8, 0x2A, 0x10, 0x00, 0x98, 0x29, 0x20, 0x01, 0x88, 0x0C, 0x10, 0x02, 0x78, 0x0B, 0x20, 0x03, 0x71, 0x28, 0x90, 0x04, 0x61, 0x27, 0xA0, 0x05, 0x51, 0x0A, 0x90, 0x06, 0x41, 0x09, 0xA0, @@ -11496,17 +11455,32 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x0E, 0xB9, 0xAF, 0x10, 0x0F, 0xA9, 0xAE, 0x20, 0x10, 0x99, 0x91, 0x10, 0x11, 0x89, 0x90, 0x20, 0x12, 0x79, 0x73, 0x10, 0x13, 0x69, 0x72, 0x20, 0x14, 0x59, 0x55, 0x10, 0x15, 0x49, 0x54, 0x20, 0x16, 0x39, 0x37, 0x10, 0x17, 0x29, 0x36, 0x20, 0x18, 0x22, 0x53, 0x90, 0x19, 0x09, 0x18, 0x20, -0x1A, 0x02, 0x35, 0x90, 0x01, 0x02, 0x03, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, +0x1A, 0x02, 0x35, 0x90, 0x56, 0x35, 0xE2, 0xA0, 0x56, 0xE5, 0x48, 0x30, 0x58, 0x1E, 0xFF, 0x20, +0x58, 0xC5, 0x2A, 0x30, 0x59, 0xFE, 0xE1, 0x20, 0x5A, 0xA5, 0x0C, 0x30, 0x5B, 0xDE, 0xC3, 0x20, +0x5C, 0x84, 0xEE, 0x30, 0x5D, 0xBE, 0xA5, 0x20, 0x5E, 0x64, 0xD0, 0x30, 0x5F, 0x9E, 0x87, 0x20, +0x60, 0x4D, 0xEC, 0xB0, 0x61, 0x87, 0xA3, 0xA0, 0x62, 0x2D, 0xCE, 0xB0, 0x63, 0x67, 0x85, 0xA0, +0x64, 0x0D, 0xB0, 0xB0, 0x65, 0x47, 0x67, 0xA0, 0x65, 0xED, 0x92, 0xB0, 0x67, 0x27, 0x49, 0xA0, +0x67, 0xCD, 0x74, 0xB0, 0x69, 0x07, 0x2B, 0xA0, 0x69, 0xAD, 0x56, 0xB0, 0x6A, 0xE7, 0x0D, 0xA0, +0x6B, 0x96, 0x73, 0x30, 0x6C, 0xD0, 0x2A, 0x20, 0x6D, 0x76, 0x55, 0x30, 0x6E, 0xB0, 0x0C, 0x20, +0x6F, 0x56, 0x37, 0x30, 0x70, 0x8F, 0xEE, 0x20, 0x71, 0x36, 0x19, 0x30, 0x72, 0x6F, 0xD0, 0x20, +0x73, 0x15, 0xFB, 0x30, 0x74, 0x4F, 0xB2, 0x20, 0x74, 0xFF, 0x17, 0xB0, 0x76, 0x38, 0xCE, 0xA0, +0x76, 0xDE, 0xF9, 0xB0, 0x78, 0x18, 0xB0, 0xA0, 0x78, 0xBE, 0xDB, 0xB0, 0x79, 0xF8, 0x92, 0xA0, +0x7A, 0x9E, 0xBD, 0xB0, 0x7B, 0xD8, 0x74, 0xA0, 0x7C, 0x7E, 0x9F, 0xB0, 0x7D, 0xB8, 0x56, 0xA0, +0x7E, 0x5E, 0x81, 0xB0, 0x7F, 0x98, 0x38, 0xA0, 0x01, 0x02, 0x03, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, -0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0xFF, 0xFF, 0x84, 0xA6, 0x00, 0x00, 0xFF, 0xFF, 0x8F, 0x80, -0x00, 0x04, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x08, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x0C, 0xFF, 0xFF, -0x9D, 0x90, 0x01, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00, -0x50, 0x50, 0x54, 0x00, 0x50, 0x44, 0x54, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, -0x01, 0x00, +0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x04, 0x01, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0x06, +0x05, 0x06, 0x05, 0x06, 0x05, 0x06, 0x05, 0xFF, 0xFF, 0x84, 0xA6, 0x00, 0x00, 0xFF, 0xFF, 0x8F, +0x80, 0x00, 0x04, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x08, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x0C, 0xFF, +0xFF, 0x9D, 0x90, 0x01, 0x10, 0xFF, 0xFF, 0x81, 0x70, 0x00, 0x14, 0xFF, 0xFF, 0x8F, 0x80, 0x01, +0x19, 0x4C, 0x4D, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00, 0x50, 0x50, 0x54, +0x00, 0x50, 0x44, 0x54, 0x00, 0x41, 0x4B, 0x53, 0x54, 0x00, 0x41, 0x4B, 0x44, 0x54, 0x00, 0x00, +0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, #ifdef TIMELIB_SUPPORTS_V2DATA 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x14, 0xF8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x51, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x1E, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x3F, 0xC0, 0xCE, 0xDA, 0xFF, 0xFF, 0xFF, 0xFF, 0x7D, 0x87, 0x30, 0x1A, 0xFF, 0xFF, 0xFF, 0xFF, 0xCB, 0x89, 0x1A, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x23, 0xF4, 0x70, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x61, 0x26, 0x10, 0xFF, 0xFF, 0xFF, 0xFF, @@ -11524,19 +11498,46 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x13, 0x69, 0x72, 0x20, 0x00, 0x00, 0x00, 0x00, 0x14, 0x59, 0x55, 0x10, 0x00, 0x00, 0x00, 0x00, 0x15, 0x49, 0x54, 0x20, 0x00, 0x00, 0x00, 0x00, 0x16, 0x39, 0x37, 0x10, 0x00, 0x00, 0x00, 0x00, 0x17, 0x29, 0x36, 0x20, 0x00, 0x00, 0x00, 0x00, 0x18, 0x22, 0x53, 0x90, 0x00, 0x00, 0x00, 0x00, -0x19, 0x09, 0x18, 0x20, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x02, 0x35, 0x90, 0x00, 0x01, 0x02, 0x03, -0x04, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, +0x19, 0x09, 0x18, 0x20, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x02, 0x35, 0x90, 0x00, 0x00, 0x00, 0x00, +0x56, 0x35, 0xE2, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x56, 0xE5, 0x48, 0x30, 0x00, 0x00, 0x00, 0x00, +0x58, 0x1E, 0xFF, 0x20, 0x00, 0x00, 0x00, 0x00, 0x58, 0xC5, 0x2A, 0x30, 0x00, 0x00, 0x00, 0x00, +0x59, 0xFE, 0xE1, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5A, 0xA5, 0x0C, 0x30, 0x00, 0x00, 0x00, 0x00, +0x5B, 0xDE, 0xC3, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5C, 0x84, 0xEE, 0x30, 0x00, 0x00, 0x00, 0x00, +0x5D, 0xBE, 0xA5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5E, 0x64, 0xD0, 0x30, 0x00, 0x00, 0x00, 0x00, +0x5F, 0x9E, 0x87, 0x20, 0x00, 0x00, 0x00, 0x00, 0x60, 0x4D, 0xEC, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x61, 0x87, 0xA3, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x62, 0x2D, 0xCE, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x63, 0x67, 0x85, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x64, 0x0D, 0xB0, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x65, 0x47, 0x67, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x65, 0xED, 0x92, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x67, 0x27, 0x49, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x67, 0xCD, 0x74, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x69, 0x07, 0x2B, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x69, 0xAD, 0x56, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x6A, 0xE7, 0x0D, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x6B, 0x96, 0x73, 0x30, 0x00, 0x00, 0x00, 0x00, +0x6C, 0xD0, 0x2A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6D, 0x76, 0x55, 0x30, 0x00, 0x00, 0x00, 0x00, +0x6E, 0xB0, 0x0C, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6F, 0x56, 0x37, 0x30, 0x00, 0x00, 0x00, 0x00, +0x70, 0x8F, 0xEE, 0x20, 0x00, 0x00, 0x00, 0x00, 0x71, 0x36, 0x19, 0x30, 0x00, 0x00, 0x00, 0x00, +0x72, 0x6F, 0xD0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x73, 0x15, 0xFB, 0x30, 0x00, 0x00, 0x00, 0x00, +0x74, 0x4F, 0xB2, 0x20, 0x00, 0x00, 0x00, 0x00, 0x74, 0xFF, 0x17, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x76, 0x38, 0xCE, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x76, 0xDE, 0xF9, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x78, 0x18, 0xB0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x78, 0xBE, 0xDB, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x79, 0xF8, 0x92, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x7A, 0x9E, 0xBD, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x7B, 0xD8, 0x74, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x7E, 0x9F, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x7D, 0xB8, 0x56, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x5E, 0x81, 0xB0, 0x00, 0x00, 0x00, 0x00, +0x7F, 0x98, 0x38, 0xA0, 0x00, 0x01, 0x02, 0x03, 0x04, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, -0x00, 0x00, 0xD6, 0x26, 0x00, 0x00, 0xFF, 0xFF, 0x84, 0xA6, 0x00, 0x00, 0xFF, 0xFF, 0x8F, 0x80, -0x00, 0x04, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x08, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x0C, 0xFF, 0xFF, -0x9D, 0x90, 0x01, 0x10, 0x4C, 0x4D, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00, -0x50, 0x50, 0x54, 0x00, 0x50, 0x44, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, -0x00, 0x00, 0x01, 0x00, 0x0A, 0x50, 0x53, 0x54, 0x38, 0x0A, +0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, +0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, +0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, 0x06, 0x07, +0x06, 0x07, 0x06, 0x07, 0x06, 0x00, 0x00, 0xD6, 0x26, 0x00, 0x00, 0xFF, 0xFF, 0x84, 0xA6, 0x00, +0x00, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x04, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x08, 0xFF, 0xFF, 0x9D, +0x90, 0x01, 0x0C, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x10, 0xFF, 0xFF, 0x81, 0x70, 0x00, 0x14, 0xFF, +0xFF, 0x8F, 0x80, 0x01, 0x19, 0x4C, 0x4D, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x57, 0x54, +0x00, 0x50, 0x50, 0x54, 0x00, 0x50, 0x44, 0x54, 0x00, 0x41, 0x4B, 0x53, 0x54, 0x00, 0x41, 0x4B, +0x44, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, +0x00, 0x00, 0x00, 0x0A, 0x41, 0x4B, 0x53, 0x54, 0x39, 0x41, 0x4B, 0x44, 0x54, 0x2C, 0x4D, 0x33, +0x2E, 0x32, 0x2E, 0x30, 0x2C, 0x4D, 0x31, 0x31, 0x2E, 0x31, 0x2E, 0x30, 0x0A, #endif -0x00, 0xDD, 0x72, 0x36, 0x00, 0x49, 0xE3, 0x79, 0x00, 0x00, 0x00, 0x2E, 0x50, 0x61, 0x63, 0x69, -0x66, 0x69, 0x63, 0x20, 0x53, 0x74, 0x61, 0x6E, 0x64, 0x61, 0x72, 0x64, 0x20, 0x54, 0x69, 0x6D, -0x65, 0x20, 0x2D, 0x20, 0x41, 0x6E, 0x6E, 0x65, 0x74, 0x74, 0x65, 0x20, 0x49, 0x73, 0x6C, 0x61, -0x6E, 0x64, 0x2C, 0x20, 0x41, 0x6C, 0x61, 0x73, 0x6B, 0x61, +0x00, 0xDD, 0x72, 0x36, 0x00, 0x49, 0xE3, 0x79, 0x00, 0x00, 0x00, 0x1C, 0x41, 0x6C, 0x61, 0x73, +0x6B, 0x61, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x20, 0x2D, 0x20, 0x41, 0x6E, 0x6E, 0x65, 0x74, 0x74, +0x65, 0x20, 0x49, 0x73, 0x6C, 0x61, 0x6E, 0x64, /* America/Mexico_City */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x4D, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -14803,7 +14804,7 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x00, 0x89, 0x54, 0x40, 0x01, 0x12, 0xA8, 0x80, 0x00, 0x00, 0x00, 0x00, /* America/Santa_Isabel */ -0x50, 0x48, 0x50, 0x32, 0x01, 0x4D, 0x58, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x50, 0x48, 0x50, 0x32, 0x00, 0x3F, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x18, 0x80, 0x00, 0x00, 0x00, 0xA5, 0xB6, 0xF6, 0x80, 0xA9, 0x79, 0x4F, 0x70, 0xAF, 0xF2, 0x7C, 0xF0, 0xB6, 0x66, 0x64, 0x70, @@ -14829,21 +14830,21 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x3F, 0x9B, 0x8D, 0x10, 0x40, 0x6F, 0xDC, 0xA0, 0x41, 0x84, 0xA9, 0x90, 0x42, 0x4F, 0xBE, 0xA0, 0x43, 0x64, 0x8B, 0x90, 0x44, 0x2F, 0xA0, 0xA0, 0x45, 0x44, 0x6D, 0x90, 0x46, 0x0F, 0x82, 0xA0, 0x47, 0x24, 0x4F, 0x90, 0x47, 0xF8, 0x9F, 0x20, 0x49, 0x04, 0x31, 0x90, 0x49, 0xD8, 0x81, 0x20, -0x4A, 0xE4, 0x13, 0x90, 0x4B, 0xB8, 0x63, 0x20, 0x4C, 0xCD, 0x30, 0x10, 0x4D, 0x98, 0x45, 0x20, -0x4E, 0xAD, 0x12, 0x10, 0x4F, 0x78, 0x27, 0x20, 0x50, 0x8C, 0xF4, 0x10, 0x51, 0x61, 0x43, 0xA0, -0x52, 0x6C, 0xD6, 0x10, 0x53, 0x41, 0x25, 0xA0, 0x54, 0x4C, 0xB8, 0x10, 0x55, 0x21, 0x07, 0xA0, -0x56, 0x2C, 0x9A, 0x10, 0x57, 0x00, 0xE9, 0xA0, 0x58, 0x15, 0xB6, 0x90, 0x58, 0xE0, 0xCB, 0xA0, -0x59, 0xF5, 0x98, 0x90, 0x5A, 0xC0, 0xAD, 0xA0, 0x5B, 0xD5, 0x7A, 0x90, 0x5C, 0xA9, 0xCA, 0x20, -0x5D, 0xB5, 0x5C, 0x90, 0x5E, 0x89, 0xAC, 0x20, 0x5F, 0x95, 0x3E, 0x90, 0x60, 0x69, 0x8E, 0x20, -0x61, 0x7E, 0x5B, 0x10, 0x62, 0x49, 0x70, 0x20, 0x63, 0x5E, 0x3D, 0x10, 0x64, 0x29, 0x52, 0x20, -0x65, 0x3E, 0x1F, 0x10, 0x66, 0x12, 0x6E, 0xA0, 0x67, 0x1E, 0x01, 0x10, 0x67, 0xF2, 0x50, 0xA0, -0x68, 0xFD, 0xE3, 0x10, 0x69, 0xD2, 0x32, 0xA0, 0x6A, 0xDD, 0xC5, 0x10, 0x6B, 0xB2, 0x14, 0xA0, -0x6C, 0xC6, 0xE1, 0x90, 0x6D, 0x91, 0xF6, 0xA0, 0x6E, 0xA6, 0xC3, 0x90, 0x6F, 0x71, 0xD8, 0xA0, -0x70, 0x86, 0xA5, 0x90, 0x71, 0x5A, 0xF5, 0x20, 0x72, 0x66, 0x87, 0x90, 0x73, 0x3A, 0xD7, 0x20, -0x74, 0x46, 0x69, 0x90, 0x75, 0x1A, 0xB9, 0x20, 0x76, 0x2F, 0x86, 0x10, 0x76, 0xFA, 0x9B, 0x20, -0x78, 0x0F, 0x68, 0x10, 0x78, 0xDA, 0x7D, 0x20, 0x79, 0xEF, 0x4A, 0x10, 0x7A, 0xBA, 0x5F, 0x20, -0x7B, 0xCF, 0x2C, 0x10, 0x7C, 0xA3, 0x7B, 0xA0, 0x7D, 0xAF, 0x0E, 0x10, 0x7E, 0x83, 0x5D, 0xA0, -0x7F, 0x8E, 0xF0, 0x10, 0x00, 0x01, 0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x05, 0x02, 0x03, 0x02, +0x4A, 0xE4, 0x13, 0x90, 0x4B, 0x9C, 0xB3, 0xA0, 0x4C, 0xD6, 0x6A, 0x90, 0x4D, 0x7C, 0x95, 0xA0, +0x4E, 0xB6, 0x4C, 0x90, 0x4F, 0x5C, 0x77, 0xA0, 0x50, 0x96, 0x2E, 0x90, 0x51, 0x3C, 0x59, 0xA0, +0x52, 0x76, 0x10, 0x90, 0x53, 0x1C, 0x3B, 0xA0, 0x54, 0x55, 0xF2, 0x90, 0x54, 0xFC, 0x1D, 0xA0, +0x56, 0x35, 0xD4, 0x90, 0x56, 0xE5, 0x3A, 0x20, 0x58, 0x1E, 0xF1, 0x10, 0x58, 0xC5, 0x1C, 0x20, +0x59, 0xFE, 0xD3, 0x10, 0x5A, 0xA4, 0xFE, 0x20, 0x5B, 0xDE, 0xB5, 0x10, 0x5C, 0x84, 0xE0, 0x20, +0x5D, 0xBE, 0x97, 0x10, 0x5E, 0x64, 0xC2, 0x20, 0x5F, 0x9E, 0x79, 0x10, 0x60, 0x4D, 0xDE, 0xA0, +0x61, 0x87, 0x95, 0x90, 0x62, 0x2D, 0xC0, 0xA0, 0x63, 0x67, 0x77, 0x90, 0x64, 0x0D, 0xA2, 0xA0, +0x65, 0x47, 0x59, 0x90, 0x65, 0xED, 0x84, 0xA0, 0x67, 0x27, 0x3B, 0x90, 0x67, 0xCD, 0x66, 0xA0, +0x69, 0x07, 0x1D, 0x90, 0x69, 0xAD, 0x48, 0xA0, 0x6A, 0xE6, 0xFF, 0x90, 0x6B, 0x96, 0x65, 0x20, +0x6C, 0xD0, 0x1C, 0x10, 0x6D, 0x76, 0x47, 0x20, 0x6E, 0xAF, 0xFE, 0x10, 0x6F, 0x56, 0x29, 0x20, +0x70, 0x8F, 0xE0, 0x10, 0x71, 0x36, 0x0B, 0x20, 0x72, 0x6F, 0xC2, 0x10, 0x73, 0x15, 0xED, 0x20, +0x74, 0x4F, 0xA4, 0x10, 0x74, 0xFF, 0x09, 0xA0, 0x76, 0x38, 0xC0, 0x90, 0x76, 0xDE, 0xEB, 0xA0, +0x78, 0x18, 0xA2, 0x90, 0x78, 0xBE, 0xCD, 0xA0, 0x79, 0xF8, 0x84, 0x90, 0x7A, 0x9E, 0xAF, 0xA0, +0x7B, 0xD8, 0x66, 0x90, 0x7C, 0x7E, 0x91, 0xA0, 0x7D, 0xB8, 0x48, 0x90, 0x7E, 0x5E, 0x73, 0xA0, +0x7F, 0x98, 0x2A, 0x90, 0x00, 0x01, 0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x05, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, @@ -14852,7 +14853,7 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, -0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0xFF, 0xFF, 0x94, 0x50, 0x00, 0x00, +0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0xFF, 0xFF, 0x92, 0x4C, 0x00, 0x00, 0xFF, 0xFF, 0x9D, 0x90, 0x00, 0x04, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x08, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x0C, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x10, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x14, 0x4C, 0x4D, 0x54, 0x00, 0x4D, 0x53, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x44, 0x54, 0x00, 0x50, 0x57, @@ -14909,34 +14910,34 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x46, 0x0F, 0x82, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x47, 0x24, 0x4F, 0x90, 0x00, 0x00, 0x00, 0x00, 0x47, 0xF8, 0x9F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x49, 0x04, 0x31, 0x90, 0x00, 0x00, 0x00, 0x00, 0x49, 0xD8, 0x81, 0x20, 0x00, 0x00, 0x00, 0x00, 0x4A, 0xE4, 0x13, 0x90, 0x00, 0x00, 0x00, 0x00, -0x4B, 0xB8, 0x63, 0x20, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xCD, 0x30, 0x10, 0x00, 0x00, 0x00, 0x00, -0x4D, 0x98, 0x45, 0x20, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xAD, 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, -0x4F, 0x78, 0x27, 0x20, 0x00, 0x00, 0x00, 0x00, 0x50, 0x8C, 0xF4, 0x10, 0x00, 0x00, 0x00, 0x00, -0x51, 0x61, 0x43, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x52, 0x6C, 0xD6, 0x10, 0x00, 0x00, 0x00, 0x00, -0x53, 0x41, 0x25, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x54, 0x4C, 0xB8, 0x10, 0x00, 0x00, 0x00, 0x00, -0x55, 0x21, 0x07, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x56, 0x2C, 0x9A, 0x10, 0x00, 0x00, 0x00, 0x00, -0x57, 0x00, 0xE9, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x58, 0x15, 0xB6, 0x90, 0x00, 0x00, 0x00, 0x00, -0x58, 0xE0, 0xCB, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x59, 0xF5, 0x98, 0x90, 0x00, 0x00, 0x00, 0x00, -0x5A, 0xC0, 0xAD, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xD5, 0x7A, 0x90, 0x00, 0x00, 0x00, 0x00, -0x5C, 0xA9, 0xCA, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xB5, 0x5C, 0x90, 0x00, 0x00, 0x00, 0x00, -0x5E, 0x89, 0xAC, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x95, 0x3E, 0x90, 0x00, 0x00, 0x00, 0x00, -0x60, 0x69, 0x8E, 0x20, 0x00, 0x00, 0x00, 0x00, 0x61, 0x7E, 0x5B, 0x10, 0x00, 0x00, 0x00, 0x00, -0x62, 0x49, 0x70, 0x20, 0x00, 0x00, 0x00, 0x00, 0x63, 0x5E, 0x3D, 0x10, 0x00, 0x00, 0x00, 0x00, -0x64, 0x29, 0x52, 0x20, 0x00, 0x00, 0x00, 0x00, 0x65, 0x3E, 0x1F, 0x10, 0x00, 0x00, 0x00, 0x00, -0x66, 0x12, 0x6E, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x67, 0x1E, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, -0x67, 0xF2, 0x50, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x68, 0xFD, 0xE3, 0x10, 0x00, 0x00, 0x00, 0x00, -0x69, 0xD2, 0x32, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x6A, 0xDD, 0xC5, 0x10, 0x00, 0x00, 0x00, 0x00, -0x6B, 0xB2, 0x14, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xC6, 0xE1, 0x90, 0x00, 0x00, 0x00, 0x00, -0x6D, 0x91, 0xF6, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x6E, 0xA6, 0xC3, 0x90, 0x00, 0x00, 0x00, 0x00, -0x6F, 0x71, 0xD8, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x70, 0x86, 0xA5, 0x90, 0x00, 0x00, 0x00, 0x00, -0x71, 0x5A, 0xF5, 0x20, 0x00, 0x00, 0x00, 0x00, 0x72, 0x66, 0x87, 0x90, 0x00, 0x00, 0x00, 0x00, -0x73, 0x3A, 0xD7, 0x20, 0x00, 0x00, 0x00, 0x00, 0x74, 0x46, 0x69, 0x90, 0x00, 0x00, 0x00, 0x00, -0x75, 0x1A, 0xB9, 0x20, 0x00, 0x00, 0x00, 0x00, 0x76, 0x2F, 0x86, 0x10, 0x00, 0x00, 0x00, 0x00, -0x76, 0xFA, 0x9B, 0x20, 0x00, 0x00, 0x00, 0x00, 0x78, 0x0F, 0x68, 0x10, 0x00, 0x00, 0x00, 0x00, -0x78, 0xDA, 0x7D, 0x20, 0x00, 0x00, 0x00, 0x00, 0x79, 0xEF, 0x4A, 0x10, 0x00, 0x00, 0x00, 0x00, -0x7A, 0xBA, 0x5F, 0x20, 0x00, 0x00, 0x00, 0x00, 0x7B, 0xCF, 0x2C, 0x10, 0x00, 0x00, 0x00, 0x00, -0x7C, 0xA3, 0x7B, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x7D, 0xAF, 0x0E, 0x10, 0x00, 0x00, 0x00, 0x00, -0x7E, 0x83, 0x5D, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x8E, 0xF0, 0x10, 0x00, 0x01, 0x02, 0x01, +0x4B, 0x9C, 0xB3, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xD6, 0x6A, 0x90, 0x00, 0x00, 0x00, 0x00, +0x4D, 0x7C, 0x95, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x4E, 0xB6, 0x4C, 0x90, 0x00, 0x00, 0x00, 0x00, +0x4F, 0x5C, 0x77, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x50, 0x96, 0x2E, 0x90, 0x00, 0x00, 0x00, 0x00, +0x51, 0x3C, 0x59, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x52, 0x76, 0x10, 0x90, 0x00, 0x00, 0x00, 0x00, +0x53, 0x1C, 0x3B, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x54, 0x55, 0xF2, 0x90, 0x00, 0x00, 0x00, 0x00, +0x54, 0xFC, 0x1D, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x56, 0x35, 0xD4, 0x90, 0x00, 0x00, 0x00, 0x00, +0x56, 0xE5, 0x3A, 0x20, 0x00, 0x00, 0x00, 0x00, 0x58, 0x1E, 0xF1, 0x10, 0x00, 0x00, 0x00, 0x00, +0x58, 0xC5, 0x1C, 0x20, 0x00, 0x00, 0x00, 0x00, 0x59, 0xFE, 0xD3, 0x10, 0x00, 0x00, 0x00, 0x00, +0x5A, 0xA4, 0xFE, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5B, 0xDE, 0xB5, 0x10, 0x00, 0x00, 0x00, 0x00, +0x5C, 0x84, 0xE0, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5D, 0xBE, 0x97, 0x10, 0x00, 0x00, 0x00, 0x00, +0x5E, 0x64, 0xC2, 0x20, 0x00, 0x00, 0x00, 0x00, 0x5F, 0x9E, 0x79, 0x10, 0x00, 0x00, 0x00, 0x00, +0x60, 0x4D, 0xDE, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x61, 0x87, 0x95, 0x90, 0x00, 0x00, 0x00, 0x00, +0x62, 0x2D, 0xC0, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x63, 0x67, 0x77, 0x90, 0x00, 0x00, 0x00, 0x00, +0x64, 0x0D, 0xA2, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x65, 0x47, 0x59, 0x90, 0x00, 0x00, 0x00, 0x00, +0x65, 0xED, 0x84, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x67, 0x27, 0x3B, 0x90, 0x00, 0x00, 0x00, 0x00, +0x67, 0xCD, 0x66, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x69, 0x07, 0x1D, 0x90, 0x00, 0x00, 0x00, 0x00, +0x69, 0xAD, 0x48, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x6A, 0xE6, 0xFF, 0x90, 0x00, 0x00, 0x00, 0x00, +0x6B, 0x96, 0x65, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6C, 0xD0, 0x1C, 0x10, 0x00, 0x00, 0x00, 0x00, +0x6D, 0x76, 0x47, 0x20, 0x00, 0x00, 0x00, 0x00, 0x6E, 0xAF, 0xFE, 0x10, 0x00, 0x00, 0x00, 0x00, +0x6F, 0x56, 0x29, 0x20, 0x00, 0x00, 0x00, 0x00, 0x70, 0x8F, 0xE0, 0x10, 0x00, 0x00, 0x00, 0x00, +0x71, 0x36, 0x0B, 0x20, 0x00, 0x00, 0x00, 0x00, 0x72, 0x6F, 0xC2, 0x10, 0x00, 0x00, 0x00, 0x00, +0x73, 0x15, 0xED, 0x20, 0x00, 0x00, 0x00, 0x00, 0x74, 0x4F, 0xA4, 0x10, 0x00, 0x00, 0x00, 0x00, +0x74, 0xFF, 0x09, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x76, 0x38, 0xC0, 0x90, 0x00, 0x00, 0x00, 0x00, +0x76, 0xDE, 0xEB, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x78, 0x18, 0xA2, 0x90, 0x00, 0x00, 0x00, 0x00, +0x78, 0xBE, 0xCD, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x79, 0xF8, 0x84, 0x90, 0x00, 0x00, 0x00, 0x00, +0x7A, 0x9E, 0xAF, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x7B, 0xD8, 0x66, 0x90, 0x00, 0x00, 0x00, 0x00, +0x7C, 0x7E, 0x91, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x7D, 0xB8, 0x48, 0x90, 0x00, 0x00, 0x00, 0x00, +0x7E, 0x5E, 0x73, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x7F, 0x98, 0x2A, 0x90, 0x00, 0x01, 0x02, 0x01, 0x02, 0x03, 0x02, 0x04, 0x05, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, @@ -14946,19 +14947,15 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, -0x03, 0x02, 0xFF, 0xFF, 0x94, 0x50, 0x00, 0x00, 0xFF, 0xFF, 0x9D, 0x90, 0x00, 0x04, 0xFF, 0xFF, +0x03, 0x02, 0xFF, 0xFF, 0x92, 0x4C, 0x00, 0x00, 0xFF, 0xFF, 0x9D, 0x90, 0x00, 0x04, 0xFF, 0xFF, 0x8F, 0x80, 0x00, 0x08, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x0C, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x10, 0xFF, 0xFF, 0x9D, 0x90, 0x01, 0x14, 0x4C, 0x4D, 0x54, 0x00, 0x4D, 0x53, 0x54, 0x00, 0x50, 0x53, 0x54, 0x00, 0x50, 0x44, 0x54, 0x00, 0x50, 0x57, 0x54, 0x00, 0x50, 0x50, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x0A, 0x50, 0x53, 0x54, 0x38, 0x50, -0x44, 0x54, 0x2C, 0x4D, 0x34, 0x2E, 0x31, 0x2E, 0x30, 0x2C, 0x4D, 0x31, 0x30, 0x2E, 0x35, 0x2E, +0x44, 0x54, 0x2C, 0x4D, 0x33, 0x2E, 0x32, 0x2E, 0x30, 0x2C, 0x4D, 0x31, 0x31, 0x2E, 0x31, 0x2E, 0x30, 0x0A, #endif -0x00, 0xB7, 0x90, 0x30, 0x00, 0x63, 0x62, 0xB5, 0x00, 0x00, 0x00, 0x3A, 0x4D, 0x65, 0x78, 0x69, -0x63, 0x61, 0x6E, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x54, 0x69, 0x6D, 0x65, -0x20, 0x2D, 0x20, 0x42, 0x61, 0x6A, 0x61, 0x20, 0x43, 0x61, 0x6C, 0x69, 0x66, 0x6F, 0x72, 0x6E, -0x69, 0x61, 0x20, 0x61, 0x77, 0x61, 0x79, 0x20, 0x66, 0x72, 0x6F, 0x6D, 0x20, 0x55, 0x53, 0x20, -0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, +0x00, 0x89, 0x54, 0x40, 0x01, 0x12, 0xA8, 0x80, 0x00, 0x00, 0x00, 0x00, /* America/Santarem */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x42, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -16532,10 +16529,10 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x44, 0x54, 0x2C, 0x4D, 0x33, 0x2E, 0x32, 0x2E, 0x30, 0x2C, 0x4D, 0x31, 0x31, 0x2E, 0x31, 0x2E, 0x30, 0x0A, #endif -0x00, 0xBA, 0xF8, 0x95, 0x00, 0x60, 0x1A, 0xDD, 0x00, 0x00, 0x00, 0x30, 0x55, 0x53, 0x20, 0x50, +0x00, 0xBA, 0xF8, 0x95, 0x00, 0x60, 0x1A, 0xDD, 0x00, 0x00, 0x00, 0x27, 0x55, 0x53, 0x20, 0x50, 0x61, 0x63, 0x69, 0x66, 0x69, 0x63, 0x20, 0x54, 0x69, 0x6D, 0x65, 0x20, 0x2D, 0x20, 0x42, 0x61, -0x6A, 0x61, 0x20, 0x43, 0x61, 0x6C, 0x69, 0x66, 0x6F, 0x72, 0x6E, 0x69, 0x61, 0x20, 0x6E, 0x65, -0x61, 0x72, 0x20, 0x55, 0x53, 0x20, 0x62, 0x6F, 0x72, 0x64, 0x65, 0x72, +0x6A, 0x61, 0x20, 0x43, 0x61, 0x6C, 0x69, 0x66, 0x6F, 0x72, 0x6E, 0x69, 0x61, 0x20, 0x73, 0x74, +0x61, 0x74, 0x65, /* America/Toronto */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x43, 0x41, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, @@ -19524,8 +19521,8 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { /* Asia/Chita */ 0x50, 0x48, 0x50, 0x32, 0x01, 0x52, 0x55, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x14, 0x80, 0x00, 0x00, 0x00, 0xA1, 0xDB, 0xF9, 0xA0, 0xB5, 0xA3, 0xC5, 0x00, 0x15, 0x27, 0x53, 0x70, 0x16, 0x18, 0x87, 0xE0, 0x17, 0x08, 0x86, 0xF0, 0x17, 0xF9, 0xBB, 0x60, 0x18, 0xE9, 0xBA, 0x70, 0x19, 0xDA, 0xEE, 0xE0, 0x1A, 0xCC, 0x3F, 0x70, 0x1B, 0xBC, 0x4C, 0x90, 0x1C, 0xAC, 0x3D, 0x90, 0x1D, 0x9C, 0x2E, 0x90, @@ -19542,22 +19539,22 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x43, 0x63, 0xAA, 0x90, 0x44, 0x25, 0x77, 0x10, 0x45, 0x43, 0x8C, 0x90, 0x46, 0x05, 0x59, 0x10, 0x47, 0x23, 0x6E, 0x90, 0x47, 0xEE, 0x75, 0x90, 0x49, 0x03, 0x50, 0x90, 0x49, 0xCE, 0x57, 0x90, 0x4A, 0xE3, 0x32, 0x90, 0x4B, 0xAE, 0x39, 0x90, 0x4C, 0xCC, 0x4F, 0x10, 0x4D, 0x8E, 0x1B, 0x90, -0x54, 0x4B, 0xC9, 0x00, 0x00, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x04, 0x05, -0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x06, 0x07, 0x04, 0x02, 0x03, -0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, +0x54, 0x4B, 0xC9, 0x00, 0x56, 0xF6, 0xCE, 0x20, 0x00, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, +0x03, 0x02, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x06, +0x07, 0x04, 0x02, 0x03, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, -0x05, 0x04, 0x05, 0x04, 0x08, 0x09, 0x00, 0x00, 0x6A, 0x60, 0x00, 0x00, 0x00, 0x00, 0x70, 0x80, -0x00, 0x04, 0x00, 0x00, 0x8C, 0xA0, 0x01, 0x09, 0x00, 0x00, 0x7E, 0x90, 0x00, 0x04, 0x00, 0x00, -0x7E, 0x90, 0x00, 0x04, 0x00, 0x00, 0x8C, 0xA0, 0x01, 0x09, 0x00, 0x00, 0x7E, 0x90, 0x01, 0x09, -0x00, 0x00, 0x70, 0x80, 0x00, 0x04, 0x00, 0x00, 0x8C, 0xA0, 0x00, 0x04, 0x00, 0x00, 0x70, 0x80, -0x00, 0x0F, 0x00, 0x00, 0x8C, 0xA0, 0x01, 0x09, 0x4C, 0x4D, 0x54, 0x00, 0x59, 0x41, 0x4B, 0x54, -0x00, 0x59, 0x41, 0x4B, 0x53, 0x54, 0x00, 0x49, 0x52, 0x4B, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, -0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, +0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x08, 0x09, 0x03, 0x00, 0x00, 0x6A, 0x60, 0x00, +0x00, 0x00, 0x00, 0x70, 0x80, 0x00, 0x04, 0x00, 0x00, 0x8C, 0xA0, 0x01, 0x09, 0x00, 0x00, 0x7E, +0x90, 0x00, 0x04, 0x00, 0x00, 0x7E, 0x90, 0x00, 0x04, 0x00, 0x00, 0x8C, 0xA0, 0x01, 0x09, 0x00, +0x00, 0x7E, 0x90, 0x01, 0x09, 0x00, 0x00, 0x70, 0x80, 0x00, 0x04, 0x00, 0x00, 0x8C, 0xA0, 0x00, +0x04, 0x00, 0x00, 0x70, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x8C, 0xA0, 0x01, 0x09, 0x00, 0x00, 0x7E, +0x90, 0x00, 0x04, 0x4C, 0x4D, 0x54, 0x00, 0x59, 0x41, 0x4B, 0x54, 0x00, 0x59, 0x41, 0x4B, 0x53, +0x54, 0x00, 0x49, 0x52, 0x4B, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, +0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, #ifdef TIMELIB_SUPPORTS_V2DATA 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x42, 0x00, 0x00, 0x00, 0x0B, 0x00, 0x00, 0x00, 0x14, 0xF8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x43, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x14, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0xA1, 0xDB, 0xF9, 0xA0, 0xFF, 0xFF, 0xFF, 0xFF, 0xB5, 0xA3, 0xC5, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x27, 0x53, 0x70, 0x00, 0x00, 0x00, 0x00, 0x16, 0x18, 0x87, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x17, 0x08, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x00, @@ -19590,19 +19587,20 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x47, 0xEE, 0x75, 0x90, 0x00, 0x00, 0x00, 0x00, 0x49, 0x03, 0x50, 0x90, 0x00, 0x00, 0x00, 0x00, 0x49, 0xCE, 0x57, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4A, 0xE3, 0x32, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4B, 0xAE, 0x39, 0x90, 0x00, 0x00, 0x00, 0x00, 0x4C, 0xCC, 0x4F, 0x10, 0x00, 0x00, 0x00, 0x00, -0x4D, 0x8E, 0x1B, 0x90, 0x00, 0x00, 0x00, 0x00, 0x54, 0x4B, 0xC9, 0x00, 0x00, 0x01, 0x03, 0x02, -0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, -0x04, 0x05, 0x04, 0x06, 0x07, 0x04, 0x02, 0x03, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, +0x4D, 0x8E, 0x1B, 0x90, 0x00, 0x00, 0x00, 0x00, 0x54, 0x4B, 0xC9, 0x00, 0x00, 0x00, 0x00, 0x00, +0x56, 0xF6, 0xCE, 0x20, 0x00, 0x01, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x03, 0x02, 0x04, 0x05, +0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x06, 0x07, 0x04, 0x02, 0x03, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, -0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x08, 0x09, 0x00, 0x00, -0x6A, 0x60, 0x00, 0x00, 0x00, 0x00, 0x70, 0x80, 0x00, 0x04, 0x00, 0x00, 0x8C, 0xA0, 0x01, 0x09, -0x00, 0x00, 0x7E, 0x90, 0x00, 0x04, 0x00, 0x00, 0x7E, 0x90, 0x00, 0x04, 0x00, 0x00, 0x8C, 0xA0, -0x01, 0x09, 0x00, 0x00, 0x7E, 0x90, 0x01, 0x09, 0x00, 0x00, 0x70, 0x80, 0x00, 0x04, 0x00, 0x00, -0x8C, 0xA0, 0x00, 0x04, 0x00, 0x00, 0x70, 0x80, 0x00, 0x0F, 0x00, 0x00, 0x8C, 0xA0, 0x01, 0x09, -0x4C, 0x4D, 0x54, 0x00, 0x59, 0x41, 0x4B, 0x54, 0x00, 0x59, 0x41, 0x4B, 0x53, 0x54, 0x00, 0x49, -0x52, 0x4B, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x49, 0x52, 0x4B, 0x54, 0x2D, -0x38, 0x0A, +0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, +0x05, 0x04, 0x05, 0x04, 0x08, 0x09, 0x03, 0x00, 0x00, 0x6A, 0x60, 0x00, 0x00, 0x00, 0x00, 0x70, +0x80, 0x00, 0x04, 0x00, 0x00, 0x8C, 0xA0, 0x01, 0x09, 0x00, 0x00, 0x7E, 0x90, 0x00, 0x04, 0x00, +0x00, 0x7E, 0x90, 0x00, 0x04, 0x00, 0x00, 0x8C, 0xA0, 0x01, 0x09, 0x00, 0x00, 0x7E, 0x90, 0x01, +0x09, 0x00, 0x00, 0x70, 0x80, 0x00, 0x04, 0x00, 0x00, 0x8C, 0xA0, 0x00, 0x04, 0x00, 0x00, 0x70, +0x80, 0x00, 0x0F, 0x00, 0x00, 0x8C, 0xA0, 0x01, 0x09, 0x00, 0x00, 0x7E, 0x90, 0x00, 0x04, 0x4C, +0x4D, 0x54, 0x00, 0x59, 0x41, 0x4B, 0x54, 0x00, 0x59, 0x41, 0x4B, 0x53, 0x54, 0x00, 0x49, 0x52, +0x4B, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, +0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x59, 0x41, 0x4B, 0x54, +0x2D, 0x39, 0x0A, #endif 0x00, 0xD8, 0xC0, 0x48, 0x01, 0xBF, 0xCB, 0x6A, 0x00, 0x00, 0x00, 0x34, 0x4D, 0x6F, 0x73, 0x63, 0x6F, 0x77, 0x2B, 0x30, 0x36, 0x20, 0x28, 0x4D, 0x6F, 0x73, 0x63, 0x6F, 0x77, 0x2B, 0x30, 0x35, @@ -21230,7 +21228,7 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x16, 0x80, 0x00, 0x00, 0x00, 0x89, 0x7E, 0xFC, 0xA4, 0xCC, 0x95, 0x32, 0xA8, 0xD2, 0x74, 0x12, 0x98, 0xDD, 0xA8, 0xE0, 0xA8, -0x02, 0x4F, 0xAB, 0x30, 0x3C, 0xAF, 0x45, 0xEC, 0x3D, 0x9F, 0x28, 0xDC, 0x48, 0x41, 0xA0, 0x30, +0x02, 0x4F, 0xAB, 0x30, 0x3C, 0xAF, 0x45, 0xB0, 0x3D, 0x9F, 0x28, 0xA0, 0x48, 0x41, 0xA0, 0x30, 0x49, 0x0B, 0x47, 0xA0, 0x49, 0xE4, 0xDD, 0x30, 0x4A, 0xEC, 0x7B, 0x20, 0x00, 0x01, 0x02, 0x01, 0x03, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x00, 0x00, 0x3E, 0xDC, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x58, 0x00, 0x04, 0x00, 0x00, 0x5B, 0x68, 0x01, 0x04, 0x00, 0x00, 0x46, 0x50, 0x00, 0x08, @@ -21244,7 +21242,7 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x89, 0x7E, 0xFC, 0xA4, 0xFF, 0xFF, 0xFF, 0xFF, 0xCC, 0x95, 0x32, 0xA8, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0x74, 0x12, 0x98, 0xFF, 0xFF, 0xFF, 0xFF, 0xDD, 0xA8, 0xE0, 0xA8, 0x00, 0x00, 0x00, 0x00, 0x02, 0x4F, 0xAB, 0x30, 0x00, 0x00, 0x00, 0x00, -0x3C, 0xAF, 0x45, 0xEC, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x9F, 0x28, 0xDC, 0x00, 0x00, 0x00, 0x00, +0x3C, 0xAF, 0x45, 0xB0, 0x00, 0x00, 0x00, 0x00, 0x3D, 0x9F, 0x28, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x48, 0x41, 0xA0, 0x30, 0x00, 0x00, 0x00, 0x00, 0x49, 0x0B, 0x47, 0xA0, 0x00, 0x00, 0x00, 0x00, 0x49, 0xE4, 0xDD, 0x30, 0x00, 0x00, 0x00, 0x00, 0x4A, 0xEC, 0x7B, 0x20, 0x00, 0x01, 0x02, 0x01, 0x03, 0x05, 0x04, 0x05, 0x04, 0x05, 0x04, 0x05, 0x00, 0x00, 0x3E, 0xDC, 0x00, 0x00, 0x00, 0x00, @@ -23118,7 +23116,7 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { #ifdef TIMELIB_SUPPORTS_V2DATA 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x12, 0xF8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x12, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xDB, 0x12, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xBB, 0xA2, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x74, 0x2D, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x8E, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00, @@ -23169,18 +23167,19 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x79, 0xBD, 0xC4, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xAC, 0x72, 0x48, 0x00, 0x00, 0x00, 0x00, 0x7B, 0x9E, 0xF8, 0x38, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x8D, 0xA5, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x7D, 0x80, 0x2B, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x6E, 0xD9, 0x48, 0x00, 0x00, 0x00, 0x00, -0x7F, 0x61, 0x5F, 0x38, 0x00, 0x00, 0x00, 0x03, 0x74, 0x0A, 0xD8, 0x00, 0x00, 0x01, 0x02, 0x04, -0x03, 0x04, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, +0x7F, 0x61, 0x5F, 0x38, 0x00, 0x01, 0x02, 0x04, 0x03, 0x04, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, -0x02, 0x06, 0x00, 0x00, 0x30, 0x38, 0x00, 0x00, 0x00, 0x00, 0x30, 0x38, 0x00, 0x04, 0x00, 0x00, -0x31, 0x38, 0x00, 0x08, 0x00, 0x00, 0x46, 0x50, 0x01, 0x0D, 0x00, 0x00, 0x38, 0x40, 0x00, 0x08, -0x00, 0x00, 0x3F, 0x48, 0x01, 0x0D, 0x00, 0x00, 0x31, 0x38, 0x00, 0x08, 0x4C, 0x4D, 0x54, 0x00, -0x54, 0x4D, 0x54, 0x00, 0x49, 0x52, 0x53, 0x54, 0x00, 0x49, 0x52, 0x44, 0x54, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0A, +0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x00, 0x00, 0x30, 0x38, 0x00, 0x00, 0x00, +0x00, 0x30, 0x38, 0x00, 0x04, 0x00, 0x00, 0x31, 0x38, 0x00, 0x08, 0x00, 0x00, 0x46, 0x50, 0x01, +0x0D, 0x00, 0x00, 0x38, 0x40, 0x00, 0x08, 0x00, 0x00, 0x3F, 0x48, 0x01, 0x0D, 0x00, 0x00, 0x31, +0x38, 0x00, 0x08, 0x4C, 0x4D, 0x54, 0x00, 0x54, 0x4D, 0x54, 0x00, 0x49, 0x52, 0x53, 0x54, 0x00, +0x49, 0x52, 0x44, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0A, 0x49, 0x52, 0x53, 0x54, 0x2D, 0x33, 0x3A, 0x33, 0x30, 0x49, 0x52, 0x44, +0x54, 0x2C, 0x4A, 0x38, 0x30, 0x2F, 0x30, 0x2C, 0x4A, 0x32, 0x36, 0x34, 0x2F, 0x30, 0x0A, #endif 0x00, 0xBF, 0xC0, 0x8A, 0x01, 0x61, 0x23, 0xA5, 0x00, 0x00, 0x00, 0x00, @@ -41527,7 +41526,7 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { #ifdef TIMELIB_SUPPORTS_V2DATA 0x54, 0x5A, 0x69, 0x66, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x66, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x12, 0xF8, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x65, 0x00, 0x00, 0x00, 0x07, 0x00, 0x00, 0x00, 0x12, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, 0x9A, 0x6C, 0x7D, 0xC8, 0xFF, 0xFF, 0xFF, 0xFF, 0xD2, 0xDB, 0x12, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xBB, 0xA2, 0x48, 0x00, 0x00, 0x00, 0x00, 0x0F, 0x74, 0x2D, 0x40, 0x00, 0x00, 0x00, 0x00, 0x10, 0x8E, 0x40, 0x30, 0x00, 0x00, 0x00, 0x00, @@ -41578,18 +41577,19 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { 0x79, 0xBD, 0xC4, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x7A, 0xAC, 0x72, 0x48, 0x00, 0x00, 0x00, 0x00, 0x7B, 0x9E, 0xF8, 0x38, 0x00, 0x00, 0x00, 0x00, 0x7C, 0x8D, 0xA5, 0xC8, 0x00, 0x00, 0x00, 0x00, 0x7D, 0x80, 0x2B, 0xB8, 0x00, 0x00, 0x00, 0x00, 0x7E, 0x6E, 0xD9, 0x48, 0x00, 0x00, 0x00, 0x00, -0x7F, 0x61, 0x5F, 0x38, 0x00, 0x00, 0x00, 0x03, 0x74, 0x0A, 0xD8, 0x00, 0x00, 0x01, 0x02, 0x04, -0x03, 0x04, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, +0x7F, 0x61, 0x5F, 0x38, 0x00, 0x01, 0x02, 0x04, 0x03, 0x04, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, -0x02, 0x06, 0x00, 0x00, 0x30, 0x38, 0x00, 0x00, 0x00, 0x00, 0x30, 0x38, 0x00, 0x04, 0x00, 0x00, -0x31, 0x38, 0x00, 0x08, 0x00, 0x00, 0x46, 0x50, 0x01, 0x0D, 0x00, 0x00, 0x38, 0x40, 0x00, 0x08, -0x00, 0x00, 0x3F, 0x48, 0x01, 0x0D, 0x00, 0x00, 0x31, 0x38, 0x00, 0x08, 0x4C, 0x4D, 0x54, 0x00, -0x54, 0x4D, 0x54, 0x00, 0x49, 0x52, 0x53, 0x54, 0x00, 0x49, 0x52, 0x44, 0x54, 0x00, 0x00, 0x00, -0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0A, 0x0A, +0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x05, 0x02, 0x00, 0x00, 0x30, 0x38, 0x00, 0x00, 0x00, +0x00, 0x30, 0x38, 0x00, 0x04, 0x00, 0x00, 0x31, 0x38, 0x00, 0x08, 0x00, 0x00, 0x46, 0x50, 0x01, +0x0D, 0x00, 0x00, 0x38, 0x40, 0x00, 0x08, 0x00, 0x00, 0x3F, 0x48, 0x01, 0x0D, 0x00, 0x00, 0x31, +0x38, 0x00, 0x08, 0x4C, 0x4D, 0x54, 0x00, 0x54, 0x4D, 0x54, 0x00, 0x49, 0x52, 0x53, 0x54, 0x00, +0x49, 0x52, 0x44, 0x54, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +0x00, 0x00, 0x00, 0x0A, 0x49, 0x52, 0x53, 0x54, 0x2D, 0x33, 0x3A, 0x33, 0x30, 0x49, 0x52, 0x44, +0x54, 0x2C, 0x4A, 0x38, 0x30, 0x2F, 0x30, 0x2C, 0x4A, 0x32, 0x36, 0x34, 0x2F, 0x30, 0x0A, #endif 0x00, 0x89, 0x54, 0x40, 0x01, 0x12, 0xA8, 0x80, 0x00, 0x00, 0x00, 0x00, @@ -47275,4 +47275,4 @@ const unsigned char timelib_timezone_db_data_builtin[270325] = { #endif 0x00, 0x89, 0x54, 0x40, 0x01, 0x12, 0xA8, 0x80, 0x00, 0x00, 0x00, 0x00,}; -const timelib_tzdb timezonedb_builtin = { "2015.7", 584, timezonedb_idx_builtin, timelib_timezone_db_data_builtin }; +const timelib_tzdb timezonedb_builtin = { "2016.1", 584, timezonedb_idx_builtin, timelib_timezone_db_data_builtin }; diff --git a/ext/date/php_date.c b/ext/date/php_date.c index ec1cabc34d..2fe78a0e69 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -2142,7 +2142,7 @@ static int date_object_compare_date(zval *d1, zval *d2) /* {{{ */ timelib_update_ts(o2->time, o2->time->tz_info); } - return (o1->time->sse == o2->time->sse) ? 0 : ((o1->time->sse < o2->time->sse) ? -1 : 1); + return timelib_time_compare(o1->time, o2->time); } /* }}} */ static HashTable *date_object_get_gc(zval *object, zval **table, int *n) /* {{{ */ @@ -3054,6 +3054,7 @@ static int php_date_modify(zval *object, char *modify, size_t modify_len) /* {{{ timelib_update_ts(dateobj->time, NULL); timelib_update_from_sse(dateobj->time); dateobj->time->have_relative = 0; + memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative)); return 1; } /* }}} */ diff --git a/ext/date/tests/bug68078.phpt b/ext/date/tests/bug68078.phpt new file mode 100644 index 0000000000..20be0a49c8 --- /dev/null +++ b/ext/date/tests/bug68078.phpt @@ -0,0 +1,19 @@ +--TEST-- +Comparing datetime objects should account for microseconds +--FILE-- +<?php + +date_default_timezone_set('UTC'); +$date1 = DateTime::createFromFormat('U.u', '1448889063.3531'); +$date2 = DateTime::createFromFormat('U.u', '1448889063.5216'); +$date3 = DateTime::createFromFormat('U.u', '1448889063.5216'); + +var_dump($date1 == $date2); +var_dump($date1 < $date2); +var_dump($date2 > $date1); +var_dump($date2 == $date3); +--EXPECT-- +bool(false) +bool(true) +bool(true) +bool(true) diff --git a/ext/date/tests/bug68078_negative.phpt b/ext/date/tests/bug68078_negative.phpt new file mode 100644 index 0000000000..93b7715fe5 --- /dev/null +++ b/ext/date/tests/bug68078_negative.phpt @@ -0,0 +1,19 @@ +--TEST-- +Comparing datetime objects with negative timestamps should account for microseconds +--FILE-- +<?php + +date_default_timezone_set('UTC'); +$earlyDate1 = DateTime::createFromFormat('U.u', '1.8642')->modify('-5 seconds'); +$earlyDate2 = DateTime::createFromFormat('U.u', '1.2768')->modify('-5 seconds'); +$earlyDate3 = DateTime::createFromFormat('U.u', '1.2768')->modify('-5 seconds'); + +var_dump($earlyDate1 == $earlyDate2); +var_dump($earlyDate1 < $earlyDate2); +var_dump($earlyDate2 > $earlyDate1); +var_dump($earlyDate2 == $earlyDate3); +--EXPECT-- +bool(false) +bool(true) +bool(true) +bool(true) diff --git a/ext/date/tests/bug71525.phpt b/ext/date/tests/bug71525.phpt new file mode 100644 index 0000000000..d0c99e4f84 --- /dev/null +++ b/ext/date/tests/bug71525.phpt @@ -0,0 +1,20 @@ +--TEST-- +Bug #71525 (Calls to date_modify will mutate timelib_rel_time, causing date_date_set issues) +--INI-- +date.timezone=UTC +--FILE-- +<?php +$date = new DateTime('2011-12-25 00:00:00'); +$date->modify('first day of next month'); +$date->setDate('2012', '1', '29'); +var_dump($date); + +--EXPECTF-- +object(DateTime)#%d (3) { + ["date"]=> + string(26) "2012-01-29 00:00:00.000000" + ["timezone_type"]=> + int(3) + ["timezone"]=> + string(3) "UTC" +} diff --git a/ext/dom/xpath.c b/ext/dom/xpath.c index b883896726..75c4a49bc1 100644 --- a/ext/dom/xpath.c +++ b/ext/dom/xpath.c @@ -474,7 +474,7 @@ static void php_xpath_eval(INTERNAL_FUNCTION_PARAMETERS, int type) /* {{{ */ break; case XPATH_NUMBER: - RETVAL_DOUBLE(xpathobjp->floatval) + RETVAL_DOUBLE(xpathobjp->floatval); break; case XPATH_STRING: diff --git a/ext/enchant/enchant.c b/ext/enchant/enchant.c index e2428b7830..ef2634918f 100644 --- a/ext/enchant/enchant.c +++ b/ext/enchant/enchant.c @@ -587,11 +587,7 @@ PHP_FUNCTION(enchant_broker_request_pwl_dict) RETURN_FALSE; } -#if PHP_API_VERSION < 20100412 - if ((PG(safe_mode) && (!php_checkuid(pwl, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(pwl)) { -#else if (php_check_open_basedir(pwl)) { -#endif RETURN_FALSE; } diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index 0cad89bb7e..cc56e188fd 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -548,11 +548,7 @@ static void _php_finfo_get_type(INTERNAL_FUNCTION_PARAMETERS, int mode, int mime } #endif -#if PHP_API_VERSION < 20100412 - stream = php_stream_open_wrapper_ex(buffer, "rb", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, context); -#else stream = php_stream_open_wrapper_ex(buffer, "rb", REPORT_ERRORS, NULL, context); -#endif if (!stream) { RETVAL_FALSE; diff --git a/ext/fileinfo/libmagic.patch b/ext/fileinfo/libmagic.patch index 2e5b09fdd1..5dce310184 100644 --- a/ext/fileinfo/libmagic.patch +++ b/ext/fileinfo/libmagic.patch @@ -1,6 +1,6 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c ---- libmagic.orig/apprentice.c Mon Feb 9 15:48:48 2015 -+++ libmagic/apprentice.c Sun Mar 29 16:51:28 2015 +--- libmagic.orig/apprentice.c 2016-01-25 11:31:21.473017702 +0800 ++++ libmagic/apprentice.c 2016-01-25 11:41:58.210723599 +0800 @@ -29,6 +29,8 @@ * apprentice - make one pass through /etc/magic, learning its secrets. */ @@ -815,7 +815,15 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c VERSIONNO, dbname, version); return -1; } -@@ -2992,14 +3014,18 @@ +@@ -2983,7 +3005,6 @@ + { + static const size_t nm = sizeof(*map->nmagic) * MAGIC_SETS; + static const size_t m = sizeof(**map->magic); +- int fd = -1; + size_t len; + char *dbname; + int rv = -1; +@@ -2992,14 +3013,18 @@ struct magic m; uint32_t h[2 + MAGIC_SETS]; } hdr; @@ -838,7 +846,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c file_error(ms, errno, "cannot open `%s'", dbname); goto out; } -@@ -3008,24 +3034,25 @@ +@@ -3008,24 +3033,25 @@ hdr.h[1] = VERSIONNO; memcpy(hdr.h + 2, map->nmagic, nm); @@ -869,7 +877,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c return rv; } -@@ -3059,16 +3086,18 @@ +@@ -3059,16 +3085,18 @@ q++; /* Compatibility with old code that looked in .mime */ if (ms->flags & MAGIC_MIME) { @@ -894,7 +902,7 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c /* Compatibility with old code that looked in .mime */ if (strstr(p, ".mime") != NULL) -@@ -3158,7 +3187,7 @@ +@@ -3158,7 +3186,7 @@ m->offset = swap4((uint32_t)m->offset); m->in_offset = swap4((uint32_t)m->in_offset); m->lineno = swap4((uint32_t)m->lineno); @@ -904,8 +912,8 @@ diff -u libmagic.orig/apprentice.c libmagic/apprentice.c m->str_flags = swap4(m->str_flags); } diff -u libmagic.orig/ascmagic.c libmagic/ascmagic.c ---- libmagic.orig/ascmagic.c Mon Feb 9 15:48:48 2015 -+++ libmagic/ascmagic.c Wed Mar 18 20:10:15 2015 +--- libmagic.orig/ascmagic.c 2016-01-25 11:31:21.495017704 +0800 ++++ libmagic/ascmagic.c 2016-01-25 11:31:32.676017695 +0800 @@ -139,7 +139,7 @@ /* malloc size is a conservative overestimate; could be improved, or at least realloced after conversion. */ @@ -926,8 +934,8 @@ diff -u libmagic.orig/ascmagic.c libmagic/ascmagic.c return rv; } diff -u libmagic.orig/cdf.c libmagic/cdf.c ---- libmagic.orig/cdf.c Thu Mar 5 15:25:12 2015 -+++ libmagic/cdf.c Sun Mar 29 16:51:28 2015 +--- libmagic.orig/cdf.c 2016-01-25 11:31:21.472017703 +0800 ++++ libmagic/cdf.c 2016-01-25 11:31:32.676017695 +0800 @@ -35,7 +35,7 @@ #include "file.h" @@ -1093,8 +1101,8 @@ diff -u libmagic.orig/cdf.c libmagic/cdf.c #ifdef CDF_DEBUG else diff -u libmagic.orig/cdf.h libmagic/cdf.h ---- libmagic.orig/cdf.h Mon Feb 9 15:48:48 2015 -+++ libmagic/cdf.h Sun Mar 29 18:04:24 2015 +--- libmagic.orig/cdf.h 2016-01-25 11:31:21.493017704 +0800 ++++ libmagic/cdf.h 2016-01-25 11:31:32.676017695 +0800 @@ -35,10 +35,12 @@ #ifndef _H_CDF_ #define _H_CDF_ @@ -1123,8 +1131,8 @@ diff -u libmagic.orig/cdf.h libmagic/cdf.h void cdf_swap_header(cdf_header_t *); void cdf_unpack_header(cdf_header_t *, char *); diff -u libmagic.orig/cdf_time.c libmagic/cdf_time.c ---- libmagic.orig/cdf_time.c Mon Feb 9 15:48:48 2015 -+++ libmagic/cdf_time.c Wed Mar 18 20:10:15 2015 +--- libmagic.orig/cdf_time.c 2016-01-25 11:31:21.494017704 +0800 ++++ libmagic/cdf_time.c 2016-01-25 11:31:32.676017695 +0800 @@ -96,7 +96,7 @@ } @@ -1174,8 +1182,8 @@ diff -u libmagic.orig/cdf_time.c libmagic/cdf_time.c static const cdf_timestamp_t tst = 0x01A5E403C2D59C00ULL; static const char *ref = "Sat Apr 23 01:30:00 1977"; diff -u libmagic.orig/compress.c libmagic/compress.c ---- libmagic.orig/compress.c Sun Mar 29 13:11:40 2015 -+++ libmagic/compress.c Sun Mar 29 18:14:23 2015 +--- libmagic.orig/compress.c 2016-01-25 11:31:21.483017704 +0800 ++++ libmagic/compress.c 2016-01-25 11:31:32.676017695 +0800 @@ -32,10 +32,11 @@ * uncompress(method, old, n, newch) - uncompress old into new, * using method, return sizeof new @@ -1374,8 +1382,8 @@ diff -u libmagic.orig/compress.c libmagic/compress.c -#endif +#endif /* if PHP_FILEINFO_UNCOMPRESS */ diff -u libmagic.orig/elfclass.h libmagic/elfclass.h ---- libmagic.orig/elfclass.h Mon Feb 9 15:48:48 2015 -+++ libmagic/elfclass.h Wed Mar 18 20:10:15 2015 +--- libmagic.orig/elfclass.h 2016-01-25 11:31:21.471017705 +0800 ++++ libmagic/elfclass.h 2016-01-25 11:31:32.677017695 +0800 @@ -41,7 +41,7 @@ return toomany(ms, "program headers", phnum); flags |= FLAGS_IS_CORE; @@ -1404,8 +1412,8 @@ diff -u libmagic.orig/elfclass.h libmagic/elfclass.h fsize, elf_getu16(swap, elfhdr.e_machine), (int)elf_getu16(swap, elfhdr.e_shstrndx), diff -u libmagic.orig/file.h libmagic/file.h ---- libmagic.orig/file.h Sat Feb 21 15:02:19 2015 -+++ libmagic/file.h Wed Mar 18 20:10:15 2015 +--- libmagic.orig/file.h 2016-01-25 11:31:21.472017703 +0800 ++++ libmagic/file.h 2016-01-25 11:31:32.677017695 +0800 @@ -33,11 +33,9 @@ #ifndef __file_h__ #define __file_h__ @@ -1609,11 +1617,10 @@ diff -u libmagic.orig/file.h libmagic/file.h #if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H) && !defined(QUICK) #define QUICK -@@ -595,6 +540,14 @@ - #endif +@@ -596,6 +541,14 @@ #else #define FILE_RCSID(id) -+#endif + #endif + +#ifdef PHP_WIN32 +#define FINFO_LSEEK_FUNC _lseek @@ -1621,12 +1628,13 @@ diff -u libmagic.orig/file.h libmagic/file.h +#else +#define FINFO_LSEEK_FUNC lseek +#define FINFO_READ_FUNC read - #endif ++#endif #ifndef __RCSID #define __RCSID(a) + #endif diff -u libmagic.orig/fsmagic.c libmagic/fsmagic.c ---- libmagic.orig/fsmagic.c Mon Feb 9 15:48:48 2015 -+++ libmagic/fsmagic.c Wed Mar 18 20:10:15 2015 +--- libmagic.orig/fsmagic.c 2016-01-25 11:31:21.471017705 +0800 ++++ libmagic/fsmagic.c 2016-01-25 11:31:32.677017695 +0800 @@ -63,27 +63,21 @@ # define minor(dev) ((dev) & 0xff) #endif @@ -1977,8 +1985,8 @@ diff -u libmagic.orig/fsmagic.c libmagic/fsmagic.c return ret; } diff -u libmagic.orig/funcs.c libmagic/funcs.c ---- libmagic.orig/funcs.c Mon Feb 9 15:48:48 2015 -+++ libmagic/funcs.c Wed Mar 18 20:10:15 2015 +--- libmagic.orig/funcs.c 2016-01-25 11:31:21.483017704 +0800 ++++ libmagic/funcs.c 2016-01-25 11:41:34.164723619 +0800 @@ -31,7 +31,6 @@ #endif /* lint */ @@ -1987,7 +1995,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c #include <stdarg.h> #include <stdlib.h> #include <string.h> -@@ -42,76 +41,80 @@ +@@ -42,76 +41,79 @@ #if defined(HAVE_WCTYPE_H) #include <wctype.h> #endif @@ -2040,7 +2048,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c protected int file_printf(struct magic_set *ms, const char *fmt, ...) { - int rv; +- int rv; va_list ap; + int len; + char *buf = NULL, *newstr; @@ -2104,7 +2112,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c ms->event_flags |= EVENT_HAD_ERR; ms->error = error; } -@@ -158,11 +161,9 @@ +@@ -158,11 +160,9 @@ file_error(ms, errno, "error reading"); } @@ -2118,7 +2126,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c { int m = 0, rv = 0, looks_text = 0; int mime = ms->flags & MAGIC_MIME; -@@ -201,10 +202,10 @@ +@@ -201,10 +201,10 @@ } } #endif @@ -2132,7 +2140,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c if ((ms->flags & MAGIC_DEBUG) != 0) (void)fprintf(stderr, "zmagic %d\n", m); goto done_encoding; -@@ -219,12 +220,16 @@ +@@ -219,12 +219,16 @@ } /* Check if we have a CDF file */ @@ -2154,16 +2162,16 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c /* try soft magic tests */ if ((ms->flags & MAGIC_NO_CHECK_SOFT) == 0) -@@ -278,16 +283,13 @@ +@@ -278,7 +282,7 @@ if (file_printf(ms, "%s", code_mime) == -1) rv = -1; } -#if HAVE_FORK ++#if PHP_FILEINFO_UNCOMPRESS done_encoding: --#endif + #endif free(u8buf); - if (rv) - return rv; +@@ -287,7 +291,6 @@ return m; } @@ -2171,7 +2179,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c protected int file_reset(struct magic_set *ms) -@@ -297,11 +299,11 @@ +@@ -297,11 +300,11 @@ return -1; } if (ms->o.buf) { @@ -2185,7 +2193,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c ms->o.pbuf = NULL; } ms->event_flags &= ~EVENT_HAD_ERR; -@@ -320,7 +322,7 @@ +@@ -320,7 +323,7 @@ protected const char * file_getbuffer(struct magic_set *ms) { @@ -2194,7 +2202,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c size_t psize, len; if (ms->event_flags & EVENT_HAD_ERR) -@@ -339,11 +341,10 @@ +@@ -339,11 +342,10 @@ return NULL; } psize = len * 4 + 1; @@ -2207,7 +2215,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c #if defined(HAVE_WCHAR_H) && defined(HAVE_MBRTOWC) && defined(HAVE_WCWIDTH) { -@@ -403,8 +404,8 @@ +@@ -403,8 +405,8 @@ if (level >= ms->c.len) { len = (ms->c.len += 20) * sizeof(*ms->c.li); ms->c.li = CAST(struct level_info *, (ms->c.li == NULL) ? @@ -2218,7 +2226,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c if (ms->c.li == NULL) { file_oomem(ms, len); return -1; -@@ -427,70 +428,41 @@ +@@ -427,70 +429,41 @@ protected int file_replace(struct magic_set *ms, const char *pat, const char *rep) { @@ -2249,7 +2257,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c + (void)setlocale(LC_CTYPE, "C"); + + opts |= PCRE_MULTILINE; -+ convert_libmagic_pattern(&patt, pat, strlen(pat), opts); ++ convert_libmagic_pattern(&patt, (char*)pat, strlen(pat), opts); + if ((pce = pcre_get_compiled_regex_cache(Z_STR(patt))) == NULL) { + zval_ptr_dtor(&patt); + rep_cnt = -1; @@ -2300,8 +2308,8 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c - freelocale(rx->c_lc_ctype); -#endif -} -+ strncpy(ms->o.buf, res->val, res->len); -+ ms->o.buf[res->len] = '\0'; ++ strncpy(ms->o.buf, ZSTR_VAL(res), ZSTR_LEN(res)); ++ ms->o.buf[ZSTR_LEN(res)] = '\0'; -protected void -file_regerror(file_regex_t *rx, int rc, struct magic_set *ms) @@ -2318,7 +2326,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c } protected file_pushbuf_t * -@@ -501,7 +473,7 @@ +@@ -501,7 +474,7 @@ if (ms->event_flags & EVENT_HAD_ERR) return NULL; @@ -2327,7 +2335,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c return NULL; pb->buf = ms->o.buf; -@@ -519,8 +491,8 @@ +@@ -519,8 +492,8 @@ char *rbuf; if (ms->event_flags & EVENT_HAD_ERR) { @@ -2338,7 +2346,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c return NULL; } -@@ -529,7 +501,7 @@ +@@ -529,7 +502,7 @@ ms->o.buf = pb->buf; ms->offset = pb->offset; @@ -2347,7 +2355,7 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c return rbuf; } -@@ -550,10 +522,11 @@ +@@ -550,10 +523,11 @@ if (ptr >= eptr - 3) break; *ptr++ = '\\'; @@ -2363,8 +2371,8 @@ diff -u libmagic.orig/funcs.c libmagic/funcs.c } + diff -u libmagic.orig/magic.c libmagic/magic.c ---- libmagic.orig/magic.c Mon Feb 9 15:48:48 2015 -+++ libmagic/magic.c Wed Mar 18 20:10:15 2015 +--- libmagic.orig/magic.c 2016-01-25 11:31:21.495017704 +0800 ++++ libmagic/magic.c 2016-01-25 11:31:32.677017695 +0800 @@ -25,11 +25,6 @@ * SUCH DAMAGE. */ @@ -2753,8 +2761,8 @@ diff -u libmagic.orig/magic.c libmagic/magic.c public const char * magic_error(struct magic_set *ms) diff -u libmagic.orig/magic.h libmagic/magic.h ---- libmagic.orig/magic.h Sat Feb 21 15:03:56 2015 -+++ libmagic/magic.h Wed Mar 18 20:10:15 2015 +--- libmagic.orig/magic.h 2016-01-25 11:31:21.471017705 +0800 ++++ libmagic/magic.h 2016-01-25 11:31:32.677017695 +0800 @@ -88,6 +88,7 @@ const char *magic_getpath(const char *, int); @@ -2772,8 +2780,8 @@ diff -u libmagic.orig/magic.h libmagic/magic.h int magic_errno(magic_t); diff -u libmagic.orig/patchlevel.h libmagic/patchlevel.h ---- libmagic.orig/patchlevel.h Mon Feb 9 15:48:48 2015 -+++ libmagic/patchlevel.h Wed Mar 18 20:10:15 2015 +--- libmagic.orig/patchlevel.h 2016-01-25 11:31:21.473017702 +0800 ++++ libmagic/patchlevel.h 2016-01-25 11:31:32.678017695 +0800 @@ -1,34 +1,43 @@ #define FILE_VERSION_MAJOR 5 -#define patchlevel 6 @@ -2838,8 +2846,8 @@ diff -u libmagic.orig/patchlevel.h libmagic/patchlevel.h * Revision 1.69 2008/07/02 15:27:05 christos * welcome to 4.25 diff -u libmagic.orig/print.c libmagic/print.c ---- libmagic.orig/print.c Mon Feb 9 15:48:48 2015 -+++ libmagic/print.c Wed Mar 18 20:10:15 2015 +--- libmagic.orig/print.c 2016-01-25 11:31:21.495017704 +0800 ++++ libmagic/print.c 2016-01-25 11:31:32.678017695 +0800 @@ -28,13 +28,17 @@ /* * print.c - debugging printout routines @@ -3111,8 +3119,8 @@ diff -u libmagic.orig/print.c libmagic/print.c if (tm == NULL) goto out; diff -u libmagic.orig/readcdf.c libmagic/readcdf.c ---- libmagic.orig/readcdf.c Thu Mar 5 15:25:12 2015 -+++ libmagic/readcdf.c Sun Mar 29 18:07:48 2015 +--- libmagic.orig/readcdf.c 2016-01-25 11:31:21.493017704 +0800 ++++ libmagic/readcdf.c 2016-01-25 11:31:32.678017695 +0800 @@ -26,15 +26,21 @@ #include "file.h" @@ -3237,8 +3245,8 @@ diff -u libmagic.orig/readcdf.c libmagic/readcdf.c #ifdef CDF_DEBUG cdf_dump_catalog(&h, &scn); diff -u libmagic.orig/softmagic.c libmagic/softmagic.c ---- libmagic.orig/softmagic.c Sat Feb 21 15:02:19 2015 -+++ libmagic/softmagic.c Sun Mar 29 17:55:55 2015 +--- libmagic.orig/softmagic.c 2016-01-25 11:31:21.471017705 +0800 ++++ libmagic/softmagic.c 2016-01-25 11:44:35.541684679 +0800 @@ -36,11 +36,19 @@ #endif /* lint */ @@ -3346,7 +3354,12 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c private int32_t mprint(struct magic_set *ms, struct magic *m) { -@@ -635,14 +629,14 @@ +@@ -630,19 +624,18 @@ + t = ms->offset + sizeof(double); + break; + +- case FILE_SEARCH: + case FILE_REGEX: { char *cp; int rval; @@ -3363,7 +3376,23 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c if (rval == -1) return -1; -@@ -879,16 +873,16 @@ +@@ -654,6 +647,15 @@ + break; + } + ++ case FILE_SEARCH: ++ if (file_printf(ms, F(ms, m, "%s"), m->value.s) == -1) ++ return -1; ++ if ((m->str_flags & REGEX_OFFSET_START)) ++ t = ms->search.offset; ++ else ++ t = ms->search.offset + m->vallen; ++ break; ++ + case FILE_DEFAULT: + case FILE_CLEAR: + if (file_printf(ms, "%s", m->desc) == -1) +@@ -879,16 +881,16 @@ if (m->num_mask) \ switch (m->mask_op & FILE_OPS_MASK) { \ case FILE_OPADD: \ @@ -3384,7 +3413,7 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c break; \ } \ -@@ -1095,16 +1089,18 @@ +@@ -1095,17 +1097,26 @@ return 0; } @@ -3394,24 +3423,33 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c - } else { - linecnt = 0; - bytecnt = m->str_range; +- } + /* bytecnt checks are to be kept for PHP, see cve-2014-3538. + PCRE might get stuck if the input buffer is too big. */ + linecnt = m->str_range; + bytecnt = linecnt * 80; -+ -+ if (bytecnt == 0) { -+ bytecnt = 1 << 14; - } - if (bytecnt == 0 || bytecnt > nbytes - offset) - bytecnt = nbytes - offset; ++ if (bytecnt == 0) { ++ bytecnt = 1 << 14; ++ } + + if (bytecnt > nbytes) { + bytecnt = nbytes; + } - ++ if (offset > bytecnt) { ++ offset = bytecnt; ++ } ++ if (s == NULL) { ++ ms->search.s_len = 0; ++ ms->search.s = NULL; ++ return 0; ++ } buf = RCAST(const char *, s) + offset; end = last = RCAST(const char *, s) + bytecnt; -@@ -1221,9 +1217,6 @@ + /* mget() guarantees buf <= last */ +@@ -1221,9 +1232,6 @@ m->type, m->flag, offset, o, nbytes, indir_level, *name_count); mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE)); @@ -3421,7 +3459,7 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c } if (m->flag & INDIR) { -@@ -1593,9 +1586,6 @@ +@@ -1593,9 +1601,6 @@ if ((ms->flags & MAGIC_DEBUG) != 0) { mdebug(offset, (char *)(void *)p, sizeof(union VALUETYPE)); @@ -3431,7 +3469,7 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c } } -@@ -1676,15 +1666,15 @@ +@@ -1676,15 +1681,15 @@ if (rv == 1) { if ((ms->flags & (MAGIC_MIME|MAGIC_APPLE)) == 0 && file_printf(ms, F(ms, m, "%u"), offset) == -1) { @@ -3450,7 +3488,7 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c return rv; case FILE_USE: -@@ -1799,6 +1789,41 @@ +@@ -1799,6 +1804,41 @@ return file_strncmp(a, b, len, flags); } @@ -3462,29 +3500,29 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c + + t = zend_string_alloc(len * 2 + 4, 0); + -+ t->val[j++] = '~'; ++ ZSTR_VAL(t)[j++] = '~'; + + for (i = 0; i < len; i++, j++) { + switch (val[i]) { + case '~': -+ t->val[j++] = '\\'; -+ t->val[j] = '~'; ++ ZSTR_VAL(t)[j++] = '\\'; ++ ZSTR_VAL(t)[j] = '~'; + break; + default: -+ t->val[j] = val[i]; ++ ZSTR_VAL(t)[j] = val[i]; + break; + } + } -+ t->val[j++] = '~'; ++ ZSTR_VAL(t)[j++] = '~'; + + if (options & PCRE_CASELESS) -+ t->val[j++] = 'i'; ++ ZSTR_VAL(t)[j++] = 'i'; + + if (options & PCRE_MULTILINE) -+ t->val[j++] = 'm'; ++ ZSTR_VAL(t)[j++] = 'm'; + -+ t->val[j]='\0'; -+ t->len = j; ++ ZSTR_VAL(t)[j]='\0'; ++ ZSTR_LEN(t) = j; + + ZVAL_NEW_STR(pattern, t); +} @@ -3492,7 +3530,7 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c private int magiccheck(struct magic_set *ms, struct magic *m) { -@@ -1959,73 +1984,111 @@ +@@ -1959,73 +1999,77 @@ break; } case FILE_REGEX: { @@ -3541,28 +3579,6 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c - memcpy(copy, ms->search.s, slen); - copy[--slen] = '\0'; - search = copy; -- } else { -- search = ms->search.s; -- copy = NULL; -- } --#else -- search = ms->search.s; -- pmatch[0].rm_so = 0; -- pmatch[0].rm_eo = slen; --#endif -- rc = file_regexec(&rx, (const char *)search, -- 1, pmatch, REG_STARTEND); --#if REG_STARTEND == 0 -- free(copy); --#endif -- switch (rc) { -- case 0: -- ms->search.s += (int)pmatch[0].rm_so; -- ms->search.offset += (size_t)pmatch[0].rm_so; -- ms->search.rm_len = -- (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so); -- v = 0; -- break; + /* pce now contains the compiled regex */ + zval retval; + zval subpats; @@ -3575,7 +3591,7 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c + haystack = estrndup(ms->search.s, ms->search.s_len); + + /* match v = 0, no match v = 1 */ -+ php_pcre_match_impl(pce, haystack, ms->search.s_len, &retval, &subpats, 1, 1, PREG_OFFSET_CAPTURE, 0); ++ php_pcre_match_impl(pce, haystack, ms->search.s_len, &retval, &subpats, 0, 1, PREG_OFFSET_CAPTURE, 0); + /* Free haystack */ + efree(haystack); + @@ -3587,73 +3603,61 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c + /* Need to fetch global match which equals pmatch[0] */ + zval *pzval; + HashTable *ht = Z_ARRVAL(subpats); -+ zval *pattern_match = NULL, *pattern_offset = NULL; -+ int first = 1, inner_first; -+ -+ ZEND_HASH_FOREACH_VAL(ht, pzval) { -+ HashTable *inner_ht; -+ zval *match, *offset; -+ zval tmpcopy, matchcopy, offsetcopy; -+ -+ if (first) { -+ first = 0; -+ continue; -+ } -+ ZVAL_DUP(&tmpcopy, pzval); - -- case REG_NOMATCH: -- v = 1; -- break; -+ inner_ht = Z_ARRVAL(tmpcopy); - -- default: -- file_regerror(&rx, rc, ms); -- v = (uint64_t)-1; -- break; ++ if ((pzval = zend_hash_index_find(ht, 0)) != NULL && Z_TYPE_P(pzval) == IS_ARRAY) { + /* If everything goes according to the master plan + tmpcopy now contains two elements: + 0 = the match + 1 = starting position of the match */ -+ inner_first = 1; -+ ZEND_HASH_FOREACH_VAL(inner_ht, match) { -+ if (inner_first) { -+ inner_first = 0; -+ continue; -+ } -+ ZVAL_DUP(&matchcopy, match); -+ convert_to_string(&matchcopy); -+ pattern_match = &matchcopy; -+ } ZEND_HASH_FOREACH_END(); -+ -+ inner_first = 1; -+ ZEND_HASH_FOREACH_VAL(inner_ht, offset) { -+ if (inner_first) { -+ inner_first = 0; -+ continue; ++ zval *match, *offset; ++ if ((match = zend_hash_index_find(Z_ARRVAL_P(pzval), 0)) && ++ (offset = zend_hash_index_find(Z_ARRVAL_P(pzval), 1))) { ++ if (Z_TYPE_P(match) != IS_STRING && Z_TYPE_P(offset) != IS_LONG) { ++ goto error_out; + } -+ ZVAL_DUP(&offsetcopy, offset); -+ convert_to_long(&offsetcopy); -+ pattern_offset = &offsetcopy; -+ } ZEND_HASH_FOREACH_END(); -+ -+ zval_dtor(&tmpcopy); -+ -+ if ((pattern_match != NULL) && (pattern_offset != NULL)) { -+ ms->search.s += Z_LVAL_P(pattern_offset); /* this is where the match starts */ -+ ms->search.offset += Z_LVAL_P(pattern_offset); /* this is where the match starts as size_t */ -+ ms->search.rm_len = Z_STRLEN_P(pattern_match) /* This is the length of the matched pattern */; ++ ms->search.s += Z_LVAL_P(offset); /* this is where the match starts */ ++ ms->search.offset += Z_LVAL_P(offset); /* this is where the match starts as size_t */ ++ ms->search.rm_len = Z_STRLEN_P(match) /* This is the length of the matched pattern */; + v = 0; -+ -+ zval_ptr_dtor(pattern_match); -+ zval_ptr_dtor(pattern_offset); + } else { -+ zval_ptr_dtor(&subpats); -+ zval_ptr_dtor(&pattern); -+ return -1; ++ goto error_out; + } -+ } ZEND_HASH_FOREACH_END(); -+ } else { -+ v = 1; ++ } else { ++error_out: ++ zval_ptr_dtor(&subpats); ++ zval_ptr_dtor(&pattern); ++ return -1; ++ } + } else { +- search = ms->search.s; +- copy = NULL; +- } +-#else +- search = ms->search.s; +- pmatch[0].rm_so = 0; +- pmatch[0].rm_eo = slen; +-#endif +- rc = file_regexec(&rx, (const char *)search, +- 1, pmatch, REG_STARTEND); +-#if REG_STARTEND == 0 +- free(copy); +-#endif +- switch (rc) { +- case 0: +- ms->search.s += (int)pmatch[0].rm_so; +- ms->search.offset += (size_t)pmatch[0].rm_so; +- ms->search.rm_len = +- (size_t)(pmatch[0].rm_eo - pmatch[0].rm_so); +- v = 0; +- break; +- +- case REG_NOMATCH: + v = 1; +- break; +- +- default: +- file_regerror(&rx, rc, ms); +- v = (uint64_t)-1; +- break; } + zval_ptr_dtor(&subpats); + zval_ptr_dtor(&pattern); @@ -3665,8 +3669,8 @@ diff -u libmagic.orig/softmagic.c libmagic/softmagic.c } case FILE_INDIRECT: diff -u libmagic.orig/strcasestr.c libmagic/strcasestr.c ---- libmagic.orig/strcasestr.c Mon Feb 9 15:48:48 2015 -+++ libmagic/strcasestr.c Wed Mar 18 20:10:15 2015 +--- libmagic.orig/strcasestr.c 2016-01-25 11:31:21.494017704 +0800 ++++ libmagic/strcasestr.c 2016-01-25 11:31:32.678017695 +0800 @@ -39,6 +39,8 @@ #include "file.h" diff --git a/ext/fileinfo/libmagic/apprentice.c b/ext/fileinfo/libmagic/apprentice.c index f1de79bad8..8347afdeb7 100644 --- a/ext/fileinfo/libmagic/apprentice.c +++ b/ext/fileinfo/libmagic/apprentice.c @@ -3005,7 +3005,6 @@ apprentice_compile(struct magic_set *ms, struct magic_map *map, const char *fn) { static const size_t nm = sizeof(*map->nmagic) * MAGIC_SETS; static const size_t m = sizeof(**map->magic); - int fd = -1; size_t len; char *dbname; int rv = -1; diff --git a/ext/fileinfo/libmagic/funcs.c b/ext/fileinfo/libmagic/funcs.c index 91e9906dcd..c6699d5147 100644 --- a/ext/fileinfo/libmagic/funcs.c +++ b/ext/fileinfo/libmagic/funcs.c @@ -61,7 +61,6 @@ extern public void convert_libmagic_pattern(zval *pattern, char *val, int len, i protected int file_printf(struct magic_set *ms, const char *fmt, ...) { - int rv; va_list ap; int len; char *buf = NULL, *newstr; @@ -283,7 +282,9 @@ simple: if (file_printf(ms, "%s", code_mime) == -1) rv = -1; } +#if PHP_FILEINFO_UNCOMPRESS done_encoding: +#endif free(u8buf); if (rv) return rv; @@ -438,7 +439,7 @@ file_replace(struct magic_set *ms, const char *pat, const char *rep) (void)setlocale(LC_CTYPE, "C"); opts |= PCRE_MULTILINE; - convert_libmagic_pattern(&patt, pat, strlen(pat), opts); + convert_libmagic_pattern(&patt, (char*)pat, strlen(pat), opts); if ((pce = pcre_get_compiled_regex_cache(Z_STR(patt))) == NULL) { zval_ptr_dtor(&patt); rep_cnt = -1; diff --git a/ext/fileinfo/libmagic/softmagic.c b/ext/fileinfo/libmagic/softmagic.c index 88c80a5434..41c4aa17d7 100644 --- a/ext/fileinfo/libmagic/softmagic.c +++ b/ext/fileinfo/libmagic/softmagic.c @@ -2028,7 +2028,7 @@ magiccheck(struct magic_set *ms, struct magic *m) haystack = estrndup(ms->search.s, ms->search.s_len); /* match v = 0, no match v = 1 */ - php_pcre_match_impl(pce, haystack, ms->search.s_len, &retval, &subpats, 1, 1, PREG_OFFSET_CAPTURE, 0); + php_pcre_match_impl(pce, haystack, ms->search.s_len, &retval, &subpats, 0, 1, PREG_OFFSET_CAPTURE, 0); /* Free haystack */ efree(haystack); @@ -2040,64 +2040,30 @@ magiccheck(struct magic_set *ms, struct magic *m) /* Need to fetch global match which equals pmatch[0] */ zval *pzval; HashTable *ht = Z_ARRVAL(subpats); - zval *pattern_match = NULL, *pattern_offset = NULL; - int first = 1, inner_first; - - ZEND_HASH_FOREACH_VAL(ht, pzval) { - HashTable *inner_ht; - zval *match, *offset; - zval tmpcopy, matchcopy, offsetcopy; - - if (first) { - first = 0; - continue; - } - ZVAL_DUP(&tmpcopy, pzval); - - inner_ht = Z_ARRVAL(tmpcopy); - + if ((pzval = zend_hash_index_find(ht, 0)) != NULL && Z_TYPE_P(pzval) == IS_ARRAY) { /* If everything goes according to the master plan tmpcopy now contains two elements: 0 = the match 1 = starting position of the match */ - inner_first = 1; - ZEND_HASH_FOREACH_VAL(inner_ht, match) { - if (inner_first) { - inner_first = 0; - continue; - } - ZVAL_DUP(&matchcopy, match); - convert_to_string(&matchcopy); - pattern_match = &matchcopy; - } ZEND_HASH_FOREACH_END(); - - inner_first = 1; - ZEND_HASH_FOREACH_VAL(inner_ht, offset) { - if (inner_first) { - inner_first = 0; - continue; + zval *match, *offset; + if ((match = zend_hash_index_find(Z_ARRVAL_P(pzval), 0)) && + (offset = zend_hash_index_find(Z_ARRVAL_P(pzval), 1))) { + if (Z_TYPE_P(match) != IS_STRING && Z_TYPE_P(offset) != IS_LONG) { + goto error_out; } - ZVAL_DUP(&offsetcopy, offset); - convert_to_long(&offsetcopy); - pattern_offset = &offsetcopy; - } ZEND_HASH_FOREACH_END(); - - zval_dtor(&tmpcopy); - - if ((pattern_match != NULL) && (pattern_offset != NULL)) { - ms->search.s += Z_LVAL_P(pattern_offset); /* this is where the match starts */ - ms->search.offset += Z_LVAL_P(pattern_offset); /* this is where the match starts as size_t */ - ms->search.rm_len = Z_STRLEN_P(pattern_match) /* This is the length of the matched pattern */; + ms->search.s += Z_LVAL_P(offset); /* this is where the match starts */ + ms->search.offset += Z_LVAL_P(offset); /* this is where the match starts as size_t */ + ms->search.rm_len = Z_STRLEN_P(match) /* This is the length of the matched pattern */; v = 0; - - zval_ptr_dtor(pattern_match); - zval_ptr_dtor(pattern_offset); } else { - zval_ptr_dtor(&subpats); - zval_ptr_dtor(&pattern); - return -1; + goto error_out; } - } ZEND_HASH_FOREACH_END(); + } else { +error_out: + zval_ptr_dtor(&subpats); + zval_ptr_dtor(&pattern); + return -1; + } } else { v = 1; } diff --git a/ext/fileinfo/tests/bug71434.phpt b/ext/fileinfo/tests/bug71434.phpt new file mode 100644 index 0000000000..d886b6607b --- /dev/null +++ b/ext/fileinfo/tests/bug71434.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #68735 fileinfo out-of-bounds memory access +--SKIPIF-- +<?php require_once(dirname(__FILE__) . '/skipif.inc'); ?> +--FILE-- +<?php +$a='#!env python +# -*- coding:utf-8 -*- + +from serial import Serial +from sys import exit +'; +$finfo = new finfo(FILEINFO_MIME_TYPE); +echo $finfo->buffer($a) . "\n"; +?> +--EXPECT-- +text/x-python diff --git a/ext/ftp/config.w32 b/ext/ftp/config.w32 index 0df5f3c609..b09d688180 100644 --- a/ext/ftp/config.w32 +++ b/ext/ftp/config.w32 @@ -1,11 +1,11 @@ // $Id$ // vim:ft=javascript -ARG_ENABLE("ftp", "ftp support", "yes"); +ARG_ENABLE("ftp", "ftp support", "no"); -if (PHP_FTP == "yes") { +if (PHP_FTP != "no") { - EXTENSION("ftp", "php_ftp.c ftp.c", true); + EXTENSION("ftp", "php_ftp.c ftp.c"); if (CHECK_HEADER_ADD_INCLUDE("openssl/ssl.h", "CFLAGS_FTP") && CHECK_LIB("ssleay32.lib", "ftp", PHP_FTP) && diff --git a/ext/gd/libgd/gd_interpolation.c b/ext/gd/libgd/gd_interpolation.c index a946e04b4d..a06e333add 100644 --- a/ext/gd/libgd/gd_interpolation.c +++ b/ext/gd/libgd/gd_interpolation.c @@ -2162,7 +2162,7 @@ gdImagePtr gdImageRotateInterpolated(const gdImagePtr src, const float angle, in { const int angle_rounded = (int)floor(angle * 100); - if (bgcolor < 0 || (!src->trueColor && bgcolor >= gdMaxColors)) { + if (bgcolor < 0) { return NULL; } @@ -2170,7 +2170,7 @@ gdImagePtr gdImageRotateInterpolated(const gdImagePtr src, const float angle, in images can be done at a later point. */ if (src->trueColor == 0) { - if (bgcolor >= 0) { + if (bgcolor < gdMaxColors) { bgcolor = gdTrueColorAlpha(src->red[bgcolor], src->green[bgcolor], src->blue[bgcolor], src->alpha[bgcolor]); } gdImagePaletteToTrueColor(src); diff --git a/ext/gd/tests/bug70976.phpt b/ext/gd/tests/bug70976.phpt index 23af4eedc7..dfbd4b49ec 100644 --- a/ext/gd/tests/bug70976.phpt +++ b/ext/gd/tests/bug70976.phpt @@ -6,8 +6,8 @@ Bug #70976 (Memory Read via gdImageRotateInterpolated Array Index Out of Bounds) ?> --FILE-- <?php -$img = imagerotate(imagecreate(1,1),45,0x7ffffff9); +$img = imagerotate(imagecreate(10,10),45,0x7ffffff9); var_dump($img); ?> --EXPECTF-- -bool(false)
\ No newline at end of file +resource(5) of type (gd)
\ No newline at end of file diff --git a/ext/hash/hash.c b/ext/hash/hash.c index d6921bb53e..de3fdf858c 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -31,12 +31,6 @@ static int php_hash_le_hash; HashTable php_hash_hashtable; -#if (PHP_MAJOR_VERSION >= 5) -# define DEFAULT_CONTEXT FG(default_context) -#else -# define DEFAULT_CONTEXT NULL -#endif - #ifdef PHP_MHASH_BC struct mhash_bc_entry { char *mhash_name; @@ -140,7 +134,7 @@ static void php_hash_do_hash(INTERNAL_FUNCTION_PARAMETERS, int isfilename, zend_ php_error_docref(NULL, E_WARNING, "Invalid path"); RETURN_FALSE; } - stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, DEFAULT_CONTEXT); + stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, FG(default_context)); if (!stream) { /* Stream will report errors opening file */ RETURN_FALSE; @@ -259,7 +253,7 @@ static void php_hash_do_hash_hmac(INTERNAL_FUNCTION_PARAMETERS, int isfilename, php_error_docref(NULL, E_WARNING, "Invalid path"); RETURN_FALSE; } - stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, DEFAULT_CONTEXT); + stream = php_stream_open_wrapper_ex(data, "rb", REPORT_ERRORS, NULL, FG(default_context)); if (!stream) { /* Stream will report errors opening file */ RETURN_FALSE; diff --git a/ext/hash/hash_adler32.c b/ext/hash/hash_adler32.c index 07d71c3f33..eac389f896 100644 --- a/ext/hash/hash_adler32.c +++ b/ext/hash/hash_adler32.c @@ -29,7 +29,7 @@ PHP_HASH_API void PHP_ADLER32Init(PHP_ADLER32_CTX *context) PHP_HASH_API void PHP_ADLER32Update(PHP_ADLER32_CTX *context, const unsigned char *input, size_t len) { - php_hash_uint32 i, s[2]; + uint32_t i, s[2]; s[0] = context->state & 0xffff; s[1] = (context->state >> 16) & 0xffff; diff --git a/ext/hash/hash_fnv.c b/ext/hash/hash_fnv.c index 9d365970c8..1e6f8d974d 100644 --- a/ext/hash/hash_fnv.c +++ b/ext/hash/hash_fnv.c @@ -147,8 +147,8 @@ PHP_HASH_API void PHP_FNV164Final(unsigned char digest[8], PHP_FNV164_CTX * cont * returns: * 32 bit hash as a static hash type */ -static php_hash_uint32 -fnv_32_buf(void *buf, size_t len, php_hash_uint32 hval, int alternate) +static uint32_t +fnv_32_buf(void *buf, size_t len, uint32_t hval, int alternate) { unsigned char *bp = (unsigned char *)buf; /* start of buffer */ unsigned char *be = bp + len; /* beyond end of buffer */ @@ -163,10 +163,10 @@ fnv_32_buf(void *buf, size_t len, php_hash_uint32 hval, int alternate) hval *= PHP_FNV_32_PRIME; /* xor the bottom with the current octet */ - hval ^= (php_hash_uint32)*bp++; + hval ^= (uint32_t)*bp++; } else { /* xor the bottom with the current octet */ - hval ^= (php_hash_uint32)*bp++; + hval ^= (uint32_t)*bp++; /* multiply by the 32 bit FNV magic prime mod 2^32 */ hval *= PHP_FNV_32_PRIME; @@ -189,8 +189,8 @@ fnv_32_buf(void *buf, size_t len, php_hash_uint32 hval, int alternate) * returns: * 64 bit hash as a static hash type */ -static php_hash_uint64 -fnv_64_buf(void *buf, size_t len, php_hash_uint64 hval, int alternate) +static uint64_t +fnv_64_buf(void *buf, size_t len, uint64_t hval, int alternate) { unsigned char *bp = (unsigned char *)buf; /* start of buffer */ unsigned char *be = bp + len; /* beyond end of buffer */ @@ -205,10 +205,10 @@ fnv_64_buf(void *buf, size_t len, php_hash_uint64 hval, int alternate) hval *= PHP_FNV_64_PRIME; /* xor the bottom with the current octet */ - hval ^= (php_hash_uint64)*bp++; + hval ^= (uint64_t)*bp++; } else { /* xor the bottom with the current octet */ - hval ^= (php_hash_uint64)*bp++; + hval ^= (uint64_t)*bp++; /* multiply by the 64 bit FNV magic prime mod 2^64 */ hval *= PHP_FNV_64_PRIME; diff --git a/ext/hash/hash_gost.c b/ext/hash/hash_gost.c index 2bc78313fb..4e72117451 100644 --- a/ext/hash/hash_gost.c +++ b/ext/hash/hash_gost.c @@ -207,10 +207,10 @@ AA(v, l, r); \ } -static inline void Gost(PHP_GOST_CTX *context, php_hash_uint32 data[8]) +static inline void Gost(PHP_GOST_CTX *context, uint32_t data[8]) { int i; - php_hash_uint32 l, r, t, key[8], u[8], v[8], w[8], s[8], *h = context->state, *m = data; + uint32_t l, r, t, key[8], u[8], v[8], w[8], s[8], *h = context->state, *m = data; memcpy(u, context->state, sizeof(u)); memcpy(v, data, sizeof(v)); @@ -227,11 +227,11 @@ static inline void Gost(PHP_GOST_CTX *context, php_hash_uint32 data[8]) static inline void GostTransform(PHP_GOST_CTX *context, const unsigned char input[32]) { int i, j; - php_hash_uint32 data[8], temp = 0, save = 0; + uint32_t data[8], temp = 0, save = 0; for (i = 0, j = 0; i < 8; ++i, j += 4) { - data[i] = ((php_hash_uint32) input[j]) | (((php_hash_uint32) input[j + 1]) << 8) | - (((php_hash_uint32) input[j + 2]) << 16) | (((php_hash_uint32) input[j + 3]) << 24); + data[i] = ((uint32_t) input[j]) | (((uint32_t) input[j + 1]) << 8) | + (((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24); save = context->state[i + 8]; context->state[i + 8] += data[i] + temp; temp = ((context->state[i + 8] < data[i]) || (context->state[i + 8] < save)) ? 1 : 0; @@ -252,7 +252,7 @@ PHP_HASH_API void PHP_GOSTInitCrypto(PHP_GOST_CTX *context) context->tables = &tables_crypto; } -static const php_hash_uint32 MAX32 = 0xffffffffLU; +static const uint32_t MAX32 = 0xffffffffLU; PHP_HASH_API void PHP_GOSTUpdate(PHP_GOST_CTX *context, const unsigned char *input, size_t len) { @@ -288,7 +288,7 @@ PHP_HASH_API void PHP_GOSTUpdate(PHP_GOST_CTX *context, const unsigned char *inp PHP_HASH_API void PHP_GOSTFinal(unsigned char digest[32], PHP_GOST_CTX *context) { - php_hash_uint32 i, j, l[8] = {0}; + uint32_t i, j, l[8] = {0}; if (context->length) { GostTransform(context, context->buffer); diff --git a/ext/hash/hash_haval.c b/ext/hash/hash_haval.c index 2dbb15a34c..08168adbe1 100644 --- a/ext/hash/hash_haval.c +++ b/ext/hash/hash_haval.c @@ -31,28 +31,28 @@ static const unsigned char PADDING[128] ={ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; -static const php_hash_uint32 D0[8] = { +static const uint32_t D0[8] = { 0x243F6A88, 0x85A308D3, 0x13198A2E, 0x03707344, 0xA4093822, 0x299F31D0, 0x082EFA98, 0xEC4E6C89 }; -static const php_hash_uint32 K2[32] = { +static const uint32_t K2[32] = { 0x452821E6, 0x38D01377, 0xBE5466CF, 0x34E90C6C, 0xC0AC29B7, 0xC97C50DD, 0x3F84D5B5, 0xB5470917, 0x9216D5D9, 0x8979FB1B, 0xD1310BA6, 0x98DFB5AC, 0x2FFD72DB, 0xD01ADFB7, 0xB8E1AFED, 0x6A267E96, 0xBA7C9045, 0xF12C7F99, 0x24A19947, 0xB3916CF7, 0x0801F2E2, 0x858EFC16, 0x636920D8, 0x71574E69, 0xA458FEA3, 0xF4933D7E, 0x0D95748F, 0x728EB658, 0x718BCD58, 0x82154AEE, 0x7B54A41D, 0xC25A59B5 }; -static const php_hash_uint32 K3[32] = { +static const uint32_t K3[32] = { 0x9C30D539, 0x2AF26013, 0xC5D1B023, 0x286085F0, 0xCA417918, 0xB8DB38EF, 0x8E79DCB0, 0x603A180E, 0x6C9E0E8B, 0xB01E8A3E, 0xD71577C1, 0xBD314B27, 0x78AF2FDA, 0x55605C60, 0xE65525F3, 0xAA55AB94, 0x57489862, 0x63E81440, 0x55CA396A, 0x2AAB10B6, 0xB4CC5C34, 0x1141E8CE, 0xA15486AF, 0x7C72E993, 0xB3EE1411, 0x636FBC2A, 0x2BA9C55D, 0x741831F6, 0xCE5C3E16, 0x9B87931E, 0xAFD6BA33, 0x6C24CF5C }; -static const php_hash_uint32 K4[32] = { +static const uint32_t K4[32] = { 0x7A325381, 0x28958677, 0x3B8F4898, 0x6B4BB9AF, 0xC4BFE81B, 0x66282193, 0x61D809CC, 0xFB21A991, 0x487CAC60, 0x5DEC8032, 0xEF845D5D, 0xE98575B1, 0xDC262302, 0xEB651B88, 0x23893E81, 0xD396ACC5, 0x0F6D6FF3, 0x83F44239, 0x2E0B4482, 0xA4842004, 0x69C8F04A, 0x9E1F9B5E, 0x21C66842, 0xF6E96C9A, 0x670C9C61, 0xABD388F0, 0x6A51A0D2, 0xD8542F68, 0x960FA728, 0xAB5133A3, 0x6EEF0B6C, 0x137A3BE4 }; -static const php_hash_uint32 K5[32] = { +static const uint32_t K5[32] = { 0xBA3BF050, 0x7EFB2A98, 0xA1F1651D, 0x39AF0176, 0x66CA593E, 0x82430E88, 0x8CEE8619, 0x456F9FB4, 0x7D84A5C3, 0x3B8B5EBE, 0xE06F75D8, 0x85C12073, 0x401A449F, 0x56C16AA6, 0x4ED3AA62, 0x363F7706, 0x1BFEDF72, 0x429B023D, 0x37D0D724, 0xD00A1248, 0xDB0FEAD3, 0x49F1C09B, 0x075372C9, 0x80991B7B, @@ -95,10 +95,10 @@ static const short M7[32] = { 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0, 7, 6, 5, 4, 3, 2, 1, 0 }; /* {{{ Encode - Encodes input (php_hash_uint32) into output (unsigned char). Assumes len is + Encodes input (uint32_t) into output (unsigned char). Assumes len is a multiple of 4. */ -static void Encode(unsigned char *output, php_hash_uint32 *input, unsigned int len) +static void Encode(unsigned char *output, uint32_t *input, unsigned int len) { unsigned int i, j; @@ -112,16 +112,16 @@ static void Encode(unsigned char *output, php_hash_uint32 *input, unsigned int l /* }}} */ /* {{{ Decode - Decodes input (unsigned char) into output (php_hash_uint32). Assumes len is + Decodes input (unsigned char) into output (uint32_t). Assumes len is a multiple of 4. */ -static void Decode(php_hash_uint32 *output, const unsigned char *input, unsigned int len) +static void Decode(uint32_t *output, const unsigned char *input, unsigned int len) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) { - output[i] = ((php_hash_uint32) input[j]) | (((php_hash_uint32) input[j + 1]) << 8) | - (((php_hash_uint32) input[j + 2]) << 16) | (((php_hash_uint32) input[j + 3]) << 24); + output[i] = ((uint32_t) input[j]) | (((uint32_t) input[j + 1]) << 8) | + (((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24); } } /* }}} */ @@ -141,10 +141,10 @@ static void Decode(php_hash_uint32 *output, const unsigned char *input, unsigned /* {{{ PHP_3HAVALTransform */ -static void PHP_3HAVALTransform(php_hash_uint32 state[8], const unsigned char block[128]) +static void PHP_3HAVALTransform(uint32_t state[8], const unsigned char block[128]) { - php_hash_uint32 E[8]; - php_hash_uint32 x[32]; + uint32_t E[8]; + uint32_t x[32]; int i; Decode(x, block, 128); @@ -175,10 +175,10 @@ static void PHP_3HAVALTransform(php_hash_uint32 state[8], const unsigned char bl /* {{{ PHP_4HAVALTransform */ -static void PHP_4HAVALTransform(php_hash_uint32 state[8], const unsigned char block[128]) +static void PHP_4HAVALTransform(uint32_t state[8], const unsigned char block[128]) { - php_hash_uint32 E[8]; - php_hash_uint32 x[32]; + uint32_t E[8]; + uint32_t x[32]; int i; Decode(x, block, 128); @@ -212,10 +212,10 @@ static void PHP_4HAVALTransform(php_hash_uint32 state[8], const unsigned char bl /* {{{ PHP_5HAVALTransform */ -static void PHP_5HAVALTransform(php_hash_uint32 state[8], const unsigned char block[128]) +static void PHP_5HAVALTransform(uint32_t state[8], const unsigned char block[128]) { - php_hash_uint32 E[8]; - php_hash_uint32 x[32]; + uint32_t E[8]; + uint32_t x[32]; int i; Decode(x, block, 128); @@ -289,10 +289,10 @@ PHP_HASH_API void PHP_HAVALUpdate(PHP_HAVAL_CTX *context, const unsigned char *i /* Compute number of bytes mod 128 */ index = (unsigned int) ((context->count[0] >> 3) & 0x7F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint32) inputLen << 3)) < ((php_hash_uint32) inputLen << 3)) { + if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) { context->count[1]++; } - context->count[1] += ((php_hash_uint32) inputLen >> 29); + context->count[1] += ((uint32_t) inputLen >> 29); partLen = 128 - index; diff --git a/ext/hash/hash_joaat.c b/ext/hash/hash_joaat.c index 545601fc90..98a11a08bc 100644 --- a/ext/hash/hash_joaat.c +++ b/ext/hash/hash_joaat.c @@ -70,8 +70,8 @@ PHP_HASH_API void PHP_JOAATFinal(unsigned char digest[4], PHP_JOAAT_CTX * contex * returns: * 32 bit hash as a static hash type */ -static php_hash_uint32 -joaat_buf(void *buf, size_t len, php_hash_uint32 hval) +static uint32_t +joaat_buf(void *buf, size_t len, uint32_t hval) { size_t i; unsigned char *input = (unsigned char *)buf; diff --git a/ext/hash/hash_md.c b/ext/hash/hash_md.c index 80681c34db..711238ad82 100644 --- a/ext/hash/hash_md.c +++ b/ext/hash/hash_md.c @@ -61,10 +61,10 @@ static const unsigned char PADDING[64] = }; /* {{{ Encode - Encodes input (php_hash_uint32) into output (unsigned char). Assumes len is + Encodes input (uint32_t) into output (unsigned char). Assumes len is a multiple of 4. */ -static void Encode(unsigned char *output, php_hash_uint32 *input, unsigned int len) +static void Encode(unsigned char *output, uint32_t *input, unsigned int len) { unsigned int i, j; @@ -78,16 +78,16 @@ static void Encode(unsigned char *output, php_hash_uint32 *input, unsigned int l /* }}} */ /* {{{ Decode - Decodes input (unsigned char) into output (php_hash_uint32). Assumes len is + Decodes input (unsigned char) into output (uint32_t). Assumes len is a multiple of 4. */ -static void Decode(php_hash_uint32 *output, const unsigned char *input, unsigned int len) +static void Decode(uint32_t *output, const unsigned char *input, unsigned int len) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((php_hash_uint32) input[j]) | (((php_hash_uint32) input[j + 1]) << 8) | - (((php_hash_uint32) input[j + 2]) << 16) | (((php_hash_uint32) input[j + 3]) << 24); + output[i] = ((uint32_t) input[j]) | (((uint32_t) input[j + 1]) << 8) | + (((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24); } /* }}} */ @@ -224,7 +224,7 @@ PHP_NAMED_FUNCTION(php_if_md5_file) #define S43 15 #define S44 21 -static void MD5Transform(php_hash_uint32[4], const unsigned char[64]); +static void MD5Transform(uint32_t[4], const unsigned char[64]); /* F, G, H and I are basic MD5 functions. */ @@ -241,22 +241,22 @@ static void MD5Transform(php_hash_uint32[4], const unsigned char[64]); Rotation is separate from addition to prevent recomputation. */ #define FF(a, b, c, d, x, s, ac) { \ - (a) += F ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \ + (a) += F ((b), (c), (d)) + (x) + (uint32_t)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define GG(a, b, c, d, x, s, ac) { \ - (a) += G ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \ + (a) += G ((b), (c), (d)) + (x) + (uint32_t)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define HH(a, b, c, d, x, s, ac) { \ - (a) += H ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \ + (a) += H ((b), (c), (d)) + (x) + (uint32_t)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } #define II(a, b, c, d, x, s, ac) { \ - (a) += I ((b), (c), (d)) + (x) + (php_hash_uint32)(ac); \ + (a) += I ((b), (c), (d)) + (x) + (uint32_t)(ac); \ (a) = ROTATE_LEFT ((a), (s)); \ (a) += (b); \ } @@ -290,10 +290,10 @@ PHP_HASH_API void PHP_MD5Update(PHP_MD5_CTX * context, const unsigned char *inpu index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint32) inputLen << 3)) - < ((php_hash_uint32) inputLen << 3)) + if ((context->count[0] += ((uint32_t) inputLen << 3)) + < ((uint32_t) inputLen << 3)) context->count[1]++; - context->count[1] += ((php_hash_uint32) inputLen >> 29); + context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; @@ -352,10 +352,10 @@ PHP_HASH_API void PHP_MD5Final(unsigned char digest[16], PHP_MD5_CTX * context) * MD5 basic transformation. Transforms state based on block. */ static void MD5Transform(state, block) -php_hash_uint32 state[4]; +uint32_t state[4]; const unsigned char block[64]; { - php_hash_uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode(x, block, 64); @@ -455,9 +455,9 @@ const unsigned char block[64]; #define MD4_R2(a,b,c,d,k,s) a = ROTL32(s, a + MD4_G(b,c,d) + x[k] + 0x5A827999) #define MD4_R3(a,b,c,d,k,s) a = ROTL32(s, a + MD4_H(b,c,d) + x[k] + 0x6ED9EBA1) -static void MD4Transform(php_hash_uint32 state[4], const unsigned char block[64]) +static void MD4Transform(uint32_t state[4], const unsigned char block[64]) { - php_hash_uint32 a = state[0], b = state[1], c = state[2], d = state[3], x[16]; + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], x[16]; Decode(x, block, 64); @@ -549,10 +549,10 @@ PHP_HASH_API void PHP_MD4Update(PHP_MD4_CTX * context, const unsigned char *inpu index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint32) inputLen << 3)) - < ((php_hash_uint32) inputLen << 3)) + if ((context->count[0] += ((uint32_t) inputLen << 3)) + < ((uint32_t) inputLen << 3)) context->count[1]++; - context->count[1] += ((php_hash_uint32) inputLen >> 29); + context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; diff --git a/ext/hash/hash_ripemd.c b/ext/hash/hash_ripemd.c index 2f22a18d53..03d4af8349 100644 --- a/ext/hash/hash_ripemd.c +++ b/ext/hash/hash_ripemd.c @@ -143,9 +143,9 @@ PHP_HASH_API void PHP_RIPEMD320Init(PHP_RIPEMD320_CTX * context) #define F3(x,y,z) (((x) & (z)) | ((y) & (~(z)))) #define F4(x,y,z) ((x) ^ ((y) | (~(z)))) -static const php_hash_uint32 K_values[5] = { 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E }; /* 128, 256, 160, 320 */ -static const php_hash_uint32 KK_values[4] = { 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x00000000 }; /* 128 & 256 */ -static const php_hash_uint32 KK160_values[5] = { 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000 }; /* 160 & 320 */ +static const uint32_t K_values[5] = { 0x00000000, 0x5A827999, 0x6ED9EBA1, 0x8F1BBCDC, 0xA953FD4E }; /* 128, 256, 160, 320 */ +static const uint32_t KK_values[4] = { 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x00000000 }; /* 128 & 256 */ +static const uint32_t KK160_values[5] = { 0x50A28BE6, 0x5C4DD124, 0x6D703EF3, 0x7A6D76E9, 0x00000000 }; /* 160 & 320 */ #define K(n) K_values[ (n) >> 4] #define KK(n) KK_values[(n) >> 4] @@ -184,27 +184,27 @@ static const unsigned char SS[80] = { #define ROL(n, x) (((x) << n) | ((x) >> (32 - n))) /* {{{ RIPEMDDecode - Decodes input (unsigned char) into output (php_hash_uint32). Assumes len is + Decodes input (unsigned char) into output (uint32_t). Assumes len is a multiple of 4. */ -static void RIPEMDDecode(php_hash_uint32 *output, const unsigned char *input, unsigned int len) +static void RIPEMDDecode(uint32_t *output, const unsigned char *input, unsigned int len) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((php_hash_uint32) input[j + 0]) | (((php_hash_uint32) input[j + 1]) << 8) | - (((php_hash_uint32) input[j + 2]) << 16) | (((php_hash_uint32) input[j + 3]) << 24); + output[i] = ((uint32_t) input[j + 0]) | (((uint32_t) input[j + 1]) << 8) | + (((uint32_t) input[j + 2]) << 16) | (((uint32_t) input[j + 3]) << 24); } /* }}} */ /* {{{ RIPEMD128Transform * ripemd128 basic transformation. Transforms state based on block. */ -static void RIPEMD128Transform(php_hash_uint32 state[4], const unsigned char block[64]) +static void RIPEMD128Transform(uint32_t state[4], const unsigned char block[64]) { - php_hash_uint32 a = state[0], b = state[1], c = state[2], d = state[3]; - php_hash_uint32 aa = state[0], bb = state[1], cc = state[2], dd = state[3]; - php_hash_uint32 tmp, x[16]; + uint32_t a = state[0], b = state[1], c = state[2], d = state[3]; + uint32_t aa = state[0], bb = state[1], cc = state[2], dd = state[3]; + uint32_t tmp, x[16]; int j; RIPEMDDecode(x, block, 64); @@ -261,10 +261,10 @@ PHP_HASH_API void PHP_RIPEMD128Update(PHP_RIPEMD128_CTX * context, const unsigne index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint32) inputLen << 3)) < ((php_hash_uint32) inputLen << 3)) { + if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) { context->count[1]++; } - context->count[1] += ((php_hash_uint32) inputLen >> 29); + context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; @@ -291,11 +291,11 @@ PHP_HASH_API void PHP_RIPEMD128Update(PHP_RIPEMD128_CTX * context, const unsigne /* {{{ RIPEMD256Transform * ripemd256 basic transformation. Transforms state based on block. */ -static void RIPEMD256Transform(php_hash_uint32 state[8], const unsigned char block[64]) +static void RIPEMD256Transform(uint32_t state[8], const unsigned char block[64]) { - php_hash_uint32 a = state[0], b = state[1], c = state[2], d = state[3]; - php_hash_uint32 aa = state[4], bb = state[5], cc = state[6], dd = state[7]; - php_hash_uint32 tmp, x[16]; + uint32_t a = state[0], b = state[1], c = state[2], d = state[3]; + uint32_t aa = state[4], bb = state[5], cc = state[6], dd = state[7]; + uint32_t tmp, x[16]; int j; RIPEMDDecode(x, block, 64); @@ -359,10 +359,10 @@ PHP_HASH_API void PHP_RIPEMD256Update(PHP_RIPEMD256_CTX * context, const unsigne index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint32) inputLen << 3)) < ((php_hash_uint32) inputLen << 3)) { + if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) { context->count[1]++; } - context->count[1] += ((php_hash_uint32) inputLen >> 29); + context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; @@ -389,11 +389,11 @@ PHP_HASH_API void PHP_RIPEMD256Update(PHP_RIPEMD256_CTX * context, const unsigne /* {{{ RIPEMD160Transform * ripemd160 basic transformation. Transforms state based on block. */ -static void RIPEMD160Transform(php_hash_uint32 state[5], const unsigned char block[64]) +static void RIPEMD160Transform(uint32_t state[5], const unsigned char block[64]) { - php_hash_uint32 a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; - php_hash_uint32 aa = state[0], bb = state[1], cc = state[2], dd = state[3], ee = state[4]; - php_hash_uint32 tmp, x[16]; + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; + uint32_t aa = state[0], bb = state[1], cc = state[2], dd = state[3], ee = state[4]; + uint32_t tmp, x[16]; int j; RIPEMDDecode(x, block, 64); @@ -458,10 +458,10 @@ PHP_HASH_API void PHP_RIPEMD160Update(PHP_RIPEMD160_CTX * context, const unsigne index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint32) inputLen << 3)) < ((php_hash_uint32) inputLen << 3)) { + if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) { context->count[1]++; } - context->count[1] += ((php_hash_uint32) inputLen >> 29); + context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; @@ -488,11 +488,11 @@ PHP_HASH_API void PHP_RIPEMD160Update(PHP_RIPEMD160_CTX * context, const unsigne /* {{{ RIPEMD320Transform * ripemd320 basic transformation. Transforms state based on block. */ -static void RIPEMD320Transform(php_hash_uint32 state[10], const unsigned char block[64]) +static void RIPEMD320Transform(uint32_t state[10], const unsigned char block[64]) { - php_hash_uint32 a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; - php_hash_uint32 aa = state[5], bb = state[6], cc = state[7], dd = state[8], ee = state[9]; - php_hash_uint32 tmp, x[16]; + uint32_t a = state[0], b = state[1], c = state[2], d = state[3], e = state[4]; + uint32_t aa = state[5], bb = state[6], cc = state[7], dd = state[8], ee = state[9]; + uint32_t tmp, x[16]; int j; RIPEMDDecode(x, block, 64); @@ -566,10 +566,10 @@ PHP_HASH_API void PHP_RIPEMD320Update(PHP_RIPEMD320_CTX * context, const unsigne index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint32) inputLen << 3)) < ((php_hash_uint32) inputLen << 3)) { + if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) { context->count[1]++; } - context->count[1] += ((php_hash_uint32) inputLen >> 29); + context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; @@ -601,10 +601,10 @@ static const unsigned char PADDING[64] = }; /* {{{ RIPEMDEncode - Encodes input (php_hash_uint32) into output (unsigned char). Assumes len is + Encodes input (uint32_t) into output (unsigned char). Assumes len is a multiple of 4. */ -static void RIPEMDEncode(unsigned char *output, php_hash_uint32 *input, unsigned int len) +static void RIPEMDEncode(unsigned char *output, uint32_t *input, unsigned int len) { unsigned int i, j; diff --git a/ext/hash/hash_sha.c b/ext/hash/hash_sha.c index 77c9bb7b4f..6bb6931c35 100644 --- a/ext/hash/hash_sha.c +++ b/ext/hash/hash_sha.c @@ -35,10 +35,10 @@ static const unsigned char PADDING[128] = }; /* {{{ SHAEncode32 - Encodes input (php_hash_uint32) into output (unsigned char). Assumes len is + Encodes input (uint32_t) into output (unsigned char). Assumes len is a multiple of 4. */ -static void SHAEncode32(unsigned char *output, php_hash_uint32 *input, unsigned int len) +static void SHAEncode32(unsigned char *output, uint32_t *input, unsigned int len) { unsigned int i, j; @@ -53,16 +53,16 @@ static void SHAEncode32(unsigned char *output, php_hash_uint32 *input, unsigned /* {{{ SHADecode32 - Decodes input (unsigned char) into output (php_hash_uint32). Assumes len is + Decodes input (unsigned char) into output (uint32_t). Assumes len is a multiple of 4. */ -static void SHADecode32(php_hash_uint32 *output, const unsigned char *input, unsigned int len) +static void SHADecode32(uint32_t *output, const unsigned char *input, unsigned int len) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((php_hash_uint32) input[j + 3]) | (((php_hash_uint32) input[j + 2]) << 8) | - (((php_hash_uint32) input[j + 1]) << 16) | (((php_hash_uint32) input[j]) << 24); + output[i] = ((uint32_t) input[j + 3]) | (((uint32_t) input[j + 2]) << 8) | + (((uint32_t) input[j + 1]) << 16) | (((uint32_t) input[j]) << 24); } /* }}} */ @@ -179,22 +179,22 @@ PHP_FUNCTION(sha1_file) /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. */ #define FF(a, b, c, d, e, w) { \ - (e) += F ((b), (c), (d)) + (w) + (php_hash_uint32)(0x5A827999); \ + (e) += F ((b), (c), (d)) + (w) + (uint32_t)(0x5A827999); \ (e) += ROTATE_LEFT ((a), 5); \ (b) = ROTATE_LEFT((b), 30); \ } #define GG(a, b, c, d, e, w) { \ - (e) += G ((b), (c), (d)) + (w) + (php_hash_uint32)(0x6ED9EBA1); \ + (e) += G ((b), (c), (d)) + (w) + (uint32_t)(0x6ED9EBA1); \ (e) += ROTATE_LEFT ((a), 5); \ (b) = ROTATE_LEFT((b), 30); \ } #define HH(a, b, c, d, e, w) { \ - (e) += H ((b), (c), (d)) + (w) + (php_hash_uint32)(0x8F1BBCDC); \ + (e) += H ((b), (c), (d)) + (w) + (uint32_t)(0x8F1BBCDC); \ (e) += ROTATE_LEFT ((a), 5); \ (b) = ROTATE_LEFT((b), 30); \ } #define II(a, b, c, d, e, w) { \ - (e) += I ((b), (c), (d)) + (w) + (php_hash_uint32)(0xCA62C1D6); \ + (e) += I ((b), (c), (d)) + (w) + (uint32_t)(0xCA62C1D6); \ (e) += ROTATE_LEFT ((a), 5); \ (b) = ROTATE_LEFT((b), 30); \ } @@ -219,10 +219,10 @@ PHP_HASH_API void PHP_SHA1Init(PHP_SHA1_CTX * context) /* {{{ SHA1Transform * SHA1 basic transformation. Transforms state based on block. */ -static void SHA1Transform(php_hash_uint32 state[5], const unsigned char block[64]) +static void SHA1Transform(uint32_t state[5], const unsigned char block[64]) { - php_hash_uint32 a = state[0], b = state[1], c = state[2]; - php_hash_uint32 d = state[3], e = state[4], x[16], tmp; + uint32_t a = state[0], b = state[1], c = state[2]; + uint32_t d = state[3], e = state[4], x[16], tmp; SHADecode32(x, block, 64); @@ -339,10 +339,10 @@ PHP_HASH_API void PHP_SHA1Update(PHP_SHA1_CTX * context, const unsigned char *in index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint32) inputLen << 3)) - < ((php_hash_uint32) inputLen << 3)) + if ((context->count[0] += ((uint32_t) inputLen << 3)) + < ((uint32_t) inputLen << 3)) context->count[1]++; - context->count[1] += ((php_hash_uint32) inputLen >> 29); + context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; @@ -445,7 +445,7 @@ const php_hash_ops php_hash_sha224_ops = { /* OM1 */ #define SHA256_F5(x) (ROTR32(17,(x)) ^ ROTR32(19,(x)) ^ SHR(10,(x))) -static const php_hash_uint32 SHA256_K[64] = { +static const uint32_t SHA256_K[64] = { 0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1, 0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3, 0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786, 0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da, @@ -477,11 +477,11 @@ PHP_HASH_API void PHP_SHA256Init(PHP_SHA256_CTX * context) /* {{{ SHA256Transform * SHA256 basic transformation. Transforms state based on block. */ -static void SHA256Transform(php_hash_uint32 state[8], const unsigned char block[64]) +static void SHA256Transform(uint32_t state[8], const unsigned char block[64]) { - php_hash_uint32 a = state[0], b = state[1], c = state[2], d = state[3]; - php_hash_uint32 e = state[4], f = state[5], g = state[6], h = state[7]; - php_hash_uint32 x[16], T1, T2, W[64]; + uint32_t a = state[0], b = state[1], c = state[2], d = state[3]; + uint32_t e = state[4], f = state[5], g = state[6], h = state[7]; + uint32_t x[16], T1, T2, W[64]; int i; SHADecode32(x, block, 64); @@ -547,10 +547,10 @@ PHP_HASH_API void PHP_SHA224Update(PHP_SHA224_CTX * context, const unsigned char index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint32) inputLen << 3)) < ((php_hash_uint32) inputLen << 3)) { + if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) { context->count[1]++; } - context->count[1] += ((php_hash_uint32) inputLen >> 29); + context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; @@ -624,10 +624,10 @@ PHP_HASH_API void PHP_SHA256Update(PHP_SHA256_CTX * context, const unsigned char index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint32) inputLen << 3)) < ((php_hash_uint32) inputLen << 3)) { + if ((context->count[0] += ((uint32_t) inputLen << 3)) < ((uint32_t) inputLen << 3)) { context->count[1]++; } - context->count[1] += ((php_hash_uint32) inputLen >> 29); + context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; @@ -703,7 +703,7 @@ PHP_HASH_API void PHP_SHA256Final(unsigned char digest[32], PHP_SHA256_CTX * con /* OM1 */ #define SHA512_F5(x) (ROTR64(19, x) ^ ROTR64(61, x) ^ SHR(6, x)) -static const php_hash_uint64 SHA512_K[128] = { +static const uint64_t SHA512_K[128] = { L64(0x428a2f98d728ae22), L64(0x7137449123ef65cd), L64(0xb5c0fbcfec4d3b2f), L64(0xe9b5dba58189dbbc), L64(0x3956c25bf348b538), L64(0x59f111f1b605d019), L64(0x923f82a4af194f9b), L64(0xab1c5ed5da6d8118), L64(0xd807aa98a3030242), L64(0x12835b0145706fbe), L64(0x243185be4ee4b28c), L64(0x550c7dc3d5ffb4e2), @@ -726,10 +726,10 @@ static const php_hash_uint64 SHA512_K[128] = { L64(0x4cc5d4becb3e42b6), L64(0x597f299cfc657e2a), L64(0x5fcb6fab3ad6faec), L64(0x6c44198c4a475817) }; /* {{{ SHAEncode64 - Encodes input (php_hash_uint64) into output (unsigned char). Assumes len is + Encodes input (uint64_t) into output (unsigned char). Assumes len is a multiple of 8. */ -static void SHAEncode64(unsigned char *output, php_hash_uint64 *input, unsigned int len) +static void SHAEncode64(unsigned char *output, uint64_t *input, unsigned int len) { unsigned int i, j; @@ -748,19 +748,19 @@ static void SHAEncode64(unsigned char *output, php_hash_uint64 *input, unsigned /* {{{ SHADecode64 - Decodes input (unsigned char) into output (php_hash_uint64). Assumes len is + Decodes input (unsigned char) into output (uint64_t). Assumes len is a multiple of 8. */ -static void SHADecode64(php_hash_uint64 *output, const unsigned char *input, unsigned int len) +static void SHADecode64(uint64_t *output, const unsigned char *input, unsigned int len) { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 8) output[i] = - ((php_hash_uint64) input[j + 7]) | (((php_hash_uint64) input[j + 6]) << 8) | - (((php_hash_uint64) input[j + 5]) << 16) | (((php_hash_uint64) input[j + 4]) << 24) | - (((php_hash_uint64) input[j + 3]) << 32) | (((php_hash_uint64) input[j + 2]) << 40) | - (((php_hash_uint64) input[j + 1]) << 48) | (((php_hash_uint64) input[j]) << 56); + ((uint64_t) input[j + 7]) | (((uint64_t) input[j + 6]) << 8) | + (((uint64_t) input[j + 5]) << 16) | (((uint64_t) input[j + 4]) << 24) | + (((uint64_t) input[j + 3]) << 32) | (((uint64_t) input[j + 2]) << 40) | + (((uint64_t) input[j + 1]) << 48) | (((uint64_t) input[j]) << 56); } /* }}} */ @@ -787,11 +787,11 @@ PHP_HASH_API void PHP_SHA384Init(PHP_SHA384_CTX * context) * SHA512 basic transformation. Transforms state based on block. * SHA384 uses the exact same algorithm */ -static void SHA512Transform(php_hash_uint64 state[8], const unsigned char block[128]) +static void SHA512Transform(uint64_t state[8], const unsigned char block[128]) { - php_hash_uint64 a = state[0], b = state[1], c = state[2], d = state[3]; - php_hash_uint64 e = state[4], f = state[5], g = state[6], h = state[7]; - php_hash_uint64 x[16], T1, T2, W[80]; + uint64_t a = state[0], b = state[1], c = state[2], d = state[3]; + uint64_t e = state[4], f = state[5], g = state[6], h = state[7]; + uint64_t x[16], T1, T2, W[80]; int i; SHADecode64(x, block, 128); @@ -838,10 +838,10 @@ PHP_HASH_API void PHP_SHA384Update(PHP_SHA384_CTX * context, const unsigned char index = (unsigned int) ((context->count[0] >> 3) & 0x7F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint64) inputLen << 3)) < ((php_hash_uint64) inputLen << 3)) { + if ((context->count[0] += ((uint64_t) inputLen << 3)) < ((uint64_t) inputLen << 3)) { context->count[1]++; } - context->count[1] += ((php_hash_uint64) inputLen >> 61); + context->count[1] += ((uint64_t) inputLen >> 61); partLen = 128 - index; @@ -952,10 +952,10 @@ PHP_HASH_API void PHP_SHA512Update(PHP_SHA512_CTX * context, const unsigned char index = (unsigned int) ((context->count[0] >> 3) & 0x7F); /* Update number of bits */ - if ((context->count[0] += ((php_hash_uint64) inputLen << 3)) < ((php_hash_uint64) inputLen << 3)) { + if ((context->count[0] += ((uint64_t) inputLen << 3)) < ((uint64_t) inputLen << 3)) { context->count[1]++; } - context->count[1] += ((php_hash_uint64) inputLen >> 61); + context->count[1] += ((uint64_t) inputLen >> 61); partLen = 128 - index; diff --git a/ext/hash/hash_sha3.c b/ext/hash/hash_sha3.c index bf05c53992..aab17c1476 100644 --- a/ext/hash/hash_sha3.c +++ b/ext/hash/hash_sha3.c @@ -29,7 +29,7 @@ # endif #endif -static inline php_hash_uint64 rol64(php_hash_uint64 v, unsigned char b) { +static inline uint64_t rol64(uint64_t v, unsigned char b) { return (v << b) | (v >> (64 - b)); } static inline unsigned char idx(unsigned char x, unsigned char y) { @@ -37,36 +37,36 @@ static inline unsigned char idx(unsigned char x, unsigned char y) { } #ifdef WORDS_BIGENDIAN -static inline php_hash_uint64 load64(const unsigned char* x) { +static inline uint64_t load64(const unsigned char* x) { unsigned char i; - php_hash_uint64 ret = 0; + uint64_t ret = 0; for (i = 7; i >= 0; --i) { ret <<= 8; ret |= x[i]; } return ret; } -static inline void store64(unsigned char* x, php_hash_uint64 val) { +static inline void store64(unsigned char* x, uint64_t val) { unsigned char i; for (i = 0; i < 8; ++i) { x[i] = val & 0xFF; val >>= 8; } } -static inline void xor64(unsigned char* x, php_hash_uint64 val) { +static inline void xor64(unsigned char* x, uint64_t val) { unsigned char i; for (i = 0; i < 8; ++i) { x[i] ^= val & 0xFF; val >>= 8; } } -# define readLane(x, y) load64(ctx->state+sizeof(php_hash_uint64)*idx(x, y)) -# define writeLane(x, y, v) store64(ctx->state+sizeof(php_hash_uint64)*idx(x, y), v) -# define XORLane(x, y, v) xor64(ctx->state+sizeof(php_hash_uint64)*idx(x, y), v) +# define readLane(x, y) load64(ctx->state+sizeof(uint64_t)*idx(x, y)) +# define writeLane(x, y, v) store64(ctx->state+sizeof(uint64_t)*idx(x, y), v) +# define XORLane(x, y, v) xor64(ctx->state+sizeof(uint64_t)*idx(x, y), v) #else -# define readLane(x, y) (((php_hash_uint64*)ctx->state)[idx(x,y)]) -# define writeLane(x, y, v) (((php_hash_uint64*)ctx->state)[idx(x,y)] = v) -# define XORLane(x, y, v) (((php_hash_uint64*)ctx->state)[idx(x,y)] ^= v) +# define readLane(x, y) (((uint64_t*)ctx->state)[idx(x,y)]) +# define writeLane(x, y, v) (((uint64_t*)ctx->state)[idx(x,y)] = v) +# define XORLane(x, y, v) (((uint64_t*)ctx->state)[idx(x,y)] ^= v) #endif static inline char LFSR86540(unsigned char* pLFSR) @@ -89,7 +89,7 @@ static void permute(PHP_SHA3_CTX* ctx) { for (round = 0; round < 24; ++round) { { // Theta step (see [Keccak Reference, Section 2.3.2]) - php_hash_uint64 C[5], D; + uint64_t C[5], D; unsigned char x, y; for (x = 0; x < 5; ++x) { C[x] = readLane(x, 0) ^ readLane(x, 1) ^ @@ -105,11 +105,11 @@ static void permute(PHP_SHA3_CTX* ctx) { { // p and Pi steps (see [Keccak Reference, Sections 2.3.3 and 2.3.4]) unsigned char x = 1, y = 0, t; - php_hash_uint64 current = readLane(x, y); + uint64_t current = readLane(x, y); for (t = 0; t < 24; ++t) { unsigned char r = ((t + 1) * (t + 2) / 2) % 64; unsigned char Y = (2*x + 3*y) % 5; - php_hash_uint64 temp; + uint64_t temp; x = y; y = Y; temp = readLane(x, y); @@ -121,7 +121,7 @@ static void permute(PHP_SHA3_CTX* ctx) { { // X step (see [Keccak Reference, Section 2.3.1]) unsigned char x, y; for (y = 0; y < 5; ++y) { - php_hash_uint64 temp[5]; + uint64_t temp[5]; for (x = 0; x < 5; ++x) { temp[x] = readLane(x, y); } @@ -135,8 +135,8 @@ static void permute(PHP_SHA3_CTX* ctx) { unsigned char j; for (j = 0; j < 7; ++j) { if (LFSR86540(&LFSRstate)) { - php_hash_uint64 bitPos = (1<<j) - 1; - XORLane(0, 0, (php_hash_uint64)1 << bitPos); + uint64_t bitPos = (1<<j) - 1; + XORLane(0, 0, (uint64_t)1 << bitPos); } } } diff --git a/ext/hash/hash_snefru.c b/ext/hash/hash_snefru.c index 1d94343c07..c7251b0bb1 100644 --- a/ext/hash/hash_snefru.c +++ b/ext/hash/hash_snefru.c @@ -33,7 +33,7 @@ #endif #if DBG_SNEFRU -void ph(php_hash_uint32 h[16]) +void ph(uint32_t h[16]) { int i; for (i = 0; i < 16; i++) @@ -41,12 +41,12 @@ void ph(php_hash_uint32 h[16]) } #endif -static inline void Snefru(php_hash_uint32 input[16]) +static inline void Snefru(uint32_t input[16]) { static int shifts[4] = {16, 8, 16, 24}; int b, index, rshift, lshift; - const php_hash_uint32 *t0,*t1; - php_hash_uint32 SBE,B00,B01,B02,B03,B04,B05,B06,B07,B08,B09,B10,B11,B12,B13,B14,B15; + const uint32_t *t0,*t1; + uint32_t SBE,B00,B01,B02,B03,B04,B05,B06,B07,B08,B09,B10,B11,B12,B13,B14,B15; B00 = input[0]; B01 = input[1]; @@ -129,7 +129,7 @@ static inline void SnefruTransform(PHP_SNEFRU_CTX *context, const unsigned char ((input[i+2] & 0xff) << 8) | (input[i+3] & 0xff); } Snefru(context->state); - memset(&context->state[8], 0, sizeof(php_hash_uint32) * 8); + memset(&context->state[8], 0, sizeof(uint32_t) * 8); } PHP_HASH_API void PHP_SNEFRUInit(PHP_SNEFRU_CTX *context) @@ -137,7 +137,7 @@ PHP_HASH_API void PHP_SNEFRUInit(PHP_SNEFRU_CTX *context) memset(context, 0, sizeof(*context)); } -static const php_hash_uint32 MAX32 = 0xffffffffLU; +static const uint32_t MAX32 = 0xffffffffLU; PHP_HASH_API void PHP_SNEFRUUpdate(PHP_SNEFRU_CTX *context, const unsigned char *input, size_t len) { @@ -173,7 +173,7 @@ PHP_HASH_API void PHP_SNEFRUUpdate(PHP_SNEFRU_CTX *context, const unsigned char PHP_HASH_API void PHP_SNEFRUFinal(unsigned char digest[32], PHP_SNEFRU_CTX *context) { - php_hash_uint32 i, j; + uint32_t i, j; if (context->length) { SnefruTransform(context, context->buffer); diff --git a/ext/hash/hash_tiger.c b/ext/hash/hash_tiger.c index ac93d7513c..61244de773 100644 --- a/ext/hash/hash_tiger.c +++ b/ext/hash/hash_tiger.c @@ -42,13 +42,13 @@ #define round(a,b,c,x,mul) \ c ^= x; \ a -= t1[(unsigned char)(c)] ^ \ - t2[(unsigned char)(((php_hash_uint32)(c))>>(2*8))] ^ \ + t2[(unsigned char)(((uint32_t)(c))>>(2*8))] ^ \ t3[(unsigned char)((c)>>(4*8))] ^ \ - t4[(unsigned char)(((php_hash_uint32)((c)>>(4*8)))>>(2*8))] ; \ - b += t4[(unsigned char)(((php_hash_uint32)(c))>>(1*8))] ^ \ - t3[(unsigned char)(((php_hash_uint32)(c))>>(3*8))] ^ \ - t2[(unsigned char)(((php_hash_uint32)((c)>>(4*8)))>>(1*8))] ^ \ - t1[(unsigned char)(((php_hash_uint32)((c)>>(4*8)))>>(3*8))]; \ + t4[(unsigned char)(((uint32_t)((c)>>(4*8)))>>(2*8))] ; \ + b += t4[(unsigned char)(((uint32_t)(c))>>(1*8))] ^ \ + t3[(unsigned char)(((uint32_t)(c))>>(3*8))] ^ \ + t2[(unsigned char)(((uint32_t)((c)>>(4*8)))>>(1*8))] ^ \ + t1[(unsigned char)(((uint32_t)((c)>>(4*8)))>>(3*8))]; \ b *= mul; #define pass(a,b,c,mul) \ @@ -105,7 +105,7 @@ # define split(str) \ { \ int i; \ - php_hash_uint64 tmp[8]; \ + uint64_t tmp[8]; \ \ for (i = 0; i < 64; ++i) { \ ((unsigned char *) tmp)[i^7] = ((unsigned char *) str)[i]; \ @@ -118,8 +118,8 @@ #define tiger_compress(passes, str, state) \ { \ - register php_hash_uint64 a, b, c, tmpa, x0, x1, x2, x3, x4, x5, x6, x7; \ - php_hash_uint64 aa, bb, cc; \ + register uint64_t a, b, c, tmpa, x0, x1, x2, x3, x4, x5, x6, x7; \ + uint64_t aa, bb, cc; \ unsigned int pass_no; \ \ a = state[0]; \ @@ -138,7 +138,7 @@ static inline void TigerFinalize(PHP_TIGER_CTX *context) { - context->passed += (php_hash_uint64) context->length << 3; + context->passed += (uint64_t) context->length << 3; context->buffer[context->length++] = 0x1; if (context->length % 8) { @@ -148,14 +148,14 @@ static inline void TigerFinalize(PHP_TIGER_CTX *context) if (context->length > 56) { memset(&context->buffer[context->length], 0, 64 - context->length); - tiger_compress(context->passes, ((php_hash_uint64 *) context->buffer), context->state); + tiger_compress(context->passes, ((uint64_t *) context->buffer), context->state); memset(context->buffer, 0, 56); } else { memset(&context->buffer[context->length], 0, 56 - context->length); } #ifndef WORDS_BIGENDIAN - memcpy(&context->buffer[56], &context->passed, sizeof(php_hash_uint64)); + memcpy(&context->buffer[56], &context->passed, sizeof(uint64_t)); #else context->buffer[56] = (unsigned char) (context->passed & 0xff); context->buffer[57] = (unsigned char) ((context->passed >> 8) & 0xff); @@ -166,7 +166,7 @@ static inline void TigerFinalize(PHP_TIGER_CTX *context) context->buffer[62] = (unsigned char) ((context->passed >> 48) & 0xff); context->buffer[63] = (unsigned char) ((context->passed >> 56) & 0xff); #endif - tiger_compress(context->passes, ((php_hash_uint64 *) context->buffer), context->state); + tiger_compress(context->passes, ((uint64_t *) context->buffer), context->state); } static inline void TigerDigest(unsigned char *digest_str, unsigned int digest_len, PHP_TIGER_CTX *context) @@ -206,14 +206,14 @@ PHP_HASH_API void PHP_TIGERUpdate(PHP_TIGER_CTX *context, const unsigned char *i if (context->length) { i = 64 - context->length; memcpy(&context->buffer[context->length], input, i); - tiger_compress(context->passes, ((const php_hash_uint64 *) context->buffer), context->state); + tiger_compress(context->passes, ((const uint64_t *) context->buffer), context->state); ZEND_SECURE_ZERO(context->buffer, 64); context->passed += 512; } for (; i + 64 <= len; i += 64) { memcpy(context->buffer, &input[i], 64); - tiger_compress(context->passes, ((const php_hash_uint64 *) context->buffer), context->state); + tiger_compress(context->passes, ((const uint64_t *) context->buffer), context->state); context->passed += 512; } ZEND_SECURE_ZERO(&context->buffer[r], 64-r); diff --git a/ext/hash/hash_whirlpool.c b/ext/hash/hash_whirlpool.c index 653b04ed0a..e856ffab0c 100644 --- a/ext/hash/hash_whirlpool.c +++ b/ext/hash/hash_whirlpool.c @@ -41,10 +41,10 @@ static void WhirlpoolTransform(PHP_WHIRLPOOL_CTX *context) { int i, r; - php_hash_uint64 K[8]; /* the round key */ - php_hash_uint64 block[8]; /* mu(buffer) */ - php_hash_uint64 state[8]; /* the cipher state */ - php_hash_uint64 L[8]; + uint64_t K[8]; /* the round key */ + uint64_t block[8]; /* mu(buffer) */ + uint64_t state[8]; /* the cipher state */ + uint64_t L[8]; unsigned char *buffer = context->buffer.data; /* @@ -52,14 +52,14 @@ static void WhirlpoolTransform(PHP_WHIRLPOOL_CTX *context) */ for (i = 0; i < 8; i++, buffer += 8) { block[i] = - (((php_hash_uint64)buffer[0] ) << 56) ^ - (((php_hash_uint64)buffer[1] & 0xffL) << 48) ^ - (((php_hash_uint64)buffer[2] & 0xffL) << 40) ^ - (((php_hash_uint64)buffer[3] & 0xffL) << 32) ^ - (((php_hash_uint64)buffer[4] & 0xffL) << 24) ^ - (((php_hash_uint64)buffer[5] & 0xffL) << 16) ^ - (((php_hash_uint64)buffer[6] & 0xffL) << 8) ^ - (((php_hash_uint64)buffer[7] & 0xffL) ); + (((uint64_t)buffer[0] ) << 56) ^ + (((uint64_t)buffer[1] & 0xffL) << 48) ^ + (((uint64_t)buffer[2] & 0xffL) << 40) ^ + (((uint64_t)buffer[3] & 0xffL) << 32) ^ + (((uint64_t)buffer[4] & 0xffL) << 24) ^ + (((uint64_t)buffer[5] & 0xffL) << 16) ^ + (((uint64_t)buffer[6] & 0xffL) << 8) ^ + (((uint64_t)buffer[7] & 0xffL) ); } /* * compute and apply K^0 to the cipher state: @@ -274,7 +274,7 @@ PHP_HASH_API void PHP_WHIRLPOOLInit(PHP_WHIRLPOOL_CTX *context) PHP_HASH_API void PHP_WHIRLPOOLUpdate(PHP_WHIRLPOOL_CTX *context, const unsigned char *input, size_t len) { - php_hash_uint64 sourceBits = len * 8; + uint64_t sourceBits = len * 8; int sourcePos = 0; /* index of leftmost source unsigned char containing data (1 to 8 bits). */ int sourceGap = (8 - ((int)sourceBits & 7)) & 7; /* space on source[sourcePos]. */ int bufferRem = context->buffer.bits & 7; /* occupied bits on buffer[bufferPos]. */ @@ -283,15 +283,15 @@ PHP_HASH_API void PHP_WHIRLPOOLUpdate(PHP_WHIRLPOOL_CTX *context, const unsigned unsigned char *bitLength = context->bitlength; int bufferBits = context->buffer.bits; int bufferPos = context->buffer.pos; - php_hash_uint32 b, carry; + uint32_t b, carry; int i; /* * tally the length of the added data: */ - php_hash_uint64 value = sourceBits; + uint64_t value = sourceBits; for (i = 31, carry = 0; i >= 0 && (carry != 0 || value != L64(0)); i--) { - carry += bitLength[i] + ((php_hash_uint32)value & 0xff); + carry += bitLength[i] + ((uint32_t)value & 0xff); bitLength[i] = (unsigned char)carry; carry >>= 8; value >>= 8; diff --git a/ext/hash/php_hash.h b/ext/hash/php_hash.h index b6b43998b4..16252e1eb7 100644 --- a/ext/hash/php_hash.h +++ b/ext/hash/php_hash.h @@ -31,10 +31,6 @@ #define PHP_HASH_HMAC 0x0001 #define L64 INT64_C -#define php_hash_int32 int32_t -#define php_hash_uint32 uint32_t -#define php_hash_int64 int64_t -#define php_hash_uint64 uint64_t typedef void (*php_hash_init_func_t)(void *context); typedef void (*php_hash_update_func_t)(void *context, const unsigned char *buf, unsigned int count); diff --git a/ext/hash/php_hash_adler32.h b/ext/hash/php_hash_adler32.h index 697498b260..dc2dfed9f5 100644 --- a/ext/hash/php_hash_adler32.h +++ b/ext/hash/php_hash_adler32.h @@ -24,7 +24,7 @@ #include "ext/standard/basic_functions.h" typedef struct { - php_hash_uint32 state; + uint32_t state; } PHP_ADLER32_CTX; PHP_HASH_API void PHP_ADLER32Init(PHP_ADLER32_CTX *context); diff --git a/ext/hash/php_hash_crc32.h b/ext/hash/php_hash_crc32.h index 0d3d13e0c8..377be020cb 100644 --- a/ext/hash/php_hash_crc32.h +++ b/ext/hash/php_hash_crc32.h @@ -24,7 +24,7 @@ #include "ext/standard/basic_functions.h" typedef struct { - php_hash_uint32 state; + uint32_t state; } PHP_CRC32_CTX; PHP_HASH_API void PHP_CRC32Init(PHP_CRC32_CTX *context); diff --git a/ext/hash/php_hash_crc32_tables.h b/ext/hash/php_hash_crc32_tables.h index 7e343442e4..6af878b3ac 100644 --- a/ext/hash/php_hash_crc32_tables.h +++ b/ext/hash/php_hash_crc32_tables.h @@ -18,7 +18,7 @@ /* $Id$ */ -static const php_hash_uint32 crc32_table[] = { 0x0, +static const uint32_t crc32_table[] = { 0x0, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b, 0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61, 0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, @@ -72,7 +72,7 @@ static const php_hash_uint32 crc32_table[] = { 0x0, 0xa2f33668, 0xbcb4666d, 0xb8757bda, 0xb5365d03, 0xb1f740b4 }; -static const php_hash_uint32 crc32b_table[] = { +static const uint32_t crc32b_table[] = { 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988, diff --git a/ext/hash/php_hash_fnv.h b/ext/hash/php_hash_fnv.h index 1edbe8631e..f825ba8849 100644 --- a/ext/hash/php_hash_fnv.h +++ b/ext/hash/php_hash_fnv.h @@ -21,15 +21,15 @@ #ifndef PHP_HASH_FNV_H #define PHP_HASH_FNV_H -#define PHP_FNV1_32_INIT ((php_hash_uint32)0x811c9dc5) +#define PHP_FNV1_32_INIT ((uint32_t)0x811c9dc5) #define PHP_FNV1_32A_INIT PHP_FNV1_32_INIT -#define PHP_FNV_32_PRIME ((php_hash_uint32)0x01000193) +#define PHP_FNV_32_PRIME ((uint32_t)0x01000193) -#define PHP_FNV1_64_INIT ((php_hash_uint64)0xcbf29ce484222325ULL) +#define PHP_FNV1_64_INIT ((uint64_t)0xcbf29ce484222325ULL) #define PHP_FNV1A_64_INIT FNV1_64_INIT -#define PHP_FNV_64_PRIME ((php_hash_uint64)0x100000001b3ULL) +#define PHP_FNV_64_PRIME ((uint64_t)0x100000001b3ULL) /* @@ -46,11 +46,11 @@ enum php_fnv_type { }; typedef struct { - php_hash_uint32 state; + uint32_t state; } PHP_FNV132_CTX; typedef struct { - php_hash_uint64 state; + uint64_t state; } PHP_FNV164_CTX; @@ -64,8 +64,8 @@ PHP_HASH_API void PHP_FNV164Update(PHP_FNV164_CTX *context, const unsigned char PHP_HASH_API void PHP_FNV1a64Update(PHP_FNV164_CTX *context, const unsigned char *input, unsigned int inputLen); PHP_HASH_API void PHP_FNV164Final(unsigned char digest[16], PHP_FNV164_CTX * context); -static php_hash_uint32 fnv_32_buf(void *buf, size_t len, php_hash_uint32 hval, int alternate); -static php_hash_uint64 fnv_64_buf(void *buf, size_t len, php_hash_uint64 hval, int alternate); +static uint32_t fnv_32_buf(void *buf, size_t len, uint32_t hval, int alternate); +static uint64_t fnv_64_buf(void *buf, size_t len, uint64_t hval, int alternate); #endif diff --git a/ext/hash/php_hash_gost.h b/ext/hash/php_hash_gost.h index 13a221edc9..a3d4a18a4c 100644 --- a/ext/hash/php_hash_gost.h +++ b/ext/hash/php_hash_gost.h @@ -25,11 +25,11 @@ /* GOST context */ typedef struct { - php_hash_uint32 state[16]; - php_hash_uint32 count[2]; + uint32_t state[16]; + uint32_t count[2]; unsigned char length; unsigned char buffer[32]; - const php_hash_uint32 (*tables)[4][256]; + const uint32_t (*tables)[4][256]; } PHP_GOST_CTX; PHP_HASH_API void PHP_GOSTInit(PHP_GOST_CTX *); diff --git a/ext/hash/php_hash_gost_tables.h b/ext/hash/php_hash_gost_tables.h index af6a78b10b..5a8f6e79fd 100644 --- a/ext/hash/php_hash_gost_tables.h +++ b/ext/hash/php_hash_gost_tables.h @@ -1,4 +1,4 @@ -static const php_hash_uint32 tables_test[4][256] = { +static const uint32_t tables_test[4][256] = { { /* table 1 */ 0x00072000LU, 0x00075000LU, 0x00074800LU, 0x00071000LU, 0x00076800LU, 0x00074000LU, 0x00070000LU, 0x00077000LU, 0x00073000LU, 0x00075800LU, 0x00070800LU, 0x00076000LU, 0x00073800LU, 0x00077800LU, 0x00072800LU, 0x00071800LU, @@ -137,7 +137,7 @@ static const php_hash_uint32 tables_test[4][256] = { }, }; -static const php_hash_uint32 tables_crypto[4][256] = { +static const uint32_t tables_crypto[4][256] = { { /* table 1 */ 0x0002d000LU, 0x0002a000LU, 0x0002a800LU, 0x0002b000LU, 0x0002c000LU, 0x00028800LU, 0x00029800LU, 0x0002b800LU, 0x0002e800LU, 0x0002e000LU, 0x0002f000LU, 0x00028000LU, 0x0002c800LU, 0x00029000LU, 0x0002d800LU, 0x0002f800LU, diff --git a/ext/hash/php_hash_haval.h b/ext/hash/php_hash_haval.h index 4d2504b037..8877797bfd 100644 --- a/ext/hash/php_hash_haval.h +++ b/ext/hash/php_hash_haval.h @@ -24,13 +24,13 @@ #include "ext/standard/basic_functions.h" /* HAVAL context. */ typedef struct { - php_hash_uint32 state[8]; - php_hash_uint32 count[2]; + uint32_t state[8]; + uint32_t count[2]; unsigned char buffer[128]; char passes; short output; - void (*Transform)(php_hash_uint32 state[8], const unsigned char block[128]); + void (*Transform)(uint32_t state[8], const unsigned char block[128]); } PHP_HAVAL_CTX; #define PHP_HASH_HAVAL_INIT_DECL(p,b) PHP_HASH_API void PHP_##p##HAVAL##b##Init(PHP_HAVAL_CTX *); \ diff --git a/ext/hash/php_hash_joaat.h b/ext/hash/php_hash_joaat.h index 9d2c7be2db..97a76daff9 100644 --- a/ext/hash/php_hash_joaat.h +++ b/ext/hash/php_hash_joaat.h @@ -22,14 +22,14 @@ #define PHP_HASH_JOAAT_H typedef struct { - php_hash_uint32 state; + uint32_t state; } PHP_JOAAT_CTX; PHP_HASH_API void PHP_JOAATInit(PHP_JOAAT_CTX *context); PHP_HASH_API void PHP_JOAATUpdate(PHP_JOAAT_CTX *context, const unsigned char *input, unsigned int inputLen); PHP_HASH_API void PHP_JOAATFinal(unsigned char digest[16], PHP_JOAAT_CTX * context); -static php_hash_uint32 joaat_buf(void *buf, size_t len, php_hash_uint32 hval); +static uint32_t joaat_buf(void *buf, size_t len, uint32_t hval); #endif diff --git a/ext/hash/php_hash_md.h b/ext/hash/php_hash_md.h index ea77eb5894..2e7121f37a 100644 --- a/ext/hash/php_hash_md.h +++ b/ext/hash/php_hash_md.h @@ -60,8 +60,8 @@ /* MD5 context. */ typedef struct { - php_hash_uint32 state[4]; /* state (ABCD) */ - php_hash_uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + uint32_t state[4]; /* state (ABCD) */ + uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_MD5_CTX; @@ -76,8 +76,8 @@ PHP_NAMED_FUNCTION(php_if_md5_file); /* MD4 context */ typedef struct { - php_hash_uint32 state[4]; - php_hash_uint32 count[2]; + uint32_t state[4]; + uint32_t count[2]; unsigned char buffer[64]; } PHP_MD4_CTX; diff --git a/ext/hash/php_hash_ripemd.h b/ext/hash/php_hash_ripemd.h index e0aca994b6..ae29737756 100644 --- a/ext/hash/php_hash_ripemd.h +++ b/ext/hash/php_hash_ripemd.h @@ -24,26 +24,26 @@ /* RIPEMD context. */ typedef struct { - php_hash_uint32 state[4]; /* state (ABCD) */ - php_hash_uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + uint32_t state[4]; /* state (ABCD) */ + uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD128_CTX; typedef struct { - php_hash_uint32 state[5]; /* state (ABCD) */ - php_hash_uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + uint32_t state[5]; /* state (ABCD) */ + uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD160_CTX; typedef struct { - php_hash_uint32 state[8]; /* state (ABCD) */ - php_hash_uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + uint32_t state[8]; /* state (ABCD) */ + uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD256_CTX; typedef struct { - php_hash_uint32 state[10]; /* state (ABCD) */ - php_hash_uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + uint32_t state[10]; /* state (ABCD) */ + uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_RIPEMD320_CTX; diff --git a/ext/hash/php_hash_sha.h b/ext/hash/php_hash_sha.h index 20564b25a2..000de614ff 100644 --- a/ext/hash/php_hash_sha.h +++ b/ext/hash/php_hash_sha.h @@ -36,8 +36,8 @@ /* SHA1 context. */ typedef struct { - php_hash_uint32 state[5]; /* state (ABCD) */ - php_hash_uint32 count[2]; /* number of bits, modulo 2^64 */ + uint32_t state[5]; /* state (ABCD) */ + uint32_t count[2]; /* number of bits, modulo 2^64 */ unsigned char buffer[64]; /* input buffer */ } PHP_SHA1_CTX; @@ -52,8 +52,8 @@ PHP_FUNCTION(sha1_file); /* SHA224 context. */ typedef struct { - php_hash_uint32 state[8]; /* state */ - php_hash_uint32 count[2]; /* number of bits, modulo 2^64 */ + uint32_t state[8]; /* state */ + uint32_t count[2]; /* number of bits, modulo 2^64 */ unsigned char buffer[64]; /* input buffer */ } PHP_SHA224_CTX; @@ -63,8 +63,8 @@ PHP_HASH_API void PHP_SHA224Final(unsigned char[28], PHP_SHA224_CTX *); /* SHA256 context. */ typedef struct { - php_hash_uint32 state[8]; /* state */ - php_hash_uint32 count[2]; /* number of bits, modulo 2^64 */ + uint32_t state[8]; /* state */ + uint32_t count[2]; /* number of bits, modulo 2^64 */ unsigned char buffer[64]; /* input buffer */ } PHP_SHA256_CTX; @@ -74,8 +74,8 @@ PHP_HASH_API void PHP_SHA256Final(unsigned char[32], PHP_SHA256_CTX *); /* SHA384 context */ typedef struct { - php_hash_uint64 state[8]; /* state */ - php_hash_uint64 count[2]; /* number of bits, modulo 2^128 */ + uint64_t state[8]; /* state */ + uint64_t count[2]; /* number of bits, modulo 2^128 */ unsigned char buffer[128]; /* input buffer */ } PHP_SHA384_CTX; @@ -85,8 +85,8 @@ PHP_HASH_API void PHP_SHA384Final(unsigned char[48], PHP_SHA384_CTX *); /* SHA512 context */ typedef struct { - php_hash_uint64 state[8]; /* state */ - php_hash_uint64 count[2]; /* number of bits, modulo 2^128 */ + uint64_t state[8]; /* state */ + uint64_t count[2]; /* number of bits, modulo 2^128 */ unsigned char buffer[128]; /* input buffer */ } PHP_SHA512_CTX; diff --git a/ext/hash/php_hash_sha3.h b/ext/hash/php_hash_sha3.h index dd52a24b3b..da7c5f46d7 100644 --- a/ext/hash/php_hash_sha3.h +++ b/ext/hash/php_hash_sha3.h @@ -24,7 +24,7 @@ typedef struct { unsigned char state[200]; // 5 * 5 * sizeof(uint64) - php_hash_uint32 pos; + uint32_t pos; } PHP_SHA3_CTX; typedef PHP_SHA3_CTX PHP_SHA3_224_CTX; diff --git a/ext/hash/php_hash_snefru.h b/ext/hash/php_hash_snefru.h index cf6699a2bd..64c88fbab1 100644 --- a/ext/hash/php_hash_snefru.h +++ b/ext/hash/php_hash_snefru.h @@ -29,8 +29,8 @@ /* SNEFRU context */ typedef struct { - php_hash_uint32 state[16]; - php_hash_uint32 count[2]; + uint32_t state[16]; + uint32_t count[2]; unsigned char length; unsigned char buffer[32]; } PHP_SNEFRU_CTX; diff --git a/ext/hash/php_hash_snefru_tables.h b/ext/hash/php_hash_snefru_tables.h index 199f9f523d..ffd1d29eb5 100644 --- a/ext/hash/php_hash_snefru_tables.h +++ b/ext/hash/php_hash_snefru_tables.h @@ -18,7 +18,7 @@ /* $Id$ */ -static const php_hash_uint32 tables[16][256]= { +static const uint32_t tables[16][256]= { { /* Start of S Box 0 */ diff --git a/ext/hash/php_hash_tiger.h b/ext/hash/php_hash_tiger.h index 536da19a94..af52a95203 100644 --- a/ext/hash/php_hash_tiger.h +++ b/ext/hash/php_hash_tiger.h @@ -23,8 +23,8 @@ /* TIGER context */ typedef struct { - php_hash_uint64 state[3]; - php_hash_uint64 passed; + uint64_t state[3]; + uint64_t passed; unsigned char buffer[64]; unsigned int passes:1; unsigned int length:7; diff --git a/ext/hash/php_hash_tiger_tables.h b/ext/hash/php_hash_tiger_tables.h index 46197c7516..616213ae28 100644 --- a/ext/hash/php_hash_tiger_tables.h +++ b/ext/hash/php_hash_tiger_tables.h @@ -24,7 +24,7 @@ #define t3 (table+256*2) #define t4 (table+256*3) -static const php_hash_uint64 table[4*256] = { +static const uint64_t table[4*256] = { L64(0x02AAB17CF7E90C5E) /* 0 */, L64(0xAC424B03E243A8EC) /* 1 */, L64(0x72CD5BE30DD5FCD3) /* 2 */, L64(0x6D019B93F6F97F3A) /* 3 */, L64(0xCD9978FFD21F9193) /* 4 */, L64(0x7573A1C9708029E2) /* 5 */, diff --git a/ext/hash/php_hash_whirlpool.h b/ext/hash/php_hash_whirlpool.h index eb9205489d..dec337a390 100644 --- a/ext/hash/php_hash_whirlpool.h +++ b/ext/hash/php_hash_whirlpool.h @@ -23,7 +23,7 @@ /* WHIRLPOOL context */ typedef struct { - php_hash_uint64 state[8]; + uint64_t state[8]; unsigned char bitlength[32]; struct { int pos; diff --git a/ext/hash/php_hash_whirlpool_tables.h b/ext/hash/php_hash_whirlpool_tables.h index 569b7530a1..286d180289 100644 --- a/ext/hash/php_hash_whirlpool_tables.h +++ b/ext/hash/php_hash_whirlpool_tables.h @@ -23,7 +23,7 @@ #define R 10 -static const php_hash_uint64 rc[R + 1] = { +static const uint64_t rc[R + 1] = { L64(0x0000000000000000), L64(0x1823c6e887b8014f), L64(0x36a6d2f5796f9152), @@ -37,7 +37,7 @@ static const php_hash_uint64 rc[R + 1] = { L64(0xca2dbf07ad5a8333), }; -static const php_hash_uint64 C0[256] = { +static const uint64_t C0[256] = { L64(0x18186018c07830d8), L64(0x23238c2305af4626), L64(0xc6c63fc67ef991b8), L64(0xe8e887e8136fcdfb), L64(0x878726874ca113cb), L64(0xb8b8dab8a9626d11), L64(0x0101040108050209), L64(0x4f4f214f426e9e0d), L64(0x3636d836adee6c9b), L64(0xa6a6a2a6590451ff), L64(0xd2d26fd2debdb90c), L64(0xf5f5f3f5fb06f70e), @@ -104,7 +104,7 @@ static const php_hash_uint64 C0[256] = { L64(0x2828a0285d885075), L64(0x5c5c6d5cda31b886), L64(0xf8f8c7f8933fed6b), L64(0x8686228644a411c2), }; -static const php_hash_uint64 C1[256] = { +static const uint64_t C1[256] = { L64(0xd818186018c07830), L64(0x2623238c2305af46), L64(0xb8c6c63fc67ef991), L64(0xfbe8e887e8136fcd), L64(0xcb878726874ca113), L64(0x11b8b8dab8a9626d), L64(0x0901010401080502), L64(0x0d4f4f214f426e9e), L64(0x9b3636d836adee6c), L64(0xffa6a6a2a6590451), L64(0x0cd2d26fd2debdb9), L64(0x0ef5f5f3f5fb06f7), @@ -171,7 +171,7 @@ static const php_hash_uint64 C1[256] = { L64(0x752828a0285d8850), L64(0x865c5c6d5cda31b8), L64(0x6bf8f8c7f8933fed), L64(0xc28686228644a411), }; -static const php_hash_uint64 C2[256] = { +static const uint64_t C2[256] = { L64(0x30d818186018c078), L64(0x462623238c2305af), L64(0x91b8c6c63fc67ef9), L64(0xcdfbe8e887e8136f), L64(0x13cb878726874ca1), L64(0x6d11b8b8dab8a962), L64(0x0209010104010805), L64(0x9e0d4f4f214f426e), L64(0x6c9b3636d836adee), L64(0x51ffa6a6a2a65904), L64(0xb90cd2d26fd2debd), L64(0xf70ef5f5f3f5fb06), @@ -238,7 +238,7 @@ static const php_hash_uint64 C2[256] = { L64(0x50752828a0285d88), L64(0xb8865c5c6d5cda31), L64(0xed6bf8f8c7f8933f), L64(0x11c28686228644a4), }; -static const php_hash_uint64 C3[256] = { +static const uint64_t C3[256] = { L64(0x7830d818186018c0), L64(0xaf462623238c2305), L64(0xf991b8c6c63fc67e), L64(0x6fcdfbe8e887e813), L64(0xa113cb878726874c), L64(0x626d11b8b8dab8a9), L64(0x0502090101040108), L64(0x6e9e0d4f4f214f42), L64(0xee6c9b3636d836ad), L64(0x0451ffa6a6a2a659), L64(0xbdb90cd2d26fd2de), L64(0x06f70ef5f5f3f5fb), @@ -305,7 +305,7 @@ static const php_hash_uint64 C3[256] = { L64(0x8850752828a0285d), L64(0x31b8865c5c6d5cda), L64(0x3fed6bf8f8c7f893), L64(0xa411c28686228644), }; -static const php_hash_uint64 C4[256] = { +static const uint64_t C4[256] = { L64(0xc07830d818186018), L64(0x05af462623238c23), L64(0x7ef991b8c6c63fc6), L64(0x136fcdfbe8e887e8), L64(0x4ca113cb87872687), L64(0xa9626d11b8b8dab8), L64(0x0805020901010401), L64(0x426e9e0d4f4f214f), L64(0xadee6c9b3636d836), L64(0x590451ffa6a6a2a6), L64(0xdebdb90cd2d26fd2), L64(0xfb06f70ef5f5f3f5), @@ -372,7 +372,7 @@ static const php_hash_uint64 C4[256] = { L64(0x5d8850752828a028), L64(0xda31b8865c5c6d5c), L64(0x933fed6bf8f8c7f8), L64(0x44a411c286862286), }; -static const php_hash_uint64 C5[256] = { +static const uint64_t C5[256] = { L64(0x18c07830d8181860), L64(0x2305af462623238c), L64(0xc67ef991b8c6c63f), L64(0xe8136fcdfbe8e887), L64(0x874ca113cb878726), L64(0xb8a9626d11b8b8da), L64(0x0108050209010104), L64(0x4f426e9e0d4f4f21), L64(0x36adee6c9b3636d8), L64(0xa6590451ffa6a6a2), L64(0xd2debdb90cd2d26f), L64(0xf5fb06f70ef5f5f3), @@ -439,7 +439,7 @@ static const php_hash_uint64 C5[256] = { L64(0x285d8850752828a0), L64(0x5cda31b8865c5c6d), L64(0xf8933fed6bf8f8c7), L64(0x8644a411c2868622), }; -static const php_hash_uint64 C6[256] = { +static const uint64_t C6[256] = { L64(0x6018c07830d81818), L64(0x8c2305af46262323), L64(0x3fc67ef991b8c6c6), L64(0x87e8136fcdfbe8e8), L64(0x26874ca113cb8787), L64(0xdab8a9626d11b8b8), L64(0x0401080502090101), L64(0x214f426e9e0d4f4f), L64(0xd836adee6c9b3636), L64(0xa2a6590451ffa6a6), L64(0x6fd2debdb90cd2d2), L64(0xf3f5fb06f70ef5f5), @@ -506,7 +506,7 @@ static const php_hash_uint64 C6[256] = { L64(0xa0285d8850752828), L64(0x6d5cda31b8865c5c), L64(0xc7f8933fed6bf8f8), L64(0x228644a411c28686), }; -static const php_hash_uint64 C7[256] = { +static const uint64_t C7[256] = { L64(0x186018c07830d818), L64(0x238c2305af462623), L64(0xc63fc67ef991b8c6), L64(0xe887e8136fcdfbe8), L64(0x8726874ca113cb87), L64(0xb8dab8a9626d11b8), L64(0x0104010805020901), L64(0x4f214f426e9e0d4f), L64(0x36d836adee6c9b36), L64(0xa6a2a6590451ffa6), L64(0xd26fd2debdb90cd2), L64(0xf5f3f5fb06f70ef5), diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c index 309258b4c7..4dd6784209 100644 --- a/ext/iconv/iconv.c +++ b/ext/iconv/iconv.c @@ -424,9 +424,9 @@ static int php_iconv_output_handler(void **nothing, php_output_context *output_c char *p = strstr(get_output_encoding(), "//"); if (p) { - len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%.*s", mimetype_len ? mimetype_len : (size_t) strlen(mimetype), mimetype, (size_t)(p - get_output_encoding()), get_output_encoding()); + 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()); } else { - len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%s", mimetype_len ? mimetype_len : (size_t) strlen(mimetype), mimetype, get_output_encoding()); + len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%s", mimetype_len ? mimetype_len : (int) strlen(mimetype), mimetype, get_output_encoding()); } if (content_type && SUCCESS == sapi_add_header(content_type, (uint)len, 0)) { SG(sapi_headers).send_default_content_type = 0; diff --git a/ext/interbase/config.m4 b/ext/interbase/config.m4 index 4f694caeab..ace3047e65 100644 --- a/ext/interbase/config.m4 +++ b/ext/interbase/config.m4 @@ -37,6 +37,6 @@ if test "$PHP_INTERBASE" != "no"; then PHP_ADD_LIBRARY_WITH_PATH($IBASE_LIBNAME, $IBASE_LIBDIR, INTERBASE_SHARED_LIBADD) PHP_ADD_INCLUDE($IBASE_INCDIR) AC_DEFINE(HAVE_IBASE,1,[ ]) - PHP_NEW_EXTENSION(interbase, interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c, $ext_shared) + PHP_NEW_EXTENSION(interbase, interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c, $ext_shared,, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1) PHP_SUBST(INTERBASE_SHARED_LIBADD) fi diff --git a/ext/interbase/config.w32 b/ext/interbase/config.w32 index 89cd67219c..9891fae442 100644 --- a/ext/interbase/config.w32 +++ b/ext/interbase/config.w32 @@ -9,7 +9,7 @@ if (PHP_INTERBASE != "no") { (CHECK_LIB("fbclient_ms.lib", "interbase", PHP_PHP_BUILD + "\\interbase\\lib_ms;" + PHP_INTERBASE) || CHECK_LIB("gds32_ms.lib", "interbase", PHP_PHP_BUILD + "\\interbase\\lib_ms;" + PHP_INTERBASE))) { - EXTENSION("interbase", "interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c"); + EXTENSION("interbase", "interbase.c ibase_query.c ibase_service.c ibase_events.c ibase_blobs.c", PHP_INTERBASE_SHARED, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1"); AC_DEFINE('HAVE_IBASE', 1, 'Have interbase library'); } else { WARNING("interbase not enabled; libraries and headers not found"); diff --git a/ext/interbase/ibase_blobs.c b/ext/interbase/ibase_blobs.c index 630b7330e9..70640236c3 100644 --- a/ext/interbase/ibase_blobs.c +++ b/ext/interbase/ibase_blobs.c @@ -36,7 +36,7 @@ static void _php_ibase_free_blob(zend_resource *rsrc) /* {{{ */ { ibase_blob *ib_blob = (ibase_blob *)rsrc->ptr; - if (ib_blob->bl_handle != NULL) { /* blob open*/ + if (ib_blob->bl_handle != 0) { /* blob open*/ if (isc_cancel_blob(IB_STATUS, &ib_blob->bl_handle)) { _php_ibase_module_error("You can lose data. Close any blob after reading from or " "writing to it. Use ibase_blob_close() before calling ibase_close()"); @@ -90,13 +90,13 @@ typedef struct { /* {{{ */ /* }}} */ } IBASE_BLOBINFO; -int _php_ibase_blob_get(zval *return_value, ibase_blob *ib_blob, unsigned long max_len) /* {{{ */ +int _php_ibase_blob_get(zval *return_value, ibase_blob *ib_blob, zend_ulong max_len) /* {{{ */ { if (ib_blob->bl_qd.gds_quad_high || ib_blob->bl_qd.gds_quad_low) { /*not null ?*/ ISC_STATUS stat; zend_string *bl_data; - unsigned long cur_len; + zend_ulong cur_len; unsigned short seg_len; bl_data = zend_string_alloc(max_len, 0); @@ -126,7 +126,7 @@ int _php_ibase_blob_get(zval *return_value, ibase_blob *ib_blob, unsigned long m int _php_ibase_blob_add(zval *string_arg, ibase_blob *ib_blob) /* {{{ */ { - unsigned long put_cnt = 0, rem_cnt; + zend_ulong put_cnt = 0, rem_cnt; unsigned short chunk_size; convert_to_string_ex(string_arg); @@ -154,7 +154,7 @@ static int _php_ibase_blob_info(isc_blob_handle bl_handle, IBASE_BLOBINFO *bl_in isc_info_blob_type }; - char bl_inf[sizeof(long)*8], *p; + char bl_inf[sizeof(zend_long)*8], *p; bl_info->max_segment = 0; bl_info->num_segments = 0; @@ -216,7 +216,7 @@ PHP_FUNCTION(ibase_blob_create) PHP_IBASE_LINK_TRANS(link, ib_link, trans); ib_blob = (ibase_blob *) emalloc(sizeof(ibase_blob)); - ib_blob->bl_handle = NULL; + ib_blob->bl_handle = 0; ib_blob->type = BLOB_INPUT; if (isc_create_blob(IB_STATUS, &ib_link->handle, &trans->handle, &ib_blob->bl_handle, &ib_blob->bl_qd)) { @@ -261,7 +261,7 @@ PHP_FUNCTION(ibase_blob_open) PHP_IBASE_LINK_TRANS(link, ib_link, trans); ib_blob = (ibase_blob *) emalloc(sizeof(ibase_blob)); - ib_blob->bl_handle = NULL; + ib_blob->bl_handle = 0; ib_blob->type = BLOB_OUTPUT; do { @@ -361,7 +361,7 @@ static void _php_ibase_blob_end(INTERNAL_FUNCTION_PARAMETERS, int bl_end) /* {{{ RETURN_FALSE; } } - ib_blob->bl_handle = NULL; + ib_blob->bl_handle = 0; RETVAL_NEW_STR(_php_ibase_quad_to_string(ib_blob->bl_qd)); } else { /* discard created blob */ @@ -369,7 +369,7 @@ static void _php_ibase_blob_end(INTERNAL_FUNCTION_PARAMETERS, int bl_end) /* {{{ _php_ibase_error(); RETURN_FALSE; } - ib_blob->bl_handle = NULL; + ib_blob->bl_handle = 0; RETVAL_TRUE; } zend_list_delete(Z_RES_P(blob_arg)); @@ -401,7 +401,7 @@ PHP_FUNCTION(ibase_blob_info) zval *link = NULL; ibase_db_link *ib_link; ibase_trans *trans = NULL; - ibase_blob ib_blob = { NULL, BLOB_INPUT }; + ibase_blob ib_blob = { 0, BLOB_INPUT }; IBASE_BLOBINFO bl_info; RESET_ERRMSG; @@ -477,7 +477,7 @@ PHP_FUNCTION(ibase_blob_echo) zval *link = NULL; ibase_db_link *ib_link; ibase_trans *trans = NULL; - ibase_blob ib_blob_id = { NULL, BLOB_OUTPUT }; + ibase_blob ib_blob_id = { 0, BLOB_OUTPUT }; char bl_data[IBASE_BLOB_SEG]; unsigned short seg_len; @@ -538,7 +538,7 @@ PHP_FUNCTION(ibase_blob_import) zval *link = NULL, *file; int size; unsigned short b; - ibase_blob ib_blob = { NULL, 0 }; + ibase_blob ib_blob = { 0, 0 }; ibase_db_link *ib_link; ibase_trans *trans = NULL; char bl_data[IBASE_BLOB_SEG]; diff --git a/ext/interbase/ibase_events.c b/ext/interbase/ibase_events.c index bac2450d81..e748c643af 100644 --- a/ext/interbase/ibase_events.c +++ b/ext/interbase/ibase_events.c @@ -45,7 +45,8 @@ void _php_ibase_free_event(ibase_event *event) /* {{{ */ if (event->link != NULL) { ibase_event **node; - if (event->link->handle != NULL && + zend_list_delete(event->link_res); + if (event->link->handle != 0 && isc_cancel_events(IB_STATUS, &event->link->handle, &event->event_id)) { _php_ibase_error(); } @@ -62,7 +63,9 @@ void _php_ibase_free_event(ibase_event *event) /* {{{ */ _php_ibase_event_free(event->event_buffer,event->result_buffer); for (i = 0; i < event->event_count; ++i) { - efree(event->events[i]); + if (event->events[i]) { + efree(event->events[i]); + } } efree(event->events); } @@ -90,7 +93,7 @@ static void _php_ibase_event_block(ibase_db_link *ib_link, unsigned short count, char **events, unsigned short *l, char **event_buf, char **result_buf) { ISC_STATUS dummy_result[20]; - unsigned long dummy_count[15]; + ISC_ULONG dummy_count[15]; /** * Unfortunately, there's no clean and portable way in C to pass arguments to @@ -128,7 +131,7 @@ PHP_FUNCTION(ibase_wait_event) int num_args; char *event_buffer, *result_buffer, *events[15]; unsigned short i = 0, event_count = 0, buffer_size; - unsigned long occurred_event[15]; + ISC_ULONG occurred_event[15]; RESET_ERRMSG; @@ -150,7 +153,7 @@ PHP_FUNCTION(ibase_wait_event) if (ZEND_NUM_ARGS() > 15) { WRONG_PARAM_COUNT; } - if ((ib_link = (ibase_db_link *)zend_fetch_resource2_ex(IBG(default_link), "InterBase link", le_link, le_plink)) == NULL) { + if ((ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), "InterBase link", le_link, le_plink)) == NULL) { RETURN_FALSE; } } @@ -187,11 +190,16 @@ PHP_FUNCTION(ibase_wait_event) } /* }}} */ -static isc_callback _php_ibase_callback(ibase_event *event, /* {{{ */ +#if FB_API_VER >= 20 +#define PHP_ISC_CALLBACK ISC_EVENT_CALLBACK +static ISC_EVENT_CALLBACK _php_ibase_callback(ibase_event *event, /* {{{ */ + ISC_USHORT buffer_size, ISC_UCHAR *result_buf) +#else +#define PHP_ISC_CALLBACK isc_callback +static isc_callback _php_ibase_callback(ibase_event *event, /* {{{ */ unsigned short buffer_size, char *result_buf) +#endif { - zval *res; - /* this function is called asynchronously by the Interbase client library. */ TSRMLS_FETCH_FROM_CTX(event->thread_ctx); @@ -202,7 +210,7 @@ static isc_callback _php_ibase_callback(ibase_event *event, /* {{{ */ */ switch (event->state) { unsigned short i; - unsigned long occurred_event[15]; + ISC_ULONG occurred_event[15]; zval return_value, args[2]; default: /* == DEAD */ @@ -211,15 +219,14 @@ static isc_callback _php_ibase_callback(ibase_event *event, /* {{{ */ /* copy the updated results into the result buffer */ memcpy(event->result_buffer, result_buf, buffer_size); - res = zend_hash_index_find(&EG(regular_list), event->link_res_id); - ZVAL_RES(&args[1], Z_RES_P(res)); + ZVAL_RES(&args[1], event->link_res); /* find out which event occurred */ isc_event_counts(occurred_event, buffer_size, event->event_buffer, event->result_buffer); for (i = 0; i < event->event_count; ++i) { if (occurred_event[i]) { ZVAL_STRING(&args[0], event->events[i]); - efree(event->events[i]); + //efree(event->events[i]); break; } } @@ -238,7 +245,7 @@ static isc_callback _php_ibase_callback(ibase_event *event, /* {{{ */ case NEW: /* re-register the event */ if (isc_que_events(IB_STATUS, &event->link->handle, &event->event_id, buffer_size, - event->event_buffer,(isc_callback)_php_ibase_callback, (void *)event)) { + event->event_buffer,(PHP_ISC_CALLBACK)_php_ibase_callback, (void *)event)) { _php_ibase_error(); } @@ -262,7 +269,8 @@ PHP_FUNCTION(ibase_set_event_handler) ibase_db_link *ib_link; ibase_event *event; unsigned short i = 1, buffer_size; - int link_res_id, num_args; + int num_args; + zend_resource *link_res; RESET_ERRMSG; @@ -291,8 +299,7 @@ PHP_FUNCTION(ibase_set_event_handler) RETURN_FALSE; } - convert_to_long_ex(&args[0]); - link_res_id = Z_LVAL(args[0]); + link_res = Z_RES(args[0]); } else { /* callback, event_1 [, ... event_15] @@ -304,10 +311,10 @@ PHP_FUNCTION(ibase_set_event_handler) cb_arg = &args[0]; - if ((ib_link = (ibase_db_link *)zend_fetch_resource2_ex(IBG(default_link), "InterBase link", le_link, le_plink)) == NULL) { + if ((ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), "InterBase link", le_link, le_plink)) == NULL) { RETURN_FALSE; } - link_res_id = IBG(default_link); + link_res = IBG(default_link); } /* get the callback */ @@ -321,17 +328,22 @@ PHP_FUNCTION(ibase_set_event_handler) /* allocate the event resource */ event = (ibase_event *) safe_emalloc(sizeof(ibase_event), 1, 0); TSRMLS_SET_CTX(event->thread_ctx); - event->link_res_id = link_res_id; + event->link_res = link_res; + GC_REFCOUNT(link_res)++; event->link = ib_link; event->event_count = 0; event->state = NEW; - event->events = (char **) safe_emalloc(sizeof(char *),ZEND_NUM_ARGS()-i,0); + event->events = (char **) safe_emalloc(sizeof(char *), 15, 0); ZVAL_DUP(&event->callback, cb_arg); - for (; i < ZEND_NUM_ARGS(); ++i) { - convert_to_string_ex(&args[i]); - event->events[event->event_count++] = estrdup(Z_STRVAL(args[i])); + for (; i < 15; ++i) { + if (i < ZEND_NUM_ARGS()) { + convert_to_string_ex(&args[i]); + event->events[event->event_count++] = estrdup(Z_STRVAL(args[i])); + } else { + event->events[i] = NULL; + } } /* fills the required data structure with information about the events */ @@ -340,7 +352,7 @@ PHP_FUNCTION(ibase_set_event_handler) /* now register the events with the Interbase API */ if (isc_que_events(IB_STATUS, &ib_link->handle, &event->event_id, buffer_size, - event->event_buffer,(isc_callback)_php_ibase_callback, (void *)event)) { + event->event_buffer,(PHP_ISC_CALLBACK)_php_ibase_callback, (void *)event)) { _php_ibase_error(); efree(event); diff --git a/ext/interbase/ibase_query.c b/ext/interbase/ibase_query.c index eaf06ed86c..37e59dd3a7 100644 --- a/ext/interbase/ibase_query.c +++ b/ext/interbase/ibase_query.c @@ -59,7 +59,7 @@ typedef struct _ib_query { ibase_db_link *link; ibase_trans *trans; ibase_result *result; - int result_res_id; + zend_resource *result_res; isc_stmt_handle stmt; XSQLDA *in_sqlda, *out_sqlda; ibase_array *in_array, *out_array; @@ -67,7 +67,7 @@ typedef struct _ib_query { unsigned short dialect; char statement_type; char *query; - long trans_res_id; + zend_resource *trans_res; } ibase_query; typedef struct { @@ -219,7 +219,7 @@ static int _php_ibase_alloc_array(ibase_array **ib_arrayp, XSQLDA *sqlda, /* {{{ for (i = n = 0; i < sqlda->sqld; ++i) { unsigned short dim; - unsigned long ar_size = 1; + zend_ulong ar_size = 1; XSQLVAR *var = &sqlda->sqlvar[i]; if ((var->sqltype & ~1) == SQL_ARRAY) { @@ -313,7 +313,7 @@ static int _php_ibase_alloc_array(ibase_array **ib_arrayp, XSQLDA *sqlda, /* {{{ /* allocate and prepare query */ static int _php_ibase_alloc_query(ibase_query *ib_query, ibase_db_link *link, /* {{{ */ - ibase_trans *trans, char *query, unsigned short dialect, int trans_res_id) + ibase_trans *trans, char *query, unsigned short dialect, zend_resource *trans_res) { static char info_type[] = {isc_info_sql_stmt_type}; char result[8]; @@ -326,14 +326,14 @@ static int _php_ibase_alloc_query(ibase_query *ib_query, ibase_db_link *link, /* ib_query->link = link; ib_query->trans = trans; - ib_query->result_res_id = 0; + ib_query->result_res = NULL; ib_query->result = NULL; - ib_query->stmt = NULL; + ib_query->stmt = 0; ib_query->in_array = NULL; ib_query->out_array = NULL; ib_query->dialect = dialect; ib_query->query = estrdup(query); - ib_query->trans_res_id = trans_res_id; + ib_query->trans_res = trans_res; ib_query->out_sqlda = NULL; ib_query->in_sqlda = NULL; @@ -430,7 +430,7 @@ _php_ibase_alloc_query_error: } /* }}} */ -static int _php_ibase_bind_array(zval *val, char *buf, unsigned long buf_size, /* {{{ */ +static int _php_ibase_bind_array(zval *val, char *buf, zend_ulong buf_size, /* {{{ */ ibase_array *array, int dim) { zval null_val, *pnull_val = &null_val; @@ -441,7 +441,7 @@ static int _php_ibase_bind_array(zval *val, char *buf, unsigned long buf_size, / ZVAL_NULL(pnull_val); if (dim < array->ar_desc.array_desc_dimensions) { - unsigned long slice_size = buf_size / dim_len; + zend_ulong slice_size = buf_size / dim_len; unsigned short i; zval *subval = val; @@ -530,8 +530,12 @@ static int _php_ibase_bind_array(zval *val, char *buf, unsigned long buf_size, / struct tm t = { 0, 0, 0, 0, 0, 0 }; switch (array->el_type) { +#ifndef HAVE_STRPTIME unsigned short n; +#endif +#if (SIZEOF_ZEND_LONG < 8) ISC_INT64 l; +#endif case SQL_SHORT: convert_to_long(val); @@ -543,7 +547,7 @@ static int _php_ibase_bind_array(zval *val, char *buf, unsigned long buf_size, / break; case SQL_LONG: convert_to_long(val); -#if (SIZEOF_LONG > 4) +#if (SIZEOF_ZEND_LONG > 4) if (Z_LVAL_P(val) > ISC_LONG_MAX || Z_LVAL_P(val) < ISC_LONG_MIN) { _php_ibase_module_error("Array parameter exceeds field width"); return FAILURE; @@ -552,9 +556,9 @@ static int _php_ibase_bind_array(zval *val, char *buf, unsigned long buf_size, / *(ISC_LONG *) buf = (ISC_LONG) Z_LVAL_P(val); break; case SQL_INT64: -#if (SIZEOF_LONG >= 8) +#if (SIZEOF_ZEND_LONG >= 8) convert_to_long(val); - *(long *) buf = Z_LVAL_P(val); + *(zend_long *) buf = Z_LVAL_P(val); #else convert_to_string(val); if (!sscanf(Z_STRVAL_P(val), "%" LL_MASK "d", &l)) { @@ -737,7 +741,7 @@ static int _php_ibase_bind(XSQLDA *sqlda, zval *b_vars, BIND_BUF *buf, /* {{{ */ if (Z_STRLEN_P(b_var) != BLOB_ID_LEN || !_php_ibase_string_to_quad(Z_STRVAL_P(b_var), &buf[i].val.qval)) { - ibase_blob ib_blob = { NULL, BLOB_INPUT }; + ibase_blob ib_blob = { 0, BLOB_INPUT }; if (isc_create_blob(IB_STATUS, &ib_query->link->handle, &ib_query->trans->handle, &ib_blob.bl_handle, &ib_blob.bl_qd)) { @@ -883,7 +887,7 @@ static int _php_ibase_exec(INTERNAL_FUNCTION_PARAMETERS, ibase_result **ib_resul case isc_info_sql_stmt_start_trans: /* a SET TRANSACTION statement should be executed with a NULL trans handle */ - tr = NULL; + tr = 0; if (isc_dsql_execute_immediate(IB_STATUS, &ib_query->link->handle, &tr, 0, ib_query->query, ib_query->dialect, NULL)) { @@ -923,11 +927,11 @@ static int _php_ibase_exec(INTERNAL_FUNCTION_PARAMETERS, ibase_result **ib_resul goto _php_ibase_exec_error; } - if (ib_query->trans->handle == NULL && ib_query->trans_res_id != 0) { + if (ib_query->trans->handle == 0 && ib_query->trans_res != NULL) { /* transaction was released by the query and was a registered resource, so we have to release it */ - zval *res = zend_hash_index_find(&EG(regular_list), ib_query->trans_res_id); - zend_list_delete(Z_RES_P(res)); + zend_list_delete(ib_query->trans_res); + ib_query->trans_res = NULL; } RETVAL_TRUE; @@ -1063,7 +1067,7 @@ PHP_FUNCTION(ibase_query) char *query; size_t query_len; int bind_i, bind_num; - long trans_res_id = 0; + zend_resource *trans_res = NULL; ibase_db_link *ib_link = NULL; ibase_trans *trans = NULL; ibase_query ib_query = { NULL, NULL, 0, 0 }; @@ -1083,7 +1087,7 @@ PHP_FUNCTION(ibase_query) ib_link = (ibase_db_link*)zend_fetch_resource2_ex(zlink, LE_LINK, le_link, le_plink); trans = (ibase_trans*)zend_fetch_resource_ex(ztrans, LE_TRANS, le_trans); - trans_res_id = Z_RES_P(ztrans)->handle; + trans_res = Z_RES_P(ztrans); bind_i = 3; break; } @@ -1093,7 +1097,7 @@ PHP_FUNCTION(ibase_query) _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, zlink, &ib_link, &trans); if (trans != NULL) { - trans_res_id = Z_RES_P(zlink)->handle; + trans_res = Z_RES_P(zlink); } bind_i = 2; break; @@ -1102,8 +1106,8 @@ PHP_FUNCTION(ibase_query) /* the statement is 'CREATE DATABASE ...' if the link argument is IBASE_CREATE */ if (SUCCESS == zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "ls", &l, &query, &query_len) && l == PHP_IBASE_CREATE) { - isc_db_handle db = NULL; - isc_tr_handle trans = NULL; + isc_db_handle db = 0; + isc_tr_handle trans = 0; if (PG(sql_safe_mode)) { _php_ibase_module_error("CREATE DATABASE is not allowed in SQL safe mode" @@ -1111,7 +1115,7 @@ PHP_FUNCTION(ibase_query) } else if (((l = INI_INT("ibase.max_links")) != -1) && (IBG(num_links) >= l)) { _php_ibase_module_error("CREATE DATABASE is not allowed: maximum link count " - "(%ld) reached", l); + "(" ZEND_LONG_FMT ") reached", l); } else if (isc_dsql_execute_immediate(IB_STATUS, &db, &trans, (short)query_len, query, SQL_DIALECT_CURRENT, NULL)) { @@ -1133,8 +1137,8 @@ PHP_FUNCTION(ibase_query) RETVAL_RES(zend_register_resource(ib_link, le_link)); Z_TRY_ADDREF_P(return_value); - IBG(default_link) = Z_RES_P(return_value)->handle; - ++IBG(num_links); + Z_TRY_ADDREF_P(return_value); + IBG(default_link) = Z_RES_P(return_value); } return; } @@ -1142,8 +1146,7 @@ PHP_FUNCTION(ibase_query) case 0: if (SUCCESS == zend_parse_parameters(ZEND_NUM_ARGS() ? 1 : 0, "s", &query, &query_len)) { - ib_link = (ibase_db_link *)zend_fetch_resource2_ex(IBG(default_link), LE_LINK, - le_link, le_plink); + ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink); bind_i = 1; break; @@ -1153,8 +1156,7 @@ PHP_FUNCTION(ibase_query) /* open default transaction */ if (ib_link == NULL || FAILURE == _php_ibase_def_trans(ib_link, &trans) - || FAILURE == _php_ibase_alloc_query(&ib_query, ib_link, trans, query, ib_link->dialect, - trans_res_id)) { + || FAILURE == _php_ibase_alloc_query(&ib_query, ib_link, trans, query, ib_link->dialect, trans_res)) { return; } @@ -1184,7 +1186,7 @@ PHP_FUNCTION(ibase_query) /* EXECUTE PROCEDURE returns only one row => statement can be released immediately */ if (ib_query.statement_type != isc_info_sql_stmt_exec_procedure) { - ib_query.stmt = NULL; /* keep stmt when free query */ + ib_query.stmt = 0; /* keep stmt when free query */ } RETVAL_RES(zend_register_resource(result, le_result)); Z_TRY_ADDREF_P(return_value); @@ -1211,7 +1213,7 @@ PHP_FUNCTION(ibase_affected_rows) } if (!arg) { - ib_link = (ibase_db_link *)zend_fetch_resource2_ex(IBG(default_link), LE_LINK, le_link, le_plink); + ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink); if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) { RETURN_FALSE; } @@ -1313,7 +1315,7 @@ static int _php_ibase_var_zval(zval *val, void *data, int type, int len, /* {{{ switch (type & ~1) { unsigned short l; - long n; + zend_long n; char string_data[255]; struct tm t; char *format; @@ -1329,8 +1331,8 @@ static int _php_ibase_var_zval(zval *val, void *data, int type, int len, /* {{{ n = *(short *) data; goto _sql_long; case SQL_INT64: -#if (SIZEOF_LONG >= 8) - n = *(long *) data; +#if (SIZEOF_ZEND_LONG >= 8) + n = *(zend_long *) data; goto _sql_long; #else if (scale == 0) { @@ -1356,14 +1358,14 @@ static int _php_ibase_var_zval(zval *val, void *data, int type, int len, /* {{{ if (scale == 0) { ZVAL_LONG(val,n); } else { - long f = (long) scales[-scale]; + zend_long f = (zend_long) scales[-scale]; if (n >= 0) { - l = slprintf(string_data, sizeof(string_data), "%ld.%0*ld", n / f, -scale, n % f); + l = slprintf(string_data, sizeof(string_data), ZEND_LONG_FMT ".%0*" ZEND_LONG_FMT_SPEC, n / f, -scale, n % f); } else if (n <= -f) { - l = slprintf(string_data, sizeof(string_data), "%ld.%0*ld", n / f, -scale, -n % f); + l = slprintf(string_data, sizeof(string_data), ZEND_LONG_FMT ".%0*" ZEND_LONG_FMT_SPEC, n / f, -scale, -n % f); } else { - l = slprintf(string_data, sizeof(string_data), "-0.%0*ld", -scale, -n % f); + l = slprintf(string_data, sizeof(string_data), "-0.%0*" ZEND_LONG_FMT_SPEC, -scale, -n % f); } ZVAL_STRINGL(val, string_data, l); } @@ -1422,7 +1424,7 @@ format_date_time: } /* }}} */ -static int _php_ibase_arr_zval(zval *ar_zval, char *data, unsigned long data_size, /* {{{ */ +static int _php_ibase_arr_zval(zval *ar_zval, char *data, zend_ulong data_size, /* {{{ */ ibase_array *ib_array, int dim, int flag) { /** @@ -1435,7 +1437,7 @@ static int _php_ibase_arr_zval(zval *ar_zval, char *data, unsigned long data_siz unsigned short i; if (dim < ib_array->ar_desc.array_desc_dimensions) { /* array again */ - unsigned long slice_size = data_size / dim_len; + zend_ulong slice_size = data_size / dim_len; array_init(ar_zval); @@ -1474,7 +1476,7 @@ static void _php_ibase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int fetch_type) { zval *result_arg; zend_long flag = 0; - long i, array_cnt = 0; + zend_long i, array_cnt = 0; ibase_result *ib_result; RESET_ERRMSG; @@ -1544,12 +1546,12 @@ static void _php_ibase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int fetch_type) if (flag & PHP_IBASE_FETCH_BLOBS) { /* fetch blob contents into hash */ ibase_blob blob_handle; - unsigned long max_len = 0; + zend_ulong max_len = 0; static char bl_items[] = {isc_info_blob_total_length}; char bl_info[20]; unsigned short i; - blob_handle.bl_handle = NULL; + blob_handle.bl_handle = 0; blob_handle.bl_qd = *(ISC_QUAD *) var->sqldata; if (isc_open_blob(IB_STATUS, &ib_result->link->handle, &ib_result->trans->handle, @@ -1599,7 +1601,6 @@ static void _php_ibase_fetch_hash(INTERNAL_FUNCTION_PARAMETERS, int fetch_type) } } else { /* blob id only */ - char *s; ISC_QUAD bl_qd = *(ISC_QUAD *) var->sqldata; ZVAL_NEW_STR(&result, _php_ibase_quad_to_string(bl_qd)); } @@ -1732,7 +1733,8 @@ PHP_FUNCTION(ibase_prepare) zval *link_arg, *trans_arg; ibase_db_link *ib_link; ibase_trans *trans = NULL; - size_t query_len, trans_res_id = 0; + size_t query_len; + zend_resource *trans_res = NULL; ibase_query *ib_query; char *query; @@ -1742,7 +1744,7 @@ PHP_FUNCTION(ibase_prepare) if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &query, &query_len) == FAILURE) { return; } - ib_link = (ibase_db_link *)zend_fetch_resource2_ex(IBG(default_link), LE_LINK, le_link, le_plink); + ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink); } else if (ZEND_NUM_ARGS() == 2) { if (zend_parse_parameters(ZEND_NUM_ARGS(), "rs", &link_arg, &query, &query_len) == FAILURE) { return; @@ -1750,7 +1752,7 @@ PHP_FUNCTION(ibase_prepare) _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, link_arg, &ib_link, &trans); if (trans != NULL) { - trans_res_id = Z_RES_P(link_arg)->handle; + trans_res = Z_RES_P(link_arg); } } else { if (zend_parse_parameters(ZEND_NUM_ARGS(), "rrs", &link_arg, &trans_arg, &query, &query_len) == FAILURE) { @@ -1758,7 +1760,7 @@ PHP_FUNCTION(ibase_prepare) } ib_link = (ibase_db_link *)zend_fetch_resource2_ex(link_arg, LE_LINK, le_link, le_plink); trans = (ibase_trans *)zend_fetch_resource_ex(trans_arg, LE_TRANS, le_trans); - trans_res_id = Z_RES_P(trans_arg)->handle; + trans_res = Z_RES_P(trans_arg); } if (FAILURE == _php_ibase_def_trans(ib_link, &trans)) { @@ -1767,7 +1769,7 @@ PHP_FUNCTION(ibase_prepare) ib_query = (ibase_query *) emalloc(sizeof(ibase_query)); - if (FAILURE == _php_ibase_alloc_query(ib_query, ib_link, trans, query, ib_link->dialect, trans_res_id)) { + if (FAILURE == _php_ibase_alloc_query(ib_query, ib_link, trans, query, ib_link->dialect, trans_res)) { efree(ib_query); RETURN_FALSE; } @@ -1808,21 +1810,16 @@ PHP_FUNCTION(ibase_execute) } /* Have we used this cursor before and it's still open (exec proc has no cursor) ? */ - if (ib_query->result_res_id != 0 + if (ib_query->result_res != NULL && ib_query->statement_type != isc_info_sql_stmt_exec_procedure) { - zval *res; - IBDEBUG("Implicitly closing a cursor"); if (isc_dsql_free_statement(IB_STATUS, &ib_query->stmt, DSQL_close)) { _php_ibase_error(); break; } - /* invalidate previous results returned by this query (not necessary for exec proc) */ - res = zend_hash_index_find(&EG(regular_list), ib_query->result_res_id); - if (res) { - zend_list_delete(Z_RES_P(res)); - } + zend_list_delete(ib_query->result_res); + ib_query->result_res = NULL; } if (FAILURE == _php_ibase_exec(INTERNAL_FUNCTION_PARAM_PASSTHRU, &result, ib_query, @@ -1831,7 +1828,7 @@ PHP_FUNCTION(ibase_execute) } /* free the query if trans handle was released */ - if (ib_query->trans->handle == NULL) { + if (ib_query->trans->handle == 0) { zend_list_delete(Z_RES_P(query)); } @@ -1840,11 +1837,11 @@ PHP_FUNCTION(ibase_execute) result->type = EXECUTE_RESULT; if (ib_query->statement_type == isc_info_sql_stmt_exec_procedure) { - result->stmt = NULL; + result->stmt = 0; } ret = zend_list_insert(result, le_result); - ib_query->result_res_id = Z_RES_HANDLE_P(ret); + ib_query->result_res = Z_RES_P(ret); ZVAL_COPY_VALUE(return_value, ret); Z_TRY_ADDREF_P(return_value); Z_TRY_ADDREF_P(return_value); @@ -1867,6 +1864,10 @@ PHP_FUNCTION(ibase_free_query) } ib_query = (ibase_query *)zend_fetch_resource_ex(query_arg, LE_QUERY, le_query); + if (!ib_query) { + RETURN_FALSE; + } + zend_list_close(Z_RES_P(query_arg)); RETURN_TRUE; } diff --git a/ext/interbase/ibase_service.c b/ext/interbase/ibase_service.c index c1b1268cd0..3116ab9def 100644 --- a/ext/interbase/ibase_service.c +++ b/ext/interbase/ibase_service.c @@ -210,7 +210,7 @@ PHP_FUNCTION(ibase_service_attach) size_t hlen, ulen, plen, spb_len; ibase_service *svm; char buf[128], *host, *user, *pass, *loc; - isc_svc_handle handle = NULL; + isc_svc_handle handle = 0; RESET_ERRMSG; @@ -274,7 +274,7 @@ static void _php_ibase_service_query(INTERNAL_FUNCTION_PARAMETERS, /* {{{ */ static char spb[] = { isc_info_svc_timeout, 10, 0, 0, 0 }; char res_buf[400], *result, *heap_buf = NULL, *heap_p; - long heap_buf_size = 200, line_len; + zend_long heap_buf_size = 200, line_len; /* info about users requires an action first */ if (info_action == isc_info_svc_get_users) { @@ -312,7 +312,7 @@ query_loop: } } if (!heap_buf || (heap_p - heap_buf + line_len +2) > heap_buf_size) { - long res_size = heap_buf ? heap_p - heap_buf : 0; + zend_long res_size = heap_buf ? heap_p - heap_buf : 0; while (heap_buf_size < (res_size + line_len +2)) { heap_buf_size *= 2; @@ -520,7 +520,7 @@ static void _php_ibase_service_action(INTERNAL_FUNCTION_PARAMETERS, char svc_act switch (action) { default: unknown_option: - _php_ibase_module_error("Unrecognised option (%ld)", action); + _php_ibase_module_error("Unrecognised option (" ZEND_LONG_FMT ")", action); RETURN_FALSE; case isc_spb_rpr_check_db: diff --git a/ext/interbase/interbase.c b/ext/interbase/interbase.c index 1eece4c000..b4c253838e 100644 --- a/ext/interbase/interbase.c +++ b/ext/interbase/interbase.c @@ -41,7 +41,7 @@ #define COMMIT 1 #define RETAIN 2 -#define CHECK_LINK(link) { if (link==-1) { php_error_docref(NULL, E_WARNING, "A link to the server could not be established"); RETURN_FALSE; } } +#define CHECK_LINK(link) { if (link==NULL) { php_error_docref(NULL, E_WARNING, "A link to the server could not be established"); RETURN_FALSE; } } ZEND_DECLARE_MODULE_GLOBALS(ibase) static PHP_GINIT_FUNCTION(ibase); @@ -460,6 +460,9 @@ zend_module_entry ibase_module_entry = { }; #ifdef COMPILE_DL_INTERBASE +#ifdef ZTS +ZEND_TSRMLS_CACHE_DEFINE(); +#endif ZEND_GET_MODULE(ibase) #endif @@ -509,7 +512,7 @@ void _php_ibase_error(void) /* {{{ */ IBG(sql_code) = isc_sqlcode(IB_STATUS); - while ((s - IBG(errmsg)) < MAX_ERRMSG - (IBASE_MSGSIZE + 2) && fb_interpret(s, MAX_ERRMSG, &statusp)) { + while ((s - IBG(errmsg)) < MAX_ERRMSG && fb_interpret(s, MAX_ERRMSG - strlen(IBG(errmsg)) - 1, &statusp)) { strcat(IBG(errmsg), " "); s = IBG(errmsg) + strlen(IBG(errmsg)); } @@ -538,7 +541,7 @@ void _php_ibase_module_error(char *msg, ...) /* {{{ */ /* {{{ internal macros, functions and structures */ typedef struct { isc_db_handle *db_ptr; - long tpb_len; + zend_long tpb_len; char *tpb_ptr; } ISC_TEB; @@ -580,9 +583,9 @@ static void _php_ibase_commit_link(ibase_db_link *link) /* {{{ */ for (l = link->tr_list; l != NULL; ++i) { ibase_tr_list *p = l; - if (p->trans != NULL) { + if (p->trans != 0) { if (i == 0) { - if (p->trans->handle != NULL) { + if (p->trans->handle != 0) { IBDEBUG("Committing default transaction..."); if (isc_commit_transaction(IB_STATUS, &p->trans->handle)) { _php_ibase_error(); @@ -590,7 +593,7 @@ static void _php_ibase_commit_link(ibase_db_link *link) /* {{{ */ } efree(p->trans); /* default transaction is not a registered resource: clean up */ } else { - if (p->trans->handle != NULL) { + if (p->trans->handle != 0) { /* non-default trans might have been rolled back by other call of this dtor */ IBDEBUG("Rolling back other transactions..."); if (isc_rollback_transaction(IB_STATUS, &p->trans->handle)) { @@ -632,7 +635,7 @@ static void _php_ibase_close_link(zend_resource *rsrc) /* {{{ */ ibase_db_link *link = (ibase_db_link *) rsrc->ptr; _php_ibase_commit_link(link); - if (link->handle != NULL) { + if (link->handle != 0) { IBDEBUG("Closing normal link..."); isc_detach_database(IB_STATUS, &link->handle); } @@ -647,7 +650,7 @@ static void _php_ibase_close_plink(zend_resource *rsrc) /* {{{ */ _php_ibase_commit_link(link); IBDEBUG("Closing permanent link..."); - if (link->handle != NULL) { + if (link->handle != 0) { isc_detach_database(IB_STATUS, &link->handle); } IBG(num_persistent)--; @@ -662,7 +665,7 @@ static void _php_ibase_free_trans(zend_resource *rsrc) /* {{{ */ unsigned short i; IBDEBUG("Cleaning up transaction resource..."); - if (trans->handle != NULL) { + if (trans->handle != 0) { IBDEBUG("Rolling back unhandled transaction..."); if (isc_rollback_transaction(IB_STATUS, &trans->handle)) { _php_ibase_error(); @@ -717,9 +720,12 @@ PHP_INI_END() static PHP_GINIT_FUNCTION(ibase) { +#if defined(COMPILE_DL_INTERBASE) && defined(ZTS) + ZEND_TSRMLS_CACHE_UPDATE(); +#endif ibase_globals->num_persistent = ibase_globals->num_links = 0; ibase_globals->sql_code = *ibase_globals->errmsg = 0; - ibase_globals->default_link = -1; + ibase_globals->default_link = NULL; } PHP_MINIT_FUNCTION(ibase) @@ -774,7 +780,7 @@ PHP_MSHUTDOWN_FUNCTION(ibase) zend_module_entry *ibase_entry; if ((ibase_entry = zend_hash_str_find_ptr(&module_registry, ibase_module_entry.name, strlen(ibase_module_entry.name))) != NULL) { - ibase_entry->handle = NULL; + ibase_entry->handle = 0; } #endif UNREGISTER_INI_ENTRIES(); @@ -784,7 +790,7 @@ PHP_MSHUTDOWN_FUNCTION(ibase) PHP_RSHUTDOWN_FUNCTION(ibase) { IBG(num_links) = IBG(num_persistent); - IBG(default_link)= -1; + IBG(default_link)= NULL; RESET_ERRMSG; @@ -842,7 +848,7 @@ static char const dpb_args[] = { 0, isc_dpb_user_name, isc_dpb_password, isc_dpb_lc_ctype, isc_dpb_sql_role_name, 0 }; -int _php_ibase_attach_db(char **args, int *len, long *largs, isc_db_handle *db) +int _php_ibase_attach_db(char **args, int *len, zend_long *largs, isc_db_handle *db) /* {{{ */ { short i, dpb_len, buf_len = 257-2; /* version byte at the front, and a null at the end */ char dpb_buffer[257] = { isc_dpb_version1, 0 }, *dpb; @@ -879,10 +885,10 @@ static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* { char *c, hash[16], *args[] = { NULL, NULL, NULL, NULL, NULL }; int i, len[] = { 0, 0, 0, 0, 0 }; - long largs[] = { 0, 0, 0 }; + zend_long largs[] = { 0, 0, 0 }; PHP_MD5_CTX hash_context; zend_resource new_index_ptr, *le; - isc_db_handle db_handle = NULL; + isc_db_handle db_handle = 0; ibase_db_link *ib_link; RESET_ERRMSG; @@ -917,8 +923,8 @@ static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* for (i = 0; i < sizeof(args)/sizeof(char*); ++i) { PHP_MD5Update(&hash_context,args[i],len[i]); } - for (i = 0; i < sizeof(largs)/sizeof(long); ++i) { - PHP_MD5Update(&hash_context,(char*)&largs[i],sizeof(long)); + for (i = 0; i < sizeof(largs)/sizeof(zend_long); ++i) { + PHP_MD5Update(&hash_context,(char*)&largs[i],sizeof(zend_long)); } PHP_MD5Final((unsigned char*)hash, &hash_context); @@ -932,15 +938,12 @@ static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* xlink = (zend_resource*) le->ptr; if ((!persistent && xlink->type == le_link) || xlink->type == le_plink) { - if (IBG(default_link) > 0) { - zval *link = zend_hash_index_find(&EG(regular_list), IBG(default_link)); - if (link) { - zend_list_delete(Z_RES_P(link)); - } + if (IBG(default_link)) { + zend_list_close(IBG(default_link)); } xlink->gc.refcount++; xlink->gc.refcount++; - IBG(default_link) = xlink->handle; + IBG(default_link) = xlink; RETVAL_RES(xlink); } else { zend_hash_str_del(&EG(regular_list), hash, sizeof(hash)-1); @@ -949,7 +952,7 @@ static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* /* ... or a persistent one */ do { - long l; + zend_long l; static char info[] = { isc_info_base_level, isc_info_end }; char result[8]; ISC_STATUS status[20]; @@ -1017,13 +1020,10 @@ static void _php_ibase_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent) /* (void *) &new_index_ptr, sizeof(zend_resource)) == NULL) { RETURN_FALSE; } - if (IBG(default_link) > 0) { - zval *link = zend_hash_index_find(&EG(regular_list), IBG(default_link)); - if (link) { - zend_list_delete(Z_RES_P(link)); - } + if (IBG(default_link)) { + zend_list_delete(IBG(default_link)); } - IBG(default_link) = Z_RES_P(return_value)->handle; + IBG(default_link) = Z_RES_P(return_value); Z_TRY_ADDREF_P(return_value); Z_TRY_ADDREF_P(return_value); } @@ -1050,8 +1050,7 @@ PHP_FUNCTION(ibase_pconnect) PHP_FUNCTION(ibase_close) { zval *link_arg = NULL; - ibase_db_link *ib_link; - int link_id; + zend_resource *link_res; RESET_ERRMSG; @@ -1060,23 +1059,18 @@ PHP_FUNCTION(ibase_close) } if (ZEND_NUM_ARGS() == 0) { - link_id = IBG(default_link); - CHECK_LINK(link_id); - IBG(default_link) = -1; + link_res = IBG(default_link); + CHECK_LINK(link_res); + IBG(default_link) = NULL; } else { - link_id = Z_RES_P(link_arg)->handle; + link_res = Z_RES_P(link_arg); } - ib_link = (ibase_db_link *)zend_fetch_resource2_ex(link_arg, LE_LINK, le_link, le_plink); - if (!link_arg) { - link_arg = zend_hash_index_find(&EG(regular_list), link_id); - zend_list_delete(Z_RES_P(link_arg)); - } /* we have at least 3 additional references to this resource ??? */ - if (GC_REFCOUNT(Z_RES_P(link_arg)) < 4) { - zend_list_close(Z_RES_P(link_arg)); + if (GC_REFCOUNT(link_res) < 4) { + zend_list_close(link_res); } else { - zend_list_delete(Z_RES_P(link_arg)); + zend_list_delete(link_res); } RETURN_TRUE; } @@ -1089,7 +1083,7 @@ PHP_FUNCTION(ibase_drop_db) zval *link_arg = NULL; ibase_db_link *ib_link; ibase_tr_list *l; - int link_id; + zend_resource *link_res; RESET_ERRMSG; @@ -1098,14 +1092,18 @@ PHP_FUNCTION(ibase_drop_db) } if (ZEND_NUM_ARGS() == 0) { - link_id = IBG(default_link); - CHECK_LINK(link_id); - IBG(default_link) = -1; + link_res = IBG(default_link); + CHECK_LINK(link_res); + IBG(default_link) = NULL; } else { - link_id = Z_RES_P(link_arg)->handle; + link_res = Z_RES_P(link_arg); } - ib_link = (ibase_db_link *)zend_fetch_resource2_ex(link_arg, LE_LINK, le_link, le_plink); + ib_link = (ibase_db_link *)zend_fetch_resource2(link_res, LE_LINK, le_link, le_plink); + + if (!ib_link) { + RETURN_FALSE; + } if (isc_drop_database(IB_STATUS, &ib_link->handle)) { _php_ibase_error(); @@ -1114,14 +1112,11 @@ PHP_FUNCTION(ibase_drop_db) /* isc_drop_database() doesn't invalidate the transaction handles */ for (l = ib_link->tr_list; l != NULL; l = l->next) { - if (l->trans != NULL) l->trans->handle = NULL; + if (l->trans != NULL) l->trans->handle = 0; } - if (!link_arg) { - link_arg = zend_hash_index_find(&EG(regular_list), link_id); - zend_list_delete(Z_RES_P(link_arg)); - } - zend_list_delete(Z_RES_P(link_arg)); + zend_list_delete(link_res); + RETURN_TRUE; } /* }}} */ @@ -1138,7 +1133,7 @@ PHP_FUNCTION(ibase_trans) char last_tpb[TPB_MAX_SIZE]; ibase_db_link **ib_link = NULL; ibase_trans *ib_trans; - isc_tr_handle tr_handle = NULL; + isc_tr_handle tr_handle = 0; ISC_STATUS result; RESET_ERRMSG; @@ -1149,7 +1144,7 @@ PHP_FUNCTION(ibase_trans) ib_link = (ibase_db_link **) safe_emalloc(sizeof(ibase_db_link *),1+argn,0); if (argn > 0) { - long trans_argl = 0; + zend_long trans_argl = 0; char *tpb; ISC_TEB *teb; zval *args = NULL; @@ -1236,7 +1231,7 @@ PHP_FUNCTION(ibase_trans) if (link_cnt == 0) { link_cnt = 1; - if ((ib_link[0] = (ibase_db_link *)zend_fetch_resource2_ex(IBG(default_link), LE_LINK, le_link, le_plink)) == NULL) { + if ((ib_link[0] = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink)) == NULL) { efree(ib_link); RETURN_FALSE; } @@ -1297,13 +1292,13 @@ int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans) /* {{{ */ if (tr == NULL) { tr = (ibase_trans *) emalloc(sizeof(ibase_trans)); - tr->handle = NULL; + tr->handle = 0; tr->link_cnt = 1; tr->affected_rows = 0; tr->db_link[0] = ib_link; ib_link->tr_list->trans = tr; } - if (tr->handle == NULL) { + if (tr->handle == 0) { if (isc_start_transaction(IB_STATUS, &tr->handle, 1, &ib_link->handle, 0, NULL)) { _php_ibase_error(); return FAILURE; @@ -1330,7 +1325,7 @@ static void _php_ibase_trans_end(INTERNAL_FUNCTION_PARAMETERS, int commit) /* {{ } if (ZEND_NUM_ARGS() == 0) { - ib_link = (ibase_db_link *)zend_fetch_resource2_ex(IBG(default_link), LE_LINK, le_link, le_plink); + ib_link = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), LE_LINK, le_link, le_plink); if (ib_link->tr_list == NULL || ib_link->tr_list->trans == NULL) { /* this link doesn't have a default transaction */ _php_ibase_module_error("Default link has no default transaction"); @@ -1461,8 +1456,8 @@ PHP_FUNCTION(ibase_gen_id) } /* don't return the generator value as a string unless it doesn't fit in a long */ -#if SIZEOF_LONG < 8 - if (result < LONG_MIN || result > LONG_MAX) { +#if SIZEOF_ZEND_LONG < 8 + if (result < ZEND_LONG_MIN || result > ZEND_LONG_MAX) { char *res; int l; @@ -1470,7 +1465,7 @@ PHP_FUNCTION(ibase_gen_id) RETURN_STRINGL(res, l); } #endif - RETURN_LONG((long)result); + RETURN_LONG((zend_long)result); } /* }}} */ diff --git a/ext/interbase/php_ibase_includes.h b/ext/interbase/php_ibase_includes.h index b7fb0a340f..860f94b876 100644 --- a/ext/interbase/php_ibase_includes.h +++ b/ext/interbase/php_ibase_includes.h @@ -60,10 +60,10 @@ extern int le_link, le_plink, le_trans; ZEND_BEGIN_MODULE_GLOBALS(ibase) ISC_STATUS status[20]; - long default_link; - long num_links, num_persistent; + zend_resource *default_link; + zend_long num_links, num_persistent; char errmsg[MAX_ERRMSG]; - long sql_code; + zend_long sql_code; ZEND_END_MODULE_GLOBALS(ibase) ZEND_EXTERN_MODULE_GLOBALS(ibase) @@ -95,7 +95,7 @@ typedef struct { typedef struct event { ibase_db_link *link; - long link_res_id; + zend_resource* link_res; ISC_LONG event_id; unsigned short event_count; char **events; @@ -155,13 +155,15 @@ void _php_ibase_module_error(char *, ...) /* determine if a resource is a link or transaction handle */ #define PHP_IBASE_LINK_TRANS(zv, lh, th) \ - do { if (!zv) { \ - lh = (ibase_db_link *)zend_fetch_resource2(IBG(default_link), \ - "InterBase link", le_link, le_plink); } \ - else \ - _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, zv, &lh, &th); \ - if (SUCCESS != _php_ibase_def_trans(lh, &th)) { RETURN_FALSE; } \ - } while (0) + do { \ + if (!zv) { \ + lh = (ibase_db_link *)zend_fetch_resource2( \ + IBG(default_link), "InterBase link", le_link, le_plink); \ + } else { \ + _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAM_PASSTHRU, zv, &lh, &th); \ + } \ + if (SUCCESS != _php_ibase_def_trans(lh, &th)) { RETURN_FALSE; } \ + } while (0) int _php_ibase_def_trans(ibase_db_link *ib_link, ibase_trans **trans); void _php_ibase_get_link_trans(INTERNAL_FUNCTION_PARAMETERS, zval *link_id, @@ -174,7 +176,7 @@ void php_ibase_query_minit(INIT_FUNC_ARGS); void php_ibase_blobs_minit(INIT_FUNC_ARGS); int _php_ibase_string_to_quad(char const *id, ISC_QUAD *qd); zend_string *_php_ibase_quad_to_string(ISC_QUAD const qd); -int _php_ibase_blob_get(zval *return_value, ibase_blob *ib_blob, unsigned long max_len); +int _php_ibase_blob_get(zval *return_value, ibase_blob *ib_blob, zend_ulong max_len); int _php_ibase_blob_add(zval *string_arg, ibase_blob *ib_blob); /* provided by ibase_events.c */ diff --git a/ext/interbase/php_ibase_udf.c b/ext/interbase/php_ibase_udf.c index 7102c17c56..e3fe6e7edc 100644 --- a/ext/interbase/php_ibase_udf.c +++ b/ext/interbase/php_ibase_udf.c @@ -250,8 +250,8 @@ static void call_php(char *name, PARAMDSC *r, int argc, PARAMDSC **argv) case dtype_int64: l = *(ISC_INT64*)argv[i]->dsc_address; - if (argv[i]->dsc_scale == 0 && l <= LONG_MAX && l >= LONG_MIN) { - ZVAL_LONG(&args[i], (long)l); + if (argv[i]->dsc_scale == 0 && l <= ZEND_LONG_MAX && l >= ZEND_LONG_MIN) { + ZVAL_LONG(&args[i], (zend_long)l); } else { ZVAL_DOUBLE(&args[i], ((double)l)/scales[-argv[i]->dsc_scale]); } @@ -309,8 +309,8 @@ static void call_php(char *name, PARAMDSC *r, int argc, PARAMDSC **argv) case IS_LONG: r->dsc_dtype = dtype_long; - *(long*)r->dsc_address = Z_LVAL(return_value); - r->dsc_length = sizeof(long); + *(zend_long*)r->dsc_address = Z_LVAL(return_value); + r->dsc_length = sizeof(zend_long); break; case IS_DOUBLE: diff --git a/ext/interbase/tests/004.phpt b/ext/interbase/tests/004.phpt index e81474a4c4..54a6b7b9b5 100644 --- a/ext/interbase/tests/004.phpt +++ b/ext/interbase/tests/004.phpt @@ -109,7 +109,7 @@ InterBase: BLOB test ibase_commit(); ibase_close(); - ibase_connect($test_base); + $link = ibase_connect($test_base); ibase_blob_echo($link, $row->V_BLOB); ibase_free_result($q); diff --git a/ext/interbase/tests/005.phpt b/ext/interbase/tests/005.phpt index cb68b0a1d5..8523443078 100644 --- a/ext/interbase/tests/005.phpt +++ b/ext/interbase/tests/005.phpt @@ -207,7 +207,7 @@ transactions on second link echo "end of test\n"; ?> ---EXPECT-- +--EXPECTF-- default transaction: empty table --- test5 --- @@ -264,7 +264,7 @@ three rows in fourth transaction with deadlock 2 3 4 -errmsg [lock conflict on no wait transaction deadlock ] +errmsg [lock conflict on no wait transaction deadlock %a] --- three rows --- test5 --- diff --git a/ext/interbase/tests/bug46543.phpt b/ext/interbase/tests/bug46543.phpt index 59e088c3d0..88f38a6bd1 100644 --- a/ext/interbase/tests/bug46543.phpt +++ b/ext/interbase/tests/bug46543.phpt @@ -19,10 +19,10 @@ ibase_trans(1, 2, $x, $x, 3); ?> --EXPECTF-- -Warning: ibase_trans(): no Firebird/InterBase link resource supplied in %s on line %d +Warning: ibase_trans(): supplied resource is not a valid Firebird/InterBase link resource in %sbug46543.php on line %d -Warning: ibase_trans(): no Firebird/InterBase link resource supplied in %s on line %d +Warning: ibase_trans(): supplied resource is not a valid Firebird/InterBase link resource in %sbug46543.php on line %d -Warning: ibase_trans(): no Firebird/InterBase link resource supplied in %s on line %d +Warning: ibase_trans(): supplied resource is not a valid Firebird/InterBase link resource in %sbug46543.php on line %d -Warning: ibase_trans(): supplied resource is not a valid Firebird/InterBase link resource in %s on line %d +Warning: ibase_trans(): supplied resource is not a valid Firebird/InterBase link resource in %sbug46543.php on line %d diff --git a/ext/interbase/tests/ibase_close_001.phpt b/ext/interbase/tests/ibase_close_001.phpt index f74d109109..cb91e8a75a 100644 --- a/ext/interbase/tests/ibase_close_001.phpt +++ b/ext/interbase/tests/ibase_close_001.phpt @@ -17,9 +17,7 @@ var_dump(ibase_close('foo')); --EXPECTF-- bool(true) bool(true) - -Warning: ibase_close(): supplied resource is not a valid Firebird/InterBase link resource in %s on line %d -bool(false) +bool(true) Warning: ibase_close() expects parameter 1 to be resource,%string given in %s on line %d NULL diff --git a/ext/interbase/tests/ibase_trans_001.phpt b/ext/interbase/tests/ibase_trans_001.phpt index d8b7c81a1b..cceb60e9a1 100644 --- a/ext/interbase/tests/ibase_trans_001.phpt +++ b/ext/interbase/tests/ibase_trans_001.phpt @@ -18,6 +18,4 @@ var_dump(ibase_close($x)); resource(%d) of type (Firebird/InterBase transaction) resource(%d) of type (Firebird/InterBase transaction) bool(true) - -Warning: ibase_close(): supplied resource is not a valid Firebird/InterBase link resource in %s on line %d -bool(false) +bool(true) diff --git a/ext/intl/collator/collator_convert.c b/ext/intl/collator/collator_convert.c index 8f06c8f1ca..2d431a19d6 100644 --- a/ext/intl/collator/collator_convert.c +++ b/ext/intl/collator/collator_convert.c @@ -28,12 +28,6 @@ #include <unicode/ustring.h> #include <php.h> -#if PHP_VERSION_ID <= 50100 -#define CAST_OBJECT_SHOULD_FREE ,0 -#else -#define CAST_OBJECT_SHOULD_FREE -#endif - #define COLLATOR_CONVERT_RETURN_FAILED(retval) { \ Z_TRY_ADDREF_P(retval); \ return retval; \ @@ -258,7 +252,7 @@ zval* collator_convert_object_to_string( zval* obj, zval *rv ) { zstr = rv; - if( Z_OBJ_HT_P(obj)->cast_object( obj, zstr, IS_STRING CAST_OBJECT_SHOULD_FREE ) == FAILURE ) + if( Z_OBJ_HT_P(obj)->cast_object( obj, zstr, IS_STRING ) == FAILURE ) { /* cast_object failed => bail out. */ zval_ptr_dtor( zstr ); diff --git a/ext/intl/collator/collator_is_numeric.c b/ext/intl/collator/collator_is_numeric.c index 6b0568dd64..4f6efbfa6d 100644 --- a/ext/intl/collator/collator_is_numeric.c +++ b/ext/intl/collator/collator_is_numeric.c @@ -17,17 +17,6 @@ #include "collator_is_numeric.h" -#if ZEND_MODULE_API_NO < 20071006 -/* not 5.3 */ -#ifndef ALLOCA_FLAG -#define ALLOCA_FLAG(use_heap) -#endif -#define _do_alloca(x, y) do_alloca((x)) -#define _free_alloca(x, y) free_alloca((x)) -#else -#define _do_alloca do_alloca -#define _free_alloca free_alloca -#endif /* {{{ collator_u_strtod * Taken from PHP6:zend_u_strtod() */ @@ -87,7 +76,7 @@ static double collator_u_strtod(const UChar *nptr, UChar **endptr) /* {{{ */ if (length < sizeof(buf)) { numbuf = buf; } else { - numbuf = (char *) _do_alloca(length + 1, use_heap); + numbuf = (char *) do_alloca(length + 1, use_heap); } bufpos = numbuf; @@ -100,7 +89,7 @@ static double collator_u_strtod(const UChar *nptr, UChar **endptr) /* {{{ */ value = zend_strtod(numbuf, NULL); if (numbuf != buf) { - _free_alloca(numbuf, use_heap); + free_alloca(numbuf, use_heap); } if (endptr != NULL) { diff --git a/ext/json/json.c b/ext/json/json.c index 20bbcdc59e..971fe15f05 100644 --- a/ext/json/json.c +++ b/ext/json/json.c @@ -117,6 +117,7 @@ static PHP_MINIT_FUNCTION(json) PHP_JSON_REGISTER_CONSTANT("JSON_UNESCAPED_UNICODE", PHP_JSON_UNESCAPED_UNICODE); PHP_JSON_REGISTER_CONSTANT("JSON_PARTIAL_OUTPUT_ON_ERROR", PHP_JSON_PARTIAL_OUTPUT_ON_ERROR); PHP_JSON_REGISTER_CONSTANT("JSON_PRESERVE_ZERO_FRACTION", PHP_JSON_PRESERVE_ZERO_FRACTION); + PHP_JSON_REGISTER_CONSTANT("JSON_UNESCAPED_LINE_TERMINATORS", PHP_JSON_UNESCAPED_LINE_TERMINATORS); /* options for json_decode */ PHP_JSON_REGISTER_CONSTANT("JSON_OBJECT_AS_ARRAY", PHP_JSON_OBJECT_AS_ARRAY); diff --git a/ext/json/json_encoder.c b/ext/json/json_encoder.c index 6c2f377034..8da5abd088 100644 --- a/ext/json/json_encoder.c +++ b/ext/json/json_encoder.c @@ -321,7 +321,7 @@ static void php_json_escape_string(smart_str *buf, char *s, size_t len, int opti do { us = (unsigned char)s[pos]; - if (us >= 0x80 && !(options & PHP_JSON_UNESCAPED_UNICODE)) { + if (us >= 0x80 && (!(options & PHP_JSON_UNESCAPED_UNICODE) || us == 0xE2)) { /* UTF-8 character */ us = php_next_utf8_char((const unsigned char *)s, len, &pos, &status); if (status != SUCCESS) { @@ -332,6 +332,15 @@ static void php_json_escape_string(smart_str *buf, char *s, size_t len, int opti smart_str_appendl(buf, "null", 4); return; } + /* Escape U+2028/U+2029 line terminators, UNLESS both + JSON_UNESCAPED_UNICODE and + JSON_UNESCAPED_LINE_TERMINATORS were provided */ + if ((options & PHP_JSON_UNESCAPED_UNICODE) + && ((options & PHP_JSON_UNESCAPED_LINE_TERMINATORS) + || us < 0x2028 || us > 0x2029)) { + smart_str_appendl(buf, &s[pos - 3], 3); + continue; + } /* From http://en.wikipedia.org/wiki/UTF16 */ if (us >= 0x10000) { unsigned int next_us; diff --git a/ext/json/php_json.h b/ext/json/php_json.h index f1edc6c65a..d8bf0dfe9d 100644 --- a/ext/json/php_json.h +++ b/ext/json/php_json.h @@ -67,6 +67,7 @@ typedef enum { #define PHP_JSON_UNESCAPED_UNICODE (1<<8) #define PHP_JSON_PARTIAL_OUTPUT_ON_ERROR (1<<9) #define PHP_JSON_PRESERVE_ZERO_FRACTION (1<<10) +#define PHP_JSON_UNESCAPED_LINE_TERMINATORS (1<<11) /* json_decode() options */ #define PHP_JSON_OBJECT_AS_ARRAY (1<<0) diff --git a/ext/json/tests/json_encode_u2028_u2029.phpt b/ext/json/tests/json_encode_u2028_u2029.phpt new file mode 100644 index 0000000000..4b87e9b307 --- /dev/null +++ b/ext/json/tests/json_encode_u2028_u2029.phpt @@ -0,0 +1,36 @@ +--TEST-- +json_encode() tests for U+2028, U+2029 +--SKIPIF-- +<?php if (!extension_loaded("json")) print "skip"; ?> +--FILE-- +<?php +var_dump(json_encode(array("a\xC3\xA1b"))); +var_dump(json_encode(array("a\xC3\xA1b"), JSON_UNESCAPED_UNICODE)); +var_dump(json_encode("a\xE2\x80\xA7b")); +var_dump(json_encode("a\xE2\x80\xA7b", JSON_UNESCAPED_UNICODE)); +var_dump(json_encode("a\xE2\x80\xA8b")); +var_dump(json_encode("a\xE2\x80\xA8b", JSON_UNESCAPED_UNICODE)); +var_dump(json_encode("a\xE2\x80\xA8b", JSON_UNESCAPED_LINE_TERMINATORS)); +var_dump(json_encode("a\xE2\x80\xA8b", JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS)); +var_dump(json_encode("a\xE2\x80\xA9b")); +var_dump(json_encode("a\xE2\x80\xA9b", JSON_UNESCAPED_UNICODE)); +var_dump(json_encode("a\xE2\x80\xA9b", JSON_UNESCAPED_LINE_TERMINATORS)); +var_dump(json_encode("a\xE2\x80\xA9b", JSON_UNESCAPED_UNICODE | JSON_UNESCAPED_LINE_TERMINATORS)); +var_dump(json_encode("a\xE2\x80\xAAb")); +var_dump(json_encode("a\xE2\x80\xAAb", JSON_UNESCAPED_UNICODE)); +?> +--EXPECT-- +string(12) "["a\u00e1b"]" +string(8) "["aáb"]" +string(10) ""a\u2027b"" +string(7) ""a‧b"" +string(10) ""a\u2028b"" +string(10) ""a\u2028b"" +string(10) ""a\u2028b"" +string(7) ""a
b"" +string(10) ""a\u2029b"" +string(10) ""a\u2029b"" +string(10) ""a\u2029b"" +string(7) ""a
b"" +string(10) ""a\u202ab"" +string(7) ""a‪b"" diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c index 5b7aca91d8..24812449ee 100644 --- a/ext/libxml/libxml.c +++ b/ext/libxml/libxml.c @@ -383,6 +383,9 @@ static int php_libxml_streams_IO_read(void *context, char *buffer, int len) static int php_libxml_streams_IO_write(void *context, const char *buffer, int len) { + if (CG(unclean_shutdown)) { + return -1; + } return php_stream_write((php_stream*)context, buffer, len); } diff --git a/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c b/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c index 77736a051b..75d249fbe8 100644 --- a/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c +++ b/ext/mbstring/libmbfl/filters/mbfilter_cp5022x.c @@ -278,7 +278,7 @@ retry: w = cp932ext1_ucs_table[s - cp932ext1_ucs_table_min]; } else if (s >= cp932ext2_ucs_table_min && s < cp932ext2_ucs_table_max) { w = cp932ext2_ucs_table[s - cp932ext2_ucs_table_min]; - } else if (s >= cp932ext3_ucs_table_min && s < cp932ext2_ucs_table_max) { + } else if (s >= cp932ext3_ucs_table_min && s < cp932ext3_ucs_table_max) { w = cp932ext3_ucs_table[s - cp932ext3_ucs_table_min]; } else if (s >= 94 * 94 && s < 114 * 94) { /* user-defined => PUA (Microsoft extended) */ diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 4fdb3d5b2e..b5812cb402 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -4145,9 +4145,10 @@ PHP_FUNCTION(mb_send_mail) suppressed_hdrs.cnt_type = 1; } - if ((s = zend_hash_str_find_ptr(&ht_headers, "CONTENT-TRANSFER-ENCODING", sizeof("CONTENT-TRANSFER-ENCODING") - 1))) { + if ((s = zend_hash_str_find(&ht_headers, "CONTENT-TRANSFER-ENCODING", sizeof("CONTENT-TRANSFER-ENCODING") - 1))) { enum mbfl_no_encoding _body_enc; + ZEND_ASSERT(Z_TYPE_P(s) == IS_STRING); _body_enc = mbfl_name2no_encoding(Z_STRVAL_P(s)); switch (_body_enc) { case mbfl_no_encoding_base64: diff --git a/ext/mcrypt/mcrypt.c b/ext/mcrypt/mcrypt.c index 536edde425..456c40ae71 100644 --- a/ext/mcrypt/mcrypt.c +++ b/ext/mcrypt/mcrypt.c @@ -564,7 +564,7 @@ PHP_FUNCTION(mcrypt_generic_init) memset(iv_s, 0, iv_size + 1); if (key_len > max_key_size) { - php_error_docref(NULL, E_WARNING, "Key size too large; supplied length: %d, max: %d", key_len, max_key_size); + php_error_docref(NULL, E_WARNING, "Key size too large; supplied length: %zd, max: %d", key_len, max_key_size); key_size = max_key_size; } else { key_size = (int)key_len; @@ -572,7 +572,7 @@ PHP_FUNCTION(mcrypt_generic_init) memcpy(key_s, key, key_len); if (iv_len != iv_size) { - php_error_docref(NULL, E_WARNING, "Iv size incorrect; supplied length: %d, needed: %d", iv_len, iv_size); + php_error_docref(NULL, E_WARNING, "Iv size incorrect; supplied length: %zd, needed: %d", iv_len, iv_size); if (iv_len > iv_size) { iv_len = iv_size; } diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index 41b5783d18..f21e752517 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -34,6 +34,7 @@ #include "php_mysqli_structs.h" #include "mysqli_priv.h" #include "zend_exceptions.h" +#include "ext/spl/spl_exceptions.h" #include "zend_interfaces.h" ZEND_DECLARE_MODULE_GLOBALS(mysqli) @@ -582,9 +583,7 @@ PHP_MINIT_FUNCTION(mysqli) mysqli_object_handlers.write_property = mysqli_write_property; mysqli_object_handlers.get_property_ptr_ptr = std_hnd->get_property_ptr_ptr; mysqli_object_handlers.has_property = mysqli_object_has_property; -#if PHP_VERSION_ID >= 50300 mysqli_object_handlers.get_debug_info = mysqli_object_get_debug_info; -#endif memcpy(&mysqli_object_driver_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers)); mysqli_object_driver_handlers.free_obj = mysqli_driver_free_storage; memcpy(&mysqli_object_link_handlers, &mysqli_object_handlers, sizeof(zend_object_handlers)); @@ -603,11 +602,7 @@ PHP_MINIT_FUNCTION(mysqli) "MySqli persistent connection", module_number); INIT_CLASS_ENTRY(cex, "mysqli_sql_exception", mysqli_exception_methods); -#ifdef HAVE_SPL mysqli_exception_class_entry = zend_register_internal_class_ex(&cex, spl_ce_RuntimeException); -#else - mysqli_exception_class_entry = zend_register_internal_class_ex(&cex, zend_ce_exception); -#endif mysqli_exception_class_entry->ce_flags |= ZEND_ACC_FINAL; zend_declare_property_long(mysqli_exception_class_entry, "code", sizeof("code")-1, 0, ZEND_ACC_PROTECTED); zend_declare_property_string(mysqli_exception_class_entry, "sqlstate", sizeof("sqlstate")-1, "00000", ZEND_ACC_PROTECTED); @@ -999,9 +994,7 @@ PHP_MINFO_FUNCTION(mysqli) /* Dependancies */ static const zend_module_dep mysqli_deps[] = { -#if defined(HAVE_SPL) && (PHP_VERSION_ID >= 50100) ZEND_MOD_REQUIRED("spl") -#endif #if defined(MYSQLI_USE_MYSQLND) ZEND_MOD_REQUIRED("mysqlnd") #endif diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c index e32b377735..333e890f3b 100644 --- a/ext/mysqli/mysqli_api.c +++ b/ext/mysqli/mysqli_api.c @@ -1697,10 +1697,6 @@ static int mysqli_options_get_option_zval_type(int option) { switch (option) { #ifdef MYSQLI_USE_MYSQLND -#if PHP_MAJOR_VERSION == 6 - /* PHP-7 doesn't supprt unicode */ - case MYSQLND_OPT_NUMERIC_AND_DATETIME_AS_UNICODE: -#endif case MYSQLND_OPT_NET_CMD_BUFFER_SIZE: case MYSQLND_OPT_NET_READ_BUFFER_SIZE: #ifdef MYSQLND_STRING_TO_INT_CONVERSION @@ -1781,11 +1777,7 @@ PHP_FUNCTION(mysqli_options) MYSQLI_FETCH_RESOURCE_CONN(mysql, mysql_link, MYSQLI_STATUS_INITIALIZED); #if !defined(MYSQLI_USE_MYSQLND) -#if PHP_API_VERSION < 20100412 - if ((PG(open_basedir) && PG(open_basedir)[0] != '\0') || PG(safe_mode)) { -#else if (PG(open_basedir) && PG(open_basedir)[0] != '\0') { -#endif if(mysql_option == MYSQL_OPT_LOCAL_INFILE) { RETURN_FALSE; } diff --git a/ext/mysqli/mysqli_fe.c b/ext/mysqli/mysqli_fe.c index 817834dfc2..abc23f0699 100644 --- a/ext/mysqli/mysqli_fe.c +++ b/ext/mysqli/mysqli_fe.c @@ -243,18 +243,14 @@ ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqli_fetch_object, 0, 0, 1) -#if PHP_VERSION_ID > 50399 MYSQLI_ZEND_ARG_OBJ_INFO_RESULT() ZEND_ARG_INFO(0, class_name) ZEND_ARG_ARRAY_INFO(0, params, 0) -#endif ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_class_mysqli_fetch_object, 0, 0, 0) -#if PHP_VERSION_ID > 50399 ZEND_ARG_INFO(0, class_name) ZEND_ARG_ARRAY_INFO(0, params, 0) -#endif ZEND_END_ARG_INFO() ZEND_BEGIN_ARG_INFO_EX(arginfo_mysqli_kill, 0, 0, 2) diff --git a/ext/mysqli/mysqli_priv.h b/ext/mysqli/mysqli_priv.h index 0a1122a836..c34049c89e 100644 --- a/ext/mysqli/mysqli_priv.h +++ b/ext/mysqli/mysqli_priv.h @@ -78,10 +78,6 @@ extern void php_mysqli_report_error(const char *sqlstate, int errorno, const cha extern void php_mysqli_report_index(const char *query, unsigned int status); extern void php_mysqli_throw_sql_exception(char *sqlstate, int errorno, char *format, ...); -#ifdef HAVE_SPL -extern PHPAPI zend_class_entry *spl_ce_RuntimeException; -#endif - #define PHP_MYSQLI_EXPORT(__type) PHP_MYSQLI_API __type PHP_MYSQLI_EXPORT(zend_object *) mysqli_objects_new(zend_class_entry *); diff --git a/ext/mysqli/php_mysqli_structs.h b/ext/mysqli/php_mysqli_structs.h index 4ef13fd198..7bfffa83c8 100644 --- a/ext/mysqli/php_mysqli_structs.h +++ b/ext/mysqli/php_mysqli_structs.h @@ -216,10 +216,6 @@ extern zend_object_iterator *php_mysqli_result_get_iterator(zend_class_entry *ce extern void php_mysqli_fetch_into_hash_aux(zval *return_value, MYSQL_RES * result, zend_long fetchtype); -#ifdef HAVE_SPL -extern PHPAPI zend_class_entry *spl_ce_RuntimeException; -#endif - #define MYSQLI_DISABLE_MQ if (mysql->multi_query) { \ mysql_set_server_option(mysql->mysql, MYSQL_OPTION_MULTI_STATEMENTS_OFF); \ mysql->multi_query = 0; \ diff --git a/ext/mysqlnd/mysqlnd_alloc.h b/ext/mysqlnd/mysqlnd_alloc.h index 2ee33e00a3..85dfba5d09 100644 --- a/ext/mysqlnd/mysqlnd_alloc.h +++ b/ext/mysqlnd/mysqlnd_alloc.h @@ -61,6 +61,7 @@ PHPAPI extern struct st_mysqlnd_allocator_methods mysqlnd_allocator; #define mnd_calloc(nmemb, size) mysqlnd_allocator.m_calloc((nmemb), (size) MYSQLND_MEM_C) #define mnd_realloc(ptr, new_size) mysqlnd_allocator.m_realloc((ptr), (new_size) MYSQLND_MEM_C) #define mnd_free(ptr) mysqlnd_allocator.m_free((ptr) MYSQLND_MEM_C) +#define mnd_pememdup(ptr, size, pers) mysqlnd_allocator.m_pememdup((ptr), (size), (pers) MYSQLND_MEM_C) #define mnd_pestrndup(ptr, size, pers) mysqlnd_allocator.m_pestrndup((ptr), (size), (pers) MYSQLND_MEM_C) #define mnd_pestrdup(ptr, pers) mysqlnd_allocator.m_pestrdup((ptr), (pers) MYSQLND_MEM_C) #define mnd_sprintf(p, mx_len, fmt,...) mysqlnd_allocator.m_sprintf((p), (mx_len), (fmt), __VA_ARGS__) diff --git a/ext/mysqlnd/mysqlnd_block_alloc.c b/ext/mysqlnd/mysqlnd_block_alloc.c index 0897c65a64..8729606ade 100644 --- a/ext/mysqlnd/mysqlnd_block_alloc.c +++ b/ext/mysqlnd/mysqlnd_block_alloc.c @@ -28,9 +28,8 @@ /* {{{ mysqlnd_mempool_free_chunk */ static void -mysqlnd_mempool_free_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk) +mysqlnd_mempool_free_chunk(MYSQLND_MEMORY_POOL * pool, MYSQLND_MEMORY_POOL_CHUNK * chunk) { - MYSQLND_MEMORY_POOL * pool = chunk->pool; DBG_ENTER("mysqlnd_mempool_free_chunk"); if (chunk->from_pool) { /* Try to back-off and guess if this is the last block allocated */ @@ -41,7 +40,6 @@ mysqlnd_mempool_free_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk) */ pool->free_size += chunk->size; } - pool->refcount--; } else { mnd_efree(chunk->ptr); } @@ -53,11 +51,10 @@ mysqlnd_mempool_free_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk) /* {{{ mysqlnd_mempool_resize_chunk */ static enum_func_status -mysqlnd_mempool_resize_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int size) +mysqlnd_mempool_resize_chunk(MYSQLND_MEMORY_POOL * pool, MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int size) { DBG_ENTER("mysqlnd_mempool_resize_chunk"); if (chunk->from_pool) { - MYSQLND_MEMORY_POOL * pool = chunk->pool; /* Try to back-off and guess if this is the last block allocated */ if (chunk->ptr == (pool->arena + (pool->arena_size - pool->free_size - chunk->size))) { /* @@ -74,8 +71,7 @@ mysqlnd_mempool_resize_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int siz chunk->ptr = new_ptr; pool->free_size += chunk->size; chunk->size = size; - chunk->pool = NULL; /* now we have no pool memory */ - pool->refcount--; + chunk->from_pool = FALSE; /* now we have no pool memory */ } else { /* If the chunk is > than asked size then free_memory increases, otherwise decreases*/ pool->free_size += (chunk->size - size); @@ -93,8 +89,7 @@ mysqlnd_mempool_resize_chunk(MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int siz memcpy(new_ptr, chunk->ptr, chunk->size); chunk->ptr = new_ptr; chunk->size = size; - chunk->pool = NULL; /* now we have non-pool memory */ - pool->refcount--; + chunk->from_pool = FALSE; /* now we have non-pool memory */ } } } else { @@ -118,25 +113,21 @@ MYSQLND_MEMORY_POOL_CHUNK * mysqlnd_mempool_get_chunk(MYSQLND_MEMORY_POOL * pool chunk = mnd_emalloc(sizeof(MYSQLND_MEMORY_POOL_CHUNK)); if (chunk) { - chunk->free_chunk = mysqlnd_mempool_free_chunk; - chunk->resize_chunk = mysqlnd_mempool_resize_chunk; chunk->size = size; /* Should not go over MYSQLND_MAX_PACKET_SIZE, since we expect non-arena memory in mysqlnd_wireprotocol.c . We realloc the non-arena memory. */ - chunk->pool = pool; if (size > pool->free_size) { chunk->from_pool = FALSE; chunk->ptr = mnd_emalloc(size); if (!chunk->ptr) { - chunk->free_chunk(chunk); + pool->free_chunk(pool, chunk); chunk = NULL; } } else { chunk->from_pool = TRUE; - ++pool->refcount; chunk->ptr = pool->arena + (pool->arena_size - pool->free_size); /* Last step, update free_size */ pool->free_size -= size; @@ -156,8 +147,9 @@ mysqlnd_mempool_create(size_t arena_size) DBG_ENTER("mysqlnd_mempool_create"); if (ret) { ret->get_chunk = mysqlnd_mempool_get_chunk; + ret->free_chunk = mysqlnd_mempool_free_chunk; + ret->resize_chunk = mysqlnd_mempool_resize_chunk; ret->free_size = ret->arena_size = arena_size ? arena_size : 0; - ret->refcount = 0; /* OOM ? */ ret->arena = mnd_emalloc(ret->arena_size); if (!ret->arena) { diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c index b121cd7458..6f350cfd79 100644 --- a/ext/mysqlnd/mysqlnd_connection.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -40,7 +40,7 @@ PHPAPI const char * const mysqlnd_server_gone = "MySQL server has gone away"; PHPAPI const char * const mysqlnd_out_of_sync = "Commands out of sync; you can't run this command now"; PHPAPI const char * const mysqlnd_out_of_memory = "Out of memory"; -PHPAPI MYSQLND_STATS *mysqlnd_global_stats = NULL; +PHPAPI MYSQLND_STATS * mysqlnd_global_stats = NULL; /* {{{ mysqlnd_upsert_status::reset */ @@ -152,8 +152,8 @@ MYSQLND_CLASS_METHODS_END; /* {{{ mysqlnd_error_info_init */ -enum_func_status -mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, zend_bool persistent) +PHPAPI enum_func_status +mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, const zend_bool persistent) { DBG_ENTER("mysqlnd_error_info_init"); info->m = mysqlnd_error_info_get_methods(); @@ -163,12 +163,28 @@ mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, zend_bool persistent) if (info->error_list) { zend_llist_init(info->error_list, sizeof(MYSQLND_ERROR_LIST_ELEMENT), (llist_dtor_func_t) mysqlnd_error_list_pdtor, persistent); } - + info->persistent = persistent; DBG_RETURN(info->error_list? PASS:FAIL); } /* }}} */ +/* {{{ mysqlnd_error_info_free_contents */ +PHPAPI void +mysqlnd_error_info_free_contents(MYSQLND_ERROR_INFO * const info) +{ + DBG_ENTER("mysqlnd_error_info_free_contents"); + info->m->reset(info); + if (info->error_list) { + mnd_pefree(info->error_list, info->persistent); + info->error_list = NULL; + } + + DBG_VOID_RETURN; +} +/* }}} */ + + /* {{{ mysqlnd_connection_state::get */ @@ -200,10 +216,8 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_connection_state) MYSQLND_CLASS_METHODS_END; - - /* {{{ mysqlnd_upsert_status_init */ -void +PHPAPI void mysqlnd_connection_state_init(struct st_mysqlnd_connection_state * const state) { DBG_ENTER("mysqlnd_error_info_init"); @@ -214,6 +228,7 @@ mysqlnd_connection_state_init(struct st_mysqlnd_connection_state * const state) /* }}} */ + /* {{{ mysqlnd_conn_data::free_options */ static void MYSQLND_METHOD(mysqlnd_conn_data, free_options)(MYSQLND_CONN_DATA * conn) @@ -318,11 +333,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn) mnd_pefree(conn->last_message.s, pers); conn->last_message.s = NULL; } - if (conn->error_info->error_list) { - zend_llist_clean(conn->error_info->error_list); - mnd_pefree(conn->error_info->error_list, pers); - conn->error_info->error_list = NULL; - } + conn->charset = NULL; conn->greet_charset = NULL; @@ -341,6 +352,11 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, dtor)(MYSQLND_CONN_DATA * conn) conn->m->free_contents(conn); conn->m->free_options(conn); + if (conn->error_info) { + mysqlnd_error_info_free_contents(conn->error_info); + conn->error_info = NULL; + } + if (conn->protocol_frame_codec) { mysqlnd_pfc_free(conn->protocol_frame_codec, conn->stats, conn->error_info); conn->protocol_frame_codec = NULL; @@ -534,29 +550,29 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn, } /* }}} */ -/* {{{ mysqlnd_conn_data::connect */ +/* {{{ mysqlnd_conn_data::get_scheme */ static MYSQLND_STRING -MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_CSTRING hostname, MYSQLND_CSTRING socket_or_pipe, unsigned int port, zend_bool * unix_socket, zend_bool * named_pipe) +MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_CSTRING hostname, MYSQLND_CSTRING *socket_or_pipe, unsigned int port, zend_bool * unix_socket, zend_bool * named_pipe) { MYSQLND_STRING transport; DBG_ENTER("mysqlnd_conn_data::get_scheme"); #ifndef PHP_WIN32 if (hostname.l == sizeof("localhost") - 1 && !strncasecmp(hostname.s, "localhost", hostname.l)) { - DBG_INF_FMT("socket=%s", socket_or_pipe.s? socket_or_pipe.s:"n/a"); - if (!socket_or_pipe.s) { - socket_or_pipe.s = "/tmp/mysql.sock"; - socket_or_pipe.l = strlen(socket_or_pipe.s); + DBG_INF_FMT("socket=%s", socket_or_pipe->s? socket_or_pipe->s:"n/a"); + if (!socket_or_pipe->s) { + socket_or_pipe->s = "/tmp/mysql.sock"; + socket_or_pipe->l = strlen(socket_or_pipe->s); } - transport.l = mnd_sprintf(&transport.s, 0, "unix://%s", socket_or_pipe.s); + transport.l = mnd_sprintf(&transport.s, 0, "unix://%s", socket_or_pipe->s); *unix_socket = TRUE; #else if (hostname.l == sizeof(".") - 1 && hostname.s[0] == '.') { /* named pipe in socket */ - if (!socket_or_pipe.s) { - socket_or_pipe.s = "\\\\.\\pipe\\MySQL"; - socket_or_pipe.l = strlen(socket_or_pipe.s); + if (!socket_or_pipe->s) { + socket_or_pipe->s = "\\\\.\\pipe\\MySQL"; + socket_or_pipe->l = strlen(socket_or_pipe->s); } - transport.l = mnd_sprintf(&transport.s, 0, "pipe://%s", socket_or_pipe.s); + transport.l = mnd_sprintf(&transport.s, 0, "pipe://%s", socket_or_pipe->s); *named_pipe = TRUE; #endif } else { @@ -657,7 +673,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn, mysql_flags |= CLIENT_CONNECT_WITH_DB; } - transport = conn->m->get_scheme(conn, hostname, socket_or_pipe, port, &unix_socket, &named_pipe); + transport = conn->m->get_scheme(conn, hostname, &socket_or_pipe, port, &unix_socket, &named_pipe); mysql_flags = conn->m->get_updated_connect_flags(conn, mysql_flags); diff --git a/ext/mysqlnd/mysqlnd_connection.h b/ext/mysqlnd/mysqlnd_connection.h index cdffe594d9..0668d09d92 100644 --- a/ext/mysqlnd/mysqlnd_connection.h +++ b/ext/mysqlnd/mysqlnd_connection.h @@ -67,12 +67,13 @@ void mysqlnd_upsert_status_init(MYSQLND_UPSERT_STATUS * const upsert_status); } -enum_func_status mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, zend_bool persistent); +PHPAPI enum_func_status mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, const zend_bool persistent); +PHPAPI void mysqlnd_error_info_free_contents(MYSQLND_ERROR_INFO * const info); #define GET_CONNECTION_STATE(state_struct) (state_struct)->m->get((state_struct)) #define SET_CONNECTION_STATE(state_struct, s) (state_struct)->m->set((state_struct), (s)) -void mysqlnd_connection_state_init(struct st_mysqlnd_connection_state * const state); +PHPAPI void mysqlnd_connection_state_init(struct st_mysqlnd_connection_state * const state); #endif /* MYSQLND_CONNECTION_H */ diff --git a/ext/mysqlnd/mysqlnd_net.c b/ext/mysqlnd/mysqlnd_net.c index a44faf75db..bf86a17a08 100644 --- a/ext/mysqlnd/mysqlnd_net.c +++ b/ext/mysqlnd/mysqlnd_net.c @@ -133,11 +133,7 @@ MYSQLND_METHOD(mysqlnd_net, open_pipe)(MYSQLND_NET * const net, const char * con const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info) { -#if PHP_API_VERSION < 20100412 - unsigned int streams_options = ENFORCE_SAFE_MODE; -#else unsigned int streams_options = 0; -#endif dtor_func_t origin_dtor; php_stream * net_stream = NULL; @@ -173,11 +169,7 @@ MYSQLND_METHOD(mysqlnd_net, open_tcp_or_unix)(MYSQLND_NET * const net, const cha const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info) { -#if PHP_API_VERSION < 20100412 - unsigned int streams_options = ENFORCE_SAFE_MODE; -#else unsigned int streams_options = 0; -#endif unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT; char * hashed_details = NULL; int hashed_details_len = 0; @@ -983,11 +975,7 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net) php_stream_context_set_option(context, "ssl", "allow_self_signed", &verify_peer_zval); } } -#if PHP_API_VERSION >= 20131106 - php_stream_context_set(net_stream, context); -#else php_stream_context_set(net_stream, context); -#endif if (php_stream_xport_crypto_setup(net_stream, STREAM_CRYPTO_METHOD_TLS_CLIENT, NULL) < 0 || php_stream_xport_crypto_enable(net_stream, 1) < 0) { @@ -1003,11 +991,7 @@ MYSQLND_METHOD(mysqlnd_net, enable_ssl)(MYSQLND_NET * const net) of the context, which means usage of already freed memory, bad. Actually we don't need this context anymore after we have enabled SSL on the connection. Thus it is very simple, we remove it. */ -#if PHP_API_VERSION >= 20131106 php_stream_context_set(net_stream, NULL); -#else - php_stream_context_set(net_stream, NULL); -#endif if (net->data->options.timeout_read) { struct timeval tv; diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c index 907ddb46e1..1e37f79bf4 100644 --- a/ext/mysqlnd/mysqlnd_ps.c +++ b/ext/mysqlnd/mysqlnd_ps.c @@ -947,7 +947,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, const unsi the bound variables. Thus we need to do part of what it does or Zend will report leaks. */ - row_packet->row_buffer->free_chunk(row_packet->row_buffer); + row_packet->result_set_memory_pool->free_chunk( + row_packet->result_set_memory_pool, row_packet->row_buffer); row_packet->row_buffer = NULL; } @@ -1141,13 +1142,15 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f the bound variables. Thus we need to do part of what it does or Zend will report leaks. */ - row_packet->row_buffer->free_chunk(row_packet->row_buffer); + row_packet->result_set_memory_pool->free_chunk( + row_packet->result_set_memory_pool, row_packet->row_buffer); row_packet->row_buffer = NULL; } /* We asked for one row, the next one should be EOF, eat it */ ret = PACKET_READ(row_packet); if (row_packet->row_buffer) { - row_packet->row_buffer->free_chunk(row_packet->row_buffer); + row_packet->result_set_memory_pool->free_chunk( + row_packet->result_set_memory_pool, row_packet->row_buffer); row_packet->row_buffer = NULL; } MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_PS_CURSOR); diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 2b709264a5..d649efcbb9 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -166,7 +166,8 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, free_last_data)(MYSQLND_RES_UNBUFFERED if (unbuf->last_row_buffer) { DBG_INF("Freeing last row buffer"); /* Nothing points to this buffer now, free it */ - unbuf->last_row_buffer->free_chunk(unbuf->last_row_buffer); + unbuf->result_set_memory_pool->free_chunk( + unbuf->result_set_memory_pool, unbuf->last_row_buffer); unbuf->last_row_buffer = NULL; } @@ -253,6 +254,7 @@ static void MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * const set) { int64_t row; + MYSQLND_MEMORY_POOL * pool; DBG_ENTER("mysqlnd_result_buffered::free_result"); DBG_INF_FMT("Freeing "MYSQLND_LLU_SPEC" row(s)", set->row_count); @@ -263,9 +265,10 @@ MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * cons MYSQLND_METHOD(mysqlnd_result_buffered_c, free_result)((MYSQLND_RES_BUFFERED_C *) set); } + pool = set->result_set_memory_pool; for (row = set->row_count - 1; row >= 0; row--) { MYSQLND_MEMORY_POOL_CHUNK *current_buffer = set->row_buffers[row]; - current_buffer->free_chunk(current_buffer); + pool->free_chunk(pool, current_buffer); } if (set->lengths) { diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h index 5bbb718cdc..4832cb1381 100644 --- a/ext/mysqlnd/mysqlnd_structs.h +++ b/ext/mysqlnd/mysqlnd_structs.h @@ -32,6 +32,9 @@ #define MYSQLND_CLASS_METHODS_START(class) MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) = { #define MYSQLND_CLASS_METHODS_END } +#define MYSQLND_CLASS_METHODS_INSTANCE_NAME(class) mysqlnd_##class##_methods_ptr +#define MYSQLND_CLASS_METHODS_INSTANCE_DECLARE(class) extern const MYSQLND_CLASS_METHODS_TYPE(class) * MYSQLND_CLASS_METHODS_INSTANCE_NAME(class) +#define MYSQLND_CLASS_METHODS_INSTANCE_DEFINE(class) const MYSQLND_CLASS_METHODS_TYPE(class) * MYSQLND_CLASS_METHODS_INSTANCE_NAME(class) = & MYSQLND_CLASS_METHOD_TABLE_NAME(class) typedef struct st_mysqlnd_string { @@ -56,20 +59,18 @@ typedef struct st_mysqlnd_memory_pool_chunk_llist MYSQLND_MEMORY_POOL_CHUNK_LLIS struct st_mysqlnd_memory_pool { zend_uchar *arena; - unsigned int refcount; unsigned int arena_size; unsigned int free_size; MYSQLND_MEMORY_POOL_CHUNK* (*get_chunk)(MYSQLND_MEMORY_POOL * pool, unsigned int size); + enum_func_status (*resize_chunk)(MYSQLND_MEMORY_POOL * pool, MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int size); + void (*free_chunk)(MYSQLND_MEMORY_POOL * pool, MYSQLND_MEMORY_POOL_CHUNK * chunk); }; struct st_mysqlnd_memory_pool_chunk { size_t app; - MYSQLND_MEMORY_POOL *pool; zend_uchar *ptr; - enum_func_status (*resize_chunk)(MYSQLND_MEMORY_POOL_CHUNK * chunk, unsigned int size); - void (*free_chunk)(MYSQLND_MEMORY_POOL_CHUNK * chunk); unsigned int size; zend_bool from_pool; }; @@ -154,6 +155,7 @@ struct st_mysqlnd_error_info unsigned int error_no; zend_llist * error_list; + zend_bool persistent; MYSQLND_CLASS_METHODS_TYPE(mysqlnd_error_info) *m; }; @@ -474,7 +476,7 @@ typedef enum_func_status (*func_mysqlnd_conn_data__set_client_option_2d)(MYSQLND typedef size_t (*func_mysqlnd_conn_data__negotiate_client_api_capabilities)(MYSQLND_CONN_DATA * const conn, const size_t flags); typedef size_t (*func_mysqlnd_conn_data__get_client_api_capabilities)(const MYSQLND_CONN_DATA * const conn); -typedef MYSQLND_STRING (*func_mysqlnd_conn_data__get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_CSTRING hostname, MYSQLND_CSTRING socket_or_pipe, unsigned int port, zend_bool * unix_socket, zend_bool * named_pipe); +typedef MYSQLND_STRING (*func_mysqlnd_conn_data__get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_CSTRING hostname, MYSQLND_CSTRING *socket_or_pipe, unsigned int port, zend_bool * unix_socket, zend_bool * named_pipe); diff --git a/ext/mysqlnd/mysqlnd_vio.c b/ext/mysqlnd/mysqlnd_vio.c index 005263fdd9..888fd8e71f 100644 --- a/ext/mysqlnd/mysqlnd_vio.c +++ b/ext/mysqlnd/mysqlnd_vio.c @@ -121,11 +121,7 @@ static php_stream * MYSQLND_METHOD(mysqlnd_vio, open_pipe)(MYSQLND_VIO * const vio, const MYSQLND_CSTRING scheme, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info) { -#if PHP_API_VERSION < 20100412 - unsigned int streams_options = ENFORCE_SAFE_MODE; -#else unsigned int streams_options = 0; -#endif dtor_func_t origin_dtor; php_stream * net_stream = NULL; @@ -160,11 +156,7 @@ static php_stream * MYSQLND_METHOD(mysqlnd_vio, open_tcp_or_unix)(MYSQLND_VIO * const vio, const MYSQLND_CSTRING scheme, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info) { -#if PHP_API_VERSION < 20100412 - unsigned int streams_options = ENFORCE_SAFE_MODE; -#else unsigned int streams_options = 0; -#endif unsigned int streams_flags = STREAM_XPORT_CLIENT | STREAM_XPORT_CONNECT; char * hashed_details = NULL; int hashed_details_len = 0; @@ -566,11 +558,7 @@ MYSQLND_METHOD(mysqlnd_vio, enable_ssl)(MYSQLND_VIO * const net) php_stream_context_set_option(context, "ssl", "allow_self_signed", &verify_peer_zval); } } -#if PHP_API_VERSION >= 20131106 - php_stream_context_set(net_stream, context); -#else php_stream_context_set(net_stream, context); -#endif if (php_stream_xport_crypto_setup(net_stream, STREAM_CRYPTO_METHOD_TLS_CLIENT, NULL) < 0 || php_stream_xport_crypto_enable(net_stream, 1) < 0) { @@ -586,11 +574,7 @@ MYSQLND_METHOD(mysqlnd_vio, enable_ssl)(MYSQLND_VIO * const net) of the context, which means usage of already freed memory, bad. Actually we don't need this context anymore after we have enabled SSL on the connection. Thus it is very simple, we remove it. */ -#if PHP_API_VERSION >= 20131106 php_stream_context_set(net_stream, NULL); -#else - php_stream_context_set(net_stream, NULL); -#endif if (net->data->options.timeout_read) { struct timeval tv; diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index b174e62687..9e96d508e9 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -1458,7 +1458,7 @@ php_mysqlnd_read_row_ex(MYSQLND_PFC * pfc, MYSQLND_VIO * vio, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info, - MYSQLND_MEMORY_POOL * result_set_memory_pool, + MYSQLND_MEMORY_POOL * pool, MYSQLND_MEMORY_POOL_CHUNK ** buffer, size_t * data_size, zend_bool persistent_alloc, unsigned int prealloc_more_bytes) @@ -1489,7 +1489,7 @@ php_mysqlnd_read_row_ex(MYSQLND_PFC * pfc, if (first_iteration) { first_iteration = FALSE; - *buffer = result_set_memory_pool->get_chunk(result_set_memory_pool, *data_size); + *buffer = pool->get_chunk(pool, *data_size); if (!*buffer) { ret = FAIL; break; @@ -1504,7 +1504,7 @@ php_mysqlnd_read_row_ex(MYSQLND_PFC * pfc, /* We have to realloc the buffer. */ - if (FAIL == (*buffer)->resize_chunk((*buffer), *data_size)) { + if (FAIL == pool->resize_chunk(pool, *buffer, *data_size)) { SET_OOM_ERROR(error_info); ret = FAIL; break; @@ -1524,7 +1524,7 @@ php_mysqlnd_read_row_ex(MYSQLND_PFC * pfc, } } if (ret == FAIL && *buffer) { - (*buffer)->free_chunk((*buffer)); + pool->free_chunk(pool, *buffer); *buffer = NULL; } *data_size -= prealloc_more_bytes; @@ -1915,7 +1915,7 @@ php_mysqlnd_rowp_free_mem(void * _packet, zend_bool stack_allocation) DBG_ENTER("php_mysqlnd_rowp_free_mem"); p = (MYSQLND_PACKET_ROW *) _packet; if (p->row_buffer) { - p->row_buffer->free_chunk(p->row_buffer); + p->result_set_memory_pool->free_chunk(p->result_set_memory_pool, p->row_buffer); p->row_buffer = NULL; } DBG_INF_FMT("stack_allocation=%u persistent=%u", (int)stack_allocation, (int)p->header.persistent); diff --git a/ext/oci8/oci8.c b/ext/oci8/oci8.c index 86f22a208f..120f055a3a 100644 --- a/ext/oci8/oci8.c +++ b/ext/oci8/oci8.c @@ -103,12 +103,6 @@ zend_class_entry *oci_coll_class_entry_ptr; #define SQLT_CFILEE 115 #endif -#if ZEND_MODULE_API_NO > 20020429 -#define ONUPDATELONGFUNC OnUpdateLong -#else -#define ONUPDATELONGFUNC OnUpdateInt -#endif - #ifdef ZTS #define PHP_OCI_INIT_MODE (OCI_DEFAULT | OCI_OBJECT | OCI_THREADED | OCI_NO_MUTEX) #else @@ -144,8 +138,6 @@ ZEND_GET_MODULE(oci8) #endif /* COMPILE_DL */ /* }}} */ -#if defined(ZEND_ENGINE_2) || defined(ZEND_ENGINE_3) - /* {{{ Function arginfo */ ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_define_by_name, 0, 0, 3) ZEND_ARG_INFO(0, statement_resource) @@ -641,118 +633,6 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_oci_collection_trim_method, 0, 0, 1) ZEND_END_ARG_INFO() /* }}} */ -#else /* defined(ZEND_ENGINE_2) || defined(ZEND_ENGINE_3) */ -/* {{{ Keep the old arginfo behavior when building with PHP 4 */ - -static unsigned char arginfo_ocifetchinto[] = { 2, BYREF_NONE, BYREF_FORCE }; -static unsigned char arginfo_oci_fetch_all[] = { 2, BYREF_NONE, BYREF_FORCE }; -static unsigned char arginfo_oci_define_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE }; -static unsigned char arginfo_oci_bind_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE }; -static unsigned char arginfo_oci_bind_array_by_name[] = { 3, BYREF_NONE, BYREF_NONE, BYREF_FORCE }; - -#define arginfo_oci_free_descriptor NULL -#define arginfo_oci_lob_save NULL -#define arginfo_oci_lob_import NULL -#define arginfo_oci_lob_load NULL -#define arginfo_oci_lob_read NULL -#define arginfo_oci_lob_eof NULL -#define arginfo_oci_lob_tell NULL -#define arginfo_oci_lob_rewind NULL -#define arginfo_oci_lob_seek NULL -#define arginfo_oci_lob_size NULL -#define arginfo_oci_lob_write NULL -#define arginfo_oci_lob_append NULL -#define arginfo_oci_lob_truncate NULL -#define arginfo_oci_lob_erase NULL -#define arginfo_oci_lob_flush NULL -#define arginfo_ocisetbufferinglob NULL -#define arginfo_ocigetbufferinglob NULL -#define arginfo_oci_lob_copy NULL -#define arginfo_oci_lob_is_equal NULL -#define arginfo_oci_lob_export NULL -#define arginfo_oci_new_descriptor NULL -#define arginfo_oci_rollback NULL -#define arginfo_oci_commit NULL -#define arginfo_oci_field_name NULL -#define arginfo_oci_field_size NULL -#define arginfo_oci_field_scale NULL -#define arginfo_oci_field_precision NULL -#define arginfo_oci_field_type NULL -#define arginfo_oci_field_type_raw NULL -#define arginfo_oci_field_is_null NULL -#define arginfo_oci_internal_debug NULL -#define arginfo_oci_execute NULL -#define arginfo_oci_cancel NULL -#define arginfo_oci_fetch NULL -#define arginfo_oci_fetch_object NULL -#define arginfo_oci_fetch_row NULL -#define arginfo_oci_fetch_assoc NULL -#define arginfo_oci_fetch_array NULL -#define arginfo_oci_free_statement NULL -#define arginfo_oci_close NULL -#define arginfo_oci_new_connect NULL -#define arginfo_oci_connect NULL -#define arginfo_oci_pconnect NULL -#define arginfo_oci_error NULL -#define arginfo_oci_num_fields NULL -#define arginfo_oci_parse NULL -#define arginfo_oci_get_implicit_resultset NULL -#define arginfo_oci_set_prefetch NULL -#define arginfo_oci_set_client_identifier NULL -#define arginfo_oci_set_edition NULL -#define arginfo_oci_set_module_name NULL -#define arginfo_oci_set_action NULL -#define arginfo_oci_set_client_info NULL -#ifdef WAITIING_ORACLE_BUG_16695981_FIX -#define arginfo_oci_set_db_operation NULL -#endif -#define arginfo_oci_password_change NULL -#define arginfo_oci_new_cursor NULL -#define arginfo_oci_result NULL -#define arginfo_oci_client_version NULL -#define arginfo_oci_server_version NULL -#define arginfo_oci_statement_type NULL -#define arginfo_oci_num_rows NULL -#define arginfo_oci_free_collection NULL -#define arginfo_oci_collection_append NULL -#define arginfo_oci_collection_element_get NULL -#define arginfo_oci_collection_assign NULL -#define arginfo_oci_collection_element_assign NULL -#define arginfo_oci_collection_size NULL -#define arginfo_oci_collection_max NULL -#define arginfo_oci_collection_trim NULL -#define arginfo_oci_new_collection NULL -#define arginfo_oci_lob_size_method NULL -#define arginfo_oci_lob_getbuffering_method NULL -#define arginfo_oci_lob_close_method NULL -#define arginfo_oci_lob_save_method NULL -#define arginfo_oci_lob_import_method NULL -#define arginfo_oci_lob_read_method NULL -#define arginfo_oci_lob_seek_method NULL -#define arginfo_oci_lob_write_method NULL -#define arginfo_oci_lob_append_method NULL -#define arginfo_oci_lob_truncate_method NULL -#define arginfo_oci_lob_erase_method NULL -#define arginfo_oci_lob_flush_method NULL -#define arginfo_oci_lob_setbuffering_method NULL -#define arginfo_oci_lob_export_method NULL -#define arginfo_oci_lob_write_temporary_method NULL -#define arginfo_oci_lob_load_method NULL -#define arginfo_oci_lob_tell_method NULL -#define arginfo_oci_lob_rewind_method NULL -#define arginfo_oci_lob_eof_method NULL -#define arginfo_oci_free_descriptor_method NULL -#define arginfo_oci_collection_append_method NULL -#define arginfo_oci_collection_element_get_method NULL -#define arginfo_oci_collection_assign_method NULL -#define arginfo_oci_collection_size_method NULL -#define arginfo_oci_collection_element_assign_method NULL -#define arginfo_oci_collection_max_method NULL -#define arginfo_oci_collection_trim_method NULL -#define arginfo_oci_collection_free_method NULL -/* }}} */ -#endif /* defined(ZEND_ENGINE_2) || defined(ZEND_ENGINE_3) */ - /* {{{ extension function prototypes */ PHP_FUNCTION(oci_bind_by_name); @@ -839,12 +719,7 @@ PHP_FUNCTION(oci_collection_trim); /* {{{ extension definition structures */ -static -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5) -/* This "if" allows PECL builds from this file to be portable to older PHP releases */ -const -#endif -zend_function_entry php_oci_functions[] = { +static const zend_function_entry php_oci_functions[] = { PHP_FE(oci_define_by_name, arginfo_oci_define_by_name) PHP_FE(oci_bind_by_name, arginfo_oci_bind_by_name) PHP_FE(oci_bind_array_by_name, arginfo_oci_bind_array_by_name) @@ -970,19 +845,10 @@ zend_function_entry php_oci_functions[] = { PHP_FALIAS(ocicollsize, oci_collection_size, arginfo_oci_collection_size) PHP_FALIAS(ocicollmax, oci_collection_max, arginfo_oci_collection_max) PHP_FALIAS(ocicolltrim, oci_collection_trim, arginfo_oci_collection_trim) -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 7) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5) PHP_FE_END -#else - {NULL,NULL,NULL} -#endif }; -static -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5) -/* This "if" allows PECL builds from this file to be portable to older PHP releases */ -const -#endif -zend_function_entry php_oci_lob_class_functions[] = { +static const zend_function_entry php_oci_lob_class_functions[] = { PHP_FALIAS(load, oci_lob_load, arginfo_oci_lob_load_method) PHP_FALIAS(tell, oci_lob_tell, arginfo_oci_lob_tell_method) PHP_FALIAS(truncate, oci_lob_truncate, arginfo_oci_lob_truncate_method) @@ -1005,19 +871,10 @@ zend_function_entry php_oci_lob_class_functions[] = { PHP_FALIAS(save, oci_lob_save, arginfo_oci_lob_save_method) PHP_FALIAS(savefile, oci_lob_import, arginfo_oci_lob_import_method) PHP_FALIAS(free, oci_free_descriptor, arginfo_oci_free_descriptor_method) -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 7) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5) PHP_FE_END -#else - {NULL,NULL,NULL} -#endif }; -static -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 2) || (PHP_MAJOR_VERSION > 5) -/* This "if" allows PECL builds from this file to be portable to older PHP releases */ -const -#endif -zend_function_entry php_oci_coll_class_functions[] = { +static const zend_function_entry php_oci_coll_class_functions[] = { PHP_FALIAS(append, oci_collection_append, arginfo_oci_collection_append_method) PHP_FALIAS(getelem, oci_collection_element_get, arginfo_oci_collection_element_get_method) PHP_FALIAS(assignelem, oci_collection_element_assign, arginfo_oci_collection_element_assign_method) @@ -1026,11 +883,7 @@ zend_function_entry php_oci_coll_class_functions[] = { PHP_FALIAS(max, oci_collection_max, arginfo_oci_collection_max_method) PHP_FALIAS(trim, oci_collection_trim, arginfo_oci_collection_trim_method) PHP_FALIAS(free, oci_free_collection, arginfo_oci_collection_free_method) -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION == 3 && PHP_RELEASE_VERSION >= 7) || (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION >= 4) || (PHP_MAJOR_VERSION > 5) PHP_FE_END -#else - {NULL,NULL,NULL} -#endif }; zend_module_entry oci8_module_entry = { @@ -1053,12 +906,12 @@ zend_module_entry oci8_module_entry = { /* {{{ PHP_INI */ PHP_INI_BEGIN() - STD_PHP_INI_ENTRY( "oci8.max_persistent", "-1", PHP_INI_SYSTEM, ONUPDATELONGFUNC, max_persistent, zend_oci_globals, oci_globals) - STD_PHP_INI_ENTRY( "oci8.persistent_timeout", "-1", PHP_INI_SYSTEM, ONUPDATELONGFUNC, persistent_timeout, zend_oci_globals, oci_globals) - STD_PHP_INI_ENTRY( "oci8.ping_interval", "60", PHP_INI_SYSTEM, ONUPDATELONGFUNC, ping_interval, zend_oci_globals, oci_globals) + STD_PHP_INI_ENTRY( "oci8.max_persistent", "-1", PHP_INI_SYSTEM, OnUpdateLong, max_persistent, zend_oci_globals, oci_globals) + STD_PHP_INI_ENTRY( "oci8.persistent_timeout", "-1", PHP_INI_SYSTEM, OnUpdateLong, persistent_timeout, zend_oci_globals, oci_globals) + STD_PHP_INI_ENTRY( "oci8.ping_interval", "60", PHP_INI_SYSTEM, OnUpdateLong, ping_interval, zend_oci_globals, oci_globals) STD_PHP_INI_BOOLEAN("oci8.privileged_connect", "0", PHP_INI_SYSTEM, OnUpdateBool, privileged_connect, zend_oci_globals, oci_globals) - STD_PHP_INI_ENTRY( "oci8.statement_cache_size", "20", PHP_INI_SYSTEM, ONUPDATELONGFUNC, statement_cache_size, zend_oci_globals, oci_globals) - STD_PHP_INI_ENTRY( "oci8.default_prefetch", "100", PHP_INI_SYSTEM, ONUPDATELONGFUNC, default_prefetch, zend_oci_globals, oci_globals) + STD_PHP_INI_ENTRY( "oci8.statement_cache_size", "20", PHP_INI_SYSTEM, OnUpdateLong, statement_cache_size, zend_oci_globals, oci_globals) + STD_PHP_INI_ENTRY( "oci8.default_prefetch", "100", PHP_INI_SYSTEM, OnUpdateLong, default_prefetch, zend_oci_globals, oci_globals) STD_PHP_INI_BOOLEAN("oci8.old_oci_close_semantics", "0", PHP_INI_SYSTEM, OnUpdateBool, old_oci_close_semantics,zend_oci_globals, oci_globals) #if (OCI_MAJOR_VERSION >= 11) STD_PHP_INI_ENTRY( "oci8.connection_class", "", PHP_INI_ALL, OnUpdateString, connection_class, zend_oci_globals, oci_globals) @@ -1839,13 +1692,6 @@ php_oci_connection *php_oci_do_connect_ex(char *username, int username_len, char php_error_docref(NULL, E_WARNING, "Privileged connect is disabled. Enable oci8.privileged_connect to be able to connect as SYSOPER or SYSDBA"); return NULL; } -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5) - /* Safe mode has been removed in PHP 5.4 */ - if (PG(safe_mode)) { - php_error_docref(NULL, E_WARNING, "Privileged connect is disabled in Safe Mode"); - return NULL; - } -#endif } } diff --git a/ext/oci8/oci8_interface.c b/ext/oci8/oci8_interface.c index 76a6530cab..e3bd509216 100644 --- a/ext/oci8/oci8_interface.c +++ b/ext/oci8/oci8_interface.c @@ -240,32 +240,16 @@ PHP_FUNCTION(oci_lob_import) size_t filename_len; if (getThis()) { -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) if (zend_parse_parameters(ZEND_NUM_ARGS(), "p", &filename, &filename_len) == FAILURE) { -#else - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &filename, &filename_len) == FAILURE) { -#endif return; } } else { -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) if (zend_parse_parameters(ZEND_NUM_ARGS(), "Op", &z_descriptor, oci_lob_class_entry_ptr, &filename, &filename_len) == FAILURE) { -#else - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os", &z_descriptor, oci_lob_class_entry_ptr, &filename, &filename_len) == FAILURE) { -#endif return; } } -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5) - /* The "p" parsing parameter handles this case in PHP 5.4+ */ - if (strlen(filename) != filename_len) { - php_error_docref(NULL, E_WARNING, "Filename cannot contain null bytes"); - RETURN_FALSE; - } -#endif - if ((tmp = zend_hash_str_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor")-1)) == NULL) { php_error_docref(NULL, E_WARNING, "Unable to find descriptor property"); RETURN_FALSE; @@ -899,11 +883,7 @@ PHP_FUNCTION(oci_lob_export) ub4 lob_length; if (getThis()) { -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|ll", &filename, &filename_len, &start, &length) == FAILURE) { -#else - if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|ll", &filename, &filename_len, &start, &length) == FAILURE) { -#endif return; } @@ -917,11 +897,7 @@ PHP_FUNCTION(oci_lob_export) } } else { -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) if (zend_parse_parameters(ZEND_NUM_ARGS(), "Op|ll", &z_descriptor, oci_lob_class_entry_ptr, &filename, &filename_len, &start, &length) == FAILURE) { -#else - if (zend_parse_parameters(ZEND_NUM_ARGS(), "Os|ll", &z_descriptor, oci_lob_class_entry_ptr, &filename, &filename_len, &start, &length) == FAILURE) { -#endif return; } @@ -935,14 +911,6 @@ PHP_FUNCTION(oci_lob_export) } } -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5) - /* The "p" parsing parameter handles this case in PHP 5.4+ */ - if (strlen(filename) != filename_len) { - php_error_docref(NULL, E_WARNING, "Filename cannot contain null bytes"); - RETURN_FALSE; - } -#endif - if ((tmp = zend_hash_str_find(Z_OBJPROP_P(z_descriptor), "descriptor", sizeof("descriptor")-1)) == NULL) { php_error_docref(NULL, E_WARNING, "Unable to find descriptor property"); RETURN_FALSE; @@ -971,22 +939,11 @@ PHP_FUNCTION(oci_lob_export) RETURN_FALSE; } -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5) - /* Safe mode has been removed in PHP 5.4 */ - if (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { - RETURN_FALSE; - } -#endif - if (php_check_open_basedir(filename)) { RETURN_FALSE; } -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) stream = php_stream_open_wrapper_ex(filename, "w", REPORT_ERRORS, NULL, NULL); -#else - stream = php_stream_open_wrapper_ex(filename, "w", ENFORCE_SAFE_MODE | REPORT_ERRORS, NULL, NULL); -#endif block_length = PHP_OCI_LOB_BUFFER_SIZE; if (block_length > length) { @@ -1985,14 +1942,6 @@ PHP_FUNCTION(oci_password_change) size_t user_len, pass_old_len, pass_new_len, dbname_len; php_oci_connection *connection; -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 4) || (PHP_MAJOR_VERSION < 5) - /* Safe mode has been removed in PHP 5.4 */ - if (PG(safe_mode)) { - php_error_docref(NULL, E_WARNING, "is disabled in Safe Mode"); - RETURN_FALSE; - } -#endif - if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "rsss", &z_connection, &user, &user_len, &pass_old, &pass_old_len, &pass_new, &pass_new_len) == SUCCESS) { PHP_OCI_ZVAL_TO_CONNECTION(z_connection, connection); diff --git a/ext/oci8/oci8_lob.c b/ext/oci8/oci8_lob.c index d7b949ae13..78ba8f11fa 100644 --- a/ext/oci8/oci8_lob.c +++ b/ext/oci8/oci8_lob.c @@ -716,12 +716,7 @@ int php_oci_lob_import (php_oci_descriptor *descriptor, char *filename) ub4 offset = 1; sword errstatus; -#if (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION > 3) || (PHP_MAJOR_VERSION > 5) - /* Safe mode has been removed in PHP 5.4 */ if (php_check_open_basedir(filename)) { -#else - if ((PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename)) { -#endif return 1; } diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index a91d7b783d..d835dfb9a0 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -445,6 +445,9 @@ static void _free_odbc_result(zend_resource *rsrc) * zend_list_delete(res->conn_ptr->id); */ } + if (res->param_info) { + efree(res->param_info); + } efree(res); } } @@ -1184,6 +1187,7 @@ PHP_FUNCTION(odbc_prepare) odbc_result *result = NULL; odbc_connection *conn; RETCODE rc; + int i; #ifdef HAVE_SQL_EXTENDED_FETCH SQLUINTEGER scrollopts; #endif @@ -1199,6 +1203,7 @@ PHP_FUNCTION(odbc_prepare) result = (odbc_result *)ecalloc(1, sizeof(odbc_result)); result->numparams = 0; + result->param_info = NULL; rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt)); if (rc == SQL_INVALID_HANDLE) { @@ -1255,6 +1260,20 @@ PHP_FUNCTION(odbc_prepare) Z_ADDREF_P(pv_conn); result->conn_ptr = conn; result->fetched = 0; + + result->param_info = (odbc_param_info *) safe_emalloc(sizeof(odbc_param_info), result->numparams, 0); + for (i=0;i<result->numparams;i++) { + rc = SQLDescribeParam(result->stmt, (SQLUSMALLINT)(i+1), &result->param_info[i].sqltype, &result->param_info[i].precision, + &result->param_info[i].scale, &result->param_info[i].nullable); + if (rc == SQL_ERROR) { + odbc_sql_error(result->conn_ptr, result->stmt, "SQLDescribeParameter"); + SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); + efree(result->param_info); + efree(result); + RETURN_FALSE; + } + } + RETURN_RES(zend_register_resource(result, le_result)); } /* }}} */ @@ -1275,9 +1294,7 @@ PHP_FUNCTION(odbc_execute) params_t *params = NULL; char *filename; unsigned char otype; - SQLSMALLINT sqltype, ctype, scale; - SQLSMALLINT nullable; - SQLULEN precision; + SQLSMALLINT ctype; odbc_result *result; int numArgs, i, ne; RETCODE rc; @@ -1337,22 +1354,10 @@ PHP_FUNCTION(odbc_execute) RETURN_FALSE; } - rc = SQLDescribeParam(result->stmt, (SQLUSMALLINT)i, &sqltype, &precision, &scale, &nullable); params[i-1].vallen = Z_STRLEN_P(tmp); params[i-1].fp = -1; - if (rc == SQL_ERROR) { - odbc_sql_error(result->conn_ptr, result->stmt, "SQLDescribeParam"); - SQLFreeStmt(result->stmt, SQL_RESET_PARAMS); - for (i = 0; i < result->numparams; i++) { - if (params[i].fp != -1) { - close(params[i].fp); - } - } - efree(params); - RETURN_FALSE; - } - if (IS_SQL_BINARY(sqltype)) { + if (IS_SQL_BINARY(result->param_info[i-1].sqltype)) { ctype = SQL_C_BINARY; } else { ctype = SQL_C_CHAR; @@ -1399,7 +1404,7 @@ PHP_FUNCTION(odbc_execute) params[i-1].vallen = SQL_LEN_DATA_AT_EXEC(0); rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT, - ctype, sqltype, precision, scale, + ctype, result->param_info[i-1].sqltype, result->param_info[i-1].precision, result->param_info[i-1].scale, (void *)(intptr_t)params[i-1].fp, 0, ¶ms[i-1].vallen); } else { @@ -1411,7 +1416,7 @@ PHP_FUNCTION(odbc_execute) } rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT, - ctype, sqltype, precision, scale, + ctype, result->param_info[i-1].sqltype, result->param_info[i-1].precision, result->param_info[i-1].scale, Z_STRVAL_P(tmp), 0, ¶ms[i-1].vallen); } diff --git a/ext/odbc/php_odbc_includes.h b/ext/odbc/php_odbc_includes.h index dad7ff1c95..fa525ed4ad 100644 --- a/ext/odbc/php_odbc_includes.h +++ b/ext/odbc/php_odbc_includes.h @@ -233,6 +233,13 @@ typedef struct odbc_result_value { SQLLEN coltype; } odbc_result_value; +typedef struct odbc_param_info { + SQLSMALLINT sqltype; + SQLSMALLINT scale; + SQLSMALLINT nullable; + SQLULEN precision; +} odbc_param_info; + typedef struct odbc_result { ODBC_SQL_STMT_T stmt; odbc_result_value *values; @@ -244,6 +251,7 @@ typedef struct odbc_result { zend_long longreadlen; int binmode; int fetched; + odbc_param_info * param_info; odbc_connection *conn_ptr; } odbc_result; diff --git a/ext/odbc/tests/bug47803.phpt b/ext/odbc/tests/bug47803.phpt new file mode 100644 index 0000000000..9a2600dd18 --- /dev/null +++ b/ext/odbc/tests/bug47803.phpt @@ -0,0 +1,185 @@ +--TEST-- +Bug #47803 Executing prepared statements is succesfull only for the first two statements +--SKIPIF-- +<?php include 'skipif.inc'; ?> +--FILE-- +<?php + +include dirname(__FILE__) . "/config.inc"; + +$create_table = "CREATE TABLE FOO( + [PAR_ID] [int] NOT NULL, + [PAR_INT] [int] NULL, + [PAR_CHR] [varchar](500) NULL +)"; + +$inserts = "INSERT INTO FOO + ([PAR_ID] + ,[PAR_INT] + ,[PAR_CHR]) + VALUES + (1,14,''), + (2,30,''), + (3,7,''), + (4,7,''), + (5,0,''), + (6,0,''), + (7,20130901,''), + (8,20140201,''), + (9,20140201,''), + (10,20140620,''), + (11,221,'')"; + + +date_default_timezone_set('Europe/Warsaw'); + +$link = odbc_connect($dsn, $user, $pass); + +odbc_exec($link, 'CREATE DATABASE odbcTEST'); +odbc_exec($link, $create_table); +odbc_exec($link, $inserts); + +$upd_params = array( + array('id'=>1, 'name'=>'test 1'), + array('id'=>2, 'name'=>'test 2'), + array('id'=>3, 'name'=>'test 3'), + array('id'=>4, 'name'=>'test 4'), + array('id'=>5, 'name'=>'test 5'), + array('id'=>10, 'name'=>'test 10'), + array('id'=>9, 'name'=>'test 9'), + array('id'=>8, 'name'=>'test 8'), + array('id'=>7, 'name'=>'test 7'), + array('id'=>6, 'name'=>'test 6'), +); +$sql = "UPDATE FOO + SET [PAR_CHR] = ? + WHERE [PAR_ID] = ?"; +$result = odbc_prepare($link, $sql); +if (!$result) { + print ('[sql] prep: '.$sql); + goto out; +} +foreach ($upd_params as &$k) { + if(!odbc_execute($result, array($k['name'], $k['id']))) { + print ('[sql] exec: '."array({$k['name']}, {$k['id']})"); + goto out; + } +} +odbc_free_result($result); + +$sql = "SELECT * FROM FOO WHERE [PAR_ID] = ?"; +$result = odbc_prepare($link, $sql); +if (!$result) { + print ('[sql] prep: '.$sql); + goto out; +} +foreach ($upd_params as $k) { + if(!odbc_execute($result, array($k['id']))) { + print ('[sql] exec: '."array({$k['id']})"); + goto out; + } + while (($r = odbc_fetch_array($result)) !== false) { + var_dump($r); + } +} + +out: +if ($result) odbc_free_result($result); +odbc_close($link); + +?> +==DONE== +--EXPECT-- +array(3) { + ["PAR_ID"]=> + string(1) "1" + ["PAR_INT"]=> + string(2) "14" + ["PAR_CHR"]=> + string(6) "test 1" +} +array(3) { + ["PAR_ID"]=> + string(1) "2" + ["PAR_INT"]=> + string(2) "30" + ["PAR_CHR"]=> + string(6) "test 2" +} +array(3) { + ["PAR_ID"]=> + string(1) "3" + ["PAR_INT"]=> + string(1) "7" + ["PAR_CHR"]=> + string(6) "test 3" +} +array(3) { + ["PAR_ID"]=> + string(1) "4" + ["PAR_INT"]=> + string(1) "7" + ["PAR_CHR"]=> + string(6) "test 4" +} +array(3) { + ["PAR_ID"]=> + string(1) "5" + ["PAR_INT"]=> + string(1) "0" + ["PAR_CHR"]=> + string(6) "test 5" +} +array(3) { + ["PAR_ID"]=> + string(2) "10" + ["PAR_INT"]=> + string(8) "20140620" + ["PAR_CHR"]=> + string(7) "test 10" +} +array(3) { + ["PAR_ID"]=> + string(1) "9" + ["PAR_INT"]=> + string(8) "20140201" + ["PAR_CHR"]=> + string(6) "test 9" +} +array(3) { + ["PAR_ID"]=> + string(1) "8" + ["PAR_INT"]=> + string(8) "20140201" + ["PAR_CHR"]=> + string(6) "test 8" +} +array(3) { + ["PAR_ID"]=> + string(1) "7" + ["PAR_INT"]=> + string(8) "20130901" + ["PAR_CHR"]=> + string(6) "test 7" +} +array(3) { + ["PAR_ID"]=> + string(1) "7" + ["PAR_INT"]=> + string(8) "20130901" + ["PAR_CHR"]=> + string(6) "test 7" +} +==DONE== +--CLEAN-- +<?php +include 'config.inc'; + +$conn = odbc_connect($dsn, $user, $pass); + +odbc_exec($conn, 'DROP TABLE FOO'); +odbc_exec($conn, 'DROP DATABASE odbcTEST'); + +odbc_close($conn); + +?> diff --git a/ext/odbc/tests/bug71171.phpt b/ext/odbc/tests/bug71171.phpt new file mode 100644 index 0000000000..94cfb4d0e8 --- /dev/null +++ b/ext/odbc/tests/bug71171.phpt @@ -0,0 +1,43 @@ +--TEST-- +Bug #71171 odbc_fetch_array generates SIGFAULT, variant 0 +--SKIPIF-- +<?php include 'skipif.inc'; ?> +--FILE-- +<?php + +include 'config.inc'; + +$conn = odbc_connect($dsn, $user, $pass); + +@odbc_exec($conn, 'CREATE DATABASE odbcTEST'); + +odbc_exec($conn, 'CREATE TABLE FOO (ID INT, VARCHAR_COL NVARCHAR(40))'); + +odbc_exec($conn, "INSERT INTO FOO(ID, VARCHAR_COL) VALUES (1, '" . chr(0x81) . "')"); + +$res = odbc_exec($conn,"SELECT ID FROM FOO WHERE VARCHAR_COL = '" . chr(0x81) . "'"); +if ($res) { + while($record = odbc_fetch_array($res)) var_dump($record); +} + +odbc_close($conn); +?> +==DONE== +--EXPECT-- +array(1) { + ["ID"]=> + string(1) "1" +} +==DONE== +--CLEAN-- +<?php +include 'config.inc'; + +$conn = odbc_connect($dsn, $user, $pass); + +odbc_exec($conn, 'DROP TABLE FOO'); +odbc_exec($conn, 'DROP DATABASE odbcTEST'); + +odbc_close($conn); + +?> diff --git a/ext/odbc/tests/config.inc b/ext/odbc/tests/config.inc index a88eea4ed0..dcc4cbb3bf 100644 --- a/ext/odbc/tests/config.inc +++ b/ext/odbc/tests/config.inc @@ -3,6 +3,17 @@ putenv('ODBCINI=/etc/odbc.ini'); putenv('ODBCSYSINI=/etc'); -$dsn = 'myodbc3'; -$user = 'root'; -$pass = ''; +$dsn = getenv("ODBC_TEST_DSN"); +$user = getenv("ODBC_TEST_USER"); +$pass = getenv("ODBC_TEST_PASS"); + +if (false === $dsn) { + $dsn = 'myodbc3'; +} +if (false === $user) { + $user = 'root'; +} +if (false == $pass) { + $pass = ''; +} + diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c index 24a9157f2c..4f4dd8e11a 100644 --- a/ext/opcache/Optimizer/block_pass.c +++ b/ext/opcache/Optimizer/block_pass.c @@ -206,7 +206,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array l = old_len + Z_STRLEN(ZEND_OP1_LITERAL(opline)); if (!Z_REFCOUNTED(ZEND_OP1_LITERAL(last_op))) { zend_string *tmp = zend_string_alloc(l, 0); - memcpy(ZSTR_VAL(tmp), Z_STRVAL(ZEND_OP1_LITERAL(last_op)), old_len); + memcpy(ZSTR_VAL(tmp), Z_STRVAL(ZEND_OP1_LITERAL(last_op)), old_len); Z_STR(ZEND_OP1_LITERAL(last_op)) = tmp; } else { Z_STR(ZEND_OP1_LITERAL(last_op)) = zend_string_extend(Z_STR(ZEND_OP1_LITERAL(last_op)), l, 0); @@ -215,10 +215,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array memcpy(Z_STRVAL(ZEND_OP1_LITERAL(last_op)) + old_len, Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline))); Z_STRVAL(ZEND_OP1_LITERAL(last_op))[l] = '\0'; zval_dtor(&ZEND_OP1_LITERAL(opline)); - Z_STR(ZEND_OP1_LITERAL(opline)) = zend_new_interned_string(Z_STR(ZEND_OP1_LITERAL(last_op))); - if (!Z_REFCOUNTED(ZEND_OP1_LITERAL(opline))) { - Z_TYPE_FLAGS(ZEND_OP1_LITERAL(opline)) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); - } + ZVAL_STR(&ZEND_OP1_LITERAL(opline), zend_new_interned_string(Z_STR(ZEND_OP1_LITERAL(last_op)))); ZVAL_NULL(&ZEND_OP1_LITERAL(last_op)); MAKE_NOP(last_op); } @@ -252,12 +249,13 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array src->opcode != ZEND_FETCH_R && src->opcode != ZEND_FETCH_STATIC_PROP_R && src->opcode != ZEND_FETCH_DIM_R && - src->opcode != ZEND_FETCH_OBJ_R) { + src->opcode != ZEND_FETCH_OBJ_R && + src->opcode != ZEND_NEW) { if (opline->extended_value & ZEND_FREE_ON_RETURN) { /* mark as removed (empty live range) */ op_array->live_range[opline->op2.num].var = (uint32_t)-1; } - ZEND_RESULT_TYPE(src) |= EXT_TYPE_UNUSED; + ZEND_RESULT_TYPE(src) = IS_UNUSED; MAKE_NOP(opline); } } @@ -586,10 +584,7 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array memcpy(Z_STRVAL(ZEND_OP2_LITERAL(src)) + old_len, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline))); Z_STRVAL(ZEND_OP2_LITERAL(src))[l] = '\0'; zend_string_release(Z_STR(ZEND_OP2_LITERAL(opline))); - Z_STR(ZEND_OP2_LITERAL(opline)) = zend_new_interned_string(Z_STR(ZEND_OP2_LITERAL(src))); - if (!Z_REFCOUNTED(ZEND_OP2_LITERAL(opline))) { - Z_TYPE_FLAGS(ZEND_OP2_LITERAL(opline)) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); - } + ZVAL_STR(&ZEND_OP2_LITERAL(opline), zend_new_interned_string(Z_STR(ZEND_OP2_LITERAL(src)))); ZVAL_NULL(&ZEND_OP2_LITERAL(src)); MAKE_NOP(src); } @@ -749,7 +744,7 @@ optimize_const_unary_op: } /* get variable source */ - if (opline->result_type == IS_VAR || opline->result_type == IS_TMP_VAR) { + if (opline->result_type & (IS_VAR|IS_TMP_VAR)) { SET_VAR_SOURCE(opline); } opline++; @@ -953,17 +948,20 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array) } if (i != j) { - zend_op *opline = new_opcodes; - zend_op *end = opline + len; - - op_array->last_live_range = j; - while (opline != end) { - if ((opline->opcode == ZEND_FREE || opline->opcode == ZEND_FE_FREE) && - opline->extended_value == ZEND_FREE_ON_RETURN) { - ZEND_ASSERT(opline->op2.num < (uint32_t) i); - opline->op2.num = map[opline->op2.num]; + if ((op_array->last_live_range = j)) { + zend_op *opline = new_opcodes; + zend_op *end = opline + len; + while (opline != end) { + if ((opline->opcode == ZEND_FREE || opline->opcode == ZEND_FE_FREE) && + opline->extended_value == ZEND_FREE_ON_RETURN) { + ZEND_ASSERT(opline->op2.num < (uint32_t) i); + opline->op2.num = map[opline->op2.num]; + } + opline++; } - opline++; + } else { + efree(op_array->live_range); + op_array->live_range = NULL; } } free_alloca(map, use_heap); @@ -1504,7 +1502,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use } while (opline<end) { - if (opline->op1_type == IS_VAR || opline->op1_type == IS_TMP_VAR) { + if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { var_num = VAR_NUM(opline->op1.var); if (!zend_bitset_in(defined_here, var_num)) { zend_bitset_incl(used_ext, var_num); @@ -1612,7 +1610,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use case ZEND_DO_ICALL: case ZEND_DO_UCALL: case ZEND_DO_FCALL_BY_NAME: - opline->result_type |= EXT_TYPE_UNUSED; + opline->result_type = IS_UNUSED; break; } } else { @@ -1624,7 +1622,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use case ZEND_POST_INC: case ZEND_POST_DEC: opline->opcode -= 2; - opline->result_type = IS_VAR | EXT_TYPE_UNUSED; + opline->result_type = IS_UNUSED; break; case ZEND_QM_ASSIGN: case ZEND_BOOL: @@ -1670,7 +1668,7 @@ static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset use zend_bitset_incl(usage, VAR_NUM(opline->op2.var)); } - if (opline->op1_type == IS_VAR || opline->op1_type == IS_TMP_VAR) { + if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { zend_bitset_incl(usage, VAR_NUM(opline->op1.var)); } @@ -1736,7 +1734,7 @@ static void zend_merge_blocks(zend_op_array *op_array, zend_cfg *cfg) #define PASSES 3 -void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx) +void zend_optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_cfg cfg; zend_basic_block *blocks, *end, *b; @@ -1749,7 +1747,7 @@ void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx) /* Build CFG */ checkpoint = zend_arena_checkpoint(ctx->arena); - if (zend_build_cfg(&ctx->arena, op_array, 0, &cfg, NULL) != SUCCESS) { + if (zend_build_cfg(&ctx->arena, op_array, ZEND_CFG_SPLIT_AT_LIVE_RANGES, &cfg, NULL) != SUCCESS) { zend_arena_release(&ctx->arena, checkpoint); return; } diff --git a/ext/opcache/Optimizer/dfa_pass.c b/ext/opcache/Optimizer/dfa_pass.c index a1872e3d81..dac4ab2f45 100644 --- a/ext/opcache/Optimizer/dfa_pass.c +++ b/ext/opcache/Optimizer/dfa_pass.c @@ -34,6 +34,11 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, { uint32_t build_flags; + if (op_array->last_try_catch) { + /* TODO: we can't analyze functions with try/catch/finally ??? */ + return FAILURE; + } + /* Build SSA */ memset(ssa, 0, sizeof(zend_ssa)); @@ -41,7 +46,8 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, return FAILURE; } - if (*flags & ZEND_FUNC_TOO_DYNAMIC) { + if (*flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) { + /* TODO: we can't analyze functions with indirect variable access ??? */ return FAILURE; } @@ -50,7 +56,7 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, } if (ctx->debug_level & ZEND_DUMP_DFA_CFG) { - zend_dump_op_array(op_array, ZEND_DUMP_CFG | ZEND_DUMP_HIDE_UNUSED_VARS, "dfa cfg", &ssa->cfg); + zend_dump_op_array(op_array, ZEND_DUMP_CFG, "dfa cfg", &ssa->cfg); } /* Compute Dominators Tree */ @@ -79,7 +85,7 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, } if (ctx->debug_level & ZEND_DUMP_DFA_SSA) { - zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "before dfa pass", ssa); + zend_dump_op_array(op_array, ZEND_DUMP_SSA, "before dfa pass", ssa); } @@ -100,7 +106,7 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, } if (ctx->debug_level & ZEND_DUMP_DFA_SSA_VARS) { - zend_dump_ssa_variables(op_array, ssa); + zend_dump_ssa_variables(op_array, ssa, 0); } return SUCCESS; @@ -109,7 +115,7 @@ int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa) { if (ctx->debug_level & ZEND_DUMP_BEFORE_DFA_PASS) { - zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "before dfa pass", ssa); + zend_dump_op_array(op_array, ZEND_DUMP_SSA, "before dfa pass", ssa); } if (ssa->var_info) { @@ -119,9 +125,7 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx // 1: #1.T = OP_Y | #3.CV = OP_Y // 2: ASSIGN #2.CV [undef,scalar] -> #3.CV, #1.T | NOP // -- - // 2: ASSIGN #2.CV [undef,scalar] -> #3.CV, C | 3.CV = QM_ASSIGN C - // -- - // 2: ASSIGN #2.CV [undef,scalar] -> #3.CV, #1.CV | 3.CV = QM_ASSIGN #1.CV + // 2: ASSIGN #2.CV [undef,scalar] -> #3.CV, X | 3.CV = QM_ASSIGN X for (i = 0; i < ssa->vars_count; i++) { int op2 = ssa->vars[i].definition; @@ -137,47 +141,46 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx && !(ssa->var_info[var2].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) ) { - if (op_array->opcodes[op2].op2_type & (IS_TMP_VAR|IS_VAR)) { + if ((op_array->opcodes[op2].op2_type & (IS_TMP_VAR|IS_VAR)) + && ssa->ops[op2].op2_use >= 0 + && !(ssa->var_info[ssa->ops[op2].op2_use].type & MAY_BE_REF) + && ssa->vars[ssa->ops[op2].op2_use].definition >= 0 + && ssa->ops[ssa->vars[ssa->ops[op2].op2_use].definition].result_def == ssa->ops[op2].op2_use + && ssa->ops[ssa->vars[ssa->ops[op2].op2_use].definition].result_use < 0 + && ssa->vars[ssa->ops[op2].op2_use].use_chain == op2 + && ssa->ops[op2].op2_use_chain < 0 + && !ssa->vars[ssa->ops[op2].op2_use].phi_use_chain + && !ssa->vars[ssa->ops[op2].op2_use].sym_use_chain + /* see Zend/tests/generators/aborted_yield_during_new.phpt */ + && op_array->opcodes[ssa->vars[ssa->ops[op2].op2_use].definition].opcode != ZEND_NEW + ) { int var1 = ssa->ops[op2].op2_use; + int op1 = ssa->vars[var1].definition; + int var3 = i; + + if (zend_ssa_unlink_use_chain(ssa, op2, var2)) { + /* Reconstruct SSA */ + ssa->vars[var3].definition = op1; + ssa->ops[op1].result_def = var3; + + ssa->vars[var1].definition = -1; + ssa->vars[var1].use_chain = -1; + + ssa->ops[op2].op1_use = -1; + ssa->ops[op2].op2_use = -1; + ssa->ops[op2].op1_def = -1; + ssa->ops[op2].op1_use_chain = -1; - if (var1 >= 0 - && !(ssa->var_info[var1].type & MAY_BE_REF) - && ssa->vars[var1].definition >= 0 - && ssa->ops[ssa->vars[var1].definition].result_def == var1 - && ssa->ops[ssa->vars[var1].definition].result_use < 0 - && ssa->vars[var1].use_chain == op2 - && ssa->ops[op2].op2_use_chain < 0 - && !ssa->vars[var1].phi_use_chain - && !ssa->vars[var1].sym_use_chain - ) { - int op1 = ssa->vars[var1].definition; - int var3 = i; - - if (zend_ssa_unlink_use_chain(ssa, op2, var2)) { - /* Reconstruct SSA */ - ssa->vars[var3].definition = op1; - ssa->ops[op1].result_def = var3; - - ssa->vars[var1].definition = -1; - ssa->vars[var1].use_chain = -1; - - ssa->ops[op2].op1_use = -1; - ssa->ops[op2].op2_use = -1; - ssa->ops[op2].op1_def = -1; - ssa->ops[op2].op1_use_chain = -1; - - /* Update opcodes */ - op_array->opcodes[op1].result_type = op_array->opcodes[op2].op1_type; - op_array->opcodes[op1].result.var = op_array->opcodes[op2].op1.var; - MAKE_NOP(&op_array->opcodes[op2]); - remove_nops = 1; - } + /* Update opcodes */ + op_array->opcodes[op1].result_type = op_array->opcodes[op2].op1_type; + op_array->opcodes[op1].result.var = op_array->opcodes[op2].op1.var; + MAKE_NOP(&op_array->opcodes[op2]); + remove_nops = 1; } } else if (op_array->opcodes[op2].op2_type == IS_CONST - || (op_array->opcodes[op2].op2_type == IS_CV + || ((op_array->opcodes[op2].op2_type & (IS_TMP_VAR|IS_VAR|IS_CV)) && ssa->ops[op2].op2_use >= 0 - && ssa->ops[op2].op2_def < 0 - && !(ssa->var_info[ssa->ops[op2].op2_use].type & MAY_BE_REF)) + && ssa->ops[op2].op2_def < 0) ) { int var3 = i; @@ -209,11 +212,11 @@ void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx } if (ctx->debug_level & ZEND_DUMP_AFTER_DFA_PASS) { - zend_dump_op_array(op_array, ZEND_DUMP_SSA | ZEND_DUMP_HIDE_UNUSED_VARS, "after dfa pass", ssa); + zend_dump_op_array(op_array, ZEND_DUMP_SSA, "after dfa pass", ssa); } } -void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx) +void zend_optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx) { void *checkpoint = zend_arena_checkpoint(ctx->arena); uint32_t flags = 0; diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c index 21896277c5..a9fb259428 100644 --- a/ext/opcache/Optimizer/optimize_func_calls.c +++ b/ext/opcache/Optimizer/optimize_func_calls.c @@ -38,7 +38,7 @@ typedef struct _optimizer_call_info { zend_op *opline; } optimizer_call_info; -void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) +void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx) { zend_op *opline = op_array->opcodes; zend_op *end = opline + op_array->last; diff --git a/ext/opcache/Optimizer/optimize_temp_vars_5.c b/ext/opcache/Optimizer/optimize_temp_vars_5.c index eb0e7686a6..f0e5747dc6 100644 --- a/ext/opcache/Optimizer/optimize_temp_vars_5.c +++ b/ext/opcache/Optimizer/optimize_temp_vars_5.c @@ -39,7 +39,7 @@ max = i; \ } -void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx) +void zend_optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx) { int T = op_array->T; int offset = op_array->last_var; @@ -139,13 +139,6 @@ void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *c } } - /* Skip OP_DATA */ - if (opline->opcode == ZEND_OP_DATA && - (opline-1)->opcode == ZEND_ASSIGN_DIM) { - opline--; - continue; - } - if ((ZEND_OP2_TYPE(opline) & (IS_VAR | IS_TMP_VAR))) { currT = VAR_NUM(ZEND_OP2(opline).var) - offset; if (!zend_bitset_in(valid_T, currT)) { @@ -156,19 +149,6 @@ void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *c ZEND_OP2(opline).var = NUM_VAR(map_T[currT] + offset); } - /* Allocate OP_DATA->op2 after "operands", but before "result" */ - if (opline->opcode == ZEND_ASSIGN_DIM && - (opline + 1)->opcode == ZEND_OP_DATA && - ZEND_OP2_TYPE(opline + 1) & (IS_VAR | IS_TMP_VAR)) { - currT = VAR_NUM(ZEND_OP2(opline + 1).var) - offset; - GET_AVAILABLE_T(); - map_T[currT] = i; - zend_bitset_incl(valid_T, currT); - zend_bitset_excl(taken_T, i); - ZEND_OP2(opline + 1).var = NUM_VAR(i + offset); - var_to_free = i; - } - if (ZEND_RESULT_TYPE(opline) & (IS_VAR | IS_TMP_VAR)) { currT = VAR_NUM(ZEND_RESULT(opline).var) - offset; if (zend_bitset_in(valid_T, currT)) { @@ -190,16 +170,11 @@ void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *c } } } - } else { /* Au still needs to be assigned a T which is a bit dumb. Should consider changing Zend */ + } else { + /* Code which gets here is using a wrongly built opcode such as RECV() */ GET_AVAILABLE_T(); - - if (RESULT_UNUSED(opline)) { - zend_bitset_excl(taken_T, i); - } else { - /* Code which gets here is using a wrongly built opcode such as RECV() */ - map_T[currT] = i; - zend_bitset_incl(valid_T, currT); - } + map_T[currT] = i; + zend_bitset_incl(valid_T, currT); ZEND_RESULT(opline).var = NUM_VAR(i + offset); } } diff --git a/ext/opcache/Optimizer/pass3.c b/ext/opcache/Optimizer/pass3.c index e3c09dc045..ce04e4f7cb 100644 --- a/ext/opcache/Optimizer/pass3.c +++ b/ext/opcache/Optimizer/pass3.c @@ -418,7 +418,7 @@ continue_jmpznz_optimization: ZEND_OP1(next_op).var == ZEND_RESULT(opline).var) { MAKE_NOP(next_op); opline->opcode -= 2; - ZEND_RESULT_TYPE(opline) = IS_VAR | EXT_TYPE_UNUSED; + ZEND_RESULT_TYPE(opline) = IS_UNUSED; } } break; diff --git a/ext/opcache/Optimizer/zend_call_graph.c b/ext/opcache/Optimizer/zend_call_graph.c index 8895bc5cb1..6c1933cfac 100644 --- a/ext/opcache/Optimizer/zend_call_graph.c +++ b/ext/opcache/Optimizer/zend_call_graph.c @@ -251,7 +251,7 @@ static void zend_analyze_recursion(zend_call_graph *call_graph) call_info->recursive = 1; func_info->flags |= ZEND_FUNC_RECURSIVE | ZEND_FUNC_RECURSIVE_DIRECTLY; } else { - memset(visited, 0, sizeof(uint32_t) * set_len); + memset(visited, 0, sizeof(zend_ulong) * set_len); if (zend_is_indirectly_recursive(op_array, call_info->caller_op_array, visited)) { call_info->recursive = 1; func_info->flags |= ZEND_FUNC_RECURSIVE | ZEND_FUNC_RECURSIVE_INDIRECTLY; diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c index 728d586026..63f14634cb 100644 --- a/ext/opcache/Optimizer/zend_cfg.c +++ b/ext/opcache/Optimizer/zend_cfg.c @@ -91,33 +91,35 @@ static void zend_mark_reachable_blocks(const zend_op_array *op_array, zend_cfg * do { changed = 0; - /* Add brk/cont paths */ - for (j = 0; j < op_array->last_live_range; j++) { - if (op_array->live_range[j].var == (uint32_t)-1) { - /* this live range already removed */ - continue; - } - b = blocks + block_map[op_array->live_range[j].start]; - if (b->flags & ZEND_BB_REACHABLE) { - while (op_array->opcodes[b->start].opcode == ZEND_NOP && b->start != b->end) { - b->start++; - } - if (op_array->opcodes[b->start].opcode == ZEND_NOP && - b->start == b->end && - b->successors[0] == block_map[op_array->live_range[j].end]) { - /* mark as removed (empty live range) */ - op_array->live_range[j].var = (uint32_t)-1; + if (cfg->split_at_live_ranges) { + /* Add live range paths */ + for (j = 0; j < op_array->last_live_range; j++) { + if (op_array->live_range[j].var == (uint32_t)-1) { + /* this live range already removed */ continue; } - b->flags |= ZEND_BB_GEN_VAR; - b = blocks + block_map[op_array->live_range[j].end]; - b->flags |= ZEND_BB_KILL_VAR; - if (!(b->flags & ZEND_BB_REACHABLE)) { - changed = 1; - zend_mark_reachable(op_array->opcodes, blocks, b); + b = blocks + block_map[op_array->live_range[j].start]; + if (b->flags & ZEND_BB_REACHABLE) { + while (op_array->opcodes[b->start].opcode == ZEND_NOP && b->start != b->end) { + b->start++; + } + if (op_array->opcodes[b->start].opcode == ZEND_NOP && + b->start == b->end && + b->successors[0] == block_map[op_array->live_range[j].end]) { + /* mark as removed (empty live range) */ + op_array->live_range[j].var = (uint32_t)-1; + continue; + } + b->flags |= ZEND_BB_GEN_VAR; + b = blocks + block_map[op_array->live_range[j].end]; + b->flags |= ZEND_BB_KILL_VAR; + if (!(b->flags & ZEND_BB_REACHABLE)) { + changed = 1; + zend_mark_reachable(op_array->opcodes, blocks, b); + } + } else { + ZEND_ASSERT(!(blocks[block_map[op_array->live_range[j].end]].flags & ZEND_BB_REACHABLE)); } - } else { - ZEND_ASSERT(!(blocks[block_map[op_array->live_range[j].end]].flags & ZEND_BB_REACHABLE)); } } @@ -244,6 +246,7 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b zend_basic_block *blocks; zval *zv; + cfg->split_at_live_ranges = (build_flags & ZEND_CFG_SPLIT_AT_LIVE_RANGES) != 0; cfg->map = block_map = zend_arena_calloc(arena, op_array->last, sizeof(uint32_t)); if (!block_map) { return FAILURE; @@ -251,10 +254,6 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b /* Build CFG, Step 1: Find basic blocks starts, calculate number of blocks */ BB_START(0); - if ((op_array->fn_flags & ZEND_ACC_CLOSURE) && op_array->static_variables) { - // FIXME: Really we should try to perform variable initialization - flags |= ZEND_FUNC_TOO_DYNAMIC; - } for (i = 0; i < op_array->last; i++) { zend_op *opline = op_array->opcodes + i; switch(opline->opcode) { @@ -268,9 +267,9 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b } break; case ZEND_INCLUDE_OR_EVAL: + flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS; case ZEND_YIELD: case ZEND_YIELD_FROM: - flags |= ZEND_FUNC_TOO_DYNAMIC; if (build_flags & ZEND_CFG_STACKLESS) { BB_START(i + 1); } @@ -296,15 +295,17 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b if ((fn = zend_hash_find_ptr(EG(function_table), Z_STR_P(zv))) != NULL) { if (fn->type == ZEND_INTERNAL_FUNCTION) { if (zend_string_equals_literal(Z_STR_P(zv), "extract")) { - flags |= ZEND_FUNC_TOO_DYNAMIC; + flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS; } else if (zend_string_equals_literal(Z_STR_P(zv), "compact")) { - flags |= ZEND_FUNC_TOO_DYNAMIC; - } else if (zend_string_equals_literal(Z_STR_P(zv), "parse_str")) { - flags |= ZEND_FUNC_TOO_DYNAMIC; - } else if (zend_string_equals_literal(Z_STR_P(zv), "mb_parse_str")) { - flags |= ZEND_FUNC_TOO_DYNAMIC; + flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS; + } else if (zend_string_equals_literal(Z_STR_P(zv), "parse_str") && + opline->extended_value == 1) { + flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS; + } else if (zend_string_equals_literal(Z_STR_P(zv), "mb_parse_str") && + opline->extended_value == 1) { + flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS; } else if (zend_string_equals_literal(Z_STR_P(zv), "get_defined_vars")) { - flags |= ZEND_FUNC_TOO_DYNAMIC; + flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS; } else if (zend_string_equals_literal(Z_STR_P(zv), "func_num_args")) { flags |= ZEND_FUNC_VARARG; } else if (zend_string_equals_literal(Z_STR_P(zv), "func_get_arg")) { @@ -316,12 +317,10 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b } break; case ZEND_FAST_CALL: - flags |= ZEND_FUNC_TOO_DYNAMIC; BB_START(OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes); BB_START(i + 1); break; case ZEND_FAST_RET: - flags |= ZEND_FUNC_TOO_DYNAMIC; if (i + 1 < op_array->last) { BB_START(i + 1); } @@ -350,7 +349,6 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b BB_START(i + 1); break; case ZEND_CATCH: - flags |= ZEND_FUNC_TOO_DYNAMIC; if (!opline->result.num) { BB_START(ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)); } @@ -370,8 +368,14 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b BB_START(i + 1); break; case ZEND_UNSET_VAR: - if (!(opline->extended_value & ZEND_QUICK_SET)) { - flags |= ZEND_FUNC_TOO_DYNAMIC; + case ZEND_ISSET_ISEMPTY_VAR: + if (((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_LOCAL) && + !(opline->extended_value & ZEND_QUICK_SET)) { + flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS; + } else if (((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL || + (opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL_LOCK) && + !op_array->function_name) { + flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS; } break; case ZEND_FETCH_R: @@ -381,19 +385,23 @@ int zend_build_cfg(zend_arena **arena, const zend_op_array *op_array, uint32_t b case ZEND_FETCH_IS: case ZEND_FETCH_UNSET: if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_LOCAL) { - flags |= ZEND_FUNC_TOO_DYNAMIC; + flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS; } else if (((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL || (opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_GLOBAL_LOCK) && !op_array->function_name) { - flags |= ZEND_FUNC_TOO_DYNAMIC; + flags |= ZEND_FUNC_INDIRECT_VAR_ACCESS; } break; } } - for (j = 0; j < op_array->last_live_range; j++) { - BB_START(op_array->live_range[j].start); - BB_START(op_array->live_range[j].end); + + if (cfg->split_at_live_ranges) { + for (j = 0; j < op_array->last_live_range; j++) { + BB_START(op_array->live_range[j].start); + BB_START(op_array->live_range[j].end); + } } + if (op_array->last_try_catch) { for (j = 0; j < op_array->last_try_catch; j++) { BB_START(op_array->try_catch_array[j].try_op); @@ -534,7 +542,7 @@ int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg) /* {{{ */ if (b->successors[0] >= 0) { edges++; blocks[b->successors[0]].predecessors_count++; - if (b->successors[1] >= 0) { + if (b->successors[1] >= 0 && b->successors[1] != b->successors[0]) { edges++; blocks[b->successors[1]].predecessors_count++; } @@ -563,7 +571,8 @@ int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg) /* {{{ */ zend_basic_block *b = blocks + blocks[j].successors[0]; predecessors[b->predecessor_offset + b->predecessors_count] = j; b->predecessors_count++; - if (blocks[j].successors[1] >= 0) { + if (blocks[j].successors[1] >= 0 + && blocks[j].successors[1] != blocks[j].successors[0]) { zend_basic_block *b = blocks + blocks[j].successors[1]; predecessors[b->predecessor_offset + b->predecessors_count] = j; b->predecessors_count++; @@ -576,16 +585,45 @@ int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg) /* {{{ */ } /* }}} */ +/* Computes a postorder numbering of the CFG */ +static void compute_postnum_recursive( + int *postnum, int *cur, const zend_cfg *cfg, int block_num) /* {{{ */ +{ + zend_basic_block *block = &cfg->blocks[block_num]; + if (postnum[block_num] != -1) { + return; + } + + postnum[block_num] = -2; /* Marker for "currently visiting" */ + if (block->successors[0] >= 0) { + compute_postnum_recursive(postnum, cur, cfg, block->successors[0]); + if (block->successors[1] >= 0) { + compute_postnum_recursive(postnum, cur, cfg, block->successors[1]); + } + } + postnum[block_num] = (*cur)++; +} +/* }}} */ + +/* Computes dominator tree using algorithm from "A Simple, Fast Dominance Algorithm" by + * Cooper, Harvey and Kennedy. */ int zend_cfg_compute_dominators_tree(const zend_op_array *op_array, zend_cfg *cfg) /* {{{ */ { zend_basic_block *blocks = cfg->blocks; int blocks_count = cfg->blocks_count; int j, k, changed; + ALLOCA_FLAG(use_heap) + int *postnum = do_alloca(sizeof(int) * cfg->blocks_count, use_heap); + memset(postnum, -1, sizeof(int) * cfg->blocks_count); + j = 0; + compute_postnum_recursive(postnum, &j, cfg, 0); + /* FIXME: move declarations */ blocks[0].idom = 0; do { changed = 0; + /* Iterating in RPO here would converge faster */ for (j = 1; j < blocks_count; j++) { int idom = -1; @@ -603,8 +641,8 @@ int zend_cfg_compute_dominators_tree(const zend_op_array *op_array, zend_cfg *cf if (blocks[pred].idom >= 0) { while (idom != pred) { - while (pred > idom) pred = blocks[pred].idom; - while (idom > pred) idom = blocks[idom].idom; + while (postnum[pred] < postnum[idom]) pred = blocks[pred].idom; + while (postnum[idom] < postnum[pred]) idom = blocks[idom].idom; } } } @@ -655,6 +693,7 @@ int zend_cfg_compute_dominators_tree(const zend_op_array *op_array, zend_cfg *cf blocks[j].level = level; } + free_alloca(postnum, use_heap); return SUCCESS; } /* }}} */ diff --git a/ext/opcache/Optimizer/zend_cfg.h b/ext/opcache/Optimizer/zend_cfg.h index fa96979838..de94997dd5 100644 --- a/ext/opcache/Optimizer/zend_cfg.h +++ b/ext/opcache/Optimizer/zend_cfg.h @@ -86,6 +86,7 @@ typedef struct _zend_cfg { zend_basic_block *blocks; /* array of basic blocks */ int *predecessors; uint32_t *map; + unsigned int split_at_live_ranges : 1; } zend_cfg; /* Build Flags */ @@ -94,6 +95,7 @@ typedef struct _zend_cfg { #define ZEND_SSA_DEBUG_LIVENESS (1<<29) #define ZEND_SSA_DEBUG_PHI_PLACEMENT (1<<28) #define ZEND_SSA_RC_INFERENCE (1<<27) +#define ZEND_CFG_SPLIT_AT_LIVE_RANGES (1<<26) #define CRT_CONSTANT_EX(op_array, node, rt_constants) \ ((rt_constants) ? \ @@ -106,7 +108,7 @@ typedef struct _zend_cfg { CRT_CONSTANT_EX(op_array, node, (build_flags & ZEND_RT_CONSTANTS)) #define RETURN_VALUE_USED(opline) \ - (!((opline)->result_type & EXT_TYPE_UNUSED)) + ((opline)->result_type != IS_UNUSED) BEGIN_EXTERN_C() diff --git a/ext/opcache/Optimizer/zend_dfg.c b/ext/opcache/Optimizer/zend_dfg.c index 1266ae5e54..e72afd1701 100644 --- a/ext/opcache/Optimizer/zend_dfg.c +++ b/ext/opcache/Optimizer/zend_dfg.c @@ -20,7 +20,7 @@ #include "zend_compile.h" #include "zend_dfg.h" -int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg) /* {{{ */ +int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg, uint32_t build_flags) /* {{{ */ { int set_size; zend_basic_block *blocks = cfg->blocks; @@ -28,7 +28,7 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg zend_bitset tmp, gen, def, use, in, out; zend_op *opline; uint32_t k; - int j, changed; + int j; /* FIXME: can we use "gen" instead of "def" for flow analyzing? */ set_size = dfg->size; @@ -55,51 +55,41 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg DFG_SET(use, set_size, j, EX_VAR_TO_NUM(next->op1.var)); } } - if (next->op2_type == IS_CV) { + if (next->op2_type & (IS_CV|IS_VAR|IS_TMP_VAR)) { if (!DFG_ISSET(def, set_size, j,EX_VAR_TO_NUM(next->op2.var))) { DFG_SET(use, set_size, j, EX_VAR_TO_NUM(next->op2.var)); } - } else if (next->op2_type == IS_VAR || - next->op2_type == IS_TMP_VAR) { - /* ZEND_ASSIGN_??? use the second operand - of the following OP_DATA instruction as - a temporary variable */ - switch (opline->opcode) { - case ZEND_ASSIGN_DIM: - case ZEND_ASSIGN_OBJ: - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: - break; - default: - if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(next->op2.var))) { - DFG_SET(use, set_size, j, EX_VAR_TO_NUM(next->op2.var)); - } - } } } if (opline->op1_type == IS_CV) { switch (opline->opcode) { + case ZEND_ADD_ARRAY_ELEMENT: + case ZEND_INIT_ARRAY: + if ((build_flags & ZEND_SSA_RC_INFERENCE) + || (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) { + goto op1_def; + } + goto op1_use; + case ZEND_FE_RESET_R: + if (build_flags & ZEND_SSA_RC_INFERENCE) { + goto op1_def; + } + goto op1_use; + case ZEND_YIELD: + if ((build_flags & ZEND_SSA_RC_INFERENCE) + || (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE)) { + goto op1_def; + } + goto op1_use; case ZEND_ASSIGN: case ZEND_ASSIGN_REF: case ZEND_BIND_GLOBAL: + case ZEND_BIND_STATIC: case ZEND_SEND_VAR_EX: case ZEND_SEND_REF: case ZEND_SEND_VAR_NO_REF: - case ZEND_FE_RESET_R: case ZEND_FE_RESET_RW: - case ZEND_ADD_ARRAY_ELEMENT: - case ZEND_INIT_ARRAY: - case ZEND_BIND_LEXICAL: +op1_def: if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->op1.var))) { // FIXME: include into "use" to ...? DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op1.var)); @@ -140,12 +130,12 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg case ZEND_FETCH_OBJ_UNSET: DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op1.var)); default: +op1_use: if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(opline->op1.var))) { DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op1.var)); } } - } else if (opline->op1_type == IS_VAR || - opline->op1_type == IS_TMP_VAR) { + } else if (opline->op1_type & (IS_VAR|IS_TMP_VAR)) { if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(opline->op1.var))) { DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op1.var)); } @@ -153,9 +143,19 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg if (opline->op2_type == IS_CV) { switch (opline->opcode) { case ZEND_ASSIGN: + if (build_flags & ZEND_SSA_RC_INFERENCE) { + goto op2_def; + } + goto op2_use; + case ZEND_BIND_LEXICAL: + if ((build_flags & ZEND_SSA_RC_INFERENCE) || opline->extended_value) { + goto op2_def; + } + goto op2_use; case ZEND_ASSIGN_REF: case ZEND_FE_FETCH_R: case ZEND_FE_FETCH_RW: +op2_def: if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var))) { // FIXME: include into "use" to ...? DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var)); @@ -164,13 +164,13 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->op2.var)); break; default: +op2_use: if (!DFG_ISSET(def, set_size, j, EX_VAR_TO_NUM(opline->op2.var))) { DFG_SET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var)); } break; } - } else if (opline->op2_type == IS_VAR || - opline->op2_type == IS_TMP_VAR) { + } else if (opline->op2_type & (IS_VAR|IS_TMP_VAR)) { if (opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW) { if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->op2.var))) { DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->op2.var)); @@ -187,27 +187,31 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->result.var)); } DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->result.var)); - } else if (opline->result_type == IS_VAR || - opline->result_type == IS_TMP_VAR) { + } else if (opline->result_type & (IS_VAR|IS_TMP_VAR)) { if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(opline->result.var))) { DFG_SET(def, set_size, j, EX_VAR_TO_NUM(opline->result.var)); } DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(opline->result.var)); } - if ((opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW) && opline->result_type == IS_TMP_VAR) { - if (!DFG_ISSET(use, set_size, j, EX_VAR_TO_NUM(next->result.var))) { - DFG_SET(def, set_size, j, EX_VAR_TO_NUM(next->result.var)); - } - DFG_SET(gen, set_size, j, EX_VAR_TO_NUM(next->result.var)); - } } } } /* Calculate "in" and "out" sets */ - do { - changed = 0; + { + uint32_t worklist_len = zend_bitset_len(blocks_count); + ALLOCA_FLAG(use_heap); + zend_bitset worklist = ZEND_BITSET_ALLOCA(worklist_len, use_heap); + memset(worklist, 0, worklist_len * ZEND_BITSET_ELM_SIZE); for (j = 0; j < blocks_count; j++) { + zend_bitset_incl(worklist, j); + } + while (!zend_bitset_empty(worklist, worklist_len)) { + /* We use the last block on the worklist, because predecessors tend to be located + * before the succeeding block, so this converges faster. */ + j = zend_bitset_last(worklist, worklist_len); + zend_bitset_excl(worklist, j); + if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) { continue; } @@ -222,10 +226,19 @@ int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg zend_bitset_union_with_difference(tmp, DFG_BITSET(use, set_size, j), DFG_BITSET(out, set_size, j), DFG_BITSET(def, set_size, j), set_size); if (!zend_bitset_equal(DFG_BITSET(in, set_size, j), tmp, set_size)) { zend_bitset_copy(DFG_BITSET(in, set_size, j), tmp, set_size); - changed = 1; + + /* Add predecessors of changed block to worklist */ + { + int *predecessors = &cfg->predecessors[blocks[j].predecessor_offset]; + for (k = 0; k < blocks[j].predecessors_count; k++) { + zend_bitset_incl(worklist, predecessors[k]); + } + } } } - } while (changed); + + free_alloca(worklist, use_heap); + } return SUCCESS; } diff --git a/ext/opcache/Optimizer/zend_dfg.h b/ext/opcache/Optimizer/zend_dfg.h index ebbb98a65b..9d864992ca 100644 --- a/ext/opcache/Optimizer/zend_dfg.h +++ b/ext/opcache/Optimizer/zend_dfg.h @@ -44,7 +44,7 @@ typedef struct _zend_dfg { BEGIN_EXTERN_C() -int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg); +int zend_build_dfg(const zend_op_array *op_array, const zend_cfg *cfg, zend_dfg *dfg, uint32_t build_flags); END_EXTERN_C() diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c index 1eacd401b1..ba5fb8a0ce 100644 --- a/ext/opcache/Optimizer/zend_dump.c +++ b/ext/opcache/Optimizer/zend_dump.c @@ -88,6 +88,28 @@ static void zend_dump_class_fetch_type(uint32_t fetch_type) } } +static void zend_dump_unused_op(const zend_op *opline, znode_op op, uint32_t flags) { + if (ZEND_VM_OP_NUM == (flags & ZEND_VM_OP_MASK)) { + fprintf(stderr, " %u", op.num); + } else if (ZEND_VM_OP_TRY_CATCH == (flags & ZEND_VM_OP_MASK)) { + if (opline->opcode != ZEND_FAST_RET || opline->extended_value) { + fprintf(stderr, " try-catch(%u)", op.num); + } + } else if (ZEND_VM_OP_LIVE_RANGE == (flags & ZEND_VM_OP_MASK)) { + if (opline->extended_value & ZEND_FREE_ON_RETURN) { + fprintf(stderr, " live-range(%u)", op.num); + } + } else if (ZEND_VM_OP_THIS == (flags & ZEND_VM_OP_MASK)) { + fprintf(stderr, " THIS"); + } else if (ZEND_VM_OP_NEXT == (flags & ZEND_VM_OP_MASK)) { + fprintf(stderr, " NEXT"); + } else if (ZEND_VM_OP_CLASS_FETCH == (flags & ZEND_VM_OP_MASK)) { + zend_dump_class_fetch_type(op.num); + } else if (ZEND_VM_OP_CONSTRUCTOR == (flags & ZEND_VM_OP_MASK)) { + fprintf(stderr, " CONSTRUCTOR"); + } +} + void zend_dump_var(const zend_op_array *op_array, zend_uchar var_type, int var_num) { if (var_type == IS_CV && var_num < op_array->last_var) { @@ -119,7 +141,7 @@ static void zend_dump_range(const zend_ssa_range *r) } } -static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_instanceof) +static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_instanceof, uint32_t dump_flags) { int first = 1; @@ -132,13 +154,15 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst if (first) first = 0; else fprintf(stderr, ", "); fprintf(stderr, "ref"); } - if (info & MAY_BE_RC1) { - if (first) first = 0; else fprintf(stderr, ", "); - fprintf(stderr, "rc1"); - } - if (info & MAY_BE_RCN) { - if (first) first = 0; else fprintf(stderr, ", "); - fprintf(stderr, "rcn"); + if (dump_flags & ZEND_DUMP_RC_INFERENCE) { + if (info & MAY_BE_RC1) { + if (first) first = 0; else fprintf(stderr, ", "); + fprintf(stderr, "rc1"); + } + if (info & MAY_BE_RCN) { + if (first) first = 0; else fprintf(stderr, ", "); + fprintf(stderr, "rcn"); + } } if (info & MAY_BE_CLASS) { if (first) first = 0; else fprintf(stderr, ", "); @@ -158,11 +182,13 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst if (first) first = 0; else fprintf(stderr, ", "); fprintf(stderr, "null"); } - if (info & MAY_BE_FALSE) { + if ((info & MAY_BE_FALSE) && (info & MAY_BE_TRUE)) { + if (first) first = 0; else fprintf(stderr, ", "); + fprintf(stderr, "bool"); + } else if (info & MAY_BE_FALSE) { if (first) first = 0; else fprintf(stderr, ", "); fprintf(stderr, "false"); - } - if (info & MAY_BE_TRUE) { + } else if (info & MAY_BE_TRUE) { if (first) first = 0; else fprintf(stderr, ", "); fprintf(stderr, "true"); } @@ -274,16 +300,17 @@ static void zend_dump_type_info(uint32_t info, zend_class_entry *ce, int is_inst fprintf(stderr, "]"); } -static void zend_dump_ssa_var_info(const zend_ssa *ssa, int ssa_var_num) +static void zend_dump_ssa_var_info(const zend_ssa *ssa, int ssa_var_num, uint32_t dump_flags) { zend_dump_type_info( ssa->var_info[ssa_var_num].type, ssa->var_info[ssa_var_num].ce, ssa->var_info[ssa_var_num].ce ? - ssa->var_info[ssa_var_num].is_instanceof : 0); + ssa->var_info[ssa_var_num].is_instanceof : 0, + dump_flags); } -void zend_dump_ssa_var(const zend_op_array *op_array, const zend_ssa *ssa, int ssa_var_num, zend_uchar var_type, int var_num) +static void zend_dump_ssa_var(const zend_op_array *op_array, const zend_ssa *ssa, int ssa_var_num, zend_uchar var_type, int var_num, uint32_t dump_flags) { if (ssa_var_num >= 0) { fprintf(stderr, "#%d.", ssa_var_num); @@ -297,7 +324,7 @@ void zend_dump_ssa_var(const zend_op_array *op_array, const zend_ssa *ssa, int s fprintf(stderr, " NOVAL"); } if (ssa->var_info) { - zend_dump_ssa_var_info(ssa, ssa_var_num); + zend_dump_ssa_var_info(ssa, ssa_var_num, dump_flags); if (ssa->var_info[ssa_var_num].has_range) { zend_dump_range(&ssa->var_info[ssa_var_num].range); } @@ -305,8 +332,14 @@ void zend_dump_ssa_var(const zend_op_array *op_array, const zend_ssa *ssa, int s } } -static void zend_dump_pi_range(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_pi_range *r) +static void zend_dump_pi_constraint(const zend_op_array *op_array, const zend_ssa *ssa, const zend_ssa_pi_constraint *r, uint32_t dump_flags) { + if (r->type_mask != (uint32_t) -1) { + fprintf(stderr, " TYPE"); + zend_dump_type_info(r->type_mask, NULL, 0, dump_flags); + return; + } + if (r->range.underflow && r->range.overflow) { return; } @@ -319,7 +352,7 @@ static void zend_dump_pi_range(const zend_op_array *op_array, const zend_ssa *ss fprintf(stderr, "-- .. "); } else { if (r->min_ssa_var >= 0) { - zend_dump_ssa_var(op_array, ssa, r->min_ssa_var, (r->min_var < op_array->last_var ? IS_CV : 0), r->min_var); + zend_dump_ssa_var(op_array, ssa, r->min_ssa_var, (r->min_var < op_array->last_var ? IS_CV : 0), r->min_var, dump_flags); if (r->range.min > 0) { fprintf(stderr, " + " ZEND_LONG_FMT, r->range.min); } else if (r->range.min < 0) { @@ -334,7 +367,7 @@ static void zend_dump_pi_range(const zend_op_array *op_array, const zend_ssa *ss fprintf(stderr, "++]"); } else { if (r->max_ssa_var >= 0) { - zend_dump_ssa_var(op_array, ssa, r->max_ssa_var, (r->max_var < op_array->last_var ? IS_CV : 0), r->max_var); + zend_dump_ssa_var(op_array, ssa, r->max_ssa_var, (r->max_var < op_array->last_var ? IS_CV : 0), r->max_var, dump_flags); if (r->range.max > 0) { fprintf(stderr, " + " ZEND_LONG_FMT, r->range.max); } else if (r->range.max < 0) { @@ -365,21 +398,15 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * fprintf(stderr, "%*c", 8-len, ' '); if (!ssa || !ssa->ops || ssa->ops[opline - op_array->opcodes].result_use < 0) { - if (opline->result_type == IS_CV || - opline->result_type == IS_VAR || - opline->result_type == IS_TMP_VAR) { + if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) { if (ssa && ssa->ops) { int ssa_var_num = ssa->ops[opline - op_array->opcodes].result_def; ZEND_ASSERT(ssa_var_num >= 0); - zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var)); + zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags); } else { zend_dump_var(op_array, opline->result_type, EX_VAR_TO_NUM(opline->result.var)); } fprintf(stderr, " = "); - } else if (!(dump_flags & ZEND_DUMP_HIDE_UNUSED_VARS) && - (opline->result_type & IS_VAR) && - (opline->result_type & EXT_TYPE_UNUSED)) { - fprintf(stderr, "U%u = ", EX_VAR_TO_NUM(opline->result.var)); } } @@ -510,9 +537,6 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * case ZEND_FETCH_LOCAL: fprintf(stderr, " (local)"); break; - case ZEND_FETCH_STATIC: - fprintf(stderr, " (static)"); - break; case ZEND_FETCH_GLOBAL_LOCK: fprintf(stderr, " (global+lock)"); break; @@ -543,30 +567,15 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * } } } - if (ZEND_VM_OP1_JMP_ADDR == (flags & ZEND_VM_OP1_MASK)) { - if (b) { - fprintf(stderr, " BB%d", b->successors[n++]); - } else { - fprintf(stderr, " L%u", (uint32_t)(OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes)); - } - } else if (ZEND_VM_OP1_NUM == (flags & ZEND_VM_OP1_MASK)) { - fprintf(stderr, " %u", opline->op1.num); - } else if (ZEND_VM_OP1_TRY_CATCH == (flags & ZEND_VM_OP1_MASK)) { - fprintf(stderr, " try-catch(%u)", opline->op1.num); - } else if (ZEND_VM_OP1_LIVE_RANGE == (flags & ZEND_VM_OP1_MASK)) { - if (opline->extended_value & ZEND_FREE_ON_RETURN) { - fprintf(stderr, " live-range(%u)", opline->op1.num); - } - } else if (opline->op1_type == IS_CONST) { + + if (opline->op1_type == IS_CONST) { zend_dump_const(CRT_CONSTANT_EX(op_array, opline->op1, (dump_flags & ZEND_DUMP_RT_CONSTANTS))); - } else if (opline->op1_type == IS_CV || - opline->op1_type == IS_VAR || - opline->op1_type == IS_TMP_VAR) { + } else if (opline->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) { if (ssa && ssa->ops) { int ssa_var_num = ssa->ops[opline - op_array->opcodes].op1_use; if (ssa_var_num >= 0) { fprintf(stderr, " "); - zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var)); + zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var), dump_flags); } else if (ssa->ops[opline - op_array->opcodes].op1_def < 0) { fprintf(stderr, " "); zend_dump_var(op_array, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var)); @@ -579,42 +588,30 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * int ssa_var_num = ssa->ops[opline - op_array->opcodes].op1_def; if (ssa_var_num >= 0) { fprintf(stderr, " -> "); - zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var)); + zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op1_type, EX_VAR_TO_NUM(opline->op1.var), dump_flags); } } - } else if (ZEND_VM_OP1_THIS == (flags & ZEND_VM_OP1_MASK)) { - fprintf(stderr, " THIS"); - } else if (ZEND_VM_OP1_NEXT == (flags & ZEND_VM_OP1_MASK)) { - fprintf(stderr, " NEXT"); - } else if (ZEND_VM_OP1_CLASS_FETCH == (flags & ZEND_VM_OP1_MASK)) { - zend_dump_class_fetch_type(opline->op1.num); - } else if (ZEND_VM_OP1_CONSTRUCTOR == (flags & ZEND_VM_OP1_MASK)) { - fprintf(stderr, " CONSTRUCTOR"); - } - if (ZEND_VM_OP2_JMP_ADDR == (flags & ZEND_VM_OP2_MASK)) { - if (b) { - fprintf(stderr, " BB%d", b->successors[n++]); + } else { + uint32_t op1_flags = ZEND_VM_OP1_FLAGS(flags); + if (ZEND_VM_OP_JMP_ADDR == (op1_flags & ZEND_VM_OP_MASK)) { + if (b) { + fprintf(stderr, " BB%d", b->successors[n++]); + } else { + fprintf(stderr, " L%u", (uint32_t)(OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes)); + } } else { - fprintf(stderr, " L%u", (uint32_t)(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes)); - } - } else if (ZEND_VM_OP2_NUM == (flags & ZEND_VM_OP2_MASK)) { - fprintf(stderr, " %u", opline->op2.num); - } else if (ZEND_VM_OP2_TRY_CATCH == (flags & ZEND_VM_OP2_MASK)) { - fprintf(stderr, " try-catch(%u)", opline->op2.num); - } else if (ZEND_VM_OP2_LIVE_RANGE == (flags & ZEND_VM_OP2_MASK)) { - if (opline->extended_value & ZEND_FREE_ON_RETURN) { - fprintf(stderr, " live-range(%u)", opline->op2.num); + zend_dump_unused_op(opline, opline->op1, op1_flags); } - } else if (opline->op2_type == IS_CONST) { + } + + if (opline->op2_type == IS_CONST) { zend_dump_const(CRT_CONSTANT_EX(op_array, opline->op2, (dump_flags & ZEND_DUMP_RT_CONSTANTS))); - } else if (opline->op2_type == IS_CV || - opline->op2_type == IS_VAR || - opline->op2_type == IS_TMP_VAR) { + } else if (opline->op2_type & (IS_CV|IS_VAR|IS_TMP_VAR)) { if (ssa && ssa->ops) { int ssa_var_num = ssa->ops[opline - op_array->opcodes].op2_use; if (ssa_var_num >= 0) { fprintf(stderr, " "); - zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var)); + zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var), dump_flags); } else if (ssa->ops[opline - op_array->opcodes].op2_def < 0) { fprintf(stderr, " "); zend_dump_var(op_array, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var)); @@ -627,18 +624,22 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * int ssa_var_num = ssa->ops[opline - op_array->opcodes].op2_def; if (ssa_var_num >= 0) { fprintf(stderr, " -> "); - zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var)); + zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->op2_type, EX_VAR_TO_NUM(opline->op2.var), dump_flags); } } - } else if (ZEND_VM_OP2_THIS == (flags & ZEND_VM_OP2_MASK)) { - fprintf(stderr, " THIS"); - } else if (ZEND_VM_OP2_NEXT == (flags & ZEND_VM_OP2_MASK)) { - fprintf(stderr, " NEXT"); - } else if (ZEND_VM_OP2_CLASS_FETCH == (flags & ZEND_VM_OP2_MASK)) { - zend_dump_class_fetch_type(opline->op2.num); - } else if (ZEND_VM_OP2_CONSTRUCTOR == (flags & ZEND_VM_OP2_MASK)) { - fprintf(stderr, " CONSTRUCTOR"); + } else { + uint32_t op2_flags = ZEND_VM_OP2_FLAGS(flags); + if (ZEND_VM_OP_JMP_ADDR == (op2_flags & ZEND_VM_OP_MASK)) { + if (b) { + fprintf(stderr, " BB%d", b->successors[n++]); + } else { + fprintf(stderr, " L%u", (uint32_t)(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes)); + } + } else { + zend_dump_unused_op(opline, opline->op2, op2_flags); + } } + if (ZEND_VM_EXT_JMP_ADDR == (flags & ZEND_VM_EXT_MASK)) { if (opline->opcode != ZEND_CATCH || !opline->result.num) { if (b) { @@ -651,14 +652,12 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * if (opline->result_type == IS_CONST) { zend_dump_const(CRT_CONSTANT_EX(op_array, opline->result, (dump_flags & ZEND_DUMP_RT_CONSTANTS))); } else if (ssa && ssa->ops && ssa->ops[opline - op_array->opcodes].result_use >= 0) { - if (opline->result_type == IS_CV || - opline->result_type == IS_VAR || - opline->result_type == IS_TMP_VAR) { + if (opline->result_type & (IS_CV|IS_VAR|IS_TMP_VAR)) { if (ssa && ssa->ops) { int ssa_var_num = ssa->ops[opline - op_array->opcodes].result_use; if (ssa_var_num >= 0) { fprintf(stderr, " "); - zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var)); + zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags); } } else { fprintf(stderr, " "); @@ -668,7 +667,7 @@ static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block * int ssa_var_num = ssa->ops[opline - op_array->opcodes].result_def; if (ssa_var_num >= 0) { fprintf(stderr, " -> "); - zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var)); + zend_dump_ssa_var(op_array, ssa, ssa_var_num, opline->result_type, EX_VAR_TO_NUM(opline->result.var), dump_flags); } } } @@ -780,21 +779,21 @@ static void zend_dump_block_header(const zend_cfg *cfg, const zend_op_array *op_ int j; fprintf(stderr, " "); - zend_dump_ssa_var(op_array, ssa, p->ssa_var, 0, p->var); + zend_dump_ssa_var(op_array, ssa, p->ssa_var, 0, p->var, dump_flags); if (p->pi < 0) { fprintf(stderr, " = Phi("); for (j = 0; j < cfg->blocks[n].predecessors_count; j++) { if (j > 0) { fprintf(stderr, ", "); } - zend_dump_ssa_var(op_array, ssa, p->sources[j], 0, p->var); + zend_dump_ssa_var(op_array, ssa, p->sources[j], 0, p->var, dump_flags); } fprintf(stderr, ")\n"); } else { - fprintf(stderr, " = Pi("); - zend_dump_ssa_var(op_array, ssa, p->sources[0], 0, p->var); + fprintf(stderr, " = Pi<BB%d>(", p->pi); + zend_dump_ssa_var(op_array, ssa, p->sources[0], 0, p->var, dump_flags); fprintf(stderr, " &"); - zend_dump_pi_range(op_array, ssa, &p->constraint); + zend_dump_pi_constraint(op_array, ssa, &p->constraint, dump_flags); fprintf(stderr, ")\n"); } p = p->next; @@ -856,6 +855,9 @@ void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, cons if (ssa) { fprintf(stderr, ", ssa_vars=%d", ssa->vars_count); } + if (func_flags & ZEND_FUNC_INDIRECT_VAR_ACCESS) { + fprintf(stderr, ", dynamic"); + } if (func_flags & ZEND_FUNC_RECURSIVE) { fprintf(stderr, ", recursive"); if (func_flags & ZEND_FUNC_RECURSIVE_DIRECTLY) { @@ -903,7 +905,7 @@ void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, cons if (func_info && func_info->num_args > 0) { for (i = 0; i < MIN(op_array->num_args, func_info->num_args ); i++) { fprintf(stderr, " ; arg %d ", i); - zend_dump_type_info(func_info->arg_info[i].info.type, func_info->arg_info[i].info.ce, func_info->arg_info[i].info.is_instanceof); + zend_dump_type_info(func_info->arg_info[i].info.type, func_info->arg_info[i].info.ce, func_info->arg_info[i].info.is_instanceof, dump_flags); zend_dump_range(&func_info->arg_info[i].info.range); fprintf(stderr, "\n"); } @@ -911,7 +913,7 @@ void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, cons if (func_info) { fprintf(stderr, " ; return "); - zend_dump_type_info(func_info->return_info.type, func_info->return_info.ce, func_info->return_info.is_instanceof); + zend_dump_type_info(func_info->return_info.type, func_info->return_info.ce, func_info->return_info.is_instanceof, dump_flags); zend_dump_range(&func_info->return_info.range); fprintf(stderr, "\n"); } @@ -919,7 +921,7 @@ void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, cons if (ssa && ssa->var_info) { for (i = 0; i < op_array->last_var; i++) { fprintf(stderr, " ; "); - zend_dump_ssa_var(op_array, ssa, i, IS_CV, i); + zend_dump_ssa_var(op_array, ssa, i, IS_CV, i, dump_flags); fprintf(stderr, "\n"); } } @@ -948,10 +950,17 @@ void zend_dump_op_array(const zend_op_array *op_array, uint32_t dump_flags, cons if (op_array->last_live_range) { fprintf(stderr, "LIVE RANGES:\n"); for (i = 0; i < op_array->last_live_range; i++) { - fprintf(stderr, " %u: BB%u - BB%u ", - EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK), - cfg->map[op_array->live_range[i].start], - cfg->map[op_array->live_range[i].end]); + if (cfg->split_at_live_ranges) { + fprintf(stderr, " %u: BB%u - BB%u ", + EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK), + cfg->map[op_array->live_range[i].start], + cfg->map[op_array->live_range[i].end]); + } else { + fprintf(stderr, " %u: L%u - L%u ", + EX_VAR_TO_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK), + op_array->live_range[i].start, + op_array->live_range[i].end); + } switch (op_array->live_range[i].var & ZEND_LIVE_MASK) { case ZEND_LIVE_TMPVAR: fprintf(stderr, "(tmp/var)\n"); @@ -1081,7 +1090,7 @@ void zend_dump_variables(const zend_op_array *op_array) } } -void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa) +void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa, uint32_t dump_flags) { int j; @@ -1092,7 +1101,7 @@ void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa) for (j = 0; j < ssa->vars_count; j++) { fprintf(stderr, " "); - zend_dump_ssa_var(op_array, ssa, j, IS_CV, ssa->vars[j].var); + zend_dump_ssa_var(op_array, ssa, j, IS_CV, ssa->vars[j].var, dump_flags); if (ssa->vars[j].scc >= 0) { if (ssa->vars[j].scc_entry) { fprintf(stderr, " *"); diff --git a/ext/opcache/Optimizer/zend_dump.h b/ext/opcache/Optimizer/zend_dump.h index 44dd79fd04..38b955c3a1 100644 --- a/ext/opcache/Optimizer/zend_dump.h +++ b/ext/opcache/Optimizer/zend_dump.h @@ -23,7 +23,7 @@ #include "zend_dfg.h" #define ZEND_DUMP_HIDE_UNREACHABLE (1<<0) -#define ZEND_DUMP_HIDE_UNUSED_VARS (1<<1) +#define ZEND_DUMP_RC_INFERENCE (1<<1) #define ZEND_DUMP_CFG (1<<2) #define ZEND_DUMP_SSA (1<<3) #define ZEND_DUMP_RT_CONSTANTS ZEND_RT_CONSTANTS @@ -35,7 +35,7 @@ void zend_dump_dominators(const zend_op_array *op_array, const zend_cfg *cfg); void zend_dump_dfg(const zend_op_array *op_array, const zend_cfg *cfg, const zend_dfg *dfg); void zend_dump_phi_placement(const zend_op_array *op_array, const zend_ssa *ssa); void zend_dump_variables(const zend_op_array *op_array); -void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa); +void zend_dump_ssa_variables(const zend_op_array *op_array, const zend_ssa *ssa, uint32_t dump_flags); void zend_dump_var(const zend_op_array *op_array, zend_uchar var_type, int var_num); END_EXTERN_C() diff --git a/ext/opcache/Optimizer/zend_func_info.h b/ext/opcache/Optimizer/zend_func_info.h index 4b0aadd4ee..8fcf00d26a 100644 --- a/ext/opcache/Optimizer/zend_func_info.h +++ b/ext/opcache/Optimizer/zend_func_info.h @@ -22,7 +22,7 @@ #include "zend_ssa.h" /* func flags */ -#define ZEND_FUNC_TOO_DYNAMIC (1<<0) +#define ZEND_FUNC_INDIRECT_VAR_ACCESS (1<<0) #define ZEND_FUNC_HAS_CALLS (1<<1) #define ZEND_FUNC_VARARG (1<<2) #define ZEND_FUNC_NO_LOOPS (1<<3) diff --git a/ext/opcache/Optimizer/zend_inference.c b/ext/opcache/Optimizer/zend_inference.c index 3206634534..a1e2335fa9 100644 --- a/ext/opcache/Optimizer/zend_inference.c +++ b/ext/opcache/Optimizer/zend_inference.c @@ -475,7 +475,7 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int tmp->min = ZEND_LONG_MAX; tmp->max = ZEND_LONG_MIN; tmp->overflow = 0; - if (p->pi >= 0) { + if (p->pi >= 0 && p->constraint.type_mask == (uint32_t) -1) { if (p->constraint.negative) { if (ssa->var_info[p->sources[0]].has_range) { tmp->underflow = ssa->var_info[p->sources[0]].range.underflow; @@ -962,7 +962,7 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int op2_max = OP2_MAX_RANGE(); tmp->min = (op1_min == op1_max && - op2_min == op2_min && + op2_min == op2_max && op1_min == op2_max); tmp->max = (op1_min <= op2_max && op1_max >= op2_min); return 1; @@ -984,7 +984,7 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int tmp->min = (op1_min > op2_max || op1_max < op2_min); tmp->max = (op1_min != op1_max || - op2_min != op2_min || + op2_min != op2_max || op1_min != op2_max); return 1; } else { @@ -1031,6 +1031,7 @@ int zend_inference_calc_range(const zend_op_array *op_array, zend_ssa *ssa, int } break; case ZEND_QM_ASSIGN: + case ZEND_JMP_SET: case ZEND_COALESCE: if (ssa->ops[line].result_def == var) { if (OP1_HAS_RANGE()) { @@ -1813,6 +1814,7 @@ static void zend_infer_ranges_warmup(const zend_op_array *op_array, zend_ssa *ss ssa->var_info[j].has_range && ssa->vars[j].definition_phi && ssa->vars[j].definition_phi->pi >= 0 && + ssa->vars[j].definition_phi->constraint.type_mask == (uint32_t) -1 && ssa->vars[j].definition_phi->constraint.negative && ssa->vars[j].definition_phi->constraint.min_ssa_var < 0 && ssa->vars[j].definition_phi->constraint.min_ssa_var < 0) { @@ -2173,6 +2175,20 @@ uint32_t zend_array_element_type(uint32_t t1, int write, int insert) return tmp; } +static inline zend_class_entry *get_class_entry(const zend_script *script, zend_string *lcname) { + zend_class_entry *ce = zend_hash_find_ptr(&script->class_table, lcname); + if (ce) { + return ce; + } + + ce = zend_hash_find_ptr(CG(class_table), lcname); + if (ce && ce->type == ZEND_INTERNAL_CLASS) { + return ce; + } + + return NULL; +} + static void zend_update_type_info(const zend_op_array *op_array, zend_ssa *ssa, const zend_script *script, @@ -2188,23 +2204,7 @@ static void zend_update_type_info(const zend_op_array *op_array, zend_class_entry *ce; int j; - if (opline->opcode == ZEND_OP_DATA && - ((opline-1)->opcode == ZEND_ASSIGN_DIM || - (opline-1)->opcode == ZEND_ASSIGN_OBJ || - (opline-1)->opcode == ZEND_ASSIGN_ADD || - (opline-1)->opcode == ZEND_ASSIGN_SUB || - (opline-1)->opcode == ZEND_ASSIGN_MUL || - (opline-1)->opcode == ZEND_ASSIGN_DIV || - (opline-1)->opcode == ZEND_ASSIGN_MOD || - (opline-1)->opcode == ZEND_ASSIGN_SL || - (opline-1)->opcode == ZEND_ASSIGN_SR || - (opline-1)->opcode == ZEND_ASSIGN_CONCAT || - (opline-1)->opcode == ZEND_ASSIGN_BW_OR || - (opline-1)->opcode == ZEND_ASSIGN_BW_AND || - (opline-1)->opcode == ZEND_ASSIGN_BW_XOR || - (opline-1)->opcode == ZEND_ASSIGN_POW || - (opline-1)->opcode == ZEND_FE_FETCH_R || - (opline-1)->opcode == ZEND_FE_FETCH_RW)) { + if (opline->opcode == ZEND_OP_DATA) { opline--; i--; } @@ -2350,6 +2350,7 @@ static void zend_update_type_info(const zend_op_array *op_array, UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def); break; case ZEND_QM_ASSIGN: + case ZEND_JMP_SET: case ZEND_COALESCE: tmp = t1 & ~(MAY_BE_UNDEF|MAY_BE_REF); if (t1 & MAY_BE_UNDEF) { @@ -2358,6 +2359,14 @@ static void zend_update_type_info(const zend_op_array *op_array, if (opline->op1_type & (IS_CV|IS_VAR)) { tmp |= MAY_BE_RCN; } + if (opline->opcode != ZEND_QM_ASSIGN) { + /* COALESCE and JMP_SET result can't be null */ + tmp &= ~MAY_BE_NULL; + if (opline->opcode == ZEND_JMP_SET) { + /* JMP_SET result can't be false either */ + tmp &= ~MAY_BE_FALSE; + } + } UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def); if ((t1 & MAY_BE_OBJECT) && ssa_ops[i].op1_use >= 0 && ssa_var_info[ssa_ops[i].op1_use].ce) { UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_ops[i].op1_use].ce, ssa_var_info[ssa_ops[i].op1_use].is_instanceof, ssa_ops[i].result_def); @@ -3051,7 +3060,11 @@ static void zend_update_type_info(const zend_op_array *op_array, } break; case ZEND_BIND_GLOBAL: - tmp = (MAY_BE_REF | MAY_BE_ANY ); + tmp = (MAY_BE_REF | MAY_BE_ANY); + UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def); + break; + case ZEND_BIND_STATIC: + tmp = MAY_BE_ANY | (opline->extended_value ? MAY_BE_REF : (MAY_BE_RC1 | MAY_BE_RCN)); UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def); break; case ZEND_SEND_VAR: @@ -3076,6 +3089,25 @@ static void zend_update_type_info(const zend_op_array *op_array, } } break; + case ZEND_YIELD: + if (ssa_ops[i].op1_def >= 0) { + tmp = t1 | MAY_BE_RC1 | MAY_BE_RCN; + if (op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) { + tmp |= MAY_BE_REF; + } + UPDATE_SSA_TYPE(tmp, ssa_ops[i].op1_def); + if ((t1 & MAY_BE_OBJECT) && ssa_var_info[ssa_ops[i].op1_use].ce) { + UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_ops[i].op1_use].ce, ssa_var_info[ssa_ops[i].op1_use].is_instanceof, ssa_ops[i].op1_def); + } else { + UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].op1_def); + } + } + if (ssa_ops[i].result_def >= 0) { + tmp = MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF + | MAY_BE_RC1 | MAY_BE_RCN; + UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def); + } + break; case ZEND_SEND_VAR_EX: case ZEND_SEND_VAR_NO_REF: case ZEND_SEND_REF: @@ -3112,13 +3144,7 @@ static void zend_update_type_info(const zend_op_array *op_array, // class type hinting... zend_string *lcname = zend_string_tolower(arg_info->class_name); tmp |= MAY_BE_OBJECT; - ce = zend_hash_find_ptr(&script->class_table, lcname); - if (!ce) { - ce = zend_hash_find_ptr(CG(class_table), lcname); - if (ce && ce->type != ZEND_INTERNAL_CLASS) { - ce = NULL; - } - } + ce = get_class_entry(script, lcname); zend_string_release(lcname); } else if (arg_info->type_hint != IS_UNDEF) { if (arg_info->type_hint == IS_CALLABLE) { @@ -3219,14 +3245,8 @@ static void zend_update_type_info(const zend_op_array *op_array, } else if (opline->op2_type == IS_CONST) { zval *zv = CRT_CONSTANT_EX(op_array, opline->op2, ssa->rt_constants); if (Z_TYPE_P(zv) == IS_STRING) { - if ((ce = zend_hash_find_ptr(&script->class_table, Z_STR_P(zv+1))) != NULL) { - UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_ops[i].result_def); - } else if ((ce = zend_hash_find_ptr(CG(class_table), Z_STR_P(zv+1))) != NULL && - ce->type == ZEND_INTERNAL_CLASS) { - UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_ops[i].result_def); - } else { - UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def); - } + ce = get_class_entry(script, Z_STR_P(zv+1)); + UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_ops[i].result_def); } else { UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].result_def); } @@ -3241,7 +3261,7 @@ static void zend_update_type_info(const zend_op_array *op_array, case ZEND_NEW: tmp = MAY_BE_RC1|MAY_BE_RCN|MAY_BE_OBJECT; if (opline->op1_type == IS_CONST && - (ce = zend_hash_find_ptr(CG(class_table), Z_STR_P(CRT_CONSTANT_EX(op_array, opline->op1, ssa->rt_constants)+1))) != NULL) { + (ce = get_class_entry(script, Z_STR_P(CRT_CONSTANT_EX(op_array, opline->op1, ssa->rt_constants)+1))) != NULL) { UPDATE_SSA_OBJ_TYPE(ce, 0, ssa_ops[i].result_def); } else if ((t1 & MAY_BE_CLASS) && ssa_ops[i].op1_use >= 0 && ssa_var_info[ssa_ops[i].op1_use].ce) { UPDATE_SSA_OBJ_TYPE(ssa_var_info[ssa_ops[i].op1_use].ce, ssa_var_info[ssa_ops[i].op1_use].is_instanceof, ssa_ops[i].result_def); @@ -3399,39 +3419,34 @@ static void zend_update_type_info(const zend_op_array *op_array, } } UPDATE_SSA_TYPE(tmp, ssa_ops[i].op2_def); - if (opline->result_type == IS_TMP_VAR) { - if (ssa_ops[i].result_def >= 0) { - tmp = MAY_BE_RC1; - if (t1 & MAY_BE_OBJECT) { - tmp |= MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; - } else if (t1 & MAY_BE_ARRAY) { - if (t1 & MAY_BE_ARRAY_KEY_LONG) { - tmp |= MAY_BE_LONG; - } - if (t1 & MAY_BE_ARRAY_KEY_STRING) { - tmp |= MAY_BE_STRING; - } - if (!(tmp & (MAY_BE_LONG|MAY_BE_STRING))) { - tmp |= MAY_BE_NULL; - } + if (ssa_ops[i].result_def >= 0) { + tmp = MAY_BE_RC1; + if (t1 & MAY_BE_OBJECT) { + tmp |= MAY_BE_RCN | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; + } else if (t1 & MAY_BE_ARRAY) { + if (t1 & MAY_BE_ARRAY_KEY_LONG) { + tmp |= MAY_BE_LONG; + } + if (t1 & MAY_BE_ARRAY_KEY_STRING) { + tmp |= MAY_BE_STRING; + } + if (!(tmp & (MAY_BE_LONG|MAY_BE_STRING))) { + tmp |= MAY_BE_NULL; } - UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def); } + UPDATE_SSA_TYPE(tmp, ssa_ops[i].result_def); } break; // case ZEND_CATCH: // TODO: ??? // break; -// case ZEND_JMP_SET: -// case ZEND_COALESCE: -// TODO: ??? -// break; case ZEND_FETCH_DIM_R: case ZEND_FETCH_DIM_IS: case ZEND_FETCH_DIM_RW: case ZEND_FETCH_DIM_W: case ZEND_FETCH_DIM_UNSET: case ZEND_FETCH_DIM_FUNC_ARG: + case ZEND_FETCH_LIST: if (ssa_ops[i].op1_def >= 0) { tmp = t1; if (opline->opcode == ZEND_FETCH_DIM_W || @@ -3514,9 +3529,11 @@ static void zend_update_type_info(const zend_op_array *op_array, UPDATE_SSA_OBJ_TYPE(NULL, 0, ssa_ops[i].op1_def); } } + /* FETCH_LIST on a string behaves like FETCH_R on null */ tmp = zend_array_element_type( - t1, - (opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS), + opline->opcode != ZEND_FETCH_LIST ? t1 : ((t1 & ~MAY_BE_STRING) | MAY_BE_NULL), + opline->opcode != ZEND_FETCH_DIM_R && opline->opcode != ZEND_FETCH_DIM_IS + && opline->opcode != ZEND_FETCH_LIST, opline->op2_type == IS_UNUSED); if (opline->opcode == ZEND_FETCH_DIM_W || opline->opcode == ZEND_FETCH_DIM_RW || @@ -3654,6 +3671,9 @@ int zend_infer_types_ex(const zend_op_array *op_array, const zend_script *script zend_ssa_phi *p = ssa_vars[j].definition_phi; if (p->pi >= 0) { tmp = get_ssa_var_info(ssa, p->sources[0]); + if (p->constraint.type_mask != (uint32_t) -1) { + tmp &= p->constraint.type_mask; + } UPDATE_SSA_TYPE(tmp, j); if (ssa_var_info[p->sources[0]].ce) { UPDATE_SSA_OBJ_TYPE(ssa_var_info[p->sources[0]].ce, ssa_var_info[p->sources[0]].is_instanceof, j); @@ -4070,17 +4090,22 @@ int zend_ssa_inference(zend_arena **arena, const zend_op_array *op_array, const } ssa_var_info = ssa->var_info; - for (i = 0; i < op_array->last_var; i++) { - if (!op_array->function_name) { + if (!op_array->function_name) { + for (i = 0; i < op_array->last_var; i++) { ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_REF | MAY_BE_ANY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY | MAY_BE_ARRAY_OF_REF; - } else if (i == EX_VAR_TO_NUM(op_array->this_var)) { - ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_OBJECT; - ssa_var_info[i].ce = op_array->scope; - ssa_var_info[i].is_instanceof = 1; - } else { - ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RCN; + ssa_var_info[i].has_range = 0; + } + } else { + for (i = 0; i < op_array->last_var; i++) { + if (i == EX_VAR_TO_NUM(op_array->this_var)) { + ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RC1 | MAY_BE_RCN | MAY_BE_OBJECT; + ssa_var_info[i].ce = op_array->scope; + ssa_var_info[i].is_instanceof = 1; + } else { + ssa_var_info[i].type = MAY_BE_UNDEF | MAY_BE_RCN; + } + ssa_var_info[i].has_range = 0; } - ssa_var_info[i].has_range = 0; } for (i = op_array->last_var; i < ssa->vars_count; i++) { ssa_var_info[i].type = 0; diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c index 1a1cebda9e..f398a83927 100644 --- a/ext/opcache/Optimizer/zend_optimizer.c +++ b/ext/opcache/Optimizer/zend_optimizer.c @@ -307,26 +307,6 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array, opline->op2.constant = zend_optimizer_add_literal(op_array, val); } break; - case ZEND_OP_DATA: - if ((opline-1)->opcode != ZEND_ASSIGN_DIM && - ((opline-1)->extended_value != ZEND_ASSIGN_DIM || - ((opline-1)->opcode != ZEND_ASSIGN_ADD && - (opline-1)->opcode != ZEND_ASSIGN_SUB && - (opline-1)->opcode != ZEND_ASSIGN_MUL && - (opline-1)->opcode != ZEND_ASSIGN_DIV && - (opline-1)->opcode != ZEND_ASSIGN_POW && - (opline-1)->opcode != ZEND_ASSIGN_MOD && - (opline-1)->opcode != ZEND_ASSIGN_SL && - (opline-1)->opcode != ZEND_ASSIGN_SR && - (opline-1)->opcode != ZEND_ASSIGN_CONCAT && - (opline-1)->opcode != ZEND_ASSIGN_BW_OR && - (opline-1)->opcode != ZEND_ASSIGN_BW_AND && - (opline-1)->opcode != ZEND_ASSIGN_BW_XOR)) - ) { - opline->op2.constant = zend_optimizer_add_literal(op_array, val); - break; - } - /* break missing intentionally */ case ZEND_ISSET_ISEMPTY_DIM_OBJ: case ZEND_ADD_ARRAY_ELEMENT: case ZEND_INIT_ARRAY: @@ -388,16 +368,20 @@ void zend_optimizer_remove_live_range(zend_op_array *op_array, uint32_t var) i++; } while (i < op_array->last_live_range); if (i != j) { - zend_op *opline = op_array->opcodes; - zend_op *end = opline + op_array->last; - - op_array->last_live_range = j; - while (opline != end) { - if ((opline->opcode == ZEND_FREE || opline->opcode == ZEND_FE_FREE) && - opline->extended_value == ZEND_FREE_ON_RETURN) { - opline->op2.num = map[opline->op2.num]; + if ((op_array->last_live_range = j)) { + zend_op *opline = op_array->opcodes; + zend_op *end = opline + op_array->last; + + while (opline != end) { + if ((opline->opcode == ZEND_FREE || opline->opcode == ZEND_FE_FREE) && + opline->extended_value == ZEND_FREE_ON_RETURN) { + opline->op2.num = map[opline->op2.num]; + } + opline++; } - opline++; + } else { + efree(op_array->live_range); + op_array->live_range = NULL; } } free_alloca(map, use_heap); @@ -595,7 +579,7 @@ static void zend_optimize(zend_op_array *op_array, * - INIT_FCALL_BY_NAME -> DO_FCALL */ if (ZEND_OPTIMIZER_PASS_4 & ctx->optimization_level) { - optimize_func_calls(op_array, ctx); + zend_optimize_func_calls(op_array, ctx); if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_4) { zend_dump_op_array(op_array, 0, "after pass 1", NULL); } @@ -605,7 +589,7 @@ static void zend_optimize(zend_op_array *op_array, * - CFG optimization */ if (ZEND_OPTIMIZER_PASS_5 & ctx->optimization_level) { - optimize_cfg(op_array, ctx); + zend_optimize_cfg(op_array, ctx); if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_5) { zend_dump_op_array(op_array, 0, "after pass 5", NULL); } @@ -617,7 +601,7 @@ static void zend_optimize(zend_op_array *op_array, */ if ((ZEND_OPTIMIZER_PASS_6 & ctx->optimization_level) && !(ZEND_OPTIMIZER_PASS_7 & ctx->optimization_level)) { - optimize_dfa(op_array, ctx); + zend_optimize_dfa(op_array, ctx); if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_6) { zend_dump_op_array(op_array, 0, "after pass 6", NULL); } @@ -628,7 +612,7 @@ static void zend_optimize(zend_op_array *op_array, * - Optimize temp variables usage */ if (ZEND_OPTIMIZER_PASS_9 & ctx->optimization_level) { - optimize_temporary_variables(op_array, ctx); + zend_optimize_temporary_variables(op_array, ctx); if (ctx->debug_level & ZEND_DUMP_AFTER_PASS_9) { zend_dump_op_array(op_array, 0, "after pass 9", NULL); } diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h index 2efb0b2030..220a00d6c4 100644 --- a/ext/opcache/Optimizer/zend_optimizer_internal.h +++ b/ext/opcache/Optimizer/zend_optimizer_internal.h @@ -43,7 +43,7 @@ #define INV_COND_EX(op) ((op) == ZEND_JMPZ ? ZEND_JMPNZ_EX : ZEND_JMPZ_EX) #define INV_EX_COND_EX(op) ((op) == ZEND_JMPZ_EX ? ZEND_JMPNZ_EX : ZEND_JMPZ_EX) -#define RESULT_UNUSED(op) ((op->result_type & EXT_TYPE_UNUSED) != 0) +#define RESULT_UNUSED(op) (op->result_type == IS_UNUSED) #define SAME_VAR(op1, op2) (op1 ## _type == op2 ## _type && op1.var == op2.var) typedef struct _zend_optimizer_ctx { @@ -97,12 +97,12 @@ void zend_optimizer_remove_live_range(zend_op_array *op_array, uint32_t var); void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx); void zend_optimizer_pass2(zend_op_array *op_array); void zend_optimizer_pass3(zend_op_array *op_array); -void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx); -void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx); -void optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx); +void zend_optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx); +void zend_optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx); +void zend_optimize_dfa(zend_op_array *op_array, zend_optimizer_ctx *ctx); int zend_dfa_analyze_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa, uint32_t *flags); void zend_dfa_optimize_op_array(zend_op_array *op_array, zend_optimizer_ctx *ctx, zend_ssa *ssa); -void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx); +void zend_optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *ctx); void zend_optimizer_nop_removal(zend_op_array *op_array); void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx *ctx); int zend_optimizer_is_disabled_func(const char *name, size_t len); diff --git a/ext/opcache/Optimizer/zend_ssa.c b/ext/opcache/Optimizer/zend_ssa.c index 70c042e946..0da793918c 100644 --- a/ext/opcache/Optimizer/zend_ssa.c +++ b/ext/opcache/Optimizer/zend_ssa.c @@ -21,6 +21,7 @@ #include "zend_dfg.h" #include "zend_ssa.h" #include "zend_dump.h" +#include "zend_inference.h" static int needs_pi(const zend_op_array *op_array, zend_dfg *dfg, zend_ssa *ssa, int from, int to, int var) /* {{{ */ { @@ -38,40 +39,84 @@ static int needs_pi(const zend_op_array *op_array, zend_dfg *dfg, zend_ssa *ssa, } /* }}} */ -static int add_pi(zend_arena **arena, const zend_op_array *op_array, zend_dfg *dfg, zend_ssa *ssa, int from, int to, int var, int min_var, int max_var, zend_long min, zend_long max, char underflow, char overflow, char negative) /* {{{ */ +static zend_ssa_phi *add_pi( + zend_arena **arena, const zend_op_array *op_array, zend_dfg *dfg, zend_ssa *ssa, + int from, int to, int var) /* {{{ */ { - if (needs_pi(op_array, dfg, ssa, from, to, var)) { - zend_ssa_phi *phi = zend_arena_calloc(arena, 1, - sizeof(zend_ssa_phi) + - sizeof(int) * ssa->cfg.blocks[to].predecessors_count + - sizeof(void*) * ssa->cfg.blocks[to].predecessors_count); + zend_ssa_phi *phi; + if (!needs_pi(op_array, dfg, ssa, from, to, var)) { + return NULL; + } - if (!phi) { - return FAILURE; - } - phi->sources = (int*)(((char*)phi) + sizeof(zend_ssa_phi)); - memset(phi->sources, 0xff, sizeof(int) * ssa->cfg.blocks[to].predecessors_count); - phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + sizeof(int) * ssa->cfg.blocks[to].predecessors_count); + phi = zend_arena_calloc(arena, 1, + sizeof(zend_ssa_phi) + + sizeof(int) * ssa->cfg.blocks[to].predecessors_count + + sizeof(void*) * ssa->cfg.blocks[to].predecessors_count); + phi->sources = (int*)(((char*)phi) + sizeof(zend_ssa_phi)); + memset(phi->sources, 0xff, sizeof(int) * ssa->cfg.blocks[to].predecessors_count); + phi->use_chains = (zend_ssa_phi**)(((char*)phi->sources) + sizeof(int) * ssa->cfg.blocks[to].predecessors_count); - phi->pi = from; - phi->constraint.min_var = min_var; - phi->constraint.max_var = max_var; - phi->constraint.min_ssa_var = -1; - phi->constraint.max_ssa_var = -1; - phi->constraint.range.min = min; - phi->constraint.range.max = max; - phi->constraint.range.underflow = underflow; - phi->constraint.range.overflow = overflow; - phi->constraint.negative = negative ? NEG_INIT : NEG_NONE; - phi->var = var; - phi->ssa_var = -1; - phi->next = ssa->blocks[to].phis; - ssa->blocks[to].phis = phi; - } - return SUCCESS; + phi->pi = from; + phi->var = var; + phi->ssa_var = -1; + phi->next = ssa->blocks[to].phis; + ssa->blocks[to].phis = phi; + + return phi; } /* }}} */ +static void pi_range( + zend_ssa_phi *phi, int min_var, int max_var, zend_long min, zend_long max, + char underflow, char overflow, char negative) /* {{{ */ +{ + phi->constraint.min_var = min_var; + phi->constraint.max_var = max_var; + phi->constraint.min_ssa_var = -1; + phi->constraint.max_ssa_var = -1; + phi->constraint.range.min = min; + phi->constraint.range.max = max; + phi->constraint.range.underflow = underflow; + phi->constraint.range.overflow = overflow; + phi->constraint.negative = negative ? NEG_INIT : NEG_NONE; + phi->constraint.type_mask = (uint32_t) -1; +} +/* }}} */ + +static inline void pi_range_equals(zend_ssa_phi *phi, int var, zend_long val) { + pi_range(phi, var, var, val, val, 0, 0, 0); +} +static inline void pi_range_not_equals(zend_ssa_phi *phi, int var, zend_long val) { + pi_range(phi, var, var, val, val, 0, 0, 1); +} +static inline void pi_range_min(zend_ssa_phi *phi, int var, zend_long val) { + pi_range(phi, var, -1, val, ZEND_LONG_MAX, 0, 1, 0); +} +static inline void pi_range_max(zend_ssa_phi *phi, int var, zend_long val) { + pi_range(phi, -1, var, ZEND_LONG_MIN, val, 1, 0, 0); +} + +static void pi_type_mask(zend_ssa_phi *phi, uint32_t type_mask) { + phi->constraint.type_mask = MAY_BE_REF|MAY_BE_RC1|MAY_BE_RCN; + phi->constraint.type_mask |= type_mask; + if (type_mask & MAY_BE_NULL) { + phi->constraint.type_mask |= MAY_BE_UNDEF; + } +} +static inline void pi_not_type_mask(zend_ssa_phi *phi, uint32_t type_mask) { + uint32_t relevant = MAY_BE_ANY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; + pi_type_mask(phi, ~type_mask & relevant); +} +static inline uint32_t mask_for_type_check(uint32_t type) { + if (type == _IS_BOOL) { + return MAY_BE_TRUE|MAY_BE_FALSE; + } else if (type == IS_ARRAY) { + return MAY_BE_ARRAY|MAY_BE_ARRAY_KEY_ANY|MAY_BE_ARRAY_OF_ANY|MAY_BE_ARRAY_OF_REF; + } else { + return 1 << type; + } +} + /* We can interpret $a + 5 == 0 as $a = 0 - 5, i.e. shift the adjustment to the other operand. * This negated adjustment is what is written into the "adjustment" parameter. */ static int find_adjusted_tmp_var(const zend_op_array *op_array, uint32_t build_flags, zend_op *opline, uint32_t var_num, zend_long *adjustment) @@ -129,6 +174,278 @@ static inline zend_bool sub_will_overflow(zend_long a, zend_long b) { || (b < 0 && a > ZEND_LONG_MAX + b); } +/* e-SSA construction: Pi placement (Pi is actually a Phi with single + * source and constraint). + * Order of Phis is importent, Pis must be placed before Phis + */ +static void place_essa_pis( + zend_arena **arena, const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, + zend_dfg *dfg) { + zend_basic_block *blocks = ssa->cfg.blocks; + int j, blocks_count = ssa->cfg.blocks_count; + for (j = 0; j < blocks_count; j++) { + zend_ssa_phi *pi; + zend_op *opline = op_array->opcodes + ssa->cfg.blocks[j].end; + int bt; /* successor block number if a condition is true */ + int bf; /* successor block number if a condition is false */ + + if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) { + continue; + } + /* the last instruction of basic block is conditional branch, + * based on comparison of CV(s) + */ + switch (opline->opcode) { + case ZEND_JMPZ: + case ZEND_JMPZNZ: + bf = ssa->cfg.blocks[j].successors[0]; + bt = ssa->cfg.blocks[j].successors[1]; + break; + case ZEND_JMPNZ: + bt = ssa->cfg.blocks[j].successors[0]; + bf = ssa->cfg.blocks[j].successors[1]; + break; + default: + continue; + } + if (opline->op1_type == IS_TMP_VAR && + ((opline-1)->opcode == ZEND_IS_EQUAL || + (opline-1)->opcode == ZEND_IS_NOT_EQUAL || + (opline-1)->opcode == ZEND_IS_SMALLER || + (opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) && + opline->op1.var == (opline-1)->result.var) { + int var1 = -1; + int var2 = -1; + zend_long val1 = 0; + zend_long val2 = 0; +// long val = 0; + + if ((opline-1)->op1_type == IS_CV) { + var1 = EX_VAR_TO_NUM((opline-1)->op1.var); + } else if ((opline-1)->op1_type == IS_TMP_VAR) { + var1 = find_adjusted_tmp_var( + op_array, build_flags, opline, (opline-1)->op1.var, &val2); + } + + if ((opline-1)->op2_type == IS_CV) { + var2 = EX_VAR_TO_NUM((opline-1)->op2.var); + } else if ((opline-1)->op2_type == IS_TMP_VAR) { + var2 = find_adjusted_tmp_var( + op_array, build_flags, opline, (opline-1)->op2.var, &val1); + } + + if (var1 >= 0 && var2 >= 0) { + if (!sub_will_overflow(val1, val2) && !sub_will_overflow(val2, val1)) { + zend_long tmp = val1; + val1 -= val2; + val2 -= tmp; + } else { + var1 = -1; + var2 = -1; + } + } else if (var1 >= 0 && var2 < 0) { + zend_long add_val2 = 0; + if ((opline-1)->op2_type == IS_CONST && + Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_LONG) { + add_val2 = Z_LVAL_P(CRT_CONSTANT((opline-1)->op2)); + } else if ((opline-1)->op2_type == IS_CONST && + Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_FALSE) { + add_val2 = 0; + } else if ((opline-1)->op2_type == IS_CONST && + Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_TRUE) { + add_val2 = 1; + } else { + var1 = -1; + } + if (!add_will_overflow(val2, add_val2)) { + val2 += add_val2; + } else { + var1 = -1; + } + } else if (var1 < 0 && var2 >= 0) { + zend_long add_val1 = 0; + if ((opline-1)->op1_type == IS_CONST && + Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_LONG) { + add_val1 = Z_LVAL_P(CRT_CONSTANT((opline-1)->op1)); + } else if ((opline-1)->op1_type == IS_CONST && + Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_FALSE) { + add_val1 = 0; + } else if ((opline-1)->op1_type == IS_CONST && + Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_TRUE) { + add_val1 = 1; + } else { + var2 = -1; + } + if (!add_will_overflow(val1, add_val1)) { + val1 += add_val1; + } else { + var2 = -1; + } + } + + if (var1 >= 0) { + if ((opline-1)->opcode == ZEND_IS_EQUAL) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) { + pi_range_equals(pi, var2, val2); + } + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) { + pi_range_not_equals(pi, var2, val2); + } + } else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) { + pi_range_equals(pi, var2, val2); + } + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) { + pi_range_not_equals(pi, var2, val2); + } + } else if ((opline-1)->opcode == ZEND_IS_SMALLER) { + if (val2 > ZEND_LONG_MIN) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) { + pi_range_max(pi, var2, val2-1); + } + } + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) { + pi_range_min(pi, var2, val2); + } + } else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var1))) { + pi_range_max(pi, var2, val2); + } + if (val2 < ZEND_LONG_MAX) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var1))) { + pi_range_min(pi, var2, val2+1); + } + } + } + } + if (var2 >= 0) { + if((opline-1)->opcode == ZEND_IS_EQUAL) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) { + pi_range_equals(pi, var1, val1); + } + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) { + pi_range_not_equals(pi, var1, val1); + } + } else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) { + pi_range_equals(pi, var1, val1); + } + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) { + pi_range_not_equals(pi, var1, val1); + } + } else if ((opline-1)->opcode == ZEND_IS_SMALLER) { + if (val1 < ZEND_LONG_MAX) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) { + pi_range_min(pi, var1, val1+1); + } + } + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) { + pi_range_max(pi, var1, val1); + } + } else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var2))) { + pi_range_min(pi, var1, val1); + } + if (val1 > ZEND_LONG_MIN) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var2))) { + pi_range_max(pi, var1, val1-1); + } + } + } + } + } else if (opline->op1_type == IS_TMP_VAR && + ((opline-1)->opcode == ZEND_POST_INC || + (opline-1)->opcode == ZEND_POST_DEC) && + opline->op1.var == (opline-1)->result.var && + (opline-1)->op1_type == IS_CV) { + int var = EX_VAR_TO_NUM((opline-1)->op1.var); + + if ((opline-1)->opcode == ZEND_POST_DEC) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) { + pi_range_equals(pi, -1, -1); + } + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) { + pi_range_not_equals(pi, -1, -1); + } + } else if ((opline-1)->opcode == ZEND_POST_INC) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) { + pi_range_equals(pi, -1, 1); + } + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) { + pi_range_not_equals(pi, -1, 1); + } + } + } else if (opline->op1_type == IS_VAR && + ((opline-1)->opcode == ZEND_PRE_INC || + (opline-1)->opcode == ZEND_PRE_DEC) && + opline->op1.var == (opline-1)->result.var && + (opline-1)->op1_type == IS_CV) { + int var = EX_VAR_TO_NUM((opline-1)->op1.var); + + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) { + pi_range_equals(pi, -1, 0); + } + /* speculative */ + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) { + pi_range_not_equals(pi, -1, 0); + } + } else if (opline->op1_type == IS_TMP_VAR && (opline-1)->opcode == ZEND_TYPE_CHECK && + opline->op1.var == (opline-1)->result.var && (opline-1)->op1_type == IS_CV) { + int var = EX_VAR_TO_NUM((opline-1)->op1.var); + uint32_t type = (opline-1)->extended_value; + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) { + pi_type_mask(pi, mask_for_type_check(type)); + } + if (type != IS_OBJECT && type != IS_RESOURCE) { + /* is_object() and is_resource() may return false, even though the value is + * an object/resource. */ + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) { + pi_not_type_mask(pi, mask_for_type_check(type)); + } + } + } else if (opline->op1_type == IS_TMP_VAR && + ((opline-1)->opcode == ZEND_IS_IDENTICAL + || (opline-1)->opcode == ZEND_IS_NOT_IDENTICAL) && + opline->op1.var == (opline-1)->result.var) { + int var; + zval *val; + uint32_t type_mask; + if ((opline-1)->op1_type == IS_CV && (opline-1)->op2_type == IS_CONST) { + var = EX_VAR_TO_NUM((opline-1)->op1.var); + val = CRT_CONSTANT((opline-1)->op2); + } else if ((opline-1)->op1_type == IS_CONST && (opline-1)->op2_type == IS_CV) { + var = EX_VAR_TO_NUM((opline-1)->op2.var); + val = CRT_CONSTANT((opline-1)->op1); + } else { + continue; + } + + /* We're interested in === null/true/false comparisons here, because they eliminate + * a type in the false-branch. Other === VAL comparisons are unlikely to be useful. */ + if (Z_TYPE_P(val) != IS_NULL && Z_TYPE_P(val) != IS_TRUE && Z_TYPE_P(val) != IS_FALSE) { + continue; + } + + type_mask = _const_op_type(val); + if ((opline-1)->opcode == ZEND_IS_IDENTICAL) { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) { + pi_type_mask(pi, type_mask); + } + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) { + pi_not_type_mask(pi, type_mask); + } + } else { + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bf, var))) { + pi_type_mask(pi, type_mask); + } + if ((pi = add_pi(arena, op_array, dfg, ssa, j, bt, var))) { + pi_not_type_mask(pi, type_mask); + } + } + } + } +} + static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags, zend_ssa *ssa, int *var, int n) /* {{{ */ { zend_basic_block *blocks = ssa->cfg.blocks; @@ -171,39 +488,16 @@ static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags, if (next->op1_type == IS_CV) { ssa_ops[k + 1].op1_use = var[EX_VAR_TO_NUM(next->op1.var)]; //USE_SSA_VAR(next->op1.var); - } else if (next->op1_type == IS_VAR || - next->op1_type == IS_TMP_VAR) { + } else if (next->op1_type & (IS_VAR|IS_TMP_VAR)) { ssa_ops[k + 1].op1_use = var[EX_VAR_TO_NUM(next->op1.var)]; //USE_SSA_VAR(op_array->last_var + next->op1.var); } if (next->op2_type == IS_CV) { ssa_ops[k + 1].op2_use = var[EX_VAR_TO_NUM(next->op2.var)]; //USE_SSA_VAR(next->op2.var); - } else if (next->op2_type == IS_VAR || - next->op2_type == IS_TMP_VAR) { - /* ZEND_ASSIGN_??? use the second operand - of the following OP_DATA instruction as - a temporary variable */ - switch (opline->opcode) { - case ZEND_ASSIGN_DIM: - case ZEND_ASSIGN_OBJ: - case ZEND_ASSIGN_ADD: - case ZEND_ASSIGN_SUB: - case ZEND_ASSIGN_MUL: - case ZEND_ASSIGN_DIV: - case ZEND_ASSIGN_MOD: - case ZEND_ASSIGN_SL: - case ZEND_ASSIGN_SR: - case ZEND_ASSIGN_CONCAT: - case ZEND_ASSIGN_BW_OR: - case ZEND_ASSIGN_BW_AND: - case ZEND_ASSIGN_BW_XOR: - case ZEND_ASSIGN_POW: - break; - default: - ssa_ops[k + 1].op2_use = var[EX_VAR_TO_NUM(next->op2.var)]; - //USE_SSA_VAR(op_array->last_var + next->op2.var); - } + } else if (next->op2_type & (IS_VAR|IS_TMP_VAR)) { + ssa_ops[k + 1].op2_use = var[EX_VAR_TO_NUM(next->op2.var)]; + //USE_SSA_VAR(op_array->last_var + next->op2.var); } } if (opline->op1_type & (IS_CV|IS_VAR|IS_TMP_VAR)) { @@ -253,6 +547,7 @@ static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags, } break; case ZEND_BIND_GLOBAL: + case ZEND_BIND_STATIC: if (opline->op1_type == IS_CV) { ssa_ops[k].op1_def = ssa_vars_count; var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count; @@ -361,6 +656,14 @@ static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags, ssa_vars_count++; } break; + case ZEND_YIELD: + if (opline->op1_type == IS_CV + && ((op_array->fn_flags & ZEND_ACC_RETURN_REFERENCE) + || (build_flags & ZEND_SSA_RC_INFERENCE))) { + ssa_ops[k].op1_def = ssa_vars_count; + var[EX_VAR_TO_NUM(opline->op1.var)] = ssa_vars_count; + ssa_vars_count++; + } default: break; } @@ -369,8 +672,7 @@ static int zend_ssa_rename(const zend_op_array *op_array, uint32_t build_flags, var[EX_VAR_TO_NUM(opline->result.var)] = ssa_vars_count; ssa_vars_count++; //NEW_SSA_VAR(opline->result.var) - } else if (opline->result_type == IS_VAR || - opline->result_type == IS_TMP_VAR) { + } else if (opline->result_type & (IS_VAR|IS_TMP_VAR)) { ssa_ops[k].result_def = ssa_vars_count; var[EX_VAR_TO_NUM(opline->result.var)] = ssa_vars_count; ssa_vars_count++; @@ -478,7 +780,7 @@ int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t b dfg.in = dfg.use + set_size * blocks_count; dfg.out = dfg.in + set_size * blocks_count; - if (zend_build_dfg(op_array, &ssa->cfg, &dfg) != SUCCESS) { + if (zend_build_dfg(op_array, &ssa->cfg, &dfg, build_flags) != SUCCESS) { free_alloca(dfg.tmp, dfg_use_heap); return FAILURE; } @@ -572,227 +874,7 @@ int zend_build_ssa(zend_arena **arena, const zend_op_array *op_array, uint32_t b } } - /* e-SSA construction: Pi placement (Pi is actually a Phi with single - * source and constraint). - * Order of Phis is importent, Pis must be placed before Phis - */ - for (j = 0; j < blocks_count; j++) { - zend_op *opline = op_array->opcodes + ssa->cfg.blocks[j].end; - int bt; /* successor block number if a condition is true */ - int bf; /* successor block number if a condition is false */ - - if ((blocks[j].flags & ZEND_BB_REACHABLE) == 0) { - continue; - } - /* the last instruction of basic block is conditional branch, - * based on comparison of CV(s) - */ - switch (opline->opcode) { - case ZEND_JMPZ: - case ZEND_JMPZNZ: - bf = ssa->cfg.blocks[j].successors[0]; - bt = ssa->cfg.blocks[j].successors[1]; - break; - case ZEND_JMPNZ: - bt = ssa->cfg.blocks[j].successors[0]; - bf = ssa->cfg.blocks[j].successors[1]; - break; - default: - continue; - } - if (opline->op1_type == IS_TMP_VAR && - ((opline-1)->opcode == ZEND_IS_EQUAL || - (opline-1)->opcode == ZEND_IS_NOT_EQUAL || - (opline-1)->opcode == ZEND_IS_SMALLER || - (opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) && - opline->op1.var == (opline-1)->result.var) { - int var1 = -1; - int var2 = -1; - zend_long val1 = 0; - zend_long val2 = 0; -// long val = 0; - - if ((opline-1)->op1_type == IS_CV) { - var1 = EX_VAR_TO_NUM((opline-1)->op1.var); - } else if ((opline-1)->op1_type == IS_TMP_VAR) { - var1 = find_adjusted_tmp_var( - op_array, build_flags, opline, (opline-1)->op1.var, &val2); - } - - if ((opline-1)->op2_type == IS_CV) { - var2 = EX_VAR_TO_NUM((opline-1)->op2.var); - } else if ((opline-1)->op2_type == IS_TMP_VAR) { - var2 = find_adjusted_tmp_var( - op_array, build_flags, opline, (opline-1)->op2.var, &val1); - } - - if (var1 >= 0 && var2 >= 0) { - if (!sub_will_overflow(val1, val2) && !sub_will_overflow(val2, val1)) { - zend_long tmp = val1; - val1 -= val2; - val2 -= tmp; - } else { - var1 = -1; - var2 = -1; - } - } else if (var1 >= 0 && var2 < 0) { - zend_long add_val2 = 0; - if ((opline-1)->op2_type == IS_CONST && - Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_LONG) { - add_val2 = Z_LVAL_P(CRT_CONSTANT((opline-1)->op2)); - } else if ((opline-1)->op2_type == IS_CONST && - Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_FALSE) { - add_val2 = 0; - } else if ((opline-1)->op2_type == IS_CONST && - Z_TYPE_P(CRT_CONSTANT((opline-1)->op2)) == IS_TRUE) { - add_val2 = 1; - } else { - var1 = -1; - } - if (!add_will_overflow(val2, add_val2)) { - val2 += add_val2; - } else { - var1 = -1; - } - } else if (var1 < 0 && var2 >= 0) { - zend_long add_val1 = 0; - if ((opline-1)->op1_type == IS_CONST && - Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_LONG) { - add_val1 = Z_LVAL_P(CRT_CONSTANT((opline-1)->op1)); - } else if ((opline-1)->op1_type == IS_CONST && - Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_FALSE) { - add_val1 = 0; - } else if ((opline-1)->op1_type == IS_CONST && - Z_TYPE_P(CRT_CONSTANT((opline-1)->op1)) == IS_TRUE) { - add_val1 = 1; - } else { - var2 = -1; - } - if (!add_will_overflow(val1, add_val1)) { - val1 += add_val1; - } else { - var2 = -1; - } - } - - if (var1 >= 0) { - if ((opline-1)->opcode == ZEND_IS_EQUAL) { - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var1, var2, var2, val2, val2, 0, 0, 0) != SUCCESS) { - goto failure; - } - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var1, var2, var2, val2, val2, 0, 0, 1) != SUCCESS) { - goto failure; - } - } else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) { - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var1, var2, var2, val2, val2, 0, 0, 0) != SUCCESS) { - goto failure; - } - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var1, var2, var2, val2, val2, 0, 0, 1) != SUCCESS) { - goto failure; - } - } else if ((opline-1)->opcode == ZEND_IS_SMALLER) { - if (val2 > ZEND_LONG_MIN) { - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var1, -1, var2, ZEND_LONG_MIN, val2-1, 1, 0, 0) != SUCCESS) { - goto failure; - } - } - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var1, var2, -1, val2, ZEND_LONG_MAX, 0, 1, 0) != SUCCESS) { - goto failure; - } - } else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) { - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var1, -1, var2, ZEND_LONG_MIN, val2, 1, 0, 0) != SUCCESS) { - goto failure; - } - if (val2 < ZEND_LONG_MAX) { - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var1, var2, -1, val2+1, ZEND_LONG_MAX, 0, 1, 0) != SUCCESS) { - goto failure; - } - } - } - } - if (var2 >= 0) { - if((opline-1)->opcode == ZEND_IS_EQUAL) { - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var2, var1, var1, val1, val1, 0, 0, 0) != SUCCESS) { - goto failure; - } - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var2, var1, var1, val1, val1, 0, 0, 1) != SUCCESS) { - goto failure; - } - } else if ((opline-1)->opcode == ZEND_IS_NOT_EQUAL) { - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var2, var1, var1, val1, val1, 0, 0, 0) != SUCCESS) { - goto failure; - } - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var2, var1, var1, val1, val1, 0, 0, 1) != SUCCESS) { - goto failure; - } - } else if ((opline-1)->opcode == ZEND_IS_SMALLER) { - if (val1 < ZEND_LONG_MAX) { - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var2, var1, -1, val1+1, ZEND_LONG_MAX, 0, 1, 0) != SUCCESS) { - goto failure; - } - } - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var2, -1, var1, ZEND_LONG_MIN, val1, 1, 0, 0) != SUCCESS) { - goto failure; - } - } else if ((opline-1)->opcode == ZEND_IS_SMALLER_OR_EQUAL) { - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var2, var1, -1, val1, ZEND_LONG_MAX, 0 ,1, 0) != SUCCESS) { - goto failure; - } - if (val1 > ZEND_LONG_MIN) { - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var2, -1, var1, ZEND_LONG_MIN, val1-1, 1, 0, 0) != SUCCESS) { - goto failure; - } - } - } - } - } else if (opline->op1_type == IS_TMP_VAR && - ((opline-1)->opcode == ZEND_POST_INC || - (opline-1)->opcode == ZEND_POST_DEC) && - opline->op1.var == (opline-1)->result.var && - (opline-1)->op1_type == IS_CV) { - int var = EX_VAR_TO_NUM((opline-1)->op1.var); - - if ((opline-1)->opcode == ZEND_POST_DEC) { - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var, -1, -1, -1, -1, 0, 0, 0) != SUCCESS) { - goto failure; - } - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var, -1, -1, -1, -1, 0, 0, 1) != SUCCESS) { - goto failure; - } - } else if ((opline-1)->opcode == ZEND_POST_INC) { - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var, -1, -1, 1, 1, 0, 0, 0) != SUCCESS) { - goto failure; - } - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var, -1, -1, 1, 1, 0, 0, 1) != SUCCESS) { - goto failure; - } - } - } else if (opline->op1_type == IS_VAR && - ((opline-1)->opcode == ZEND_PRE_INC || - (opline-1)->opcode == ZEND_PRE_DEC) && - opline->op1.var == (opline-1)->result.var && - (opline-1)->op1_type == IS_CV) { - int var = EX_VAR_TO_NUM((opline-1)->op1.var); - - if ((opline-1)->opcode == ZEND_PRE_DEC) { - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var, -1, -1, 0, 0, 0, 0, 0) != SUCCESS) { - goto failure; - } - /* speculative */ - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var, -1, -1, 0, 0, 0, 0, 1) != SUCCESS) { - goto failure; - } - } else if ((opline-1)->opcode == ZEND_PRE_INC) { - if (add_pi(arena, op_array, &dfg, ssa, j, bf, var, -1, -1, 0, 0, 0, 0, 0) != SUCCESS) { - goto failure; - } - /* speculative */ - if (add_pi(arena, op_array, &dfg, ssa, j, bt, var, -1, -1, 0, 0, 0, 0, 1) != SUCCESS) { - goto failure; - } - } - } - } + place_essa_pis(arena, op_array, build_flags, ssa, &dfg); /* SSA construction, Step ?: Phi after Pi placement based on Dominance Frontiers */ for (j = 0; j < blocks_count; j++) { diff --git a/ext/opcache/Optimizer/zend_ssa.h b/ext/opcache/Optimizer/zend_ssa.h index 0e1bc84dbc..dbf260c4d8 100644 --- a/ext/opcache/Optimizer/zend_ssa.h +++ b/ext/opcache/Optimizer/zend_ssa.h @@ -38,21 +38,22 @@ typedef enum _zend_ssa_negative_lat { } zend_ssa_negative_lat; /* Special kind of SSA Phi function used in eSSA */ -typedef struct _zend_ssa_pi_range { +typedef struct _zend_ssa_pi_constraint { zend_ssa_range range; /* simple range constraint */ int min_var; int max_var; int min_ssa_var; /* ((min_var>0) ? MIN(ssa_var) : 0) + range.min */ int max_ssa_var; /* ((man_var>0) ? MAX(ssa_var) : 0) + range.man */ zend_ssa_negative_lat negative; -} zend_ssa_pi_range; + uint32_t type_mask; /* If -1 this is a range constraint */ +} zend_ssa_pi_constraint; /* SSA Phi - ssa_var = Phi(source0, source1, ...sourceN) */ typedef struct _zend_ssa_phi zend_ssa_phi; struct _zend_ssa_phi { zend_ssa_phi *next; /* next Phi in the same BB */ int pi; /* if >= 0 this is actually a e-SSA Pi */ - zend_ssa_pi_range constraint; /* e-SSA Pi constraint */ + zend_ssa_pi_constraint constraint; /* e-SSA Pi constraint */ int var; /* Original CV, VAR or TMP variable index */ int ssa_var; /* SSA variable index */ int block; /* current BB index */ @@ -121,7 +122,7 @@ int zend_ssa_unlink_use_chain(zend_ssa *ssa, int op, int var); END_EXTERN_C() -static zend_always_inline int zend_ssa_next_use(zend_ssa_op *ssa_op, int var, int use) +static zend_always_inline int zend_ssa_next_use(const zend_ssa_op *ssa_op, int var, int use) { ssa_op += use; if (ssa_op->result_use == var) { @@ -130,7 +131,7 @@ static zend_always_inline int zend_ssa_next_use(zend_ssa_op *ssa_op, int var, in return (ssa_op->op1_use == var) ? ssa_op->op1_use_chain : ssa_op->op2_use_chain; } -static zend_always_inline zend_ssa_phi* zend_ssa_next_use_phi(zend_ssa *ssa, int var, zend_ssa_phi *p) +static zend_always_inline zend_ssa_phi* zend_ssa_next_use_phi(const zend_ssa *ssa, int var, const zend_ssa_phi *p) { if (p->pi >= 0) { return p->use_chains[0]; diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c index f18488da1c..f1dc0e185c 100644 --- a/ext/opcache/ZendAccelerator.c +++ b/ext/opcache/ZendAccelerator.c @@ -220,6 +220,104 @@ static ZEND_INI_MH(accel_include_path_on_modify) return ret; } +static inline void accel_restart_enter(void) +{ +#ifdef ZEND_WIN32 + INCREMENT(restart_in); +#else + static const FLOCK_STRUCTURE(restart_in_progress, F_WRLCK, SEEK_SET, 2, 1); + + if (fcntl(lock_file, F_SETLK, &restart_in_progress) == -1) { + zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(+1): %s (%d)", strerror(errno), errno); + } +#endif + ZCSG(restart_in_progress) = 1; +} + +static inline void accel_restart_leave(void) +{ +#ifdef ZEND_WIN32 + ZCSG(restart_in_progress) = 0; + DECREMENT(restart_in); +#else + static const FLOCK_STRUCTURE(restart_finished, F_UNLCK, SEEK_SET, 2, 1); + + ZCSG(restart_in_progress) = 0; + if (fcntl(lock_file, F_SETLK, &restart_finished) == -1) { + zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(-1): %s (%d)", strerror(errno), errno); + } +#endif +} + +static inline int accel_restart_is_active(void) +{ + if (ZCSG(restart_in_progress)) { +#ifndef ZEND_WIN32 + FLOCK_STRUCTURE(restart_check, F_WRLCK, SEEK_SET, 2, 1); + + if (fcntl(lock_file, F_GETLK, &restart_check) == -1) { + zend_accel_error(ACCEL_LOG_DEBUG, "RestartC: %s (%d)", strerror(errno), errno); + return FAILURE; + } + if (restart_check.l_type == F_UNLCK) { + ZCSG(restart_in_progress) = 0; + return 0; + } else { + return 1; + } +#else + return LOCKVAL(restart_in) != 0; +#endif + } + return 0; +} + +/* Creates a read lock for SHM access */ +static inline int accel_activate_add(void) +{ +#ifdef ZEND_WIN32 + INCREMENT(mem_usage); +#else + static const FLOCK_STRUCTURE(mem_usage_lock, F_RDLCK, SEEK_SET, 1, 1); + + if (fcntl(lock_file, F_SETLK, &mem_usage_lock) == -1) { + zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(+1): %s (%d)", strerror(errno), errno); + return FAILURE; + } +#endif + return SUCCESS; +} + +/* Releases a lock for SHM access */ +static inline void accel_deactivate_sub(void) +{ +#ifdef ZEND_WIN32 + if (ZCG(counted)) { + DECREMENT(mem_usage); + ZCG(counted) = 0; + } +#else + static const FLOCK_STRUCTURE(mem_usage_unlock, F_UNLCK, SEEK_SET, 1, 1); + + if (fcntl(lock_file, F_SETLK, &mem_usage_unlock) == -1) { + zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(-1): %s (%d)", strerror(errno), errno); + } +#endif +} + +static inline void accel_unlock_all(void) +{ +#ifdef ZEND_WIN32 + accel_deactivate_sub(); +#else + static const FLOCK_STRUCTURE(mem_usage_unlock_all, F_UNLCK, SEEK_SET, 0, 0); + + if (fcntl(lock_file, F_SETLK, &mem_usage_unlock_all) == -1) { + zend_accel_error(ACCEL_LOG_DEBUG, "UnlockAll: %s (%d)", strerror(errno), errno); + } +#endif +} + /* Interned strings support */ static zend_string *(*orig_new_interned_string)(zend_string *str); static void (*orig_interned_strings_snapshot)(void); @@ -291,6 +389,12 @@ static zend_string *accel_find_interned_string(zend_string *str) /* this is already an interned string */ return str; } + if (!ZCG(counted)) { + if (accel_activate_add() == FAILURE) { + return str; + } + ZCG(counted) = 1; + } h = zend_string_hash_val(str); nIndex = h | ZCSG(interned_strings).nTableMask; @@ -492,102 +596,6 @@ static void accel_use_shm_interned_strings(void) } #endif -static inline void accel_restart_enter(void) -{ -#ifdef ZEND_WIN32 - INCREMENT(restart_in); -#else - static const FLOCK_STRUCTURE(restart_in_progress, F_WRLCK, SEEK_SET, 2, 1); - - if (fcntl(lock_file, F_SETLK, &restart_in_progress) == -1) { - zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(+1): %s (%d)", strerror(errno), errno); - } -#endif - ZCSG(restart_in_progress) = 1; -} - -static inline void accel_restart_leave(void) -{ -#ifdef ZEND_WIN32 - ZCSG(restart_in_progress) = 0; - DECREMENT(restart_in); -#else - static const FLOCK_STRUCTURE(restart_finished, F_UNLCK, SEEK_SET, 2, 1); - - ZCSG(restart_in_progress) = 0; - if (fcntl(lock_file, F_SETLK, &restart_finished) == -1) { - zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(-1): %s (%d)", strerror(errno), errno); - } -#endif -} - -static inline int accel_restart_is_active(void) -{ - if (ZCSG(restart_in_progress)) { -#ifndef ZEND_WIN32 - FLOCK_STRUCTURE(restart_check, F_WRLCK, SEEK_SET, 2, 1); - - if (fcntl(lock_file, F_GETLK, &restart_check) == -1) { - zend_accel_error(ACCEL_LOG_DEBUG, "RestartC: %s (%d)", strerror(errno), errno); - return FAILURE; - } - if (restart_check.l_type == F_UNLCK) { - ZCSG(restart_in_progress) = 0; - return 0; - } else { - return 1; - } -#else - return LOCKVAL(restart_in) != 0; -#endif - } - return 0; -} - -/* Creates a read lock for SHM access */ -static inline void accel_activate_add(void) -{ -#ifdef ZEND_WIN32 - INCREMENT(mem_usage); -#else - static const FLOCK_STRUCTURE(mem_usage_lock, F_RDLCK, SEEK_SET, 1, 1); - - if (fcntl(lock_file, F_SETLK, &mem_usage_lock) == -1) { - zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(+1): %s (%d)", strerror(errno), errno); - } -#endif -} - -/* Releases a lock for SHM access */ -static inline void accel_deactivate_sub(void) -{ -#ifdef ZEND_WIN32 - if (ZCG(counted)) { - DECREMENT(mem_usage); - ZCG(counted) = 0; - } -#else - static const FLOCK_STRUCTURE(mem_usage_unlock, F_UNLCK, SEEK_SET, 1, 1); - - if (fcntl(lock_file, F_SETLK, &mem_usage_unlock) == -1) { - zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(-1): %s (%d)", strerror(errno), errno); - } -#endif -} - -static inline void accel_unlock_all(void) -{ -#ifdef ZEND_WIN32 - accel_deactivate_sub(); -#else - static const FLOCK_STRUCTURE(mem_usage_unlock_all, F_UNLCK, SEEK_SET, 0, 0); - - if (fcntl(lock_file, F_SETLK, &mem_usage_unlock_all) == -1) { - zend_accel_error(ACCEL_LOG_DEBUG, "UnlockAll: %s (%d)", strerror(errno), errno); - } -#endif -} - #ifndef ZEND_WIN32 static inline void kill_all_lockers(struct flock *mem_usage_check) { @@ -962,6 +970,7 @@ char *accel_make_persistent_key(const char *path, int path_length, int *key_len) zend_shared_alloc_lock(); str = accel_new_interned_string(zend_string_copy(cwd_str)); if (str == cwd_str) { + zend_string_release(str); str = NULL; } zend_shared_alloc_unlock(); @@ -1562,7 +1571,9 @@ zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int type) } } + SHM_UNPROTECT(); persistent_script = zend_file_cache_script_load(file_handle); + SHM_PROTECT(); if (persistent_script) { /* see bug #15471 (old BTS) */ if (persistent_script->script.filename) { @@ -1588,8 +1599,6 @@ zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int type) } zend_file_handle_dtor(file_handle); - persistent_script->dynamic_members.last_used = ZCG(request_time); - if (persistent_script->ping_auto_globals_mask) { zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask); } @@ -1708,8 +1717,15 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type) * each execution) */ if (!ZCG(counted)) { + if (accel_activate_add() == FAILURE) { +#ifdef HAVE_OPCACHE_FILE_CACHE + if (ZCG(accel_directives).file_cache) { + return file_cache_compile_file(file_handle, type); + } +#endif + return accelerator_orig_compile_file(file_handle, type); + } ZCG(counted) = 1; - accel_activate_add(); } SHM_UNPROTECT(); @@ -1976,7 +1992,7 @@ static void accel_reset_pcre_cache(void) ZEND_HASH_FOREACH_BUCKET(&PCRE_G(pcre_cache), p) { /* Remove PCRE cache entries with inconsistent keys */ - if (ZSTR_IS_INTERNED(p->key)) { + if (zend_accel_in_shm(p->key)) { p->key = NULL; zend_hash_del_bucket(&PCRE_G(pcre_cache), p); } @@ -2277,6 +2293,19 @@ static void zend_accel_fast_shutdown(void) } #endif +int accel_post_deactivate(void) +{ + if (!ZCG(enabled) || !accel_startup_ok) { + return SUCCESS; + } + + zend_shared_alloc_safe_unlock(); /* be sure we didn't leave cache locked */ + accel_unlock_all(); + ZCG(counted) = 0; + + return SUCCESS; +} + static void accel_deactivate(void) { /* ensure that we restore function_table and class_table @@ -2284,25 +2313,20 @@ static void accel_deactivate(void) * the script is aborted abnormally, they may become messed up. */ + if (ZCG(cwd)) { + zend_string_release(ZCG(cwd)); + ZCG(cwd) = NULL; + } + if (!ZCG(enabled) || !accel_startup_ok) { return; } - zend_shared_alloc_safe_unlock(); /* be sure we didn't leave cache locked */ - accel_unlock_all(); - ZCG(counted) = 0; - #if !ZEND_DEBUG if (ZCG(accel_directives).fast_shutdown && is_zend_mm()) { zend_accel_fast_shutdown(); } #endif - - if (ZCG(cwd)) { - zend_string_release(ZCG(cwd)); - ZCG(cwd) = NULL; - } - } static int accelerator_remove_cb(zend_extension *element1, zend_extension *element2) @@ -2869,13 +2893,16 @@ int accelerator_shm_read_lock(void) } else { /* here accelerator is active but we do not hold SHM lock. This means restart was scheduled or is in progress now */ - accel_activate_add(); /* acquire usage lock */ + if (accel_activate_add() == FAILURE) { /* acquire usage lock */ + return FAILURE; + } /* Now if we weren't inside restart, restart would not begin until we remove usage lock */ if (ZCSG(restart_in_progress)) { /* we already were inside restart this means it's not safe to touch shm */ accel_deactivate_now(); /* drop usage lock */ return FAILURE; } + ZCG(counted) = 1; } return SUCCESS; } diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h index ccfd7efe15..7a6cf8b108 100644 --- a/ext/opcache/ZendAccelerator.h +++ b/ext/opcache/ZendAccelerator.h @@ -296,6 +296,7 @@ extern zend_accel_globals accel_globals; extern char *zps_api_failure_reason; void accel_shutdown(void); +int accel_post_deactivate(void); void zend_accel_schedule_restart(zend_accel_restart_reason reason); void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason); accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size); diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4 index 770c8034c0..15613285ff 100644 --- a/ext/opcache/config.m4 +++ b/ext/opcache/config.m4 @@ -14,11 +14,11 @@ PHP_ARG_ENABLE(huge-code-pages, whether to enable copying PHP CODE pages into HU if test "$PHP_OPCACHE" != "no"; then - if test "$PHP_OPCACHE_FILE" == "yes"; then + if test "$PHP_OPCACHE_FILE" = "yes"; then AC_DEFINE(HAVE_OPCACHE_FILE_CACHE, 1, [Define to enable file based caching (experimental)]) fi - if test "$PHP_HUGE_CODE_PAGES" == "yes"; then + if test "$PHP_HUGE_CODE_PAGES" = "yes"; then AC_DEFINE(HAVE_HUGE_CODE_PAGES, 1, [Define to enable copying PHP CODE pages into HUGE PAGES (experimental)]) fi diff --git a/ext/opcache/shared_alloc_win32.c b/ext/opcache/shared_alloc_win32.c index a56546557c..c71f253b0a 100644 --- a/ext/opcache/shared_alloc_win32.c +++ b/ext/opcache/shared_alloc_win32.c @@ -176,7 +176,7 @@ static int zend_shared_alloc_reattach(size_t requested_size, char **error_in) } #endif err = ERROR_INVALID_ADDRESS; - zend_win_error_message(ACCEL_LOG_FATAL, "Base address marks unusable memory region", err); + zend_win_error_message(ACCEL_LOG_FATAL, "Base address marks unusable memory region. Please setup opcache.file_cache and opcache.file_cache_callback directives for more convenient Opcache usage", err); return ALLOC_FAILURE; } diff --git a/ext/opcache/tests/bug65915.phpt b/ext/opcache/tests/bug65915.phpt index 6496ee3253..c616c4fb5f 100644 --- a/ext/opcache/tests/bug65915.phpt +++ b/ext/opcache/tests/bug65915.phpt @@ -3,6 +3,7 @@ Bug #65915 (Inconsistent results with require return value) --INI-- opcache.enable=1 opcache.enable_cli=1 +opcache.file_cache_only=0 --SKIPIF-- <?php require_once('skipif.inc'); ?> --FILE-- @@ -13,7 +14,7 @@ file_put_contents($tmp, '<?php return function(){ return "a";};'); $f = require $tmp; var_dump($f()); -opcache_invalidate($tmp, true); +var_dump(opcache_invalidate($tmp, true)); file_put_contents($tmp, '<?php return function(){ return "b";};'); $f = require $tmp; @@ -23,4 +24,5 @@ var_dump($f()); ?> --EXPECT-- string(1) "a" +bool(true) string(1) "b" diff --git a/ext/opcache/tests/bug66338.phpt b/ext/opcache/tests/bug66338.phpt index ed7f8ab475..6553f83f29 100644 --- a/ext/opcache/tests/bug66338.phpt +++ b/ext/opcache/tests/bug66338.phpt @@ -15,13 +15,13 @@ file_put_contents( "$root-Officials.inc", '<?php file_put_contents( "$root-clientUS.php", '<?php class LocalTerms { const GOV_LEADER = "Barack Hussein Obama II"; } - require "'.$root.'-Officials.inc"; + require \''.$root.'-Officials.inc\'; printf( "The President of the USA is %s\n", Officials::getLeader() ); ' ); file_put_contents( "$root-clientUK.php", '<?php class LocalTerms { const GOV_LEADER = "David William Donald Cameron"; } - require "'.$root.'-Officials.inc"; + require \''.$root.'-Officials.inc\'; printf( "The Prime Minister of the UK is %s\n", Officials::getLeader() ); ' ); diff --git a/ext/opcache/tests/bug67215.phpt b/ext/opcache/tests/bug67215.phpt index 24842b4e04..4a9ac7c711 100644 --- a/ext/opcache/tests/bug67215.phpt +++ b/ext/opcache/tests/bug67215.phpt @@ -11,7 +11,7 @@ opcache.file_update_protection=0 $file_c = __DIR__ . "/bug67215.c.php"; $file_p = __DIR__ . "/bug67215.p.php"; -file_put_contents($file_c, "<?php require \"$file_p\"; class c extends p {} ?>"); +file_put_contents($file_c, "<?php require '$file_p'; class c extends p {} ?>"); file_put_contents($file_p, '<?php class p { protected $var = ""; } ?>'); require $file_c; $a = new c(); diff --git a/ext/opcache/tests/bug71443.phpt b/ext/opcache/tests/bug71443.phpt new file mode 100644 index 0000000000..558ac075b6 --- /dev/null +++ b/ext/opcache/tests/bug71443.phpt @@ -0,0 +1,17 @@ +--TEST-- +Bug #71443 (Segfault using built-in webserver with intl using symfony) +--INI-- +opcache.enable=1 +opcache.enable_cli=1 +opcache.file_cache=/tmp/ +opcache.file_cache_only=1 +--SKIPIF-- +<?php require_once('skipif.inc'); ?> +<?php if (substr(PHP_OS, 0, 3) == 'WIN') die('skip.. not for Windows'); ?> +--FILE-- +<?php +ini_set("include_path", "/tmp"); +?> +okey +--EXPECT-- +okey diff --git a/ext/opcache/tests/revalidate_path_01.phpt b/ext/opcache/tests/revalidate_path_01.phpt index cf2ac0d829..8261633334 100644 --- a/ext/opcache/tests/revalidate_path_01.phpt +++ b/ext/opcache/tests/revalidate_path_01.phpt @@ -25,16 +25,30 @@ while (filemtime($file1) != filemtime($file2)) { touch($file1); touch($file2); } -@unlink($link); -@symlink($dir1, $link); +if (substr(PHP_OS, 0, 3) == 'WIN') { + @rmdir($link); + $ln = str_replace('/', '\\', $link); + $d1 = realpath($dir1); + `mklink /j $ln $d1`; +} else { + @unlink($link); + @symlink($dir1, $link); +} include "php_cli_server.inc"; //php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.revalidate_path=1'); php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.revalidate_path=1 -d opcache.file_update_protection=0 -d realpath_cache_size=0'); echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/main.php'); echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/main.php'); -@unlink($link); -@symlink($dir2, $link); +if (substr(PHP_OS, 0, 3) == 'WIN') { + @rmdir($link); + $ln = str_replace('/', '\\', $link); + $d2 = realpath($dir2); + `mklink /j $ln $d2`; +} else { + @unlink($link); + @symlink($dir2, $link); +} echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/main.php'); echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/main.php'); ?> @@ -48,7 +62,11 @@ $file1 = "$dir1/index.php"; $file2 = "$dir2/index.php"; $main = "$dir/main.php"; @unlink($main); -@unlink($link); +if (substr(PHP_OS, 0, 3) == 'WIN') { + @rmdir($link); +} else { + @unlink($link); +} @unlink($file1); @unlink($file2); @rmdir($dir1); diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c index d5925585ca..21d4e2a71e 100644 --- a/ext/opcache/zend_accelerator_module.c +++ b/ext/opcache/zend_accelerator_module.c @@ -517,7 +517,9 @@ static zend_module_entry accel_module_entry = { NULL, zend_accel_info, ACCELERATOR_VERSION "FE", - STANDARD_MODULE_PROPERTIES + NO_MODULE_GLOBALS, + accel_post_deactivate, + STANDARD_MODULE_PROPERTIES_EX }; int start_accel_module(void) diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c index 6a9bb9c580..2184267ecd 100644 --- a/ext/opcache/zend_file_cache.c +++ b/ext/opcache/zend_file_cache.c @@ -224,15 +224,16 @@ static void *zend_file_cache_unserialize_interned(zend_string *str, int in_shm) zend_string *ret; str = (zend_string*)((char*)ZCG(mem) + ((size_t)(str) & ~Z_UL(1))); - ret = accel_new_interned_string(str); - if (ret == str) { - /* String wasn't interned but we will use it as interned anyway */ - if (in_shm) { + if (in_shm) { + ret = accel_new_interned_string(str); + if (ret == str) { + /* String wasn't interned but we will use it as interned anyway */ GC_FLAGS(ret) |= IS_STR_INTERNED | IS_STR_PERMANENT; - } else { - GC_FLAGS(ret) |= IS_STR_INTERNED; - GC_FLAGS(ret) &= ~IS_STR_PERMANENT; } + } else { + ret = str; + GC_FLAGS(ret) |= IS_STR_INTERNED; + GC_FLAGS(ret) &= ~IS_STR_PERMANENT; } return ret; } @@ -1087,7 +1088,7 @@ static void zend_file_cache_unserialize_class_constant(zval * UNSERIALIZE_PTR(Z_PTR_P(zv)); c = Z_PTR_P(zv); - zend_file_cache_unserialize_class_constant(&c->value, script, buf); + zend_file_cache_unserialize_zval(&c->value, script, buf); if (c->ce && !IS_UNSERIALIZED(c->ce)) { UNSERIALIZE_PTR(c->ce); } @@ -1345,7 +1346,9 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl return NULL; } - if (!ZCG(accel_directives).file_cache_only) { + if (!ZCG(accel_directives).file_cache_only && + !ZCSG(restart_in_progress) && + accelerator_shm_read_lock() == SUCCESS) { /* exclusive lock */ zend_shared_alloc_lock(); @@ -1399,6 +1402,7 @@ use_process_mem: if (cache_it) { script->dynamic_members.checksum = zend_accel_script_checksum(script); + script->dynamic_members.last_used = ZCG(request_time); zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(script->script.filename), ZSTR_LEN(script->script.filename), 0, script); diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c index 9516c4e53b..22e74d6b36 100644 --- a/ext/opcache/zend_persist_calc.c +++ b/ext/opcache/zend_persist_calc.c @@ -34,7 +34,9 @@ # define ADD_STRING(str) ADD_DUP_SIZE((str), _ZSTR_STRUCT_SIZE(ZSTR_LEN(str))) # define ADD_INTERNED_STRING(str, do_free) do { \ - if (!IS_ACCEL_INTERNED(str)) { \ + if (ZCG(current_persistent_script)->corrupted) { \ + ADD_STRING(str); \ + } else if (!IS_ACCEL_INTERNED(str)) { \ zend_string *tmp = accel_new_interned_string(str); \ if (tmp != (str)) { \ if (do_free) { \ @@ -126,7 +128,7 @@ static void zend_persist_zval_calc(zval *z) case IS_CONSTANT: flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT); ADD_INTERNED_STRING(Z_STR_P(z), 0); - if (!Z_REFCOUNTED_P(z)) { + if (ZSTR_IS_INTERNED(Z_STR_P(z))) { Z_TYPE_FLAGS_P(z) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE); } Z_GC_FLAGS_P(z) |= flags; @@ -400,11 +402,15 @@ uint zend_accel_script_persist_calc(zend_persistent_script *new_persistent_scrip new_persistent_script->size = 0; new_persistent_script->arena_mem = NULL; new_persistent_script->arena_size = 0; + new_persistent_script->corrupted = 0; ZCG(current_persistent_script) = new_persistent_script; ADD_DUP_SIZE(new_persistent_script, sizeof(zend_persistent_script)); if (key) { ADD_DUP_SIZE(key, key_length + 1); + } else { + /* script is not going to be saved in SHM */ + new_persistent_script->corrupted = 1; } ADD_STRING(new_persistent_script->script.filename); @@ -423,6 +429,7 @@ uint zend_accel_script_persist_calc(zend_persistent_script *new_persistent_scrip #endif new_persistent_script->size += new_persistent_script->arena_size; + new_persistent_script->corrupted = 0; ZCG(current_persistent_script) = NULL; diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c index d616c7d62f..deae886991 100644 --- a/ext/opcache/zend_shared_alloc.c +++ b/ext/opcache/zend_shared_alloc.c @@ -507,3 +507,20 @@ void zend_accel_shared_protect(int mode) } #endif } + +int zend_accel_in_shm(void *ptr) +{ + int i; + + if (!smm_shared_globals) { + return 0; + } + + for (i = 0; i < ZSMMG(shared_segments_count); i++) { + if ((char*)ptr >= (char*)ZSMMG(shared_segments)[i]->p && + (char*)ptr < (char*)ZSMMG(shared_segments)[i]->p + ZSMMG(shared_segments)[i]->size) { + return 1; + } + } + return 0; +} diff --git a/ext/opcache/zend_shared_alloc.h b/ext/opcache/zend_shared_alloc.h index 3993b0689e..03b82d16ac 100644 --- a/ext/opcache/zend_shared_alloc.h +++ b/ext/opcache/zend_shared_alloc.h @@ -128,6 +128,8 @@ void *zend_shared_alloc(size_t size); void *_zend_shared_memdup(void *p, size_t size, zend_bool free_source); int zend_shared_memdup_size(void *p, size_t size); +int zend_accel_in_shm(void *ptr); + typedef union _align_test { void *ptr; double dbl; diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index cc2506165f..abe22849f8 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -1328,6 +1328,10 @@ PHP_MSHUTDOWN_FUNCTION(openssl) { EVP_cleanup(); +#if OPENSSL_VERSION_NUMBER >= 0x00090805f + ERR_free_strings(); +#endif + php_unregister_url_stream_wrapper("https"); php_unregister_url_stream_wrapper("ftps"); @@ -4949,6 +4953,7 @@ PHP_FUNCTION(openssl_seal) memset(eks, 0, sizeof(*eks) * nkeys); key_resources = safe_emalloc(nkeys, sizeof(zend_resource*), 0); memset(key_resources, 0, sizeof(zend_resource*) * nkeys); + memset(pkeys, 0, sizeof(*pkeys) * nkeys); /* get the public keys we are using to seal this data */ i = 0; @@ -5010,7 +5015,7 @@ PHP_FUNCTION(openssl_seal) clean_exit: for (i=0; i<nkeys; i++) { - if (key_resources[i] == NULL) { + if (key_resources[i] == NULL && pkeys[i] != NULL) { EVP_PKEY_free(pkeys[i]); } if (eks[i]) { @@ -5269,7 +5274,7 @@ static int php_openssl_validate_iv(char **piv, size_t *piv_len, size_t iv_requir if (*piv_len < iv_required_len) { php_error_docref(NULL, E_WARNING, - "IV passed is only %d bytes long, cipher expects an IV of precisely %d bytes, padding with \\0", + "IV passed is only %zd bytes long, cipher expects an IV of precisely %zd bytes, padding with \\0", *piv_len, iv_required_len); memcpy(iv_new, *piv, *piv_len); *piv_len = iv_required_len; @@ -5279,7 +5284,7 @@ static int php_openssl_validate_iv(char **piv, size_t *piv_len, size_t iv_requir } php_error_docref(NULL, E_WARNING, - "IV passed is %d bytes long which is longer than the %d expected by selected cipher, truncating", + "IV passed is %zd bytes long which is longer than the %zd expected by selected cipher, truncating", *piv_len, iv_required_len); memcpy(iv_new, *piv, iv_required_len); *piv_len = iv_required_len; diff --git a/ext/openssl/tests/002.phpt b/ext/openssl/tests/002.phpt deleted file mode 100644 index dd4f04a25c..0000000000 --- a/ext/openssl/tests/002.phpt +++ /dev/null @@ -1,32 +0,0 @@ ---TEST-- -openssl_seal() tests ---SKIPIF-- -<?php if (!extension_loaded("openssl")) print "skip"; ?> ---FILE-- -<?php - -$a = 1; -$b = array(1); -$c = array(1); -$d = array(1); - -var_dump(openssl_seal($a, $b, $c, $d)); -var_dump(openssl_seal($a, $a, $a, array())); -var_dump(openssl_seal($c, $c, $c, 1)); -var_dump(openssl_seal($b, $b, $b, "")); - -echo "Done\n"; -?> ---EXPECTF-- -Warning: openssl_seal(): not a public key (1th member of pubkeys) in %s on line %d -bool(false) - -Warning: openssl_seal(): Fourth argument to openssl_seal() must be a non-empty array in %s on line %d -bool(false) - -Warning: openssl_seal() expects parameter 1 to be string, array given in %s on line %d -NULL - -Warning: openssl_seal() expects parameter 1 to be string, array given in %s on line %d -NULL -Done diff --git a/ext/openssl/tests/007.phpt b/ext/openssl/tests/007.phpt deleted file mode 100644 index 0a74bd3411..0000000000 --- a/ext/openssl/tests/007.phpt +++ /dev/null @@ -1,60 +0,0 @@ ---TEST-- -openssl_x509_read() and openssl_x509_free() tests ---SKIPIF-- -<?php if (!extension_loaded("openssl")) print "skip"; ?> ---FILE-- -<?php -$fp = fopen(dirname(__FILE__) . "/cert.crt","r"); -$a = fread($fp,8192); -fclose($fp); - -$b = "file://" . dirname(__FILE__) . "/cert.crt"; -$c = "invalid cert"; -$d = openssl_x509_read($a); -$e = array(); -$f = array($b); - -var_dump($res = openssl_x509_read($a)); // read cert as a string -openssl_x509_free($res); -var_dump($res); -var_dump($res = openssl_x509_read($b)); // read cert as a filename string -openssl_x509_free($res); -var_dump($res); -var_dump($res = openssl_x509_read($c)); // read an invalid cert, fails -openssl_x509_free($res); -var_dump($res); -var_dump($res = openssl_x509_read($d)); // read cert from a resource -openssl_x509_free($res); -var_dump($res); -var_dump($res = openssl_x509_read($e)); // read an array -openssl_x509_free($res); -var_dump($res); -var_dump($res = openssl_x509_read($f)); // read an array with the filename -openssl_x509_free($res); -var_dump($res); -?> ---EXPECTF-- -resource(%d) of type (OpenSSL X.509) -resource(%d) of type (Unknown) -resource(%d) of type (OpenSSL X.509) -resource(%d) of type (Unknown) - -Warning: openssl_x509_read(): supplied parameter cannot be coerced into an X509 certificate! in %s on line %d -bool(false) - -Warning: openssl_x509_free() expects parameter 1 to be resource, boolean given in %s on line %d -bool(false) -resource(%d) of type (OpenSSL X.509) -resource(%d) of type (Unknown) - -Warning: openssl_x509_read(): supplied parameter cannot be coerced into an X509 certificate! in %s on line %d -bool(false) - -Warning: openssl_x509_free() expects parameter 1 to be resource, boolean given in %s on line %d -bool(false) - -Warning: openssl_x509_read(): supplied parameter cannot be coerced into an X509 certificate! in %s on line %d -bool(false) - -Warning: openssl_x509_free() expects parameter 1 to be resource, boolean given in %s on line %d -bool(false) diff --git a/ext/openssl/tests/008.phpt b/ext/openssl/tests/008.phpt deleted file mode 100644 index 171ca27fba..0000000000 --- a/ext/openssl/tests/008.phpt +++ /dev/null @@ -1,79 +0,0 @@ ---TEST-- -openssl_x509_export() and openssl_x509_export_to_file() tests ---SKIPIF-- -<?php if (!extension_loaded("openssl")) print "skip"; ?> ---FILE-- -<?php -$fp = fopen(dirname(__FILE__) . "/cert.crt","r"); -$a = fread($fp,8192); -fclose($fp); - -$b = "file://" . dirname(__FILE__) . "/cert.crt"; -$c = "invalid cert"; -$d = openssl_x509_read($a); -$e = array(); - -var_dump(openssl_x509_export($a, $output)); // read cert as a binary string -var_dump(openssl_x509_export($b, $output2)); // read cert from a filename string -var_dump(openssl_x509_export($c, $output3)); // read an invalid cert, fails -var_dump(openssl_x509_export($d, $output4)); // read cert from a resource -var_dump(openssl_x509_export($e, $output5)); // read an array, fails - -$outfilename = tempnam("/tmp", "ssl"); -if ($outfilename === false) - die("failed to get a temporary filename!"); - -echo "---\n"; - -var_dump(openssl_x509_export_to_file($a, $outfilename)); // read cert as a binary string -var_dump(openssl_x509_export_to_file($b, $outfilename)); // read cert from a filename string -var_dump(openssl_x509_export_to_file($c, $outfilename)); // read an invalid cert, fails -var_dump(openssl_x509_export_to_file($d, $outfilename)); // read cert from a resource -var_dump(openssl_x509_export_to_file($e, $outfilename)); // read an array, fails -echo "---\n"; - -var_dump($exists = file_exists($outfilename)); -if ($exists) { - @unlink($outfilename); -} -echo "---\n"; - -if (PHP_EOL !== "\n") { - $a = str_replace(PHP_EOL, "\n", $a); -} - -var_dump(strcmp($output, $a)); -var_dump(strcmp($output, $output2)); -var_dump(strcmp($output, $output3)); -var_dump(strcmp($output, $output4)); // different -var_dump(strcmp($output, $output5)); // different - -?> ---EXPECTF-- -bool(true) -bool(true) - -Warning: openssl_x509_export(): cannot get cert from parameter 1 in %s on line %d -bool(false) -bool(true) - -Warning: openssl_x509_export(): cannot get cert from parameter 1 in %s on line %d -bool(false) ---- -bool(true) -bool(true) - -Warning: openssl_x509_export_to_file(): cannot get cert from parameter 1 in %s on line %d -bool(false) -bool(true) - -Warning: openssl_x509_export_to_file(): cannot get cert from parameter 1 in %s on line %d -bool(false) ---- -bool(true) ---- -int(0) -int(0) -int(%d) -int(0) -int(%d) diff --git a/ext/openssl/tests/012.phpt b/ext/openssl/tests/012.phpt deleted file mode 100644 index dbd03ac0af..0000000000 --- a/ext/openssl/tests/012.phpt +++ /dev/null @@ -1,27 +0,0 @@ ---TEST-- -openssl_seal() error tests ---SKIPIF-- -<?php if (!extension_loaded("openssl")) print "skip"; ?> ---FILE-- -<?php -$data = "openssl_open() test"; -$pub_key = "file://" . dirname(__FILE__) . "/public.key"; -$wrong = "wrong"; - -openssl_seal($data, $sealed, $ekeys, array($pub_key)); // no output -openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key)); // no output -openssl_seal($data, $sealed, $ekeys, array($pub_key, $wrong)); -openssl_seal($data, $sealed, $ekeys, $pub_key); -openssl_seal($data, $sealed, $ekeys, array()); -openssl_seal($data, $sealed, $ekeys, array($wrong)); -?> ---EXPECTF-- - -Warning: openssl_seal(): not a public key (2th member of pubkeys) in %s on line %d - -Warning: openssl_seal() expects parameter 4 to be array, string given in %s on line %d - -Warning: openssl_seal(): Fourth argument to openssl_seal() must be a non-empty array in %s on line %d - -Warning: openssl_seal(): not a public key (1th member of pubkeys) in %s on line %d - diff --git a/ext/openssl/tests/026.phpt b/ext/openssl/tests/026.phpt deleted file mode 100644 index 38d626d742..0000000000 --- a/ext/openssl/tests/026.phpt +++ /dev/null @@ -1,12 +0,0 @@ ---TEST-- -Options type checks ---SKIPIF-- -<?php if (!extension_loaded("openssl")) print "skip"; ?> ---FILE-- -<?php -$x = openssl_pkey_new(); -$csr = openssl_csr_new(["countryName" => "DE"], $x, ["x509_extensions" => 0xDEADBEEF]); -?> -DONE ---EXPECT-- -DONE diff --git a/ext/openssl/tests/bug70438.phpt b/ext/openssl/tests/bug70438.phpt index de87a51a7a..937e9f3bd9 100644 --- a/ext/openssl/tests/bug70438.phpt +++ b/ext/openssl/tests/bug70438.phpt @@ -14,7 +14,7 @@ if (!in_array('AES-128-CBC', openssl_get_cipher_methods(true))) { $data = "openssl_seal() test"; $cipher = 'AES-128-CBC'; $pub_key = "file://" . dirname(__FILE__) . "/public.key"; -$priv_key = "file://" . dirname(__FILE__) . "/private.key"; +$priv_key = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key), $cipher); openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key), 'sparkles', $iv); diff --git a/ext/openssl/tests/bug71475.phpt b/ext/openssl/tests/bug71475.phpt new file mode 100644 index 0000000000..e959371c4c --- /dev/null +++ b/ext/openssl/tests/bug71475.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #71475: openssl_seal() uninitialized memory usage +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip openssl not loaded"); +?> +--FILE-- +<?php +$_ = str_repeat("A", 512); +openssl_seal($_, $_, $_, array_fill(0,64,0)); +?> +DONE +--EXPECTF-- + +Warning: openssl_seal(): not a public key (1th member of pubkeys) in %s%ebug71475.php on line %d +DONE diff --git a/ext/openssl/tests/005_crt.txt b/ext/openssl/tests/cert.csr index 39084bce05..39084bce05 100644 --- a/ext/openssl/tests/005_crt.txt +++ b/ext/openssl/tests/cert.csr diff --git a/ext/openssl/tests/022.phpt b/ext/openssl/tests/openssl_csr_export_bacis.phpt index 1fa84d9f42..d3f8842e71 100644 --- a/ext/openssl/tests/022.phpt +++ b/ext/openssl/tests/openssl_csr_export_bacis.phpt @@ -14,7 +14,7 @@ $dn = array( "localityName" => "Porto Alegre", "commonName" => "Henrique do N. Angelo", "emailAddress" => "hnangelo@php.net" - ); +); $args = array( "digest_alg" => "sha1", @@ -22,7 +22,7 @@ $args = array( "private_key_type" => OPENSSL_KEYTYPE_DSA, "encrypt_key" => true, "config" => $config, - ); +); $privkey = openssl_pkey_new($config_arg); $csr = openssl_csr_new($dn, $privkey, $args); diff --git a/ext/openssl/tests/005.phpt b/ext/openssl/tests/openssl_csr_get_subject_basic.phpt index f7fa201561..895ed3695d 100644 --- a/ext/openssl/tests/005.phpt +++ b/ext/openssl/tests/openssl_csr_get_subject_basic.phpt @@ -8,7 +8,7 @@ if (!function_exists("utf8_decode")) die("skip"); --FILE-- <?php -$csr = file_get_contents(dirname(__FILE__) . '/005_crt.txt'); +$csr = file_get_contents(dirname(__FILE__) . '/cert.csr'); if ($out = openssl_csr_get_subject($csr, 1)) { var_dump($out); } diff --git a/ext/openssl/tests/004.phpt b/ext/openssl/tests/openssl_csr_new_basic.phpt index 508ccabc85..e0f52d739f 100644 --- a/ext/openssl/tests/004.phpt +++ b/ext/openssl/tests/openssl_csr_new_basic.phpt @@ -9,12 +9,18 @@ $a = 1; var_dump(openssl_csr_new(1,$a)); var_dump(openssl_csr_new(1,$a,1,1)); $a = array(); -var_dump(openssl_csr_new(array(), $a, array('config' => __DIR__ . DIRECTORY_SEPARATOR . 'openssl.cnf'), array())); -//this leaks +$conf = array('config' => dirname(__FILE__) . DIRECTORY_SEPARATOR . 'openssl.cnf'); +var_dump(openssl_csr_new(array(), $a, $conf, array())); + +// this leaks $a = array(1,2); $b = array(1,2); -var_dump(openssl_csr_new($a, $b, array('config' => __DIR__ . DIRECTORY_SEPARATOR . 'openssl.cnf'))); +var_dump(openssl_csr_new($a, $b, $conf)); + +// options type check +$x = openssl_pkey_new($conf); +var_dump(openssl_csr_new(["countryName" => "DE"], $x, $conf + ["x509_extensions" => 0xDEADBEEF])); echo "Done\n"; @@ -31,4 +37,5 @@ Warning: openssl_csr_new(): key array must be of the form array(0 => key, 1 => p Warning: openssl_csr_new(): add1_attr_by_txt challengePassword_min -> 4 (failed; check error queue and value of string_mask OpenSSL option if illegal characters are reported) in %s on line %d bool(false) resource(%d) of type (OpenSSL X.509 CSR) +resource(%d) of type (OpenSSL X.509 CSR) Done diff --git a/ext/openssl/tests/021.phpt b/ext/openssl/tests/openssl_csr_sign_basic.phpt index 9fdf8e4e65..34cf50a997 100644 --- a/ext/openssl/tests/021.phpt +++ b/ext/openssl/tests/openssl_csr_sign_basic.phpt @@ -5,7 +5,7 @@ openssl_csr_sign() tests --FILE-- <?php $cert = "file://" . dirname(__FILE__) . "/cert.crt"; -$priv = "file://" . dirname(__FILE__) . "/private.key"; +$priv = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; $wrong = "wrong"; $pub = "file://" . dirname(__FILE__) . "/public.key"; $config = __DIR__ . DIRECTORY_SEPARATOR . 'openssl.cnf'; diff --git a/ext/openssl/tests/011.phpt b/ext/openssl/tests/openssl_decrypt_basic.phpt index 118e952a51..1c29767cc5 100644 --- a/ext/openssl/tests/011.phpt +++ b/ext/openssl/tests/openssl_decrypt_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -openssl_encrypt() and openssl_decrypt() tests +openssl_decrypt() tests dependent on openssl_encrypt --SKIPIF-- <?php if (!extension_loaded("openssl")) print "skip"; ?> --FILE-- diff --git a/ext/openssl/tests/013.phpt b/ext/openssl/tests/openssl_open_basic.phpt index 91bb73dab3..55bb9eb0e3 100644 --- a/ext/openssl/tests/013.phpt +++ b/ext/openssl/tests/openssl_open_basic.phpt @@ -6,7 +6,7 @@ openssl_open() tests <?php $data = "openssl_open() test"; $pub_key = "file://" . dirname(__FILE__) . "/public.key"; -$priv_key = "file://" . dirname(__FILE__) . "/private.key"; +$priv_key = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; $wrong = "wrong"; openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key, $pub_key)); diff --git a/ext/openssl/tests/openssl_pbkdf2.phpt b/ext/openssl/tests/openssl_pbkdf2_basic.phpt index 3ec4dce236..3ec4dce236 100644 --- a/ext/openssl/tests/openssl_pbkdf2.phpt +++ b/ext/openssl/tests/openssl_pbkdf2_basic.phpt diff --git a/ext/openssl/tests/openssl_peer_fingerprint.phpt b/ext/openssl/tests/openssl_peer_fingerprint_basic.phpt index 743233579a..743233579a 100644 --- a/ext/openssl/tests/openssl_peer_fingerprint.phpt +++ b/ext/openssl/tests/openssl_peer_fingerprint_basic.phpt diff --git a/ext/openssl/tests/024.phpt b/ext/openssl/tests/openssl_pkcs7_decrypt_basic.phpt index 0a61840de3..5589abb039 100644 --- a/ext/openssl/tests/024.phpt +++ b/ext/openssl/tests/openssl_pkcs7_decrypt_basic.phpt @@ -5,7 +5,7 @@ openssl_pkcs7_decrypt() tests --FILE-- <?php $infile = dirname(__FILE__) . "/cert.crt"; -$privkey = "file://" . dirname(__FILE__) . "/private.key"; +$privkey = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; $encrypted = tempnam("/tmp", "ssl"); if ($encrypted === false) die("failed to get a temporary filename!"); diff --git a/ext/openssl/tests/003.phpt b/ext/openssl/tests/openssl_pkcs7_decrypt_error.phpt index 39363c4548..e8ba264550 100644 --- a/ext/openssl/tests/003.phpt +++ b/ext/openssl/tests/openssl_pkcs7_decrypt_error.phpt @@ -6,7 +6,7 @@ openssl_pkcs7_decrypt() and invalid parameters <?php function myErrorHandler($errno, $errstr, $errfile, $errline) { -var_dump($errstr); + var_dump($errstr); } set_error_handler("myErrorHandler"); diff --git a/ext/openssl/tests/023.phpt b/ext/openssl/tests/openssl_pkcs7_encrypt_basic.phpt index 1489613327..5f74f97b0c 100644 --- a/ext/openssl/tests/023.phpt +++ b/ext/openssl/tests/openssl_pkcs7_encrypt_basic.phpt @@ -13,7 +13,7 @@ if ($outfile2 === false) die("failed to get a temporary filename!"); $single_cert = "file://" . dirname(__FILE__) . "/cert.crt"; -$privkey = "file://" . dirname(__FILE__) . "/private.key"; +$privkey = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; $multi_certs = array($single_cert, $single_cert); $assoc_headers = array("To" => "test@test", "Subject" => "testing openssl_pkcs7_encrypt()"); $headers = array("test@test", "testing openssl_pkcs7_encrypt()"); diff --git a/ext/openssl/tests/025.phpt b/ext/openssl/tests/openssl_pkcs7_sign_basic.phpt index ac567a517a..ac8edf19a9 100644 --- a/ext/openssl/tests/025.phpt +++ b/ext/openssl/tests/openssl_pkcs7_sign_basic.phpt @@ -6,10 +6,11 @@ openssl_pkcs7_sign() tests <?php $infile = dirname(__FILE__) . "/cert.crt"; $outfile = tempnam("/tmp", "ssl"); -if ($outfile === false) +if ($outfile === false) { die("failed to get a temporary filename!"); +} -$privkey = "file://" . dirname(__FILE__) . "/private.key"; +$privkey = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; $single_cert = "file://" . dirname(__FILE__) . "/cert.crt"; $assoc_headers = array("To" => "test@test", "Subject" => "testing openssl_pkcs7_sign()"); $headers = array("test@test", "testing openssl_pkcs7_sign()"); diff --git a/ext/openssl/tests/027.phpt b/ext/openssl/tests/openssl_pkey_export_basic.phpt index d229d6b135..d229d6b135 100644 --- a/ext/openssl/tests/027.phpt +++ b/ext/openssl/tests/openssl_pkey_export_basic.phpt diff --git a/ext/openssl/tests/028.phpt b/ext/openssl/tests/openssl_pkey_get_details_basic.phpt index 8e0cef46c0..8e0cef46c0 100644 --- a/ext/openssl/tests/028.phpt +++ b/ext/openssl/tests/openssl_pkey_get_details_basic.phpt diff --git a/ext/openssl/tests/006.phpt b/ext/openssl/tests/openssl_pkey_new_basic.phpt index d6e41e496b..3c434978d2 100644 --- a/ext/openssl/tests/006.phpt +++ b/ext/openssl/tests/openssl_pkey_new_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -openssl_pkey_new() with an empty sub-array arg generates a malformed resource +openssl_pkey_new() tests --SKIPIF-- <?php if (!extension_loaded("openssl")) print "skip"; ?> --FILE-- diff --git a/ext/openssl/tests/017.phpt b/ext/openssl/tests/openssl_private_decrypt_basic.phpt index 65a7cd1025..76a08b8d55 100644 --- a/ext/openssl/tests/017.phpt +++ b/ext/openssl/tests/openssl_private_decrypt_basic.phpt @@ -5,7 +5,7 @@ openssl_private_decrypt() tests --FILE-- <?php $data = "Testing openssl_public_decrypt()"; -$privkey = "file://" . dirname(__FILE__) . "/private.key"; +$privkey = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; $pubkey = "file://" . dirname(__FILE__) . "/public.key"; $wrong = "wrong"; diff --git a/ext/openssl/tests/014.phpt b/ext/openssl/tests/openssl_private_encrypt_basic.phpt index 6123964ee5..a2a5152158 100644 --- a/ext/openssl/tests/014.phpt +++ b/ext/openssl/tests/openssl_private_encrypt_basic.phpt @@ -5,13 +5,14 @@ openssl_private_encrypt() tests --FILE-- <?php $data = "Testing openssl_private_encrypt()"; -$privkey = "file://" . dirname(__FILE__) . "/private.key"; +$privkey = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; $pubkey = "file://" . dirname(__FILE__) . "/public.key"; $wrong = "wrong"; + class test { - function __toString() { - return "test"; - } + function __toString() { + return "test"; + } } $obj = new test; diff --git a/ext/openssl/tests/016.phpt b/ext/openssl/tests/openssl_public_decrypt_basic.phpt index 2d772e7a36..42d72b9cd4 100644 --- a/ext/openssl/tests/016.phpt +++ b/ext/openssl/tests/openssl_public_decrypt_basic.phpt @@ -5,7 +5,7 @@ openssl_public_decrypt() tests --FILE-- <?php $data = "Testing openssl_public_decrypt()"; -$privkey = "file://" . dirname(__FILE__) . "/private.key"; +$privkey = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; $pubkey = "file://" . dirname(__FILE__) . "/public.key"; $wrong = "wrong"; diff --git a/ext/openssl/tests/015.phpt b/ext/openssl/tests/openssl_public_encrypt_basic.phpt index a89121de10..a3c4c57539 100644 --- a/ext/openssl/tests/015.phpt +++ b/ext/openssl/tests/openssl_public_encrypt_basic.phpt @@ -5,13 +5,14 @@ openssl_public_encrypt() tests --FILE-- <?php $data = "Testing openssl_public_encrypt()"; -$privkey = "file://" . dirname(__FILE__) . "/private.key"; +$privkey = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; $pubkey = "file://" . dirname(__FILE__) . "/public.key"; $wrong = "wrong"; + class test { - function __toString() { - return "test"; - } + function __toString() { + return "test"; + } } $obj = new test; diff --git a/ext/openssl/tests/openssl_random_pseudo_bytes.phpt b/ext/openssl/tests/openssl_random_pseudo_bytes_basic.phpt index ac5a3079a1..ac5a3079a1 100644 --- a/ext/openssl/tests/openssl_random_pseudo_bytes.phpt +++ b/ext/openssl/tests/openssl_random_pseudo_bytes_basic.phpt diff --git a/ext/openssl/tests/openssl_seal_basic.phpt b/ext/openssl/tests/openssl_seal_basic.phpt new file mode 100644 index 0000000000..4f1958a365 --- /dev/null +++ b/ext/openssl/tests/openssl_seal_basic.phpt @@ -0,0 +1,58 @@ +--TEST-- +openssl_seal() tests +--SKIPIF-- +<?php if (!extension_loaded("openssl")) print "skip"; ?> +--FILE-- +<?php +// simple tests +$a = 1; +$b = array(1); +$c = array(1); +$d = array(1); + +var_dump(openssl_seal($a, $b, $c, $d)); +var_dump(openssl_seal($a, $a, $a, array())); +var_dump(openssl_seal($c, $c, $c, 1)); +var_dump(openssl_seal($b, $b, $b, "")); + +// tests with cert +$data = "openssl_open() test"; +$pub_key = "file://" . dirname(__FILE__) . "/public.key"; +$wrong = "wrong"; + +var_dump(openssl_seal($data, $sealed, $ekeys, array($pub_key))); // no output +var_dump(openssl_seal($data, $sealed, $ekeys, array($pub_key, $pub_key))); // no output +var_dump(openssl_seal($data, $sealed, $ekeys, array($pub_key, $wrong))); +var_dump(openssl_seal($data, $sealed, $ekeys, $pub_key)); +var_dump(openssl_seal($data, $sealed, $ekeys, array())); +var_dump(openssl_seal($data, $sealed, $ekeys, array($wrong))); + +echo "Done\n"; +?> +--EXPECTF-- +Warning: openssl_seal(): not a public key (1th member of pubkeys) in %s on line %d +bool(false) + +Warning: openssl_seal(): Fourth argument to openssl_seal() must be a non-empty array in %s on line %d +bool(false) + +Warning: openssl_seal() expects parameter 1 to be string, array given in %s on line %d +NULL + +Warning: openssl_seal() expects parameter 1 to be string, array given in %s on line %d +NULL +int(19) +int(19) + +Warning: openssl_seal(): not a public key (2th member of pubkeys) in %s on line %d +bool(false) + +Warning: openssl_seal() expects parameter 4 to be array, string given in %s on line %d +NULL + +Warning: openssl_seal(): Fourth argument to openssl_seal() must be a non-empty array in %s on line %d +bool(false) + +Warning: openssl_seal(): not a public key (1th member of pubkeys) in %s on line %d +bool(false) +Done diff --git a/ext/openssl/tests/018.phpt b/ext/openssl/tests/openssl_sign_basic.phpt index 230c0a89db..3d41ee1d34 100644 --- a/ext/openssl/tests/018.phpt +++ b/ext/openssl/tests/openssl_sign_basic.phpt @@ -5,7 +5,7 @@ openssl_sign() tests --FILE-- <?php $data = "Testing openssl_sign()"; -$privkey = "file://" . dirname(__FILE__) . "/private.key"; +$privkey = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; $wrong = "wrong"; var_dump(openssl_sign($data, $sign, $privkey)); // no output diff --git a/ext/openssl/tests/openssl_spki_export.phpt b/ext/openssl/tests/openssl_spki_export.phpt deleted file mode 100644 index 59332f70a5..0000000000 --- a/ext/openssl/tests/openssl_spki_export.phpt +++ /dev/null @@ -1,62 +0,0 @@ ---TEST-- -Testing openssl_spki_export() -Creates SPKAC for all available key sizes & signature algorithms and exports public key ---SKIPIF-- -<?php -if (!extension_loaded("openssl")) die("skip"); -if (!@openssl_pkey_new()) die("skip cannot create private key"); -?> ---FILE-- -<?php - -/* array of private key sizes to test */ -$ksize = array('1024'=>1024, - '2048'=>2048, - '4096'=>4096); - -/* array of available hashings to test */ -$algo = array('md4'=>OPENSSL_ALGO_MD4, - 'md5'=>OPENSSL_ALGO_MD5, - 'sha1'=>OPENSSL_ALGO_SHA1, - 'sha224'=>OPENSSL_ALGO_SHA224, - 'sha256'=>OPENSSL_ALGO_SHA256, - 'sha384'=>OPENSSL_ALGO_SHA384, - 'sha512'=>OPENSSL_ALGO_SHA512, - 'rmd160'=>OPENSSL_ALGO_RMD160); - -/* loop over key sizes for test */ -foreach($ksize as $k => $v) { - - /* generate new private key of specified size to use for tests */ - $pkey = openssl_pkey_new(array('digest_alg' => 'sha512', - 'private_key_type' => OPENSSL_KEYTYPE_RSA, - 'private_key_bits' => $v)); - openssl_pkey_export($pkey, $pass); - - /* loop to create and verify results */ - foreach($algo as $key => $value) { - $spkac = openssl_spki_new($pkey, _uuid(), $value); - echo openssl_spki_export(preg_replace('/SPKAC=/', '', $spkac)); - } - openssl_free_key($pkey); -} - -/* generate a random challenge */ -function _uuid() -{ - return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), - mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, - mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), - mt_rand(0, 0xffff), mt_rand(0, 0xffff)); -} - -?> ---EXPECTREGEX-- -\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- -\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- -\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- -\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- -\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- -\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- -\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- -\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- diff --git a/ext/openssl/tests/openssl_spki_export_basic.phpt b/ext/openssl/tests/openssl_spki_export_basic.phpt new file mode 100644 index 0000000000..1e3bd1fd39 --- /dev/null +++ b/ext/openssl/tests/openssl_spki_export_basic.phpt @@ -0,0 +1,60 @@ +--TEST-- +openssl_spki_export() tests for exporting public key +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +if (!@openssl_pkey_new()) die("skip cannot create private key"); +?> +--FILE-- +<?php + +/* array of private key sizes to test */ +$key_sizes = array(1024, 2048, 4096); +$pkeys = array(); +foreach ($key_sizes as $key_size) { + $key_file = "file://" . dirname(__FILE__) . "/private_rsa_" . $key_size . ".key"; + $pkeys[] = openssl_pkey_get_private($key_file); +} + + +/* array of available hashings to test */ +$algo = array( + OPENSSL_ALGO_MD4, + OPENSSL_ALGO_MD5, + OPENSSL_ALGO_SHA1, + OPENSSL_ALGO_SHA224, + OPENSSL_ALGO_SHA256, + OPENSSL_ALGO_SHA384, + OPENSSL_ALGO_SHA512, + OPENSSL_ALGO_RMD160 +); + +/* loop over key sizes for test */ +foreach ($pkeys as $pkey) { + + /* loop to create and verify results */ + foreach ($algo as $value) { + $spkac = openssl_spki_new($pkey, _uuid(), $value); + echo openssl_spki_export(preg_replace('/SPKAC=/', '', $spkac)); + } +} + +/* generate a random challenge */ +function _uuid() { + return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff)); +} + + +?> +--EXPECTREGEX-- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- +\-\-\-\-\-BEGIN PUBLIC KEY\-\-\-\-\-.*\-\-\-\-\-END PUBLIC KEY\-\-\-\-\- diff --git a/ext/openssl/tests/openssl_spki_export_challenge.phpt b/ext/openssl/tests/openssl_spki_export_challenge_basic.phpt index 71ef62edd5..07a69d3b45 100644 --- a/ext/openssl/tests/openssl_spki_export_challenge.phpt +++ b/ext/openssl/tests/openssl_spki_export_challenge_basic.phpt @@ -1,6 +1,5 @@ --TEST-- -Testing openssl_spki_export_challenge() -Creates SPKAC for all available key sizes & signature algorithms and exports challenge +openssl_spki_export_challenge() tests for exporting challenge --INI-- error_reporting=0 --SKIPIF-- @@ -12,47 +11,46 @@ if (!@openssl_pkey_new()) die("skip cannot create private key"); <?php /* array of private key sizes to test */ -$ksize = array('1024'=>1024, - '2048'=>2048, - '4096'=>4096); +$key_sizes = array(1024, 2048, 4096); +$pkeys = array(); +foreach ($key_sizes as $key_size) { + $key_file = "file://" . dirname(__FILE__) . "/private_rsa_" . $key_size . ".key"; + $pkeys[] = openssl_pkey_get_private($key_file); +} + /* array of available hashings to test */ -$algo = array('md4'=>OPENSSL_ALGO_MD4, - 'md5'=>OPENSSL_ALGO_MD5, - 'sha1'=>OPENSSL_ALGO_SHA1, - 'sha224'=>OPENSSL_ALGO_SHA224, - 'sha256'=>OPENSSL_ALGO_SHA256, - 'sha384'=>OPENSSL_ALGO_SHA384, - 'sha512'=>OPENSSL_ALGO_SHA512, - 'rmd160'=>OPENSSL_ALGO_RMD160); +$algo = array( + OPENSSL_ALGO_MD4, + OPENSSL_ALGO_MD5, + OPENSSL_ALGO_SHA1, + OPENSSL_ALGO_SHA224, + OPENSSL_ALGO_SHA256, + OPENSSL_ALGO_SHA384, + OPENSSL_ALGO_SHA512, + OPENSSL_ALGO_RMD160 +); /* loop over key sizes for test */ -foreach($ksize as $k => $v) { - - /* generate new private key of specified size to use for tests */ - $pkey = openssl_pkey_new(array('digest_alg' => 'sha512', - 'private_key_type' => OPENSSL_KEYTYPE_RSA, - 'private_key_bits' => $v)); - openssl_pkey_export($pkey, $pass); +foreach ($pkeys as $pkey) { /* loop to create and verify results */ - foreach($algo as $key => $value) { + foreach ($algo as $value) { $spkac = openssl_spki_new($pkey, _uuid(), $value); var_dump(openssl_spki_export_challenge(preg_replace('/SPKAC=/', '', $spkac))); - var_dump(openssl_spki_export_challenge($spkac.'Make it fail')); + var_dump(openssl_spki_export_challenge($spkac . 'Make it fail')); } - openssl_free_key($pkey); } /* generate a random challenge */ -function _uuid() -{ - return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), - mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, - mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), - mt_rand(0, 0xffff), mt_rand(0, 0xffff)); +function _uuid() { + return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff)); } + ?> --EXPECTREGEX-- string\(36\) \"[0-9a-f]{8}\-([0-9a-f]{4}\-){3}[0-9a-f]{12}\" diff --git a/ext/openssl/tests/openssl_spki_new.phpt b/ext/openssl/tests/openssl_spki_new.phpt deleted file mode 100644 index e40f9bf28e..0000000000 --- a/ext/openssl/tests/openssl_spki_new.phpt +++ /dev/null @@ -1,77 +0,0 @@ ---TEST-- -Testing openssl_spki_new() -Tests SPKAC for all available private key sizes & hashing algorithms ---SKIPIF-- -<?php -if (!extension_loaded("openssl")) die("skip"); -if (!@openssl_pkey_new()) die("skip cannot create private key"); -?> ---FILE-- -<?php - -/* array of private key sizes to test */ -$ksize = array('1024'=>1024, - '2048'=>2048, - '4096'=>4096); - -/* array of available hashings to test */ -$algo = array('md4'=>OPENSSL_ALGO_MD4, - 'md5'=>OPENSSL_ALGO_MD5, - 'sha1'=>OPENSSL_ALGO_SHA1, - 'sha224'=>OPENSSL_ALGO_SHA224, - 'sha256'=>OPENSSL_ALGO_SHA256, - 'sha384'=>OPENSSL_ALGO_SHA384, - 'sha512'=>OPENSSL_ALGO_SHA512, - 'rmd160'=>OPENSSL_ALGO_RMD160); - -/* loop over key sizes for test */ -foreach($ksize as $k => $v) { - - /* generate new private key of specified size to use for tests */ - $pkey = openssl_pkey_new(array('digest_alg' => 'sha512', - 'private_key_type' => OPENSSL_KEYTYPE_RSA, - 'private_key_bits' => $v)); - openssl_pkey_export($pkey, $pass); - - /* loop to create and verify results */ - foreach($algo as $key => $value) { - var_dump(openssl_spki_new($pkey, _uuid(), $value)); - } - openssl_free_key($pkey); -} - -/* generate a random challenge */ -function _uuid() -{ - return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), - mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, - mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), - mt_rand(0, 0xffff), mt_rand(0, 0xffff)); -} - -?> ---EXPECTF-- -string(478) "%s" -string(478) "%s" -string(478) "%s" -string(478) "%s" -string(478) "%s" -string(478) "%s" -string(478) "%s" -string(474) "%s" -string(830) "%s" -string(830) "%s" -string(830) "%s" -string(830) "%s" -string(830) "%s" -string(830) "%s" -string(830) "%s" -string(826) "%s" -string(1510) "%s" -string(1510) "%s" -string(1510) "%s" -string(1510) "%s" -string(1510) "%s" -string(1510) "%s" -string(1510) "%s" -string(1506) "%s" diff --git a/ext/openssl/tests/openssl_spki_new_basic.phpt b/ext/openssl/tests/openssl_spki_new_basic.phpt new file mode 100644 index 0000000000..b31d6f9184 --- /dev/null +++ b/ext/openssl/tests/openssl_spki_new_basic.phpt @@ -0,0 +1,73 @@ +--TEST-- +openssl_spki_new() test for creating SPKI string +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +?> +--FILE-- +<?php + +/* array of private key sizes to test */ +$key_sizes = array(1024, 2048, 4096); +$pkeys = array(); +foreach ($key_sizes as $key_size) { + $key_file = "file://" . dirname(__FILE__) . "/private_rsa_" . $key_size . ".key"; + $pkeys[] = openssl_pkey_get_private($key_file); +} + + +/* array of available hashings to test */ +$algo = array( + OPENSSL_ALGO_MD4, + OPENSSL_ALGO_MD5, + OPENSSL_ALGO_SHA1, + OPENSSL_ALGO_SHA224, + OPENSSL_ALGO_SHA256, + OPENSSL_ALGO_SHA384, + OPENSSL_ALGO_SHA512, + OPENSSL_ALGO_RMD160 +); + +/* loop over key sizes for test */ +foreach ($pkeys as $pkey) { + + /* loop to create and verify results */ + foreach ($algo as $value) { + var_dump(openssl_spki_new($pkey, _uuid(), $value)); + } +} + +/* generate a random challenge */ +function _uuid() { + return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff)); +} + +?> +--EXPECTF-- +string(478) "%s" +string(478) "%s" +string(478) "%s" +string(478) "%s" +string(478) "%s" +string(478) "%s" +string(478) "%s" +string(474) "%s" +string(830) "%s" +string(830) "%s" +string(830) "%s" +string(830) "%s" +string(830) "%s" +string(830) "%s" +string(830) "%s" +string(826) "%s" +string(1510) "%s" +string(1510) "%s" +string(1510) "%s" +string(1510) "%s" +string(1510) "%s" +string(1510) "%s" +string(1510) "%s" +string(1506) "%s" diff --git a/ext/openssl/tests/openssl_spki_verify.phpt b/ext/openssl/tests/openssl_spki_verify.phpt deleted file mode 100644 index 52dc8e2045..0000000000 --- a/ext/openssl/tests/openssl_spki_verify.phpt +++ /dev/null @@ -1,91 +0,0 @@ ---TEST-- -Testing openssl_spki_verify() -Creates SPKAC for all available key sizes & signature algorithms and tests for valid signature ---INI-- -error_reporting=0 ---SKIPIF-- -<?php -if (!extension_loaded("openssl")) die("skip"); -if (!@openssl_pkey_new()) die("skip cannot create private key"); -?> ---FILE-- -<?php - -/* array of private key sizes to test */ -$ksize = array('1024'=>1024, - '2048'=>2048, - '4096'=>4096); - -/* array of available hashings to test */ -$algo = array('sha1'=>OPENSSL_ALGO_SHA1, - 'sha224'=>OPENSSL_ALGO_SHA224, - 'sha256'=>OPENSSL_ALGO_SHA256, - 'sha384'=>OPENSSL_ALGO_SHA384, - 'sha512'=>OPENSSL_ALGO_SHA512, - 'rmd160'=>OPENSSL_ALGO_RMD160); - -/* loop over key sizes for test */ -foreach($ksize as $k => $v) { - - /* generate new private key of specified size to use for tests */ - $pkey = openssl_pkey_new(array('digest_alg' => 'sha512', - 'private_key_type' => OPENSSL_KEYTYPE_RSA, - 'private_key_bits' => $v)); - openssl_pkey_export($pkey, $pass); - - /* loop to create and verify results */ - foreach($algo as $key => $value) { - $spkac = openssl_spki_new($pkey, _uuid(), $value); - var_dump(openssl_spki_verify(preg_replace('/SPKAC=/', '', $spkac))); - var_dump(openssl_spki_verify($spkac.'Make it fail')); - } - openssl_free_key($pkey); -} - -/* generate a random challenge */ -function _uuid() -{ - return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), - mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, - mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), - mt_rand(0, 0xffff), mt_rand(0, 0xffff)); -} - -?> ---EXPECT-- -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false) -bool(true) -bool(false)
\ No newline at end of file diff --git a/ext/openssl/tests/openssl_spki_verify_basic.phpt b/ext/openssl/tests/openssl_spki_verify_basic.phpt new file mode 100644 index 0000000000..7b56a37e13 --- /dev/null +++ b/ext/openssl/tests/openssl_spki_verify_basic.phpt @@ -0,0 +1,88 @@ +--TEST-- +openssl_spki_verify() tests for valid signature +--INI-- +error_reporting=0 +--SKIPIF-- +<?php +if (!extension_loaded("openssl")) die("skip"); +?> +--FILE-- +<?php + +/* array of private key sizes to test */ +$key_sizes = array(1024, 2048, 4096); +$pkeys = array(); +foreach ($key_sizes as $key_size) { + $key_file = "file://" . dirname(__FILE__) . "/private_rsa_" . $key_size . ".key"; + $pkeys[] = openssl_pkey_get_private($key_file); +} + + +/* array of available hashings to test */ +$algo = array( + OPENSSL_ALGO_SHA1, + OPENSSL_ALGO_SHA224, + OPENSSL_ALGO_SHA256, + OPENSSL_ALGO_SHA384, + OPENSSL_ALGO_SHA512, + OPENSSL_ALGO_RMD160 +); + +/* loop over key sizes for test */ +foreach ($pkeys as $pkey) { + + /* loop to create and verify results */ + foreach ($algo as $value) { + $spkac = openssl_spki_new($pkey, _uuid(), $value); + var_dump(openssl_spki_verify(preg_replace('/SPKAC=/', '', $spkac))); + var_dump(openssl_spki_verify($spkac . 'Make it fail')); + } +} + +/* generate a random challenge */ +function _uuid() { + return sprintf('%04x%04x-%04x-%04x-%04x-%04x%04x%04x', mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff), mt_rand(0, 0x0fff) | 0x4000, + mt_rand(0, 0x3fff) | 0x8000, mt_rand(0, 0xffff), + mt_rand(0, 0xffff), mt_rand(0, 0xffff)); +} + + +?> +--EXPECT-- +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) diff --git a/ext/openssl/tests/019.phpt b/ext/openssl/tests/openssl_verify_basic.phpt index c1f186c335..a21dfedb01 100644 --- a/ext/openssl/tests/019.phpt +++ b/ext/openssl/tests/openssl_verify_basic.phpt @@ -5,7 +5,7 @@ openssl_verify() tests --FILE-- <?php $data = "Testing openssl_verify()"; -$privkey = "file://" . dirname(__FILE__) . "/private.key"; +$privkey = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; $pubkey = "file://" . dirname(__FILE__) . "/public.key"; $wrong = "wrong"; diff --git a/ext/openssl/tests/009.phpt b/ext/openssl/tests/openssl_x509_check_private_key_basic.phpt index a7156dd8d0..b4842aae18 100644 --- a/ext/openssl/tests/009.phpt +++ b/ext/openssl/tests/openssl_x509_check_private_key_basic.phpt @@ -5,15 +5,15 @@ openssl_x509_check_private_key() tests --FILE-- <?php $fp = fopen(dirname(__FILE__) . "/cert.crt","r"); -$a = fread($fp,8192); +$a = fread($fp, 8192); fclose($fp); -$fp = fopen(dirname(__FILE__) . "/private.key","r"); -$b = fread($fp,8192); +$fp = fopen(dirname(__FILE__) . "/private_rsa_1024.key","r"); +$b = fread($fp, 8192); fclose($fp); $cert = "file://" . dirname(__FILE__) . "/cert.crt"; -$key = "file://" . dirname(__FILE__) . "/private.key"; +$key = "file://" . dirname(__FILE__) . "/private_rsa_1024.key"; var_dump(openssl_x509_check_private_key($cert, $key)); var_dump(openssl_x509_check_private_key("", $key)); diff --git a/ext/openssl/tests/openssl_x509_export_basic.phpt b/ext/openssl/tests/openssl_x509_export_basic.phpt new file mode 100644 index 0000000000..4177bd7798 --- /dev/null +++ b/ext/openssl/tests/openssl_x509_export_basic.phpt @@ -0,0 +1,45 @@ +--TEST-- +openssl_x509_export() tests +--SKIPIF-- +<?php if (!extension_loaded("openssl")) print "skip"; ?> +--FILE-- +<?php +$cert_file = dirname(__FILE__) . "/cert.crt"; + +$a = file_get_contents($cert_file); +$b = "file://" . $cert_file; +$c = "invalid cert"; +$d = openssl_x509_read($a); +$e = array(); + +var_dump(openssl_x509_export($a, $output)); // read cert as a binary string +var_dump(openssl_x509_export($b, $output2)); // read cert from a filename string +var_dump(openssl_x509_export($c, $output3)); // read an invalid cert, fails +var_dump(openssl_x509_export($d, $output4)); // read cert from a resource +var_dump(openssl_x509_export($e, $output5)); // read an array, fails + +if (PHP_EOL !== "\n") { + $a = str_replace(PHP_EOL, "\n", $a); +} + +var_dump(strcmp($output, $a)); +var_dump(strcmp($output, $output2)); +var_dump(strcmp($output, $output3)); +var_dump(strcmp($output, $output4)); // different +var_dump(strcmp($output, $output5)); // different +?> +--EXPECTF-- +bool(true) +bool(true) + +Warning: openssl_x509_export(): cannot get cert from parameter 1 in %s on line %d +bool(false) +bool(true) + +Warning: openssl_x509_export(): cannot get cert from parameter 1 in %s on line %d +bool(false) +int(0) +int(0) +int(%d) +int(0) +int(%d) diff --git a/ext/openssl/tests/openssl_x509_export_to_file_basic.phpt b/ext/openssl/tests/openssl_x509_export_to_file_basic.phpt new file mode 100644 index 0000000000..68ba93230d --- /dev/null +++ b/ext/openssl/tests/openssl_x509_export_to_file_basic.phpt @@ -0,0 +1,42 @@ +--TEST-- +openssl_x509_export_to_file() tests +--SKIPIF-- +<?php if (!extension_loaded("openssl")) print "skip"; ?> +--FILE-- +<?php +$outfilename = dirname(__FILE__) . "/openssl_x509_export_to_file__outfilename.tmp"; +$cert_file = dirname(__FILE__) . "/cert.crt"; + +$a = file_get_contents($cert_file); +$b = "file://" . $cert_file; +$c = "invalid cert"; +$d = openssl_x509_read($a); +$e = array(); + +var_dump(openssl_x509_export_to_file($a, $outfilename)); // read cert as a binary string +var_dump(openssl_x509_export_to_file($b, $outfilename)); // read cert from a filename string +var_dump(openssl_x509_export_to_file($c, $outfilename)); // read an invalid cert, fails +var_dump(openssl_x509_export_to_file($d, $outfilename)); // read cert from a resource +var_dump(openssl_x509_export_to_file($e, $outfilename)); // read an array, fails +echo "---\n"; +var_dump($exists = file_exists($outfilename)); +?> +--CLEAN-- +<?php +$outfilename = dirname(__FILE__) . "/openssl_x509_export_to_file__outfilename.tmp"; +if (file_exists($outfilename)) { + unlink($outfilename); +} +?> +--EXPECTF-- +bool(true) +bool(true) + +Warning: openssl_x509_export_to_file(): cannot get cert from parameter 1 in %s on line %d +bool(false) +bool(true) + +Warning: openssl_x509_export_to_file(): cannot get cert from parameter 1 in %s on line %d +bool(false) +--- +bool(true) diff --git a/ext/openssl/tests/openssl_x509_fingerprint.phpt b/ext/openssl/tests/openssl_x509_fingerprint_basic.phpt index 6cd464a894..766b158fab 100644 --- a/ext/openssl/tests/openssl_x509_fingerprint.phpt +++ b/ext/openssl/tests/openssl_x509_fingerprint_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -Testing openssl_x509_fingerprint() +openssl_x509_fingerprint() tests --SKIPIF-- <?php if (!extension_loaded("openssl")) die("skip"); diff --git a/ext/openssl/tests/openssl_x509_free_basic.phpt b/ext/openssl/tests/openssl_x509_free_basic.phpt new file mode 100644 index 0000000000..d8b586e8b4 --- /dev/null +++ b/ext/openssl/tests/openssl_x509_free_basic.phpt @@ -0,0 +1,16 @@ +--TEST-- +openssl_x509_free() tests +--SKIPIF-- +<?php if (!extension_loaded("openssl")) print "skip"; ?> +--FILE-- +<?php +var_dump($res = openssl_x509_read("file://" . dirname(__FILE__) . "/cert.crt")); +openssl_x509_free($res); +var_dump($res); +openssl_x509_free(false); +?> +--EXPECTF-- +resource(%d) of type (OpenSSL X.509) +resource(%d) of type (Unknown) + +Warning: openssl_x509_free() expects parameter 1 to be resource, boolean given in %s on line %d diff --git a/ext/openssl/tests/openssl_x509_parse_basic.phpt b/ext/openssl/tests/openssl_x509_parse_basic.phpt index 325b2ee4b9..00e32c3b60 100644 --- a/ext/openssl/tests/openssl_x509_parse_basic.phpt +++ b/ext/openssl/tests/openssl_x509_parse_basic.phpt @@ -1,5 +1,5 @@ --TEST-- -openssl_x509_parse() basic test +openssl_x509_parse() tests --SKIPIF-- <?php if (!extension_loaded("openssl")) print "skip"; if (OPENSSL_VERSION_NUMBER < 0x10000000) die("skip Output requires OpenSSL 1.0"); diff --git a/ext/openssl/tests/openssl_x509_parse_basic_v9.phpt b/ext/openssl/tests/openssl_x509_parse_v9_basic.phpt index 89862eff50..89862eff50 100644 --- a/ext/openssl/tests/openssl_x509_parse_basic_v9.phpt +++ b/ext/openssl/tests/openssl_x509_parse_v9_basic.phpt diff --git a/ext/openssl/tests/openssl_x509_read_basic.phpt b/ext/openssl/tests/openssl_x509_read_basic.phpt new file mode 100644 index 0000000000..5f530534ff --- /dev/null +++ b/ext/openssl/tests/openssl_x509_read_basic.phpt @@ -0,0 +1,37 @@ +--TEST-- +openssl_x509_read() tests +--SKIPIF-- +<?php if (!extension_loaded("openssl")) print "skip"; ?> +--FILE-- +<?php +$fp = fopen(dirname(__FILE__) . "/cert.crt","r"); +$a = fread($fp,8192); +fclose($fp); + +$b = "file://" . dirname(__FILE__) . "/cert.crt"; +$c = "invalid cert"; +$d = openssl_x509_read($a); +$e = array(); +$f = array($b); + +var_dump(openssl_x509_read($a)); // read cert as a string +var_dump(openssl_x509_read($b)); // read cert as a filename string +var_dump(openssl_x509_read($c)); // read an invalid cert, fails +var_dump(openssl_x509_read($d)); // read cert from a resource +var_dump(openssl_x509_read($e)); // read an array +var_dump(openssl_x509_read($f)); // read an array with the filename +?> +--EXPECTF-- +resource(%d) of type (OpenSSL X.509) +resource(%d) of type (OpenSSL X.509) + +Warning: openssl_x509_read(): supplied parameter cannot be coerced into an X509 certificate! in %s on line %d +bool(false) +resource(%d) of type (OpenSSL X.509) + +Warning: openssl_x509_read(): supplied parameter cannot be coerced into an X509 certificate! in %s on line %d +bool(false) + +Warning: openssl_x509_read(): supplied parameter cannot be coerced into an X509 certificate! in %s on line %d +bool(false) + diff --git a/ext/openssl/tests/private.key b/ext/openssl/tests/private_rsa_1024.key index bce512e050..bce512e050 100644 --- a/ext/openssl/tests/private.key +++ b/ext/openssl/tests/private_rsa_1024.key diff --git a/ext/openssl/tests/private_rsa_2048.key b/ext/openssl/tests/private_rsa_2048.key new file mode 100644 index 0000000000..d83e1b85c9 --- /dev/null +++ b/ext/openssl/tests/private_rsa_2048.key @@ -0,0 +1,27 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIEpAIBAAKCAQEArbUmVW1Y+rJzZRC3DYB0kdIgvk7MAday78ybGPPDhVlbAb4C +jWbaPs4nyUCTEt9KVG0H7pXHxDbWSsC2974zdvqlP0L2op1/M2SteTcGCBOdwGH2 +jORVAZL8/WbTOf9IpKAM77oN14scsyOlQBJqhh+xrLg8ksB2dOos54yDqo0Tq7R5 +tldV+alKZXWlJnqRCfFuxvqtfWI5nGTAedVZhvjQfLQQgujfXHoFWoGbXn2buzfw +KGJEeqWPbQOZF/FeOJPlgOBhhDb3BAFNVCtM3k71Rblj54pNd3yvq152xsgFd0o3 +s15fuSwZgerUjeEuw/wTK9k7vyp+MrIQHQmPdQIDAQABAoIBABPDKDlP12+uHbLB +1BGVK63rWg5MqKkM5A6kGIEeOoBRSilIlMHBkdLTYXNkBVeAT9SLEvvxzmhkVLzs +b+R/nxtKKMKpu6WEhZQzQAkqWWVR1gCtJH+i+ojTUDUEHcPbZ0hTbSVY5XpAOWOo +CoTfk37u3CfqTfnkK5XhjnpJYjFk60fLeTKKG90xb4WmPGCOxBZGeI9yk+gEgMVx +4qYBQEgcaJEBXebvM0q8BCDh/rlYxwQ/q0RJ6W1D84SOeyYv/9LesFZSbnUN16tA +/YezkhYVkVIrQFzh1al7NKvWEUZ3Yx3AEuggKtijlZyO9zOAOigSiFQjtqOl7S6e +jbVfLYECgYEA51E5TNvN6IW6p58wOXTmINnsW3sDYS1CyPh3TkSvWU2OqMXJxQSA +bASpXtqicAY32wkBOiazyY/+L7x1ReG/8z3tTm53AsYwkLKrgUfjdrOFhXWk8QI3 +0WS/1hS7qZ4Ycxi5B2X+rPPLnc2+mUvaEX6/B2Fjbqp4nIt+ZAE8SvcCgYEAwD47 +anMk8z68wdgzxY4J10sgCKfgHCe7J8ikpzloznX1HnbZTWf74FLlA/8ctfFJCVAy +4dG1s0D+JSpxxMSkk4hvi10Ha6t5U+BreD9VPAQRspGSKhn8JfwvLfKPH65uazBP +yvBtVIdagBf/msLfF33vkrQSjAEJM1njl6XMEfMCgYB1BddqNa0G3Figol0gRC6E +Iht78FC2YdJun5yj4QWgtSbd5Sn9XRinDPiufwc8izjIu9Z+F8ROzWT3u2zMzLdy +FDswuZvFsIQzP+CaB8dgbtO2v9yQ/OFGMqUGZfjGh6+w0qoQvx3HW5MAI20wWnpY +7Xkw/6jw/JcGA2AOsb1R4wKBgQCFfnF54Q1GkEk4/m4tAA4bX4KWICUCyCAxZyXX +LYl23PhiuDr7gnqockevt8ZzHWMPQY6juyFGoZoZqtinv7lc7YAvsWEGxmMQ+KUI +Mkp4y4aSjn2GGNc8dVs5t9blNBZe/oRaMwxohzkz+/Y1vJ54TK5BHCRI7is6anAd +jTchOwKBgQDP9yOdQTfUwJRUMERWmzXWU2oDXeEMdpbGPLGJ4/e/hu1CW7bdQRoc +jBSEpn3hOodmdwdmoXtbJReMCE8qS6yVHNn4orpJf+uOBr5fVnHwttFfN8HID9js +Lml8jAAQItMFw1CEPR75NVdFb7ksNKlxE9376tG63JhrTttRGwO3CA== +-----END RSA PRIVATE KEY----- diff --git a/ext/openssl/tests/private_rsa_4096.key b/ext/openssl/tests/private_rsa_4096.key new file mode 100644 index 0000000000..8338c86cbb --- /dev/null +++ b/ext/openssl/tests/private_rsa_4096.key @@ -0,0 +1,51 @@ +-----BEGIN RSA PRIVATE KEY----- +MIIJKAIBAAKCAgEAtlmPieG4yL/HQ1j98U+VqlAzO55+aSHKXOV9q5+uTevtzXVV +s+rOPUAlPkUi7kcp3Yrum+Y0rNCnTNpSmpFB2f/Y1rHb6Rxn8SXzWSq8BM0BhbCm +yE+PY3DyIBizX6isb13vJyvU7f8Ayv4xAQ/ve8ytFAnBXUdIhtQNygraxvr8aoZw +81cBRQ8NhBkk/qDZWVkOiePC9voZ05sENhL4aUZw3Xew2JtZyw+lRxheczkYYc71 +OQuOKoU06j3ZpLhdhtdjpOVC6csIk9qyq8ki8t9m66a2BdiPaz1cWGZGqQg4SDrJ +0XKG6/wdSWgdUKMp0wB2Kwph2SWwLm7BQEpdtMtXnNGB2dT+lffjtqRvyT4HKO03 +R9b7ZxUVA34Tzi+kX04g3e4qI4eD0bsHYwioUlkKf/q7E1+WjwaQ2LLbOUnWeKqb +wGBsZYMWeWGTc/FO4oyDJBG9gnsqmSHasAsxsW6ojsGnz9IXywpwInlz+R4pB+ua +dXHiUZEuT8lCdBUWKAtCIb/F9cNEJg/Vq0iVoWFaOYd5D4PHXV5aXjEx18ez7GvN +98XPYNXQmVBmsIlOHQpytz0RdrlstksxBqWhaBUT3ZJU6czchNgYeFsEuYKkUNK+ +fwQLhA9aeT6RBdet2efhyaf4y3vQFb5kxx4JcljXjIYVR3yB9iZnD0WGQxkCAwEA +AQKCAgBHrhkQmFxs/YY04SyhySkKFBCvpPQIG7JSphuqdVCtbMrD8xXHbcu4pBh/ +y+mZRPweDFkTi4C1VigNu9ywydza9wmkC7JohjQNxV9Nc9EJChVJGlHVeADjlCh5 +mXwZZFK0THaQLVi8XXtQUG+u/TaksaZvtA4Avt6xsXXiMDYj9dF3hnWsEk17ehlU +DhZOyafmyW0/ovqm31V7qvoSz446w+fmBwDLhPXdLr9HnTqzjIQbHqGi1PoDmO1e +DwYZDCgns0+GKGEPSjKK/HMzuBM26b6pb5Up4yEthKdiUIICPCrzqbhfzudeqHJS +wsyTQDBWs13AOYqRM5F4Dy2EOjdvCgt2zElO0c3r/pOTplk3/v7VrsqiNN33xGfc +4zGw3d0xLjQRhA9vhG5Kdtqqs1GqZDf3mNmPxv8gHJDdB6Twkk9iNlUnV5neew6R +0KKklZvMApE+KMVrRKmez0+ab/ktpoAe9Xox9ChBfLaZQgJlDwNDktjRu8RT1da8 +L6SMy5+mP+aSKxWxgNGoM0BQiv3DBriyTuyhcu+2SIr4c0LrWqedZRI1eRREZjhG +VLBpftvQH7AMTZuIHXYjtF8XcZneaa2/fI7SNH6RpPc7WJmLCF3ufjv6HVp3qA8B +ahRCgsr4sBZDJqwMkbNJQfuF/zNOAGmO5VRBodb/P9UQeEVeAQKCAQEA6TkahKZq +374hUnElMH3mmYPVxOKfqx4EMrS+MP8cjXXmiw7bWjQlufcmbMhxHaXkGiU9+/TB +VdFPtLZvo7Aa+m2sHCySJ1pG2T4kkmV9cNVExKPllraH3/QvDK3o34aA2DxgOXAT +33wxlxvmmaMmrjjP6BZduvS/W/vwL6+aA1erZbsBuA1CoeyiyE95zdcD43+TlZWi +fwCqCZ27wrKHCPFcEN/ecpjKQTQQdogDNWdJJzaTH7y3iWNOsLdTNeLRYrvu94dS +J9n7cCoLCEFzdylaXx/jGCNrnaNtqDj46JHW6XSQ6e3D0UpV2hx5V2+0q1gbEhWe +wtBrhGsHj/jj+QKCAQEAyCiOlcE6a1tjIdMihAO1hqdUiFcIKzoiDQKNBEaY9ELz +oWkuZj2fUnhjeAKhkQ4ZheH6+fk2Tt0+kU1Jl+Iym/ciE/m/N8RUyqq2FOnmwktz +yGqD9fQeLix2b2txp+0dyi1niQ+S8ZKAJBbxKTb3CBefowrkz5JK7+jWqaUDNQ5h +8KoGCcAB8kSkXGgqVOapXyGb31YdyM3X1mJGv95jO4A+OmFI2faPAOtZrg9EicSI +7U84bfFMhfhrpxZuU7Bbyz6Kg9hleAv0q/3tBFSJvMTOiuM7OFtlUAByL+pWwZ9Y +haQ4ojojsPaQ6pMmf0JNXwnp8Rhz2+QNDyFzRm/gIQKCAQEA3dmA/S/kuAL/ZZHV +g4QvyFYdEdVVdwvtiGJgDPGPsoy1ig/O3sZ+IKEWPyKIX2B/U9ObW8Hd6wlZXZix +J68Maq3Kq15GhQKeJGa1mUDLi3qDmN4jNjNZmtKHsvL3czFZ/Nep3NldPhjAf3J9 +8CW/VLkcJDSqYn4QTaqhNms/APDzTKkQIIkUmj0kN5FKV2CyBUVFGWSml1MFbHJL +ug/i3cHiBvc9fhsTQeUJyAbnrnQapR+H4ge9OwZpQzaQA9FHxjjpPzLNFrWHNZH4 +vpisAm0m1xfZCQwggWqFlCDlvS2FlrtYYf3XaI3ijsDJOEA9R0RfM9u3Eq/5ppO9 +NNnX2QKCAQAJ63ilk14B1BWlp4EeadClS8W0vBt7iPYHDwlOHPGXqXnJlhzmlEdB +HxZO7FJ1je1V5U069k7quaxQJzRugpdfg2/87XO8n85T/QHpJ254UqT6Wc0Qc3jL +cQitnPWVDPtc+cMX193AezI+l6R8Fm1HyWPwAKo2X1m3aiK5ZaQzDPNtqf+CnDF8 +gEplCgSPEJ90R4YiG3J+cTUxOs2m1K62VDTBT/D8XGvZ79ASAE+1RDhFCpgRWtQg +D5/GOCZfn23tNLxIrIDa4jzOCVelz0rEQDy8RWa59E2hGWSPW13RWsRYWzszTw5V +xuKHvaM6y15qR2OAv2V+kF7VUSMVapYBAoIBAEyZDn9H+IMQBkRyZgxPLsE5cgd3 +DeR2Txn2RxQBpop9+lgniuq/NVHiUIRscynsJ01/bFifmFNkgD2cRORy7SU+wsNr +zsWlLPO1e/axdfMsT0OIBOQ84jZ6FDGi5JnqnC8zVVPU7g2iNoDEtA7ltlXknUUX +uigFoR1CXoNz8KdW+18MtYDjBLR1crfGa+zqPOpxfjoXBhehtCKG9ZxtrBSWq6mz +lR9N5Tv9USiJW1r6+85aLsC5E9ARjAxMLhTKvD+NXbQDwZJgfM/vs1eZ6eIYMYE9 +lB7kMFfHKqsagNXdyhRFzfEfx+FkKTHaqC6V5rOp6q0t8AO41ZvZO/tKdi8= +-----END RSA PRIVATE KEY----- diff --git a/ext/pcre/pcrelib/ChangeLog b/ext/pcre/pcrelib/ChangeLog index 359b412958..5e5bf188ce 100644 --- a/ext/pcre/pcrelib/ChangeLog +++ b/ext/pcre/pcrelib/ChangeLog @@ -1,6 +1,182 @@ ChangeLog for PCRE ------------------ +Note that the PCRE 8.xx series (PCRE1) is now in a bugfix-only state. All +development is happening in the PCRE2 10.xx series. + +Version 8.38 23-November-2015 +----------------------------- + +1. If a group that contained a recursive back reference also contained a + forward reference subroutine call followed by a non-forward-reference + subroutine call, for example /.((?2)(?R)\1)()/, pcre2_compile() failed to + compile correct code, leading to undefined behaviour or an internally + detected error. This bug was discovered by the LLVM fuzzer. + +2. Quantification of certain items (e.g. atomic back references) could cause + incorrect code to be compiled when recursive forward references were + involved. For example, in this pattern: /(?1)()((((((\1++))\x85)+)|))/. + This bug was discovered by the LLVM fuzzer. + +3. A repeated conditional group whose condition was a reference by name caused + a buffer overflow if there was more than one group with the given name. + This bug was discovered by the LLVM fuzzer. + +4. A recursive back reference by name within a group that had the same name as + another group caused a buffer overflow. For example: + /(?J)(?'d'(?'d'\g{d}))/. This bug was discovered by the LLVM fuzzer. + +5. A forward reference by name to a group whose number is the same as the + current group, for example in this pattern: /(?|(\k'Pm')|(?'Pm'))/, caused + a buffer overflow at compile time. This bug was discovered by the LLVM + fuzzer. + +6. A lookbehind assertion within a set of mutually recursive subpatterns could + provoke a buffer overflow. This bug was discovered by the LLVM fuzzer. + +7. Another buffer overflow bug involved duplicate named groups with a + reference between their definition, with a group that reset capture + numbers, for example: /(?J:(?|(?'R')(\k'R')|((?'R'))))/. This has been + fixed by always allowing for more memory, even if not needed. (A proper fix + is implemented in PCRE2, but it involves more refactoring.) + +8. There was no check for integer overflow in subroutine calls such as (?123). + +9. The table entry for \l in EBCDIC environments was incorrect, leading to its + being treated as a literal 'l' instead of causing an error. + +10. There was a buffer overflow if pcre_exec() was called with an ovector of + size 1. This bug was found by american fuzzy lop. + +11. If a non-capturing group containing a conditional group that could match + an empty string was repeated, it was not identified as matching an empty + string itself. For example: /^(?:(?(1)x|)+)+$()/. + +12. In an EBCDIC environment, pcretest was mishandling the escape sequences + \a and \e in test subject lines. + +13. In an EBCDIC environment, \a in a pattern was converted to the ASCII + instead of the EBCDIC value. + +14. The handling of \c in an EBCDIC environment has been revised so that it is + now compatible with the specification in Perl's perlebcdic page. + +15. The EBCDIC character 0x41 is a non-breaking space, equivalent to 0xa0 in + ASCII/Unicode. This has now been added to the list of characters that are + recognized as white space in EBCDIC. + +16. When PCRE was compiled without UCP support, the use of \p and \P gave an + error (correctly) when used outside a class, but did not give an error + within a class. + +17. \h within a class was incorrectly compiled in EBCDIC environments. + +18. A pattern with an unmatched closing parenthesis that contained a backward + assertion which itself contained a forward reference caused buffer + overflow. And example pattern is: /(?=di(?<=(?1))|(?=(.))))/. + +19. JIT should return with error when the compiled pattern requires more stack + space than the maximum. + +20. A possessively repeated conditional group that could match an empty string, + for example, /(?(R))*+/, was incorrectly compiled. + +21. Fix infinite recursion in the JIT compiler when certain patterns such as + /(?:|a|){100}x/ are analysed. + +22. Some patterns with character classes involving [: and \\ were incorrectly + compiled and could cause reading from uninitialized memory or an incorrect + error diagnosis. + +23. Pathological patterns containing many nested occurrences of [: caused + pcre_compile() to run for a very long time. + +24. A conditional group with only one branch has an implicit empty alternative + branch and must therefore be treated as potentially matching an empty + string. + +25. If (?R was followed by - or + incorrect behaviour happened instead of a + diagnostic. + +26. Arrange to give up on finding the minimum matching length for overly + complex patterns. + +27. Similar to (4) above: in a pattern with duplicated named groups and an + occurrence of (?| it is possible for an apparently non-recursive back + reference to become recursive if a later named group with the relevant + number is encountered. This could lead to a buffer overflow. Wen Guanxing + from Venustech ADLAB discovered this bug. + +28. If pcregrep was given the -q option with -c or -l, or when handling a + binary file, it incorrectly wrote output to stdout. + +29. The JIT compiler did not restore the control verb head in case of *THEN + control verbs. This issue was found by Karl Skomski with a custom LLVM + fuzzer. + +30. Error messages for syntax errors following \g and \k were giving inaccurate + offsets in the pattern. + +31. Added a check for integer overflow in conditions (?(<digits>) and + (?(R<digits>). This omission was discovered by Karl Skomski with the LLVM + fuzzer. + +32. Handling recursive references such as (?2) when the reference is to a group + later in the pattern uses code that is very hacked about and error-prone. + It has been re-written for PCRE2. Here in PCRE1, a check has been added to + give an internal error if it is obvious that compiling has gone wrong. + +33. The JIT compiler should not check repeats after a {0,1} repeat byte code. + This issue was found by Karl Skomski with a custom LLVM fuzzer. + +34. The JIT compiler should restore the control chain for empty possessive + repeats. This issue was found by Karl Skomski with a custom LLVM fuzzer. + +35. Match limit check added to JIT recursion. This issue was found by Karl + Skomski with a custom LLVM fuzzer. + +36. Yet another case similar to 27 above has been circumvented by an + unconditional allocation of extra memory. This issue is fixed "properly" in + PCRE2 by refactoring the way references are handled. Wen Guanxing + from Venustech ADLAB discovered this bug. + +37. Fix two assertion fails in JIT. These issues were found by Karl Skomski + with a custom LLVM fuzzer. + +38. Fixed a corner case of range optimization in JIT. + +39. An incorrect error "overran compiling workspace" was given if there were + exactly enough group forward references such that the last one extended + into the workspace safety margin. The next one would have expanded the + workspace. The test for overflow was not including the safety margin. + +40. A match limit issue is fixed in JIT which was found by Karl Skomski + with a custom LLVM fuzzer. + +41. Remove the use of /dev/null in testdata/testinput2, because it doesn't + work under Windows. (Why has it taken so long for anyone to notice?) + +42. In a character class such as [\W\p{Any}] where both a negative-type escape + ("not a word character") and a property escape were present, the property + escape was being ignored. + +43. Fix crash caused by very long (*MARK) or (*THEN) names. + +44. A sequence such as [[:punct:]b] that is, a POSIX character class followed + by a single ASCII character in a class item, was incorrectly compiled in + UCP mode. The POSIX class got lost, but only if the single character + followed it. + +45. [:punct:] in UCP mode was matching some characters in the range 128-255 + that should not have been matched. + +46. If [:^ascii:] or [:^xdigit:] or [:^cntrl:] are present in a non-negated + class, all characters with code points greater than 255 are in the class. + When a Unicode property was also in the class (if PCRE_UCP is set, escapes + such as \w are turned into Unicode properties), wide characters were not + correctly handled, and could fail to match. + + Version 8.37 28-April-2015 -------------------------- diff --git a/ext/pcre/pcrelib/NEWS b/ext/pcre/pcrelib/NEWS index 064bf27819..7e42dcb360 100644 --- a/ext/pcre/pcrelib/NEWS +++ b/ext/pcre/pcrelib/NEWS @@ -1,6 +1,14 @@ News about PCRE releases ------------------------ +Release 8.38 23-November-2015 +----------------------------- + +This is bug-fix release. Note that this library (now called PCRE1) is now being +maintained for bug fixes only. New projects are advised to use the new PCRE2 +libraries. + + Release 8.37 28-April-2015 -------------------------- diff --git a/ext/pcre/pcrelib/config.h b/ext/pcre/pcrelib/config.h index 9714cf5bbd..0f7a9f73ff 100644 --- a/ext/pcre/pcrelib/config.h +++ b/ext/pcre/pcrelib/config.h @@ -24,41 +24,37 @@ #endif +/* Exclude these below definitions when building within PHP */ +#ifndef ZEND_API + /* config.h. Generated from config.h.in by configure. */ /* config.h.in. Generated from configure.ac by autoheader. */ + /* PCRE is written in Standard C, but there are a few non-standard things it can cope with, allowing it to run on SunOS4 and other "close to standard" systems. -In environments that support the GNU autotools, config.h.in is converted into -config.h by the "configure" script. In environments that use CMake, -config-cmake.in is converted into config.h. If you are going to build PCRE "by -hand" without using "configure" or CMake, you should copy the distributed -config.h.generic to config.h, and edit the macro definitions to be the way you -need them. You must then add -DHAVE_CONFIG_H to all of your compile commands, -so that config.h is included at the start of every source. +In environments that support the facilities, config.h.in is converted by +"configure", or config-cmake.h.in is converted by CMake, into config.h. If you +are going to build PCRE "by hand" without using "configure" or CMake, you +should copy the distributed config.h.generic to config.h, and then edit the +macro definitions to be the way you need them. You must then add +-DHAVE_CONFIG_H to all of your compile commands, so that config.h is included +at the start of every source. Alternatively, you can avoid editing by using -D on the compiler command line -to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H, -but if you do, default values will be taken from config.h for non-boolean -macros that are not defined on the command line. - -Boolean macros such as HAVE_STDLIB_H and SUPPORT_PCRE8 should either be defined -(conventionally to 1) for TRUE, and not defined at all for FALSE. All such -macros are listed as a commented #undef in config.h.generic. Macros such as -MATCH_LIMIT, whose actual value is relevant, have defaults defined, but are -surrounded by #ifndef/#endif lines so that the value can be overridden by -D. +to set the macro values. In this case, you do not have to set -DHAVE_CONFIG_H. -PCRE uses memmove() if HAVE_MEMMOVE is defined; otherwise it uses bcopy() if -HAVE_BCOPY is defined. If your system has neither bcopy() nor memmove(), make -sure both macros are undefined; an emulation function will then be used. */ +PCRE uses memmove() if HAVE_MEMMOVE is set to 1; otherwise it uses bcopy() if +HAVE_BCOPY is set to 1. If your system has neither bcopy() nor memmove(), set +them both to 0; an emulation function will be used. */ /* By default, the \R escape sequence matches any Unicode line ending character or sequence of characters. If BSR_ANYCRLF is defined (to any value), this is changed so that backslash-R matches only CR, LF, or CRLF. The build-time default can be overridden by the user of PCRE at runtime. */ -/* #undef BSR_ANYCRLF */ +#undef BSR_ANYCRLF /* If you are compiling for a system that uses EBCDIC instead of ASCII character codes, define this macro to any value. You must also edit the @@ -68,80 +64,113 @@ sure both macros are undefined; an emulation function will then be used. */ strings are in EBCDIC. If you do not define this macro, PCRE will assume input strings are ASCII or UTF-8/16/32 Unicode. It is not possible to build a version of PCRE that supports both EBCDIC and UTF-8/16/32. */ -/* #undef EBCDIC */ +#undef EBCDIC /* In an EBCDIC environment, define this macro to any value to arrange for the NL character to be 0x25 instead of the default 0x15. NL plays the role that LF does in an ASCII/Unicode environment. The value must also be set in the NEWLINE macro below. On systems that can use "configure" or CMake to set EBCDIC_NL25, the adjustment of NEWLINE is automatic. */ -/* #undef EBCDIC_NL25 */ +#undef EBCDIC_NL25 /* Define to 1 if you have the `bcopy' function. */ -/* #undef HAVE_BCOPY */ +#ifndef HAVE_BCOPY +#define HAVE_BCOPY 1 +#endif /* Define to 1 if you have the <bits/type_traits.h> header file. */ /* #undef HAVE_BITS_TYPE_TRAITS_H */ /* Define to 1 if you have the <bzlib.h> header file. */ -/* #undef HAVE_BZLIB_H */ +#ifndef HAVE_BZLIB_H +#define HAVE_BZLIB_H 1 +#endif /* Define to 1 if you have the <dirent.h> header file. */ -/* #undef HAVE_DIRENT_H */ +#ifndef HAVE_DIRENT_H +#define HAVE_DIRENT_H 1 +#endif /* Define to 1 if you have the <dlfcn.h> header file. */ -/* #undef HAVE_DLFCN_H */ +#ifndef HAVE_DLFCN_H +#define HAVE_DLFCN_H 1 +#endif /* Define to 1 if you have the <editline/readline.h> header file. */ -/* #undef HAVE_EDITLINE_READLINE_H */ +/*#undef HAVE_EDITLINE_READLINE_H*/ /* Define to 1 if you have the <edit/readline/readline.h> header file. */ /* #undef HAVE_EDIT_READLINE_READLINE_H */ /* Define to 1 if you have the <inttypes.h> header file. */ -/* #undef HAVE_INTTYPES_H */ +#ifndef HAVE_INTTYPES_H +#define HAVE_INTTYPES_H 1 +#endif /* Define to 1 if you have the <limits.h> header file. */ -/* #undef HAVE_LIMITS_H */ +#ifndef HAVE_LIMITS_H +#define HAVE_LIMITS_H 1 +#endif /* Define to 1 if the system has the type `long long'. */ -/* #undef HAVE_LONG_LONG */ +#ifndef HAVE_LONG_LONG +#define HAVE_LONG_LONG 1 +#endif /* Define to 1 if you have the `memmove' function. */ -/* #undef HAVE_MEMMOVE */ +#ifndef HAVE_MEMMOVE +#define HAVE_MEMMOVE 1 +#endif /* Define to 1 if you have the <memory.h> header file. */ -/* #undef HAVE_MEMORY_H */ +#ifndef HAVE_MEMORY_H +#define HAVE_MEMORY_H 1 +#endif /* Define if you have POSIX threads libraries and header files. */ -/* #undef HAVE_PTHREAD */ +#undef HAVE_PTHREAD /* Have PTHREAD_PRIO_INHERIT. */ -/* #undef HAVE_PTHREAD_PRIO_INHERIT */ - +#undef HAVE_PTHREAD_PRIO_INHERIT /* Define to 1 if you have the <readline/history.h> header file. */ -/* #undef HAVE_READLINE_HISTORY_H */ +#ifndef HAVE_READLINE_HISTORY_H +#define HAVE_READLINE_HISTORY_H 1 +#endif /* Define to 1 if you have the <readline/readline.h> header file. */ -/* #undef HAVE_READLINE_READLINE_H */ +#ifndef HAVE_READLINE_READLINE_H +#define HAVE_READLINE_READLINE_H 1 +#endif /* Define to 1 if you have the <stdint.h> header file. */ -/* #undef HAVE_STDINT_H */ +#ifndef HAVE_STDINT_H +#define HAVE_STDINT_H 1 +#endif /* Define to 1 if you have the <stdlib.h> header file. */ -/* #undef HAVE_STDLIB_H */ +#ifndef HAVE_STDLIB_H +#define HAVE_STDLIB_H 1 +#endif /* Define to 1 if you have the `strerror' function. */ -/* #undef HAVE_STRERROR */ +#ifndef HAVE_STRERROR +#define HAVE_STRERROR 1 +#endif /* Define to 1 if you have the <string> header file. */ -/* #undef HAVE_STRING */ +#ifndef HAVE_STRING +#define HAVE_STRING 1 +#endif /* Define to 1 if you have the <strings.h> header file. */ -/* #undef HAVE_STRINGS_H */ +#ifndef HAVE_STRINGS_H +#define HAVE_STRINGS_H 1 +#endif /* Define to 1 if you have the <string.h> header file. */ -/* #undef HAVE_STRING_H */ +#ifndef HAVE_STRING_H +#define HAVE_STRING_H 1 +#endif /* Define to 1 if you have `strtoimax'. */ /* #undef HAVE_STRTOIMAX */ @@ -150,46 +179,62 @@ sure both macros are undefined; an emulation function will then be used. */ /* #undef HAVE_STRTOLL */ /* Define to 1 if you have `strtoq'. */ -/* #undef HAVE_STRTOQ */ +#ifndef HAVE_STRTOQ +#define HAVE_STRTOQ 1 +#endif /* Define to 1 if you have the <sys/stat.h> header file. */ -/* #undef HAVE_SYS_STAT_H */ +#ifndef HAVE_SYS_STAT_H +#define HAVE_SYS_STAT_H 1 +#endif /* Define to 1 if you have the <sys/types.h> header file. */ -/* #undef HAVE_SYS_TYPES_H */ +#ifndef HAVE_SYS_TYPES_H +#define HAVE_SYS_TYPES_H 1 +#endif /* Define to 1 if you have the <type_traits.h> header file. */ /* #undef HAVE_TYPE_TRAITS_H */ /* Define to 1 if you have the <unistd.h> header file. */ -/* #undef HAVE_UNISTD_H */ +#ifndef HAVE_UNISTD_H +#define HAVE_UNISTD_H 1 +#endif /* Define to 1 if the system has the type `unsigned long long'. */ -/* #undef HAVE_UNSIGNED_LONG_LONG */ +#ifndef HAVE_UNSIGNED_LONG_LONG +#define HAVE_UNSIGNED_LONG_LONG 1 +#endif -/* Define to 1 if the compiler supports simple visibility declarations. */ +/* Define to 1 or 0, depending whether the compiler supports simple visibility + declarations. */ /* #undef HAVE_VISIBILITY */ /* Define to 1 if you have the <windows.h> header file. */ /* #undef HAVE_WINDOWS_H */ /* Define to 1 if you have the <zlib.h> header file. */ -/* #undef HAVE_ZLIB_H */ +#ifndef HAVE_ZLIB_H +#define HAVE_ZLIB_H 1 +#endif /* Define to 1 if you have `_strtoi64'. */ /* #undef HAVE__STRTOI64 */ +/* Exclude these above definitions when building within PHP */ +#endif + /* The value of LINK_SIZE determines the number of bytes used to store links as offsets within the compiled regex. The default is 2, which allows for compiled patterns up to 64K long. This covers the vast majority of cases. However, PCRE can also be compiled to use 3 or 4 bytes instead. This allows - for longer patterns in extreme cases. */ + for longer patterns in extreme cases. On systems that support it, + "configure" can be used to override this default. */ #ifndef LINK_SIZE #define LINK_SIZE 2 #endif -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ +/* Define to the sub-directory where libtool stores uninstalled libraries. */ /* This is ignored unless you are using libtool. */ #ifndef LT_OBJDIR #define LT_OBJDIR ".libs/" @@ -200,7 +245,8 @@ sure both macros are undefined; an emulation function will then be used. */ pcre_exec(). There is a runtime interface for setting a different limit. The limit exists in order to catch runaway regular expressions that take for ever to determine that they do not match. The default is set very large - so that it does not accidentally catch legitimate cases. */ + so that it does not accidentally catch legitimate cases. On systems that + support it, "configure" can be used to override this default default. */ #ifndef MATCH_LIMIT #define MATCH_LIMIT 10000000 #endif @@ -212,7 +258,8 @@ sure both macros are undefined; an emulation function will then be used. */ used. The value of MATCH_LIMIT_RECURSION applies only to recursive calls of match(). To have any useful effect, it must be less than the value of MATCH_LIMIT. The default is to use the same value as MATCH_LIMIT. There is - a runtime method for setting a different limit. */ + a runtime method for setting a different limit. On systems that support it, + "configure" can be used to override the default. */ #ifndef MATCH_LIMIT_RECURSION #define MATCH_LIMIT_RECURSION MATCH_LIMIT #endif @@ -243,6 +290,9 @@ sure both macros are undefined; an emulation function will then be used. */ #define NEWLINE 10 #endif +/* Define to 1 if your C compiler doesn't accept -c and -o together. */ +/* #undef NO_MINUS_C_MINUS_O */ + /* PCRE uses recursive function calls to handle backtracking while matching. This can sometimes be a problem on systems that have stacks of limited size. Define NO_RECURSE to any value to get a version that doesn't use @@ -252,6 +302,8 @@ sure both macros are undefined; an emulation function will then be used. */ */ /* #undef NO_RECURSE */ +#define PARENS_NEST_LIMIT 250 + /* Name of package */ #define PACKAGE "pcre" @@ -262,7 +314,7 @@ sure both macros are undefined; an emulation function will then be used. */ #define PACKAGE_NAME "PCRE" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "PCRE 8.37" +#define PACKAGE_STRING "PCRE 8.38" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "pcre" @@ -271,7 +323,13 @@ sure both macros are undefined; an emulation function will then be used. */ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "8.37" +#define PACKAGE_VERSION "8.38" + +/* to make a symbol visible */ +/* #undef PCRECPP_EXP_DECL */ + +/* to make a symbol visible */ +/* #undef PCRECPP_EXP_DEFN */ /* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested parentheses (of any kind) in a pattern. This limits the amount of system @@ -285,9 +343,20 @@ sure both macros are undefined; an emulation function will then be used. */ minimum value. The actual amount of memory used by pcregrep is three times this number, because it allows for the buffering of "before" and "after" lines. */ -#ifndef PCREGREP_BUFSIZE -#define PCREGREP_BUFSIZE 20480 -#endif +/* #undef PCREGREP_BUFSIZE */ + +/* to make a symbol visible */ +/* #undef PCREPOSIX_EXP_DECL */ + +/* to make a symbol visible */ +/* #undef PCREPOSIX_EXP_DEFN */ + +/* to make a symbol visible */ +/* #undef PCRE_EXP_DATA_DEFN */ + +/* to make a symbol visible */ +/* #undef PCRE_EXP_DECL */ + /* If you are compiling for a system other than a Unix-like system or Win32, and it needs some magic to be inserted before the definition @@ -319,7 +388,13 @@ sure both macros are undefined; an emulation function will then be used. */ /* #undef PTHREAD_CREATE_JOINABLE */ /* Define to 1 if you have the ANSI C header files. */ -/* #undef STDC_HEADERS */ +#ifndef STDC_HEADERS +#define STDC_HEADERS 1 +#endif + +/* Define to allow pcretest and pcregrep to be linked with gcov, so that they + are able to generate code coverage reports. */ +#undef SUPPORT_GCOV /* Define to any value to enable support for Just-In-Time compiling. */ #define SUPPORT_JIT @@ -329,7 +404,7 @@ sure both macros are undefined; an emulation function will then be used. */ /* #undef SUPPORT_LIBBZ2 */ /* Define to any value to allow pcretest to be linked with libedit. */ -/* #undef SUPPORT_LIBEDIT */ +#undef SUPPORT_LIBEDIT /* Define to any value to allow pcretest to be linked with libreadline. */ /* #undef SUPPORT_LIBREADLINE */ @@ -348,23 +423,23 @@ sure both macros are undefined; an emulation function will then be used. */ /* #undef SUPPORT_PCRE8 */ /* Define to any value to enable JIT support in pcregrep. */ -#define SUPPORT_PCREGREP_JIT +/* #undef SUPPORT_PCREGREP_JIT */ -/* Define to any value to enable support for Unicode properties. */ +/* Define to enable support for Unicode properties */ /* #undef SUPPORT_UCP */ /* Define to any value to enable support for the UTF-8/16/32 Unicode encoding. This will work even in an EBCDIC environment, but it is incompatible with the EBCDIC macro. That is, PCRE can support *either* EBCDIC code *or* ASCII/UTF-8/16/32, but not both at once. */ -/* #undef SUPPORT_UTF */ +/* #undef SUPPORT_UTF8 */ -/* Define to any value for valgrind support to find invalid memory reads. */ +/* Valgrind support to find invalid memory reads. */ /* #undef SUPPORT_VALGRIND */ /* Version number of package */ #ifndef VERSION -#define VERSION "8.37" +#define VERSION "8.38" #endif /* Define to empty if `const' does not conform to ANSI C. */ @@ -376,4 +451,3 @@ sure both macros are undefined; an emulation function will then be used. */ /* Define to `unsigned int' if <sys/types.h> does not define. */ /* #undef size_t */ - diff --git a/ext/pcre/pcrelib/doc/pcre.txt b/ext/pcre/pcrelib/doc/pcre.txt index ce27f4b3e0..76a47c79ef 100644 --- a/ext/pcre/pcrelib/doc/pcre.txt +++ b/ext/pcre/pcrelib/doc/pcre.txt @@ -13,7 +13,18 @@ PCRE(3) Library Functions Manual PCRE(3) NAME - PCRE - Perl-compatible regular expressions + PCRE - Perl-compatible regular expressions (original API) + +PLEASE TAKE NOTE + + This document relates to PCRE releases that use the original API, with + library names libpcre, libpcre16, and libpcre32. January 2015 saw the + first release of a new API, known as PCRE2, with release numbers start- + ing at 10.00 and library names libpcre2-8, libpcre2-16, and + libpcre2-32. The old libraries (now called PCRE1) are still being main- + tained for bug fixes, but there will be no new development. New + projects are advised to use the new PCRE2 libraries. + INTRODUCTION @@ -179,8 +190,8 @@ AUTHOR REVISION - Last updated: 08 January 2014 - Copyright (c) 1997-2014 University of Cambridge. + Last updated: 10 February 2015 + Copyright (c) 1997-2015 University of Cambridge. ------------------------------------------------------------------------------ @@ -4989,7 +5000,8 @@ BACKSLASH appearance of non-printing characters, apart from the binary zero that terminates a pattern, but when a pattern is being prepared by text editing, it is often easier to use one of the following escape - sequences than the binary character it represents: + sequences than the binary character it represents. In an ASCII or Uni- + code environment, these escapes are as follows: \a alarm, that is, the BEL character (hex 07) \cx "control-x", where x is any ASCII character @@ -5005,55 +5017,67 @@ BACKSLASH \x{hhh..} character with hex code hhh.. (non-JavaScript mode) \uhhhh character with hex code hhhh (JavaScript mode only) - The precise effect of \cx on ASCII characters is as follows: if x is a - lower case letter, it is converted to upper case. Then bit 6 of the + The precise effect of \cx on ASCII characters is as follows: if x is a + lower case letter, it is converted to upper case. Then bit 6 of the character (hex 40) is inverted. Thus \cA to \cZ become hex 01 to hex 1A - (A is 41, Z is 5A), but \c{ becomes hex 3B ({ is 7B), and \c; becomes - hex 7B (; is 3B). If the data item (byte or 16-bit value) following \c - has a value greater than 127, a compile-time error occurs. This locks + (A is 41, Z is 5A), but \c{ becomes hex 3B ({ is 7B), and \c; becomes + hex 7B (; is 3B). If the data item (byte or 16-bit value) following \c + has a value greater than 127, a compile-time error occurs. This locks out non-ASCII characters in all modes. - The \c facility was designed for use with ASCII characters, but with - the extension to Unicode it is even less useful than it once was. It - is, however, recognized when PCRE is compiled in EBCDIC mode, where - data items are always bytes. In this mode, all values are valid after - \c. If the next character is a lower case letter, it is converted to - upper case. Then the 0xc0 bits of the byte are inverted. Thus \cA - becomes hex 01, as in ASCII (A is C1), but because the EBCDIC letters - are disjoint, \cZ becomes hex 29 (Z is E9), and other characters also - generate different values. - - After \0 up to two further octal digits are read. If there are fewer - than two digits, just those that are present are used. Thus the - sequence \0\x\07 specifies two binary zeros followed by a BEL character - (code value 7). Make sure you supply two digits after the initial zero + When PCRE is compiled in EBCDIC mode, \a, \e, \f, \n, \r, and \t gener- + ate the appropriate EBCDIC code values. The \c escape is processed as + specified for Perl in the perlebcdic document. The only characters that + are allowed after \c are A-Z, a-z, or one of @, [, \, ], ^, _, or ?. + Any other character provokes a compile-time error. The sequence \@ + encodes character code 0; the letters (in either case) encode charac- + ters 1-26 (hex 01 to hex 1A); [, \, ], ^, and _ encode characters 27-31 + (hex 1B to hex 1F), and \? becomes either 255 (hex FF) or 95 (hex 5F). + + Thus, apart from \?, these escapes generate the same character code + values as they do in an ASCII environment, though the meanings of the + values mostly differ. For example, \G always generates code value 7, + which is BEL in ASCII but DEL in EBCDIC. + + The sequence \? generates DEL (127, hex 7F) in an ASCII environment, + but because 127 is not a control character in EBCDIC, Perl makes it + generate the APC character. Unfortunately, there are several variants + of EBCDIC. In most of them the APC character has the value 255 (hex + FF), but in the one Perl calls POSIX-BC its value is 95 (hex 5F). If + certain other characters have POSIX-BC values, PCRE makes \? generate + 95; otherwise it generates 255. + + After \0 up to two further octal digits are read. If there are fewer + than two digits, just those that are present are used. Thus the + sequence \0\x\015 specifies two binary zeros followed by a CR character + (code value 13). Make sure you supply two digits after the initial zero if the pattern character that follows is itself an octal digit. - The escape \o must be followed by a sequence of octal digits, enclosed - in braces. An error occurs if this is not the case. This escape is a - recent addition to Perl; it provides way of specifying character code - points as octal numbers greater than 0777, and it also allows octal + The escape \o must be followed by a sequence of octal digits, enclosed + in braces. An error occurs if this is not the case. This escape is a + recent addition to Perl; it provides way of specifying character code + points as octal numbers greater than 0777, and it also allows octal numbers and back references to be unambiguously specified. For greater clarity and unambiguity, it is best to avoid following \ by a digit greater than zero. Instead, use \o{} or \x{} to specify charac- - ter numbers, and \g{} to specify back references. The following para- + ter numbers, and \g{} to specify back references. The following para- graphs describe the old, ambiguous syntax. The handling of a backslash followed by a digit other than 0 is compli- - cated, and Perl has changed in recent releases, causing PCRE also to + cated, and Perl has changed in recent releases, causing PCRE also to change. Outside a character class, PCRE reads the digit and any follow- - ing digits as a decimal number. If the number is less than 8, or if - there have been at least that many previous capturing left parentheses - in the expression, the entire sequence is taken as a back reference. A - description of how this works is given later, following the discussion + ing digits as a decimal number. If the number is less than 8, or if + there have been at least that many previous capturing left parentheses + in the expression, the entire sequence is taken as a back reference. A + description of how this works is given later, following the discussion of parenthesized subpatterns. - Inside a character class, or if the decimal number following \ is + Inside a character class, or if the decimal number following \ is greater than 7 and there have not been that many capturing subpatterns, - PCRE handles \8 and \9 as the literal characters "8" and "9", and oth- + PCRE handles \8 and \9 as the literal characters "8" and "9", and oth- erwise re-reads up to three octal digits following the backslash, using - them to generate a data character. Any subsequent digits stand for + them to generate a data character. Any subsequent digits stand for themselves. For example: \040 is another way of writing an ASCII space @@ -5071,31 +5095,31 @@ BACKSLASH \81 is either a back reference, or the two characters "8" and "1" - Note that octal values of 100 or greater that are specified using this - syntax must not be introduced by a leading zero, because no more than + Note that octal values of 100 or greater that are specified using this + syntax must not be introduced by a leading zero, because no more than three octal digits are ever read. - By default, after \x that is not followed by {, from zero to two hexa- - decimal digits are read (letters can be in upper or lower case). Any + By default, after \x that is not followed by {, from zero to two hexa- + decimal digits are read (letters can be in upper or lower case). Any number of hexadecimal digits may appear between \x{ and }. If a charac- - ter other than a hexadecimal digit appears between \x{ and }, or if + ter other than a hexadecimal digit appears between \x{ and }, or if there is no terminating }, an error occurs. - If the PCRE_JAVASCRIPT_COMPAT option is set, the interpretation of \x - is as just described only when it is followed by two hexadecimal dig- - its. Otherwise, it matches a literal "x" character. In JavaScript + If the PCRE_JAVASCRIPT_COMPAT option is set, the interpretation of \x + is as just described only when it is followed by two hexadecimal dig- + its. Otherwise, it matches a literal "x" character. In JavaScript mode, support for code points greater than 256 is provided by \u, which - must be followed by four hexadecimal digits; otherwise it matches a + must be followed by four hexadecimal digits; otherwise it matches a literal "u" character. Characters whose value is less than 256 can be defined by either of the - two syntaxes for \x (or by \u in JavaScript mode). There is no differ- + two syntaxes for \x (or by \u in JavaScript mode). There is no differ- ence in the way they are handled. For example, \xdc is exactly the same as \x{dc} (or \u00dc in JavaScript mode). Constraints on character values - Characters that are specified using octal or hexadecimal numbers are + Characters that are specified using octal or hexadecimal numbers are limited to certain values, as follows: 8-bit non-UTF mode less than 0x100 @@ -5105,44 +5129,44 @@ BACKSLASH 32-bit non-UTF mode less than 0x100000000 32-bit UTF-32 mode less than 0x10ffff and a valid codepoint - Invalid Unicode codepoints are the range 0xd800 to 0xdfff (the so- + Invalid Unicode codepoints are the range 0xd800 to 0xdfff (the so- called "surrogate" codepoints), and 0xffef. Escape sequences in character classes All the sequences that define a single character value can be used both - inside and outside character classes. In addition, inside a character + inside and outside character classes. In addition, inside a character class, \b is interpreted as the backspace character (hex 08). - \N is not allowed in a character class. \B, \R, and \X are not special - inside a character class. Like other unrecognized escape sequences, - they are treated as the literal characters "B", "R", and "X" by - default, but cause an error if the PCRE_EXTRA option is set. Outside a + \N is not allowed in a character class. \B, \R, and \X are not special + inside a character class. Like other unrecognized escape sequences, + they are treated as the literal characters "B", "R", and "X" by + default, but cause an error if the PCRE_EXTRA option is set. Outside a character class, these sequences have different meanings. Unsupported escape sequences - In Perl, the sequences \l, \L, \u, and \U are recognized by its string - handler and used to modify the case of following characters. By - default, PCRE does not support these escape sequences. However, if the - PCRE_JAVASCRIPT_COMPAT option is set, \U matches a "U" character, and + In Perl, the sequences \l, \L, \u, and \U are recognized by its string + handler and used to modify the case of following characters. By + default, PCRE does not support these escape sequences. However, if the + PCRE_JAVASCRIPT_COMPAT option is set, \U matches a "U" character, and \u can be used to define a character by code point, as described in the previous section. Absolute and relative back references - The sequence \g followed by an unsigned or a negative number, option- - ally enclosed in braces, is an absolute or relative back reference. A + The sequence \g followed by an unsigned or a negative number, option- + ally enclosed in braces, is an absolute or relative back reference. A named back reference can be coded as \g{name}. Back references are dis- cussed later, following the discussion of parenthesized subpatterns. Absolute and relative subroutine calls - For compatibility with Oniguruma, the non-Perl syntax \g followed by a + For compatibility with Oniguruma, the non-Perl syntax \g followed by a name or a number enclosed either in angle brackets or single quotes, is - an alternative syntax for referencing a subpattern as a "subroutine". - Details are discussed later. Note that \g{...} (Perl syntax) and - \g<...> (Oniguruma syntax) are not synonymous. The former is a back + an alternative syntax for referencing a subpattern as a "subroutine". + Details are discussed later. Note that \g{...} (Perl syntax) and + \g<...> (Oniguruma syntax) are not synonymous. The former is a back reference; the latter is a subroutine call. Generic character types @@ -5161,59 +5185,59 @@ BACKSLASH \W any "non-word" character There is also the single sequence \N, which matches a non-newline char- - acter. This is the same as the "." metacharacter when PCRE_DOTALL is - not set. Perl also uses \N to match characters by name; PCRE does not + acter. This is the same as the "." metacharacter when PCRE_DOTALL is + not set. Perl also uses \N to match characters by name; PCRE does not support this. - Each pair of lower and upper case escape sequences partitions the com- - plete set of characters into two disjoint sets. Any given character - matches one, and only one, of each pair. The sequences can appear both - inside and outside character classes. They each match one character of - the appropriate type. If the current matching point is at the end of - the subject string, all of them fail, because there is no character to + Each pair of lower and upper case escape sequences partitions the com- + plete set of characters into two disjoint sets. Any given character + matches one, and only one, of each pair. The sequences can appear both + inside and outside character classes. They each match one character of + the appropriate type. If the current matching point is at the end of + the subject string, all of them fail, because there is no character to match. - For compatibility with Perl, \s did not used to match the VT character - (code 11), which made it different from the the POSIX "space" class. - However, Perl added VT at release 5.18, and PCRE followed suit at - release 8.34. The default \s characters are now HT (9), LF (10), VT - (11), FF (12), CR (13), and space (32), which are defined as white + For compatibility with Perl, \s did not used to match the VT character + (code 11), which made it different from the the POSIX "space" class. + However, Perl added VT at release 5.18, and PCRE followed suit at + release 8.34. The default \s characters are now HT (9), LF (10), VT + (11), FF (12), CR (13), and space (32), which are defined as white space in the "C" locale. This list may vary if locale-specific matching - is taking place. For example, in some locales the "non-breaking space" - character (\xA0) is recognized as white space, and in others the VT + is taking place. For example, in some locales the "non-breaking space" + character (\xA0) is recognized as white space, and in others the VT character is not. - A "word" character is an underscore or any character that is a letter - or digit. By default, the definition of letters and digits is con- - trolled by PCRE's low-valued character tables, and may vary if locale- - specific matching is taking place (see "Locale support" in the pcreapi - page). For example, in a French locale such as "fr_FR" in Unix-like - systems, or "french" in Windows, some character codes greater than 127 - are used for accented letters, and these are then matched by \w. The + A "word" character is an underscore or any character that is a letter + or digit. By default, the definition of letters and digits is con- + trolled by PCRE's low-valued character tables, and may vary if locale- + specific matching is taking place (see "Locale support" in the pcreapi + page). For example, in a French locale such as "fr_FR" in Unix-like + systems, or "french" in Windows, some character codes greater than 127 + are used for accented letters, and these are then matched by \w. The use of locales with Unicode is discouraged. - By default, characters whose code points are greater than 127 never + By default, characters whose code points are greater than 127 never match \d, \s, or \w, and always match \D, \S, and \W, although this may - vary for characters in the range 128-255 when locale-specific matching - is happening. These escape sequences retain their original meanings - from before Unicode support was available, mainly for efficiency rea- - sons. If PCRE is compiled with Unicode property support, and the - PCRE_UCP option is set, the behaviour is changed so that Unicode prop- + vary for characters in the range 128-255 when locale-specific matching + is happening. These escape sequences retain their original meanings + from before Unicode support was available, mainly for efficiency rea- + sons. If PCRE is compiled with Unicode property support, and the + PCRE_UCP option is set, the behaviour is changed so that Unicode prop- erties are used to determine character types, as follows: \d any character that matches \p{Nd} (decimal digit) \s any character that matches \p{Z} or \h or \v \w any character that matches \p{L} or \p{N}, plus underscore - The upper case escapes match the inverse sets of characters. Note that - \d matches only decimal digits, whereas \w matches any Unicode digit, - as well as any Unicode letter, and underscore. Note also that PCRE_UCP - affects \b, and \B because they are defined in terms of \w and \W. + The upper case escapes match the inverse sets of characters. Note that + \d matches only decimal digits, whereas \w matches any Unicode digit, + as well as any Unicode letter, and underscore. Note also that PCRE_UCP + affects \b, and \B because they are defined in terms of \w and \W. Matching these sequences is noticeably slower when PCRE_UCP is set. - The sequences \h, \H, \v, and \V are features that were added to Perl - at release 5.10. In contrast to the other sequences, which match only - ASCII characters by default, these always match certain high-valued + The sequences \h, \H, \v, and \V are features that were added to Perl + at release 5.10. In contrast to the other sequences, which match only + ASCII characters by default, these always match certain high-valued code points, whether or not PCRE_UCP is set. The horizontal space char- acters are: @@ -5252,110 +5276,110 @@ BACKSLASH Newline sequences - Outside a character class, by default, the escape sequence \R matches - any Unicode newline sequence. In 8-bit non-UTF-8 mode \R is equivalent + Outside a character class, by default, the escape sequence \R matches + any Unicode newline sequence. In 8-bit non-UTF-8 mode \R is equivalent to the following: (?>\r\n|\n|\x0b|\f|\r|\x85) - This is an example of an "atomic group", details of which are given + This is an example of an "atomic group", details of which are given below. This particular group matches either the two-character sequence - CR followed by LF, or one of the single characters LF (linefeed, - U+000A), VT (vertical tab, U+000B), FF (form feed, U+000C), CR (car- - riage return, U+000D), or NEL (next line, U+0085). The two-character + CR followed by LF, or one of the single characters LF (linefeed, + U+000A), VT (vertical tab, U+000B), FF (form feed, U+000C), CR (car- + riage return, U+000D), or NEL (next line, U+0085). The two-character sequence is treated as a single unit that cannot be split. - In other modes, two additional characters whose codepoints are greater + In other modes, two additional characters whose codepoints are greater than 255 are added: LS (line separator, U+2028) and PS (paragraph sepa- - rator, U+2029). Unicode character property support is not needed for + rator, U+2029). Unicode character property support is not needed for these characters to be recognized. It is possible to restrict \R to match only CR, LF, or CRLF (instead of - the complete set of Unicode line endings) by setting the option + the complete set of Unicode line endings) by setting the option PCRE_BSR_ANYCRLF either at compile time or when the pattern is matched. (BSR is an abbrevation for "backslash R".) This can be made the default - when PCRE is built; if this is the case, the other behaviour can be - requested via the PCRE_BSR_UNICODE option. It is also possible to - specify these settings by starting a pattern string with one of the + when PCRE is built; if this is the case, the other behaviour can be + requested via the PCRE_BSR_UNICODE option. It is also possible to + specify these settings by starting a pattern string with one of the following sequences: (*BSR_ANYCRLF) CR, LF, or CRLF only (*BSR_UNICODE) any Unicode newline sequence These override the default and the options given to the compiling func- - tion, but they can themselves be overridden by options given to a - matching function. Note that these special settings, which are not - Perl-compatible, are recognized only at the very start of a pattern, - and that they must be in upper case. If more than one of them is - present, the last one is used. They can be combined with a change of + tion, but they can themselves be overridden by options given to a + matching function. Note that these special settings, which are not + Perl-compatible, are recognized only at the very start of a pattern, + and that they must be in upper case. If more than one of them is + present, the last one is used. They can be combined with a change of newline convention; for example, a pattern can start with: (*ANY)(*BSR_ANYCRLF) - They can also be combined with the (*UTF8), (*UTF16), (*UTF32), (*UTF) + They can also be combined with the (*UTF8), (*UTF16), (*UTF32), (*UTF) or (*UCP) special sequences. Inside a character class, \R is treated as - an unrecognized escape sequence, and so matches the letter "R" by + an unrecognized escape sequence, and so matches the letter "R" by default, but causes an error if PCRE_EXTRA is set. Unicode character properties When PCRE is built with Unicode character property support, three addi- - tional escape sequences that match characters with specific properties - are available. When in 8-bit non-UTF-8 mode, these sequences are of - course limited to testing characters whose codepoints are less than + tional escape sequences that match characters with specific properties + are available. When in 8-bit non-UTF-8 mode, these sequences are of + course limited to testing characters whose codepoints are less than 256, but they do work in this mode. The extra escape sequences are: \p{xx} a character with the xx property \P{xx} a character without the xx property \X a Unicode extended grapheme cluster - The property names represented by xx above are limited to the Unicode + The property names represented by xx above are limited to the Unicode script names, the general category properties, "Any", which matches any - character (including newline), and some special PCRE properties - (described in the next section). Other Perl properties such as "InMu- - sicalSymbols" are not currently supported by PCRE. Note that \P{Any} + character (including newline), and some special PCRE properties + (described in the next section). Other Perl properties such as "InMu- + sicalSymbols" are not currently supported by PCRE. Note that \P{Any} does not match any characters, so always causes a match failure. Sets of Unicode characters are defined as belonging to certain scripts. - A character from one of these sets can be matched using a script name. + A character from one of these sets can be matched using a script name. For example: \p{Greek} \P{Han} - Those that are not part of an identified script are lumped together as + Those that are not part of an identified script are lumped together as "Common". The current list of scripts is: - Arabic, Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak, Bengali, - Bopomofo, Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Car- + Arabic, Armenian, Avestan, Balinese, Bamum, Bassa_Vah, Batak, Bengali, + Bopomofo, Brahmi, Braille, Buginese, Buhid, Canadian_Aboriginal, Car- ian, Caucasian_Albanian, Chakma, Cham, Cherokee, Common, Coptic, Cunei- form, Cypriot, Cyrillic, Deseret, Devanagari, Duployan, Egyptian_Hiero- glyphs, Elbasan, Ethiopic, Georgian, Glagolitic, Gothic, Grantha, - Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, - Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscrip- - tional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li, - Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin, Lepcha, Limbu, Lin- - ear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani, Malayalam, Mandaic, - Manichaean, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive, - Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Myanmar, Nabataean, - New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_North_Arabian, + Greek, Gujarati, Gurmukhi, Han, Hangul, Hanunoo, Hebrew, Hiragana, + Imperial_Aramaic, Inherited, Inscriptional_Pahlavi, Inscrip- + tional_Parthian, Javanese, Kaithi, Kannada, Katakana, Kayah_Li, + Kharoshthi, Khmer, Khojki, Khudawadi, Lao, Latin, Lepcha, Limbu, Lin- + ear_A, Linear_B, Lisu, Lycian, Lydian, Mahajani, Malayalam, Mandaic, + Manichaean, Meetei_Mayek, Mende_Kikakui, Meroitic_Cursive, + Meroitic_Hieroglyphs, Miao, Modi, Mongolian, Mro, Myanmar, Nabataean, + New_Tai_Lue, Nko, Ogham, Ol_Chiki, Old_Italic, Old_North_Arabian, Old_Permic, Old_Persian, Old_South_Arabian, Old_Turkic, Oriya, Osmanya, Pahawh_Hmong, Palmyrene, Pau_Cin_Hau, Phags_Pa, Phoenician, - Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Sha- - vian, Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri, Syriac, - Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet, Takri, Tamil, Telugu, - Thaana, Thai, Tibetan, Tifinagh, Tirhuta, Ugaritic, Vai, Warang_Citi, + Psalter_Pahlavi, Rejang, Runic, Samaritan, Saurashtra, Sharada, Sha- + vian, Siddham, Sinhala, Sora_Sompeng, Sundanese, Syloti_Nagri, Syriac, + Tagalog, Tagbanwa, Tai_Le, Tai_Tham, Tai_Viet, Takri, Tamil, Telugu, + Thaana, Thai, Tibetan, Tifinagh, Tirhuta, Ugaritic, Vai, Warang_Citi, Yi. Each character has exactly one Unicode general category property, spec- - ified by a two-letter abbreviation. For compatibility with Perl, nega- - tion can be specified by including a circumflex between the opening - brace and the property name. For example, \p{^Lu} is the same as + ified by a two-letter abbreviation. For compatibility with Perl, nega- + tion can be specified by including a circumflex between the opening + brace and the property name. For example, \p{^Lu} is the same as \P{Lu}. If only one letter is specified with \p or \P, it includes all the gen- - eral category properties that start with that letter. In this case, in - the absence of negation, the curly brackets in the escape sequence are + eral category properties that start with that letter. In this case, in + the absence of negation, the curly brackets in the escape sequence are optional; these two examples have the same effect: \p{L} @@ -5407,73 +5431,73 @@ BACKSLASH Zp Paragraph separator Zs Space separator - The special property L& is also supported: it matches a character that - has the Lu, Ll, or Lt property, in other words, a letter that is not + The special property L& is also supported: it matches a character that + has the Lu, Ll, or Lt property, in other words, a letter that is not classified as a modifier or "other". - The Cs (Surrogate) property applies only to characters in the range - U+D800 to U+DFFF. Such characters are not valid in Unicode strings and - so cannot be tested by PCRE, unless UTF validity checking has been + The Cs (Surrogate) property applies only to characters in the range + U+D800 to U+DFFF. Such characters are not valid in Unicode strings and + so cannot be tested by PCRE, unless UTF validity checking has been turned off (see the discussion of PCRE_NO_UTF8_CHECK, - PCRE_NO_UTF16_CHECK and PCRE_NO_UTF32_CHECK in the pcreapi page). Perl + PCRE_NO_UTF16_CHECK and PCRE_NO_UTF32_CHECK in the pcreapi page). Perl does not support the Cs property. - The long synonyms for property names that Perl supports (such as - \p{Letter}) are not supported by PCRE, nor is it permitted to prefix + The long synonyms for property names that Perl supports (such as + \p{Letter}) are not supported by PCRE, nor is it permitted to prefix any of these properties with "Is". No character that is in the Unicode table has the Cn (unassigned) prop- erty. Instead, this property is assumed for any code point that is not in the Unicode table. - Specifying caseless matching does not affect these escape sequences. - For example, \p{Lu} always matches only upper case letters. This is + Specifying caseless matching does not affect these escape sequences. + For example, \p{Lu} always matches only upper case letters. This is different from the behaviour of current versions of Perl. - Matching characters by Unicode property is not fast, because PCRE has - to do a multistage table lookup in order to find a character's prop- + Matching characters by Unicode property is not fast, because PCRE has + to do a multistage table lookup in order to find a character's prop- erty. That is why the traditional escape sequences such as \d and \w do not use Unicode properties in PCRE by default, though you can make them - do so by setting the PCRE_UCP option or by starting the pattern with + do so by setting the PCRE_UCP option or by starting the pattern with (*UCP). Extended grapheme clusters - The \X escape matches any number of Unicode characters that form an + The \X escape matches any number of Unicode characters that form an "extended grapheme cluster", and treats the sequence as an atomic group - (see below). Up to and including release 8.31, PCRE matched an ear- + (see below). Up to and including release 8.31, PCRE matched an ear- lier, simpler definition that was equivalent to (?>\PM\pM*) - That is, it matched a character without the "mark" property, followed - by zero or more characters with the "mark" property. Characters with - the "mark" property are typically non-spacing accents that affect the + That is, it matched a character without the "mark" property, followed + by zero or more characters with the "mark" property. Characters with + the "mark" property are typically non-spacing accents that affect the preceding character. - This simple definition was extended in Unicode to include more compli- - cated kinds of composite character by giving each character a grapheme - breaking property, and creating rules that use these properties to - define the boundaries of extended grapheme clusters. In releases of + This simple definition was extended in Unicode to include more compli- + cated kinds of composite character by giving each character a grapheme + breaking property, and creating rules that use these properties to + define the boundaries of extended grapheme clusters. In releases of PCRE later than 8.31, \X matches one of these clusters. - \X always matches at least one character. Then it decides whether to + \X always matches at least one character. Then it decides whether to add additional characters according to the following rules for ending a cluster: 1. End at the end of the subject string. - 2. Do not end between CR and LF; otherwise end after any control char- + 2. Do not end between CR and LF; otherwise end after any control char- acter. - 3. Do not break Hangul (a Korean script) syllable sequences. Hangul - characters are of five types: L, V, T, LV, and LVT. An L character may - be followed by an L, V, LV, or LVT character; an LV or V character may + 3. Do not break Hangul (a Korean script) syllable sequences. Hangul + characters are of five types: L, V, T, LV, and LVT. An L character may + be followed by an L, V, LV, or LVT character; an LV or V character may be followed by a V or T character; an LVT or T character may be follwed only by a T character. - 4. Do not end before extending characters or spacing marks. Characters - with the "mark" property always have the "extend" grapheme breaking + 4. Do not end before extending characters or spacing marks. Characters + with the "mark" property always have the "extend" grapheme breaking property. 5. Do not end after prepend characters. @@ -5482,9 +5506,9 @@ BACKSLASH PCRE's additional properties - As well as the standard Unicode properties described above, PCRE sup- - ports four more that make it possible to convert traditional escape - sequences such as \w and \s to use Unicode properties. PCRE uses these + As well as the standard Unicode properties described above, PCRE sup- + ports four more that make it possible to convert traditional escape + sequences such as \w and \s to use Unicode properties. PCRE uses these non-standard, non-Perl properties internally when PCRE_UCP is set. How- ever, they may also be used explicitly. These properties are: @@ -5493,54 +5517,54 @@ BACKSLASH Xsp Any Perl space character Xwd Any Perl "word" character - Xan matches characters that have either the L (letter) or the N (num- - ber) property. Xps matches the characters tab, linefeed, vertical tab, - form feed, or carriage return, and any other character that has the Z - (separator) property. Xsp is the same as Xps; it used to exclude ver- - tical tab, for Perl compatibility, but Perl changed, and so PCRE fol- - lowed at release 8.34. Xwd matches the same characters as Xan, plus + Xan matches characters that have either the L (letter) or the N (num- + ber) property. Xps matches the characters tab, linefeed, vertical tab, + form feed, or carriage return, and any other character that has the Z + (separator) property. Xsp is the same as Xps; it used to exclude ver- + tical tab, for Perl compatibility, but Perl changed, and so PCRE fol- + lowed at release 8.34. Xwd matches the same characters as Xan, plus underscore. - There is another non-standard property, Xuc, which matches any charac- - ter that can be represented by a Universal Character Name in C++ and - other programming languages. These are the characters $, @, ` (grave - accent), and all characters with Unicode code points greater than or - equal to U+00A0, except for the surrogates U+D800 to U+DFFF. Note that - most base (ASCII) characters are excluded. (Universal Character Names - are of the form \uHHHH or \UHHHHHHHH where H is a hexadecimal digit. + There is another non-standard property, Xuc, which matches any charac- + ter that can be represented by a Universal Character Name in C++ and + other programming languages. These are the characters $, @, ` (grave + accent), and all characters with Unicode code points greater than or + equal to U+00A0, except for the surrogates U+D800 to U+DFFF. Note that + most base (ASCII) characters are excluded. (Universal Character Names + are of the form \uHHHH or \UHHHHHHHH where H is a hexadecimal digit. Note that the Xuc property does not match these sequences but the char- acters that they represent.) Resetting the match start - The escape sequence \K causes any previously matched characters not to + The escape sequence \K causes any previously matched characters not to be included in the final matched sequence. For example, the pattern: foo\Kbar - matches "foobar", but reports that it has matched "bar". This feature - is similar to a lookbehind assertion (described below). However, in - this case, the part of the subject before the real match does not have - to be of fixed length, as lookbehind assertions do. The use of \K does - not interfere with the setting of captured substrings. For example, + matches "foobar", but reports that it has matched "bar". This feature + is similar to a lookbehind assertion (described below). However, in + this case, the part of the subject before the real match does not have + to be of fixed length, as lookbehind assertions do. The use of \K does + not interfere with the setting of captured substrings. For example, when the pattern (foo)\Kbar matches "foobar", the first substring is still set to "foo". - Perl documents that the use of \K within assertions is "not well - defined". In PCRE, \K is acted upon when it occurs inside positive - assertions, but is ignored in negative assertions. Note that when a - pattern such as (?=ab\K) matches, the reported start of the match can + Perl documents that the use of \K within assertions is "not well + defined". In PCRE, \K is acted upon when it occurs inside positive + assertions, but is ignored in negative assertions. Note that when a + pattern such as (?=ab\K) matches, the reported start of the match can be greater than the end of the match. Simple assertions - The final use of backslash is for certain simple assertions. An asser- - tion specifies a condition that has to be met at a particular point in - a match, without consuming any characters from the subject string. The - use of subpatterns for more complicated assertions is described below. + The final use of backslash is for certain simple assertions. An asser- + tion specifies a condition that has to be met at a particular point in + a match, without consuming any characters from the subject string. The + use of subpatterns for more complicated assertions is described below. The backslashed assertions are: \b matches at a word boundary @@ -5551,161 +5575,161 @@ BACKSLASH \z matches only at the end of the subject \G matches at the first matching position in the subject - Inside a character class, \b has a different meaning; it matches the - backspace character. If any other of these assertions appears in a - character class, by default it matches the corresponding literal char- + Inside a character class, \b has a different meaning; it matches the + backspace character. If any other of these assertions appears in a + character class, by default it matches the corresponding literal char- acter (for example, \B matches the letter B). However, if the - PCRE_EXTRA option is set, an "invalid escape sequence" error is gener- + PCRE_EXTRA option is set, an "invalid escape sequence" error is gener- ated instead. - A word boundary is a position in the subject string where the current - character and the previous character do not both match \w or \W (i.e. - one matches \w and the other matches \W), or the start or end of the - string if the first or last character matches \w, respectively. In a - UTF mode, the meanings of \w and \W can be changed by setting the - PCRE_UCP option. When this is done, it also affects \b and \B. Neither - PCRE nor Perl has a separate "start of word" or "end of word" metase- - quence. However, whatever follows \b normally determines which it is. + A word boundary is a position in the subject string where the current + character and the previous character do not both match \w or \W (i.e. + one matches \w and the other matches \W), or the start or end of the + string if the first or last character matches \w, respectively. In a + UTF mode, the meanings of \w and \W can be changed by setting the + PCRE_UCP option. When this is done, it also affects \b and \B. Neither + PCRE nor Perl has a separate "start of word" or "end of word" metase- + quence. However, whatever follows \b normally determines which it is. For example, the fragment \ba matches "a" at the start of a word. - The \A, \Z, and \z assertions differ from the traditional circumflex + The \A, \Z, and \z assertions differ from the traditional circumflex and dollar (described in the next section) in that they only ever match - at the very start and end of the subject string, whatever options are - set. Thus, they are independent of multiline mode. These three asser- + at the very start and end of the subject string, whatever options are + set. Thus, they are independent of multiline mode. These three asser- tions are not affected by the PCRE_NOTBOL or PCRE_NOTEOL options, which - affect only the behaviour of the circumflex and dollar metacharacters. - However, if the startoffset argument of pcre_exec() is non-zero, indi- + affect only the behaviour of the circumflex and dollar metacharacters. + However, if the startoffset argument of pcre_exec() is non-zero, indi- cating that matching is to start at a point other than the beginning of - the subject, \A can never match. The difference between \Z and \z is + the subject, \A can never match. The difference between \Z and \z is that \Z matches before a newline at the end of the string as well as at the very end, whereas \z matches only at the end. - The \G assertion is true only when the current matching position is at - the start point of the match, as specified by the startoffset argument - of pcre_exec(). It differs from \A when the value of startoffset is - non-zero. By calling pcre_exec() multiple times with appropriate argu- + The \G assertion is true only when the current matching position is at + the start point of the match, as specified by the startoffset argument + of pcre_exec(). It differs from \A when the value of startoffset is + non-zero. By calling pcre_exec() multiple times with appropriate argu- ments, you can mimic Perl's /g option, and it is in this kind of imple- mentation where \G can be useful. - Note, however, that PCRE's interpretation of \G, as the start of the + Note, however, that PCRE's interpretation of \G, as the start of the current match, is subtly different from Perl's, which defines it as the - end of the previous match. In Perl, these can be different when the - previously matched string was empty. Because PCRE does just one match + end of the previous match. In Perl, these can be different when the + previously matched string was empty. Because PCRE does just one match at a time, it cannot reproduce this behaviour. - If all the alternatives of a pattern begin with \G, the expression is + If all the alternatives of a pattern begin with \G, the expression is anchored to the starting match position, and the "anchored" flag is set in the compiled regular expression. CIRCUMFLEX AND DOLLAR - The circumflex and dollar metacharacters are zero-width assertions. - That is, they test for a particular condition being true without con- + The circumflex and dollar metacharacters are zero-width assertions. + That is, they test for a particular condition being true without con- suming any characters from the subject string. Outside a character class, in the default matching mode, the circumflex - character is an assertion that is true only if the current matching - point is at the start of the subject string. If the startoffset argu- - ment of pcre_exec() is non-zero, circumflex can never match if the - PCRE_MULTILINE option is unset. Inside a character class, circumflex + character is an assertion that is true only if the current matching + point is at the start of the subject string. If the startoffset argu- + ment of pcre_exec() is non-zero, circumflex can never match if the + PCRE_MULTILINE option is unset. Inside a character class, circumflex has an entirely different meaning (see below). - Circumflex need not be the first character of the pattern if a number - of alternatives are involved, but it should be the first thing in each - alternative in which it appears if the pattern is ever to match that - branch. If all possible alternatives start with a circumflex, that is, - if the pattern is constrained to match only at the start of the sub- - ject, it is said to be an "anchored" pattern. (There are also other + Circumflex need not be the first character of the pattern if a number + of alternatives are involved, but it should be the first thing in each + alternative in which it appears if the pattern is ever to match that + branch. If all possible alternatives start with a circumflex, that is, + if the pattern is constrained to match only at the start of the sub- + ject, it is said to be an "anchored" pattern. (There are also other constructs that can cause a pattern to be anchored.) - The dollar character is an assertion that is true only if the current - matching point is at the end of the subject string, or immediately - before a newline at the end of the string (by default). Note, however, - that it does not actually match the newline. Dollar need not be the + The dollar character is an assertion that is true only if the current + matching point is at the end of the subject string, or immediately + before a newline at the end of the string (by default). Note, however, + that it does not actually match the newline. Dollar need not be the last character of the pattern if a number of alternatives are involved, - but it should be the last item in any branch in which it appears. Dol- + but it should be the last item in any branch in which it appears. Dol- lar has no special meaning in a character class. - The meaning of dollar can be changed so that it matches only at the - very end of the string, by setting the PCRE_DOLLAR_ENDONLY option at + The meaning of dollar can be changed so that it matches only at the + very end of the string, by setting the PCRE_DOLLAR_ENDONLY option at compile time. This does not affect the \Z assertion. The meanings of the circumflex and dollar characters are changed if the - PCRE_MULTILINE option is set. When this is the case, a circumflex - matches immediately after internal newlines as well as at the start of - the subject string. It does not match after a newline that ends the - string. A dollar matches before any newlines in the string, as well as - at the very end, when PCRE_MULTILINE is set. When newline is specified - as the two-character sequence CRLF, isolated CR and LF characters do + PCRE_MULTILINE option is set. When this is the case, a circumflex + matches immediately after internal newlines as well as at the start of + the subject string. It does not match after a newline that ends the + string. A dollar matches before any newlines in the string, as well as + at the very end, when PCRE_MULTILINE is set. When newline is specified + as the two-character sequence CRLF, isolated CR and LF characters do not indicate newlines. - For example, the pattern /^abc$/ matches the subject string "def\nabc" - (where \n represents a newline) in multiline mode, but not otherwise. - Consequently, patterns that are anchored in single line mode because - all branches start with ^ are not anchored in multiline mode, and a - match for circumflex is possible when the startoffset argument of - pcre_exec() is non-zero. The PCRE_DOLLAR_ENDONLY option is ignored if + For example, the pattern /^abc$/ matches the subject string "def\nabc" + (where \n represents a newline) in multiline mode, but not otherwise. + Consequently, patterns that are anchored in single line mode because + all branches start with ^ are not anchored in multiline mode, and a + match for circumflex is possible when the startoffset argument of + pcre_exec() is non-zero. The PCRE_DOLLAR_ENDONLY option is ignored if PCRE_MULTILINE is set. - Note that the sequences \A, \Z, and \z can be used to match the start - and end of the subject in both modes, and if all branches of a pattern - start with \A it is always anchored, whether or not PCRE_MULTILINE is + Note that the sequences \A, \Z, and \z can be used to match the start + and end of the subject in both modes, and if all branches of a pattern + start with \A it is always anchored, whether or not PCRE_MULTILINE is set. FULL STOP (PERIOD, DOT) AND \N Outside a character class, a dot in the pattern matches any one charac- - ter in the subject string except (by default) a character that signi- + ter in the subject string except (by default) a character that signi- fies the end of a line. - When a line ending is defined as a single character, dot never matches - that character; when the two-character sequence CRLF is used, dot does - not match CR if it is immediately followed by LF, but otherwise it - matches all characters (including isolated CRs and LFs). When any Uni- - code line endings are being recognized, dot does not match CR or LF or + When a line ending is defined as a single character, dot never matches + that character; when the two-character sequence CRLF is used, dot does + not match CR if it is immediately followed by LF, but otherwise it + matches all characters (including isolated CRs and LFs). When any Uni- + code line endings are being recognized, dot does not match CR or LF or any of the other line ending characters. - The behaviour of dot with regard to newlines can be changed. If the - PCRE_DOTALL option is set, a dot matches any one character, without + The behaviour of dot with regard to newlines can be changed. If the + PCRE_DOTALL option is set, a dot matches any one character, without exception. If the two-character sequence CRLF is present in the subject string, it takes two dots to match it. - The handling of dot is entirely independent of the handling of circum- - flex and dollar, the only relationship being that they both involve + The handling of dot is entirely independent of the handling of circum- + flex and dollar, the only relationship being that they both involve newlines. Dot has no special meaning in a character class. - The escape sequence \N behaves like a dot, except that it is not - affected by the PCRE_DOTALL option. In other words, it matches any - character except one that signifies the end of a line. Perl also uses + The escape sequence \N behaves like a dot, except that it is not + affected by the PCRE_DOTALL option. In other words, it matches any + character except one that signifies the end of a line. Perl also uses \N to match characters by name; PCRE does not support this. MATCHING A SINGLE DATA UNIT - Outside a character class, the escape sequence \C matches any one data - unit, whether or not a UTF mode is set. In the 8-bit library, one data - unit is one byte; in the 16-bit library it is a 16-bit unit; in the - 32-bit library it is a 32-bit unit. Unlike a dot, \C always matches - line-ending characters. The feature is provided in Perl in order to + Outside a character class, the escape sequence \C matches any one data + unit, whether or not a UTF mode is set. In the 8-bit library, one data + unit is one byte; in the 16-bit library it is a 16-bit unit; in the + 32-bit library it is a 32-bit unit. Unlike a dot, \C always matches + line-ending characters. The feature is provided in Perl in order to match individual bytes in UTF-8 mode, but it is unclear how it can use- - fully be used. Because \C breaks up characters into individual data - units, matching one unit with \C in a UTF mode means that the rest of + fully be used. Because \C breaks up characters into individual data + units, matching one unit with \C in a UTF mode means that the rest of the string may start with a malformed UTF character. This has undefined results, because PCRE assumes that it is dealing with valid UTF strings - (and by default it checks this at the start of processing unless the - PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK or PCRE_NO_UTF32_CHECK option + (and by default it checks this at the start of processing unless the + PCRE_NO_UTF8_CHECK, PCRE_NO_UTF16_CHECK or PCRE_NO_UTF32_CHECK option is used). - PCRE does not allow \C to appear in lookbehind assertions (described - below) in a UTF mode, because this would make it impossible to calcu- + PCRE does not allow \C to appear in lookbehind assertions (described + below) in a UTF mode, because this would make it impossible to calcu- late the length of the lookbehind. In general, the \C escape sequence is best avoided. However, one way of - using it that avoids the problem of malformed UTF characters is to use - a lookahead to check the length of the next character, as in this pat- - tern, which could be used with a UTF-8 string (ignore white space and + using it that avoids the problem of malformed UTF characters is to use + a lookahead to check the length of the next character, as in this pat- + tern, which could be used with a UTF-8 string (ignore white space and line breaks): (?| (?=[\x00-\x7f])(\C) | @@ -5713,11 +5737,11 @@ MATCHING A SINGLE DATA UNIT (?=[\x{800}-\x{ffff}])(\C)(\C)(\C) | (?=[\x{10000}-\x{1fffff}])(\C)(\C)(\C)(\C)) - A group that starts with (?| resets the capturing parentheses numbers - in each alternative (see "Duplicate Subpattern Numbers" below). The - assertions at the start of each branch check the next UTF-8 character - for values whose encoding uses 1, 2, 3, or 4 bytes, respectively. The - character's individual bytes are then captured by the appropriate num- + A group that starts with (?| resets the capturing parentheses numbers + in each alternative (see "Duplicate Subpattern Numbers" below). The + assertions at the start of each branch check the next UTF-8 character + for values whose encoding uses 1, 2, 3, or 4 bytes, respectively. The + character's individual bytes are then captured by the appropriate num- ber of groups. @@ -5727,109 +5751,109 @@ SQUARE BRACKETS AND CHARACTER CLASSES closing square bracket. A closing square bracket on its own is not spe- cial by default. However, if the PCRE_JAVASCRIPT_COMPAT option is set, a lone closing square bracket causes a compile-time error. If a closing - square bracket is required as a member of the class, it should be the - first data character in the class (after an initial circumflex, if + square bracket is required as a member of the class, it should be the + first data character in the class (after an initial circumflex, if present) or escaped with a backslash. - A character class matches a single character in the subject. In a UTF - mode, the character may be more than one data unit long. A matched + A character class matches a single character in the subject. In a UTF + mode, the character may be more than one data unit long. A matched character must be in the set of characters defined by the class, unless - the first character in the class definition is a circumflex, in which + the first character in the class definition is a circumflex, in which case the subject character must not be in the set defined by the class. - If a circumflex is actually required as a member of the class, ensure + If a circumflex is actually required as a member of the class, ensure it is not the first character, or escape it with a backslash. - For example, the character class [aeiou] matches any lower case vowel, - while [^aeiou] matches any character that is not a lower case vowel. + For example, the character class [aeiou] matches any lower case vowel, + while [^aeiou] matches any character that is not a lower case vowel. Note that a circumflex is just a convenient notation for specifying the - characters that are in the class by enumerating those that are not. A - class that starts with a circumflex is not an assertion; it still con- - sumes a character from the subject string, and therefore it fails if + characters that are in the class by enumerating those that are not. A + class that starts with a circumflex is not an assertion; it still con- + sumes a character from the subject string, and therefore it fails if the current pointer is at the end of the string. In UTF-8 (UTF-16, UTF-32) mode, characters with values greater than 255 - (0xffff) can be included in a class as a literal string of data units, + (0xffff) can be included in a class as a literal string of data units, or by using the \x{ escaping mechanism. - When caseless matching is set, any letters in a class represent both - their upper case and lower case versions, so for example, a caseless - [aeiou] matches "A" as well as "a", and a caseless [^aeiou] does not - match "A", whereas a caseful version would. In a UTF mode, PCRE always - understands the concept of case for characters whose values are less - than 128, so caseless matching is always possible. For characters with - higher values, the concept of case is supported if PCRE is compiled - with Unicode property support, but not otherwise. If you want to use - caseless matching in a UTF mode for characters 128 and above, you must - ensure that PCRE is compiled with Unicode property support as well as + When caseless matching is set, any letters in a class represent both + their upper case and lower case versions, so for example, a caseless + [aeiou] matches "A" as well as "a", and a caseless [^aeiou] does not + match "A", whereas a caseful version would. In a UTF mode, PCRE always + understands the concept of case for characters whose values are less + than 128, so caseless matching is always possible. For characters with + higher values, the concept of case is supported if PCRE is compiled + with Unicode property support, but not otherwise. If you want to use + caseless matching in a UTF mode for characters 128 and above, you must + ensure that PCRE is compiled with Unicode property support as well as with UTF support. - Characters that might indicate line breaks are never treated in any - special way when matching character classes, whatever line-ending - sequence is in use, and whatever setting of the PCRE_DOTALL and + Characters that might indicate line breaks are never treated in any + special way when matching character classes, whatever line-ending + sequence is in use, and whatever setting of the PCRE_DOTALL and PCRE_MULTILINE options is used. A class such as [^a] always matches one of these characters. - The minus (hyphen) character can be used to specify a range of charac- - ters in a character class. For example, [d-m] matches any letter - between d and m, inclusive. If a minus character is required in a - class, it must be escaped with a backslash or appear in a position - where it cannot be interpreted as indicating a range, typically as the + The minus (hyphen) character can be used to specify a range of charac- + ters in a character class. For example, [d-m] matches any letter + between d and m, inclusive. If a minus character is required in a + class, it must be escaped with a backslash or appear in a position + where it cannot be interpreted as indicating a range, typically as the first or last character in the class, or immediately after a range. For - example, [b-d-z] matches letters in the range b to d, a hyphen charac- + example, [b-d-z] matches letters in the range b to d, a hyphen charac- ter, or z. It is not possible to have the literal character "]" as the end charac- - ter of a range. A pattern such as [W-]46] is interpreted as a class of - two characters ("W" and "-") followed by a literal string "46]", so it - would match "W46]" or "-46]". However, if the "]" is escaped with a - backslash it is interpreted as the end of range, so [W-\]46] is inter- - preted as a class containing a range followed by two other characters. - The octal or hexadecimal representation of "]" can also be used to end + ter of a range. A pattern such as [W-]46] is interpreted as a class of + two characters ("W" and "-") followed by a literal string "46]", so it + would match "W46]" or "-46]". However, if the "]" is escaped with a + backslash it is interpreted as the end of range, so [W-\]46] is inter- + preted as a class containing a range followed by two other characters. + The octal or hexadecimal representation of "]" can also be used to end a range. - An error is generated if a POSIX character class (see below) or an - escape sequence other than one that defines a single character appears - at a point where a range ending character is expected. For example, + An error is generated if a POSIX character class (see below) or an + escape sequence other than one that defines a single character appears + at a point where a range ending character is expected. For example, [z-\xff] is valid, but [A-\d] and [A-[:digit:]] are not. - Ranges operate in the collating sequence of character values. They can - also be used for characters specified numerically, for example - [\000-\037]. Ranges can include any characters that are valid for the + Ranges operate in the collating sequence of character values. They can + also be used for characters specified numerically, for example + [\000-\037]. Ranges can include any characters that are valid for the current mode. If a range that includes letters is used when caseless matching is set, it matches the letters in either case. For example, [W-c] is equivalent - to [][\\^_`wxyzabc], matched caselessly, and in a non-UTF mode, if - character tables for a French locale are in use, [\xc8-\xcb] matches - accented E characters in both cases. In UTF modes, PCRE supports the - concept of case for characters with values greater than 128 only when + to [][\\^_`wxyzabc], matched caselessly, and in a non-UTF mode, if + character tables for a French locale are in use, [\xc8-\xcb] matches + accented E characters in both cases. In UTF modes, PCRE supports the + concept of case for characters with values greater than 128 only when it is compiled with Unicode property support. - The character escape sequences \d, \D, \h, \H, \p, \P, \s, \S, \v, \V, + The character escape sequences \d, \D, \h, \H, \p, \P, \s, \S, \v, \V, \w, and \W may appear in a character class, and add the characters that - they match to the class. For example, [\dABCDEF] matches any hexadeci- - mal digit. In UTF modes, the PCRE_UCP option affects the meanings of - \d, \s, \w and their upper case partners, just as it does when they - appear outside a character class, as described in the section entitled + they match to the class. For example, [\dABCDEF] matches any hexadeci- + mal digit. In UTF modes, the PCRE_UCP option affects the meanings of + \d, \s, \w and their upper case partners, just as it does when they + appear outside a character class, as described in the section entitled "Generic character types" above. The escape sequence \b has a different - meaning inside a character class; it matches the backspace character. - The sequences \B, \N, \R, and \X are not special inside a character - class. Like any other unrecognized escape sequences, they are treated - as the literal characters "B", "N", "R", and "X" by default, but cause + meaning inside a character class; it matches the backspace character. + The sequences \B, \N, \R, and \X are not special inside a character + class. Like any other unrecognized escape sequences, they are treated + as the literal characters "B", "N", "R", and "X" by default, but cause an error if the PCRE_EXTRA option is set. - A circumflex can conveniently be used with the upper case character - types to specify a more restricted set of characters than the matching - lower case type. For example, the class [^\W_] matches any letter or + A circumflex can conveniently be used with the upper case character + types to specify a more restricted set of characters than the matching + lower case type. For example, the class [^\W_] matches any letter or digit, but not underscore, whereas [\w] includes underscore. A positive character class should be read as "something OR something OR ..." and a negative class as "NOT something AND NOT something AND NOT ...". - The only metacharacters that are recognized in character classes are - backslash, hyphen (only where it can be interpreted as specifying a - range), circumflex (only at the start), opening square bracket (only - when it can be interpreted as introducing a POSIX class name, or for a - special compatibility feature - see the next two sections), and the + The only metacharacters that are recognized in character classes are + backslash, hyphen (only where it can be interpreted as specifying a + range), circumflex (only at the start), opening square bracket (only + when it can be interpreted as introducing a POSIX class name, or for a + special compatibility feature - see the next two sections), and the terminating closing square bracket. However, escaping other non- alphanumeric characters does no harm. @@ -5837,7 +5861,7 @@ SQUARE BRACKETS AND CHARACTER CLASSES POSIX CHARACTER CLASSES Perl supports the POSIX notation for character classes. This uses names - enclosed by [: and :] within the enclosing square brackets. PCRE also + enclosed by [: and :] within the enclosing square brackets. PCRE also supports this notation. For example, [01[:alpha:]%] @@ -5860,28 +5884,28 @@ POSIX CHARACTER CLASSES word "word" characters (same as \w) xdigit hexadecimal digits - The default "space" characters are HT (9), LF (10), VT (11), FF (12), - CR (13), and space (32). If locale-specific matching is taking place, - the list of space characters may be different; there may be fewer or + The default "space" characters are HT (9), LF (10), VT (11), FF (12), + CR (13), and space (32). If locale-specific matching is taking place, + the list of space characters may be different; there may be fewer or more of them. "Space" used to be different to \s, which did not include VT, for Perl compatibility. However, Perl changed at release 5.18, and - PCRE followed at release 8.34. "Space" and \s now match the same set + PCRE followed at release 8.34. "Space" and \s now match the same set of characters. - The name "word" is a Perl extension, and "blank" is a GNU extension - from Perl 5.8. Another Perl extension is negation, which is indicated + The name "word" is a Perl extension, and "blank" is a GNU extension + from Perl 5.8. Another Perl extension is negation, which is indicated by a ^ character after the colon. For example, [12[:^digit:]] - matches "1", "2", or any non-digit. PCRE (and Perl) also recognize the + matches "1", "2", or any non-digit. PCRE (and Perl) also recognize the POSIX syntax [.ch.] and [=ch=] where "ch" is a "collating element", but these are not supported, and an error is given if they are encountered. By default, characters with values greater than 128 do not match any of - the POSIX character classes. However, if the PCRE_UCP option is passed - to pcre_compile(), some of the classes are changed so that Unicode - character properties are used. This is achieved by replacing certain + the POSIX character classes. However, if the PCRE_UCP option is passed + to pcre_compile(), some of the classes are changed so that Unicode + character properties are used. This is achieved by replacing certain POSIX classes by other sequences, as follows: [:alnum:] becomes \p{Xan} @@ -5893,10 +5917,10 @@ POSIX CHARACTER CLASSES [:upper:] becomes \p{Lu} [:word:] becomes \p{Xwd} - Negated versions, such as [:^alpha:] use \P instead of \p. Three other + Negated versions, such as [:^alpha:] use \P instead of \p. Three other POSIX classes are handled specially in UCP mode: - [:graph:] This matches characters that have glyphs that mark the page + [:graph:] This matches characters that have glyphs that mark the page when printed. In Unicode property terms, it matches all char- acters with the L, M, N, P, S, or Cf properties, except for: @@ -5905,58 +5929,58 @@ POSIX CHARACTER CLASSES U+2066 - U+2069 Various "isolate"s - [:print:] This matches the same characters as [:graph:] plus space - characters that are not controls, that is, characters with + [:print:] This matches the same characters as [:graph:] plus space + characters that are not controls, that is, characters with the Zs property. [:punct:] This matches all characters that have the Unicode P (punctua- - tion) property, plus those characters whose code points are + tion) property, plus those characters whose code points are less than 128 that have the S (Symbol) property. - The other POSIX classes are unchanged, and match only characters with + The other POSIX classes are unchanged, and match only characters with code points less than 128. COMPATIBILITY FEATURE FOR WORD BOUNDARIES - In the POSIX.2 compliant library that was included in 4.4BSD Unix, the - ugly syntax [[:<:]] and [[:>:]] is used for matching "start of word" + In the POSIX.2 compliant library that was included in 4.4BSD Unix, the + ugly syntax [[:<:]] and [[:>:]] is used for matching "start of word" and "end of word". PCRE treats these items as follows: [[:<:]] is converted to \b(?=\w) [[:>:]] is converted to \b(?<=\w) Only these exact character sequences are recognized. A sequence such as - [a[:<:]b] provokes error for an unrecognized POSIX class name. This - support is not compatible with Perl. It is provided to help migrations + [a[:<:]b] provokes error for an unrecognized POSIX class name. This + support is not compatible with Perl. It is provided to help migrations from other environments, and is best not used in any new patterns. Note - that \b matches at the start and the end of a word (see "Simple asser- - tions" above), and in a Perl-style pattern the preceding or following - character normally shows which is wanted, without the need for the - assertions that are used above in order to give exactly the POSIX be- + that \b matches at the start and the end of a word (see "Simple asser- + tions" above), and in a Perl-style pattern the preceding or following + character normally shows which is wanted, without the need for the + assertions that are used above in order to give exactly the POSIX be- haviour. VERTICAL BAR - Vertical bar characters are used to separate alternative patterns. For + Vertical bar characters are used to separate alternative patterns. For example, the pattern gilbert|sullivan - matches either "gilbert" or "sullivan". Any number of alternatives may - appear, and an empty alternative is permitted (matching the empty + matches either "gilbert" or "sullivan". Any number of alternatives may + appear, and an empty alternative is permitted (matching the empty string). The matching process tries each alternative in turn, from left - to right, and the first one that succeeds is used. If the alternatives - are within a subpattern (defined below), "succeeds" means matching the + to right, and the first one that succeeds is used. If the alternatives + are within a subpattern (defined below), "succeeds" means matching the rest of the main pattern as well as the alternative in the subpattern. INTERNAL OPTION SETTING - The settings of the PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL, and - PCRE_EXTENDED options (which are Perl-compatible) can be changed from - within the pattern by a sequence of Perl option letters enclosed + The settings of the PCRE_CASELESS, PCRE_MULTILINE, PCRE_DOTALL, and + PCRE_EXTENDED options (which are Perl-compatible) can be changed from + within the pattern by a sequence of Perl option letters enclosed between "(?" and ")". The option letters are i for PCRE_CASELESS @@ -5966,51 +5990,51 @@ INTERNAL OPTION SETTING For example, (?im) sets caseless, multiline matching. It is also possi- ble to unset these options by preceding the letter with a hyphen, and a - combined setting and unsetting such as (?im-sx), which sets PCRE_CASE- - LESS and PCRE_MULTILINE while unsetting PCRE_DOTALL and PCRE_EXTENDED, - is also permitted. If a letter appears both before and after the + combined setting and unsetting such as (?im-sx), which sets PCRE_CASE- + LESS and PCRE_MULTILINE while unsetting PCRE_DOTALL and PCRE_EXTENDED, + is also permitted. If a letter appears both before and after the hyphen, the option is unset. - The PCRE-specific options PCRE_DUPNAMES, PCRE_UNGREEDY, and PCRE_EXTRA - can be changed in the same way as the Perl-compatible options by using + The PCRE-specific options PCRE_DUPNAMES, PCRE_UNGREEDY, and PCRE_EXTRA + can be changed in the same way as the Perl-compatible options by using the characters J, U and X respectively. - When one of these option changes occurs at top level (that is, not - inside subpattern parentheses), the change applies to the remainder of + When one of these option changes occurs at top level (that is, not + inside subpattern parentheses), the change applies to the remainder of the pattern that follows. If the change is placed right at the start of a pattern, PCRE extracts it into the global options (and it will there- fore show up in data extracted by the pcre_fullinfo() function). - An option change within a subpattern (see below for a description of - subpatterns) affects only that part of the subpattern that follows it, + An option change within a subpattern (see below for a description of + subpatterns) affects only that part of the subpattern that follows it, so (a(?i)b)c matches abc and aBc and no other strings (assuming PCRE_CASELESS is not - used). By this means, options can be made to have different settings - in different parts of the pattern. Any changes made in one alternative - do carry on into subsequent branches within the same subpattern. For + used). By this means, options can be made to have different settings + in different parts of the pattern. Any changes made in one alternative + do carry on into subsequent branches within the same subpattern. For example, (a(?i)b|c) - matches "ab", "aB", "c", and "C", even though when matching "C" the - first branch is abandoned before the option setting. This is because - the effects of option settings happen at compile time. There would be + matches "ab", "aB", "c", and "C", even though when matching "C" the + first branch is abandoned before the option setting. This is because + the effects of option settings happen at compile time. There would be some very weird behaviour otherwise. - Note: There are other PCRE-specific options that can be set by the - application when the compiling or matching functions are called. In - some cases the pattern can contain special leading sequences such as - (*CRLF) to override what the application has set or what has been - defaulted. Details are given in the section entitled "Newline - sequences" above. There are also the (*UTF8), (*UTF16),(*UTF32), and - (*UCP) leading sequences that can be used to set UTF and Unicode prop- - erty modes; they are equivalent to setting the PCRE_UTF8, PCRE_UTF16, - PCRE_UTF32 and the PCRE_UCP options, respectively. The (*UTF) sequence - is a generic version that can be used with any of the libraries. How- - ever, the application can set the PCRE_NEVER_UTF option, which locks + Note: There are other PCRE-specific options that can be set by the + application when the compiling or matching functions are called. In + some cases the pattern can contain special leading sequences such as + (*CRLF) to override what the application has set or what has been + defaulted. Details are given in the section entitled "Newline + sequences" above. There are also the (*UTF8), (*UTF16),(*UTF32), and + (*UCP) leading sequences that can be used to set UTF and Unicode prop- + erty modes; they are equivalent to setting the PCRE_UTF8, PCRE_UTF16, + PCRE_UTF32 and the PCRE_UCP options, respectively. The (*UTF) sequence + is a generic version that can be used with any of the libraries. How- + ever, the application can set the PCRE_NEVER_UTF option, which locks out the use of the (*UTF) sequences. @@ -6023,18 +6047,18 @@ SUBPATTERNS cat(aract|erpillar|) - matches "cataract", "caterpillar", or "cat". Without the parentheses, + matches "cataract", "caterpillar", or "cat". Without the parentheses, it would match "cataract", "erpillar" or an empty string. - 2. It sets up the subpattern as a capturing subpattern. This means - that, when the whole pattern matches, that portion of the subject + 2. It sets up the subpattern as a capturing subpattern. This means + that, when the whole pattern matches, that portion of the subject string that matched the subpattern is passed back to the caller via the - ovector argument of the matching function. (This applies only to the - traditional matching functions; the DFA matching functions do not sup- + ovector argument of the matching function. (This applies only to the + traditional matching functions; the DFA matching functions do not sup- port capturing.) Opening parentheses are counted from left to right (starting from 1) to - obtain numbers for the capturing subpatterns. For example, if the + obtain numbers for the capturing subpatterns. For example, if the string "the red king" is matched against the pattern the ((red|white) (king|queen)) @@ -6042,12 +6066,12 @@ SUBPATTERNS the captured substrings are "red king", "red", and "king", and are num- bered 1, 2, and 3, respectively. - The fact that plain parentheses fulfil two functions is not always - helpful. There are often times when a grouping subpattern is required - without a capturing requirement. If an opening parenthesis is followed - by a question mark and a colon, the subpattern does not do any captur- - ing, and is not counted when computing the number of any subsequent - capturing subpatterns. For example, if the string "the white queen" is + The fact that plain parentheses fulfil two functions is not always + helpful. There are often times when a grouping subpattern is required + without a capturing requirement. If an opening parenthesis is followed + by a question mark and a colon, the subpattern does not do any captur- + ing, and is not counted when computing the number of any subsequent + capturing subpatterns. For example, if the string "the white queen" is matched against the pattern the ((?:red|white) (king|queen)) @@ -6055,37 +6079,37 @@ SUBPATTERNS the captured substrings are "white queen" and "queen", and are numbered 1 and 2. The maximum number of capturing subpatterns is 65535. - As a convenient shorthand, if any option settings are required at the - start of a non-capturing subpattern, the option letters may appear + As a convenient shorthand, if any option settings are required at the + start of a non-capturing subpattern, the option letters may appear between the "?" and the ":". Thus the two patterns (?i:saturday|sunday) (?:(?i)saturday|sunday) match exactly the same set of strings. Because alternative branches are - tried from left to right, and options are not reset until the end of - the subpattern is reached, an option setting in one branch does affect - subsequent branches, so the above patterns match "SUNDAY" as well as + tried from left to right, and options are not reset until the end of + the subpattern is reached, an option setting in one branch does affect + subsequent branches, so the above patterns match "SUNDAY" as well as "Saturday". DUPLICATE SUBPATTERN NUMBERS Perl 5.10 introduced a feature whereby each alternative in a subpattern - uses the same numbers for its capturing parentheses. Such a subpattern - starts with (?| and is itself a non-capturing subpattern. For example, + uses the same numbers for its capturing parentheses. Such a subpattern + starts with (?| and is itself a non-capturing subpattern. For example, consider this pattern: (?|(Sat)ur|(Sun))day - Because the two alternatives are inside a (?| group, both sets of cap- - turing parentheses are numbered one. Thus, when the pattern matches, - you can look at captured substring number one, whichever alternative - matched. This construct is useful when you want to capture part, but + Because the two alternatives are inside a (?| group, both sets of cap- + turing parentheses are numbered one. Thus, when the pattern matches, + you can look at captured substring number one, whichever alternative + matched. This construct is useful when you want to capture part, but not all, of one of a number of alternatives. Inside a (?| group, paren- - theses are numbered as usual, but the number is reset at the start of - each branch. The numbers of any capturing parentheses that follow the - subpattern start after the highest number used in any branch. The fol- + theses are numbered as usual, but the number is reset at the start of + each branch. The numbers of any capturing parentheses that follow the + subpattern start after the highest number used in any branch. The fol- lowing example is taken from the Perl documentation. The numbers under- neath show in which buffer the captured content will be stored. @@ -6093,58 +6117,58 @@ DUPLICATE SUBPATTERN NUMBERS / ( a ) (?| x ( y ) z | (p (q) r) | (t) u (v) ) ( z ) /x # 1 2 2 3 2 3 4 - A back reference to a numbered subpattern uses the most recent value - that is set for that number by any subpattern. The following pattern + A back reference to a numbered subpattern uses the most recent value + that is set for that number by any subpattern. The following pattern matches "abcabc" or "defdef": /(?|(abc)|(def))\1/ - In contrast, a subroutine call to a numbered subpattern always refers - to the first one in the pattern with the given number. The following + In contrast, a subroutine call to a numbered subpattern always refers + to the first one in the pattern with the given number. The following pattern matches "abcabc" or "defabc": /(?|(abc)|(def))(?1)/ - If a condition test for a subpattern's having matched refers to a non- - unique number, the test is true if any of the subpatterns of that num- + If a condition test for a subpattern's having matched refers to a non- + unique number, the test is true if any of the subpatterns of that num- ber have matched. - An alternative approach to using this "branch reset" feature is to use + An alternative approach to using this "branch reset" feature is to use duplicate named subpatterns, as described in the next section. NAMED SUBPATTERNS - Identifying capturing parentheses by number is simple, but it can be - very hard to keep track of the numbers in complicated regular expres- - sions. Furthermore, if an expression is modified, the numbers may - change. To help with this difficulty, PCRE supports the naming of sub- + Identifying capturing parentheses by number is simple, but it can be + very hard to keep track of the numbers in complicated regular expres- + sions. Furthermore, if an expression is modified, the numbers may + change. To help with this difficulty, PCRE supports the naming of sub- patterns. This feature was not added to Perl until release 5.10. Python - had the feature earlier, and PCRE introduced it at release 4.0, using - the Python syntax. PCRE now supports both the Perl and the Python syn- - tax. Perl allows identically numbered subpatterns to have different + had the feature earlier, and PCRE introduced it at release 4.0, using + the Python syntax. PCRE now supports both the Perl and the Python syn- + tax. Perl allows identically numbered subpatterns to have different names, but PCRE does not. - In PCRE, a subpattern can be named in one of three ways: (?<name>...) - or (?'name'...) as in Perl, or (?P<name>...) as in Python. References - to capturing parentheses from other parts of the pattern, such as back - references, recursion, and conditions, can be made by name as well as + In PCRE, a subpattern can be named in one of three ways: (?<name>...) + or (?'name'...) as in Perl, or (?P<name>...) as in Python. References + to capturing parentheses from other parts of the pattern, such as back + references, recursion, and conditions, can be made by name as well as by number. - Names consist of up to 32 alphanumeric characters and underscores, but - must start with a non-digit. Named capturing parentheses are still - allocated numbers as well as names, exactly as if the names were not - present. The PCRE API provides function calls for extracting the name- - to-number translation table from a compiled pattern. There is also a + Names consist of up to 32 alphanumeric characters and underscores, but + must start with a non-digit. Named capturing parentheses are still + allocated numbers as well as names, exactly as if the names were not + present. The PCRE API provides function calls for extracting the name- + to-number translation table from a compiled pattern. There is also a convenience function for extracting a captured substring by name. - By default, a name must be unique within a pattern, but it is possible + By default, a name must be unique within a pattern, but it is possible to relax this constraint by setting the PCRE_DUPNAMES option at compile - time. (Duplicate names are also always permitted for subpatterns with - the same number, set up as described in the previous section.) Dupli- - cate names can be useful for patterns where only one instance of the - named parentheses can match. Suppose you want to match the name of a - weekday, either as a 3-letter abbreviation or as the full name, and in + time. (Duplicate names are also always permitted for subpatterns with + the same number, set up as described in the previous section.) Dupli- + cate names can be useful for patterns where only one instance of the + named parentheses can match. Suppose you want to match the name of a + weekday, either as a 3-letter abbreviation or as the full name, and in both cases you want to extract the abbreviation. This pattern (ignoring the line breaks) does the job: @@ -6154,18 +6178,18 @@ NAMED SUBPATTERNS (?<DN>Thu)(?:rsday)?| (?<DN>Sat)(?:urday)? - There are five capturing substrings, but only one is ever set after a + There are five capturing substrings, but only one is ever set after a match. (An alternative way of solving this problem is to use a "branch reset" subpattern, as described in the previous section.) - The convenience function for extracting the data by name returns the - substring for the first (and in this example, the only) subpattern of - that name that matched. This saves searching to find which numbered + The convenience function for extracting the data by name returns the + substring for the first (and in this example, the only) subpattern of + that name that matched. This saves searching to find which numbered subpattern it was. - If you make a back reference to a non-unique named subpattern from - elsewhere in the pattern, the subpatterns to which the name refers are - checked in the order in which they appear in the overall pattern. The + If you make a back reference to a non-unique named subpattern from + elsewhere in the pattern, the subpatterns to which the name refers are + checked in the order in which they appear in the overall pattern. The first one that is set is used for the reference. For example, this pat- tern matches both "foofoo" and "barbar" but not "foobar" or "barfoo": @@ -6173,29 +6197,29 @@ NAMED SUBPATTERNS If you make a subroutine call to a non-unique named subpattern, the one - that corresponds to the first occurrence of the name is used. In the + that corresponds to the first occurrence of the name is used. In the absence of duplicate numbers (see the previous section) this is the one with the lowest number. If you use a named reference in a condition test (see the section about conditions below), either to check whether a subpattern has matched, or - to check for recursion, all subpatterns with the same name are tested. - If the condition is true for any one of them, the overall condition is - true. This is the same behaviour as testing by number. For further - details of the interfaces for handling named subpatterns, see the + to check for recursion, all subpatterns with the same name are tested. + If the condition is true for any one of them, the overall condition is + true. This is the same behaviour as testing by number. For further + details of the interfaces for handling named subpatterns, see the pcreapi documentation. Warning: You cannot use different names to distinguish between two sub- - patterns with the same number because PCRE uses only the numbers when + patterns with the same number because PCRE uses only the numbers when matching. For this reason, an error is given at compile time if differ- - ent names are given to subpatterns with the same number. However, you + ent names are given to subpatterns with the same number. However, you can always give the same name to subpatterns with the same number, even when PCRE_DUPNAMES is not set. REPETITION - Repetition is specified by quantifiers, which can follow any of the + Repetition is specified by quantifiers, which can follow any of the following items: a literal data character @@ -6209,17 +6233,17 @@ REPETITION a parenthesized subpattern (including assertions) a subroutine call to a subpattern (recursive or otherwise) - The general repetition quantifier specifies a minimum and maximum num- - ber of permitted matches, by giving the two numbers in curly brackets - (braces), separated by a comma. The numbers must be less than 65536, + The general repetition quantifier specifies a minimum and maximum num- + ber of permitted matches, by giving the two numbers in curly brackets + (braces), separated by a comma. The numbers must be less than 65536, and the first must be less than or equal to the second. For example: z{2,4} - matches "zz", "zzz", or "zzzz". A closing brace on its own is not a - special character. If the second number is omitted, but the comma is - present, there is no upper limit; if the second number and the comma - are both omitted, the quantifier specifies an exact number of required + matches "zz", "zzz", or "zzzz". A closing brace on its own is not a + special character. If the second number is omitted, but the comma is + present, there is no upper limit; if the second number and the comma + are both omitted, the quantifier specifies an exact number of required matches. Thus [aeiou]{3,} @@ -6228,50 +6252,50 @@ REPETITION \d{8} - matches exactly 8 digits. An opening curly bracket that appears in a - position where a quantifier is not allowed, or one that does not match - the syntax of a quantifier, is taken as a literal character. For exam- + matches exactly 8 digits. An opening curly bracket that appears in a + position where a quantifier is not allowed, or one that does not match + the syntax of a quantifier, is taken as a literal character. For exam- ple, {,6} is not a quantifier, but a literal string of four characters. In UTF modes, quantifiers apply to characters rather than to individual - data units. Thus, for example, \x{100}{2} matches two characters, each + data units. Thus, for example, \x{100}{2} matches two characters, each of which is represented by a two-byte sequence in a UTF-8 string. Simi- - larly, \X{3} matches three Unicode extended grapheme clusters, each of - which may be several data units long (and they may be of different + larly, \X{3} matches three Unicode extended grapheme clusters, each of + which may be several data units long (and they may be of different lengths). The quantifier {0} is permitted, causing the expression to behave as if the previous item and the quantifier were not present. This may be use- - ful for subpatterns that are referenced as subroutines from elsewhere + ful for subpatterns that are referenced as subroutines from elsewhere in the pattern (but see also the section entitled "Defining subpatterns - for use by reference only" below). Items other than subpatterns that + for use by reference only" below). Items other than subpatterns that have a {0} quantifier are omitted from the compiled pattern. - For convenience, the three most common quantifiers have single-charac- + For convenience, the three most common quantifiers have single-charac- ter abbreviations: * is equivalent to {0,} + is equivalent to {1,} ? is equivalent to {0,1} - It is possible to construct infinite loops by following a subpattern + It is possible to construct infinite loops by following a subpattern that can match no characters with a quantifier that has no upper limit, for example: (a?)* Earlier versions of Perl and PCRE used to give an error at compile time - for such patterns. However, because there are cases where this can be - useful, such patterns are now accepted, but if any repetition of the - subpattern does in fact match no characters, the loop is forcibly bro- + for such patterns. However, because there are cases where this can be + useful, such patterns are now accepted, but if any repetition of the + subpattern does in fact match no characters, the loop is forcibly bro- ken. - By default, the quantifiers are "greedy", that is, they match as much - as possible (up to the maximum number of permitted times), without - causing the rest of the pattern to fail. The classic example of where + By default, the quantifiers are "greedy", that is, they match as much + as possible (up to the maximum number of permitted times), without + causing the rest of the pattern to fail. The classic example of where this gives problems is in trying to match comments in C programs. These - appear between /* and */ and within the comment, individual * and / - characters may appear. An attempt to match C comments by applying the + appear between /* and */ and within the comment, individual * and / + characters may appear. An attempt to match C comments by applying the pattern /\*.*\*/ @@ -6280,19 +6304,19 @@ REPETITION /* first comment */ not comment /* second comment */ - fails, because it matches the entire string owing to the greediness of + fails, because it matches the entire string owing to the greediness of the .* item. - However, if a quantifier is followed by a question mark, it ceases to + However, if a quantifier is followed by a question mark, it ceases to be greedy, and instead matches the minimum number of times possible, so the pattern /\*.*?\*/ - does the right thing with the C comments. The meaning of the various - quantifiers is not otherwise changed, just the preferred number of - matches. Do not confuse this use of question mark with its use as a - quantifier in its own right. Because it has two uses, it can sometimes + does the right thing with the C comments. The meaning of the various + quantifiers is not otherwise changed, just the preferred number of + matches. Do not confuse this use of question mark with its use as a + quantifier in its own right. Because it has two uses, it can sometimes appear doubled, as in \d??\d @@ -6300,45 +6324,45 @@ REPETITION which matches one digit by preference, but can match two if that is the only way the rest of the pattern matches. - If the PCRE_UNGREEDY option is set (an option that is not available in - Perl), the quantifiers are not greedy by default, but individual ones - can be made greedy by following them with a question mark. In other + If the PCRE_UNGREEDY option is set (an option that is not available in + Perl), the quantifiers are not greedy by default, but individual ones + can be made greedy by following them with a question mark. In other words, it inverts the default behaviour. - When a parenthesized subpattern is quantified with a minimum repeat - count that is greater than 1 or with a limited maximum, more memory is - required for the compiled pattern, in proportion to the size of the + When a parenthesized subpattern is quantified with a minimum repeat + count that is greater than 1 or with a limited maximum, more memory is + required for the compiled pattern, in proportion to the size of the minimum or maximum. If a pattern starts with .* or .{0,} and the PCRE_DOTALL option (equiv- - alent to Perl's /s) is set, thus allowing the dot to match newlines, - the pattern is implicitly anchored, because whatever follows will be - tried against every character position in the subject string, so there - is no point in retrying the overall match at any position after the - first. PCRE normally treats such a pattern as though it were preceded + alent to Perl's /s) is set, thus allowing the dot to match newlines, + the pattern is implicitly anchored, because whatever follows will be + tried against every character position in the subject string, so there + is no point in retrying the overall match at any position after the + first. PCRE normally treats such a pattern as though it were preceded by \A. - In cases where it is known that the subject string contains no new- - lines, it is worth setting PCRE_DOTALL in order to obtain this opti- + In cases where it is known that the subject string contains no new- + lines, it is worth setting PCRE_DOTALL in order to obtain this opti- mization, or alternatively using ^ to indicate anchoring explicitly. - However, there are some cases where the optimization cannot be used. + However, there are some cases where the optimization cannot be used. When .* is inside capturing parentheses that are the subject of a back reference elsewhere in the pattern, a match at the start may fail where a later one succeeds. Consider, for example: (.*)abc\1 - If the subject is "xyz123abc123" the match point is the fourth charac- + If the subject is "xyz123abc123" the match point is the fourth charac- ter. For this reason, such a pattern is not implicitly anchored. - Another case where implicit anchoring is not applied is when the lead- - ing .* is inside an atomic group. Once again, a match at the start may + Another case where implicit anchoring is not applied is when the lead- + ing .* is inside an atomic group. Once again, a match at the start may fail where a later one succeeds. Consider this pattern: (?>.*?a)b - It matches "ab" in the subject "aab". The use of the backtracking con- + It matches "ab" in the subject "aab". The use of the backtracking con- trol verbs (*PRUNE) and (*SKIP) also disable this optimization. When a capturing subpattern is repeated, the value captured is the sub- @@ -6347,8 +6371,8 @@ REPETITION (tweedle[dume]{3}\s*)+ has matched "tweedledum tweedledee" the value of the captured substring - is "tweedledee". However, if there are nested capturing subpatterns, - the corresponding captured values may have been set in previous itera- + is "tweedledee". However, if there are nested capturing subpatterns, + the corresponding captured values may have been set in previous itera- tions. For example, after /(a|(b))+/ @@ -6358,53 +6382,53 @@ REPETITION ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS - With both maximizing ("greedy") and minimizing ("ungreedy" or "lazy") - repetition, failure of what follows normally causes the repeated item - to be re-evaluated to see if a different number of repeats allows the - rest of the pattern to match. Sometimes it is useful to prevent this, - either to change the nature of the match, or to cause it fail earlier - than it otherwise might, when the author of the pattern knows there is + With both maximizing ("greedy") and minimizing ("ungreedy" or "lazy") + repetition, failure of what follows normally causes the repeated item + to be re-evaluated to see if a different number of repeats allows the + rest of the pattern to match. Sometimes it is useful to prevent this, + either to change the nature of the match, or to cause it fail earlier + than it otherwise might, when the author of the pattern knows there is no point in carrying on. - Consider, for example, the pattern \d+foo when applied to the subject + Consider, for example, the pattern \d+foo when applied to the subject line 123456bar After matching all 6 digits and then failing to match "foo", the normal - action of the matcher is to try again with only 5 digits matching the - \d+ item, and then with 4, and so on, before ultimately failing. - "Atomic grouping" (a term taken from Jeffrey Friedl's book) provides - the means for specifying that once a subpattern has matched, it is not + action of the matcher is to try again with only 5 digits matching the + \d+ item, and then with 4, and so on, before ultimately failing. + "Atomic grouping" (a term taken from Jeffrey Friedl's book) provides + the means for specifying that once a subpattern has matched, it is not to be re-evaluated in this way. - If we use atomic grouping for the previous example, the matcher gives - up immediately on failing to match "foo" the first time. The notation + If we use atomic grouping for the previous example, the matcher gives + up immediately on failing to match "foo" the first time. The notation is a kind of special parenthesis, starting with (?> as in this example: (?>\d+)foo - This kind of parenthesis "locks up" the part of the pattern it con- - tains once it has matched, and a failure further into the pattern is - prevented from backtracking into it. Backtracking past it to previous + This kind of parenthesis "locks up" the part of the pattern it con- + tains once it has matched, and a failure further into the pattern is + prevented from backtracking into it. Backtracking past it to previous items, however, works as normal. - An alternative description is that a subpattern of this type matches - the string of characters that an identical standalone pattern would + An alternative description is that a subpattern of this type matches + the string of characters that an identical standalone pattern would match, if anchored at the current point in the subject string. Atomic grouping subpatterns are not capturing subpatterns. Simple cases such as the above example can be thought of as a maximizing repeat that - must swallow everything it can. So, while both \d+ and \d+? are pre- - pared to adjust the number of digits they match in order to make the + must swallow everything it can. So, while both \d+ and \d+? are pre- + pared to adjust the number of digits they match in order to make the rest of the pattern match, (?>\d+) can only match an entire sequence of digits. - Atomic groups in general can of course contain arbitrarily complicated - subpatterns, and can be nested. However, when the subpattern for an + Atomic groups in general can of course contain arbitrarily complicated + subpatterns, and can be nested. However, when the subpattern for an atomic group is just a single repeated item, as in the example above, a - simpler notation, called a "possessive quantifier" can be used. This - consists of an additional + character following a quantifier. Using + simpler notation, called a "possessive quantifier" can be used. This + consists of an additional + character following a quantifier. Using this notation, the previous example can be rewritten as \d++foo @@ -6414,45 +6438,45 @@ ATOMIC GROUPING AND POSSESSIVE QUANTIFIERS (abc|xyz){2,3}+ - Possessive quantifiers are always greedy; the setting of the + Possessive quantifiers are always greedy; the setting of the PCRE_UNGREEDY option is ignored. They are a convenient notation for the - simpler forms of atomic group. However, there is no difference in the - meaning of a possessive quantifier and the equivalent atomic group, - though there may be a performance difference; possessive quantifiers + simpler forms of atomic group. However, there is no difference in the + meaning of a possessive quantifier and the equivalent atomic group, + though there may be a performance difference; possessive quantifiers should be slightly faster. - The possessive quantifier syntax is an extension to the Perl 5.8 syn- - tax. Jeffrey Friedl originated the idea (and the name) in the first + The possessive quantifier syntax is an extension to the Perl 5.8 syn- + tax. Jeffrey Friedl originated the idea (and the name) in the first edition of his book. Mike McCloskey liked it, so implemented it when he - built Sun's Java package, and PCRE copied it from there. It ultimately + built Sun's Java package, and PCRE copied it from there. It ultimately found its way into Perl at release 5.10. PCRE has an optimization that automatically "possessifies" certain sim- - ple pattern constructs. For example, the sequence A+B is treated as - A++B because there is no point in backtracking into a sequence of A's + ple pattern constructs. For example, the sequence A+B is treated as + A++B because there is no point in backtracking into a sequence of A's when B must follow. - When a pattern contains an unlimited repeat inside a subpattern that - can itself be repeated an unlimited number of times, the use of an - atomic group is the only way to avoid some failing matches taking a + When a pattern contains an unlimited repeat inside a subpattern that + can itself be repeated an unlimited number of times, the use of an + atomic group is the only way to avoid some failing matches taking a very long time indeed. The pattern (\D+|<\d+>)*[!?] - matches an unlimited number of substrings that either consist of non- - digits, or digits enclosed in <>, followed by either ! or ?. When it + matches an unlimited number of substrings that either consist of non- + digits, or digits enclosed in <>, followed by either ! or ?. When it matches, it runs quickly. However, if it is applied to aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa - it takes a long time before reporting failure. This is because the - string can be divided between the internal \D+ repeat and the external - * repeat in a large number of ways, and all have to be tried. (The - example uses [!?] rather than a single character at the end, because - both PCRE and Perl have an optimization that allows for fast failure - when a single character is used. They remember the last single charac- - ter that is required for a match, and fail early if it is not present - in the string.) If the pattern is changed so that it uses an atomic + it takes a long time before reporting failure. This is because the + string can be divided between the internal \D+ repeat and the external + * repeat in a large number of ways, and all have to be tried. (The + example uses [!?] rather than a single character at the end, because + both PCRE and Perl have an optimization that allows for fast failure + when a single character is used. They remember the last single charac- + ter that is required for a match, and fail early if it is not present + in the string.) If the pattern is changed so that it uses an atomic group, like this: ((?>\D+)|<\d+>)*[!?] @@ -6464,28 +6488,28 @@ BACK REFERENCES Outside a character class, a backslash followed by a digit greater than 0 (and possibly further digits) is a back reference to a capturing sub- - pattern earlier (that is, to its left) in the pattern, provided there + pattern earlier (that is, to its left) in the pattern, provided there have been that many previous capturing left parentheses. However, if the decimal number following the backslash is less than 10, - it is always taken as a back reference, and causes an error only if - there are not that many capturing left parentheses in the entire pat- - tern. In other words, the parentheses that are referenced need not be - to the left of the reference for numbers less than 10. A "forward back - reference" of this type can make sense when a repetition is involved - and the subpattern to the right has participated in an earlier itera- + it is always taken as a back reference, and causes an error only if + there are not that many capturing left parentheses in the entire pat- + tern. In other words, the parentheses that are referenced need not be + to the left of the reference for numbers less than 10. A "forward back + reference" of this type can make sense when a repetition is involved + and the subpattern to the right has participated in an earlier itera- tion. - It is not possible to have a numerical "forward back reference" to a - subpattern whose number is 10 or more using this syntax because a - sequence such as \50 is interpreted as a character defined in octal. + It is not possible to have a numerical "forward back reference" to a + subpattern whose number is 10 or more using this syntax because a + sequence such as \50 is interpreted as a character defined in octal. See the subsection entitled "Non-printing characters" above for further - details of the handling of digits following a backslash. There is no - such problem when named parentheses are used. A back reference to any + details of the handling of digits following a backslash. There is no + such problem when named parentheses are used. A back reference to any subpattern is possible using named parentheses (see below). - Another way of avoiding the ambiguity inherent in the use of digits - following a backslash is to use the \g escape sequence. This escape + Another way of avoiding the ambiguity inherent in the use of digits + following a backslash is to use the \g escape sequence. This escape must be followed by an unsigned number or a negative number, optionally enclosed in braces. These examples are all identical: @@ -6493,7 +6517,7 @@ BACK REFERENCES (ring), \g1 (ring), \g{1} - An unsigned number specifies an absolute reference without the ambigu- + An unsigned number specifies an absolute reference without the ambigu- ity that is present in the older syntax. It is also useful when literal digits follow the reference. A negative number is a relative reference. Consider this example: @@ -6502,33 +6526,33 @@ BACK REFERENCES The sequence \g{-1} is a reference to the most recently started captur- ing subpattern before \g, that is, is it equivalent to \2 in this exam- - ple. Similarly, \g{-2} would be equivalent to \1. The use of relative - references can be helpful in long patterns, and also in patterns that - are created by joining together fragments that contain references + ple. Similarly, \g{-2} would be equivalent to \1. The use of relative + references can be helpful in long patterns, and also in patterns that + are created by joining together fragments that contain references within themselves. - A back reference matches whatever actually matched the capturing sub- - pattern in the current subject string, rather than anything matching + A back reference matches whatever actually matched the capturing sub- + pattern in the current subject string, rather than anything matching the subpattern itself (see "Subpatterns as subroutines" below for a way of doing that). So the pattern (sens|respons)e and \1ibility - matches "sense and sensibility" and "response and responsibility", but - not "sense and responsibility". If caseful matching is in force at the - time of the back reference, the case of letters is relevant. For exam- + matches "sense and sensibility" and "response and responsibility", but + not "sense and responsibility". If caseful matching is in force at the + time of the back reference, the case of letters is relevant. For exam- ple, ((?i)rah)\s+\1 - matches "rah rah" and "RAH RAH", but not "RAH rah", even though the + matches "rah rah" and "RAH RAH", but not "RAH rah", even though the original capturing subpattern is matched caselessly. - There are several different ways of writing back references to named - subpatterns. The .NET syntax \k{name} and the Perl syntax \k<name> or - \k'name' are supported, as is the Python syntax (?P=name). Perl 5.10's + There are several different ways of writing back references to named + subpatterns. The .NET syntax \k{name} and the Perl syntax \k<name> or + \k'name' are supported, as is the Python syntax (?P=name). Perl 5.10's unified back reference syntax, in which \g can be used for both numeric - and named references, is also supported. We could rewrite the above + and named references, is also supported. We could rewrite the above example in any of the following ways: (?<p1>(?i)rah)\s+\k<p1> @@ -6536,84 +6560,84 @@ BACK REFERENCES (?P<p1>(?i)rah)\s+(?P=p1) (?<p1>(?i)rah)\s+\g{p1} - A subpattern that is referenced by name may appear in the pattern + A subpattern that is referenced by name may appear in the pattern before or after the reference. - There may be more than one back reference to the same subpattern. If a - subpattern has not actually been used in a particular match, any back + There may be more than one back reference to the same subpattern. If a + subpattern has not actually been used in a particular match, any back references to it always fail by default. For example, the pattern (a|(bc))\2 - always fails if it starts to match "a" rather than "bc". However, if + always fails if it starts to match "a" rather than "bc". However, if the PCRE_JAVASCRIPT_COMPAT option is set at compile time, a back refer- ence to an unset value matches an empty string. - Because there may be many capturing parentheses in a pattern, all dig- - its following a backslash are taken as part of a potential back refer- - ence number. If the pattern continues with a digit character, some - delimiter must be used to terminate the back reference. If the - PCRE_EXTENDED option is set, this can be white space. Otherwise, the + Because there may be many capturing parentheses in a pattern, all dig- + its following a backslash are taken as part of a potential back refer- + ence number. If the pattern continues with a digit character, some + delimiter must be used to terminate the back reference. If the + PCRE_EXTENDED option is set, this can be white space. Otherwise, the \g{ syntax or an empty comment (see "Comments" below) can be used. Recursive back references - A back reference that occurs inside the parentheses to which it refers - fails when the subpattern is first used, so, for example, (a\1) never - matches. However, such references can be useful inside repeated sub- + A back reference that occurs inside the parentheses to which it refers + fails when the subpattern is first used, so, for example, (a\1) never + matches. However, such references can be useful inside repeated sub- patterns. For example, the pattern (a|b\1)+ matches any number of "a"s and also "aba", "ababbaa" etc. At each iter- - ation of the subpattern, the back reference matches the character - string corresponding to the previous iteration. In order for this to - work, the pattern must be such that the first iteration does not need - to match the back reference. This can be done using alternation, as in + ation of the subpattern, the back reference matches the character + string corresponding to the previous iteration. In order for this to + work, the pattern must be such that the first iteration does not need + to match the back reference. This can be done using alternation, as in the example above, or by a quantifier with a minimum of zero. - Back references of this type cause the group that they reference to be - treated as an atomic group. Once the whole group has been matched, a - subsequent matching failure cannot cause backtracking into the middle + Back references of this type cause the group that they reference to be + treated as an atomic group. Once the whole group has been matched, a + subsequent matching failure cannot cause backtracking into the middle of the group. ASSERTIONS - An assertion is a test on the characters following or preceding the - current matching point that does not actually consume any characters. - The simple assertions coded as \b, \B, \A, \G, \Z, \z, ^ and $ are + An assertion is a test on the characters following or preceding the + current matching point that does not actually consume any characters. + The simple assertions coded as \b, \B, \A, \G, \Z, \z, ^ and $ are described above. - More complicated assertions are coded as subpatterns. There are two - kinds: those that look ahead of the current position in the subject - string, and those that look behind it. An assertion subpattern is - matched in the normal way, except that it does not cause the current + More complicated assertions are coded as subpatterns. There are two + kinds: those that look ahead of the current position in the subject + string, and those that look behind it. An assertion subpattern is + matched in the normal way, except that it does not cause the current matching position to be changed. - Assertion subpatterns are not capturing subpatterns. If such an asser- - tion contains capturing subpatterns within it, these are counted for - the purposes of numbering the capturing subpatterns in the whole pat- - tern. However, substring capturing is carried out only for positive + Assertion subpatterns are not capturing subpatterns. If such an asser- + tion contains capturing subpatterns within it, these are counted for + the purposes of numbering the capturing subpatterns in the whole pat- + tern. However, substring capturing is carried out only for positive assertions. (Perl sometimes, but not always, does do capturing in nega- tive assertions.) - For compatibility with Perl, assertion subpatterns may be repeated; - though it makes no sense to assert the same thing several times, the - side effect of capturing parentheses may occasionally be useful. In + For compatibility with Perl, assertion subpatterns may be repeated; + though it makes no sense to assert the same thing several times, the + side effect of capturing parentheses may occasionally be useful. In practice, there only three cases: - (1) If the quantifier is {0}, the assertion is never obeyed during - matching. However, it may contain internal capturing parenthesized + (1) If the quantifier is {0}, the assertion is never obeyed during + matching. However, it may contain internal capturing parenthesized groups that are called from elsewhere via the subroutine mechanism. - (2) If quantifier is {0,n} where n is greater than zero, it is treated - as if it were {0,1}. At run time, the rest of the pattern match is + (2) If quantifier is {0,n} where n is greater than zero, it is treated + as if it were {0,1}. At run time, the rest of the pattern match is tried with and without the assertion, the order depending on the greed- iness of the quantifier. - (3) If the minimum repetition is greater than zero, the quantifier is - ignored. The assertion is obeyed just once when encountered during + (3) If the minimum repetition is greater than zero, the quantifier is + ignored. The assertion is obeyed just once when encountered during matching. Lookahead assertions @@ -6623,38 +6647,38 @@ ASSERTIONS \w+(?=;) - matches a word followed by a semicolon, but does not include the semi- + matches a word followed by a semicolon, but does not include the semi- colon in the match, and foo(?!bar) - matches any occurrence of "foo" that is not followed by "bar". Note + matches any occurrence of "foo" that is not followed by "bar". Note that the apparently similar pattern (?!foo)bar - does not find an occurrence of "bar" that is preceded by something - other than "foo"; it finds any occurrence of "bar" whatsoever, because + does not find an occurrence of "bar" that is preceded by something + other than "foo"; it finds any occurrence of "bar" whatsoever, because the assertion (?!foo) is always true when the next three characters are "bar". A lookbehind assertion is needed to achieve the other effect. If you want to force a matching failure at some point in a pattern, the - most convenient way to do it is with (?!) because an empty string - always matches, so an assertion that requires there not to be an empty + most convenient way to do it is with (?!) because an empty string + always matches, so an assertion that requires there not to be an empty string must always fail. The backtracking control verb (*FAIL) or (*F) is a synonym for (?!). Lookbehind assertions - Lookbehind assertions start with (?<= for positive assertions and (?<! + Lookbehind assertions start with (?<= for positive assertions and (?<! for negative assertions. For example, (?<!foo)bar - does find an occurrence of "bar" that is not preceded by "foo". The - contents of a lookbehind assertion are restricted such that all the + does find an occurrence of "bar" that is not preceded by "foo". The + contents of a lookbehind assertion are restricted such that all the strings it matches must have a fixed length. However, if there are sev- - eral top-level alternatives, they do not all have to have the same + eral top-level alternatives, they do not all have to have the same fixed length. Thus (?<=bullock|donkey) @@ -6663,62 +6687,62 @@ ASSERTIONS (?<!dogs?|cats?) - causes an error at compile time. Branches that match different length - strings are permitted only at the top level of a lookbehind assertion. + causes an error at compile time. Branches that match different length + strings are permitted only at the top level of a lookbehind assertion. This is an extension compared with Perl, which requires all branches to match the same length of string. An assertion such as (?<=ab(c|de)) - is not permitted, because its single top-level branch can match two + is not permitted, because its single top-level branch can match two different lengths, but it is acceptable to PCRE if rewritten to use two top-level branches: (?<=abc|abde) - In some cases, the escape sequence \K (see above) can be used instead + In some cases, the escape sequence \K (see above) can be used instead of a lookbehind assertion to get round the fixed-length restriction. - The implementation of lookbehind assertions is, for each alternative, - to temporarily move the current position back by the fixed length and + The implementation of lookbehind assertions is, for each alternative, + to temporarily move the current position back by the fixed length and then try to match. If there are insufficient characters before the cur- rent position, the assertion fails. - In a UTF mode, PCRE does not allow the \C escape (which matches a sin- - gle data unit even in a UTF mode) to appear in lookbehind assertions, - because it makes it impossible to calculate the length of the lookbe- - hind. The \X and \R escapes, which can match different numbers of data + In a UTF mode, PCRE does not allow the \C escape (which matches a sin- + gle data unit even in a UTF mode) to appear in lookbehind assertions, + because it makes it impossible to calculate the length of the lookbe- + hind. The \X and \R escapes, which can match different numbers of data units, are also not permitted. - "Subroutine" calls (see below) such as (?2) or (?&X) are permitted in - lookbehinds, as long as the subpattern matches a fixed-length string. + "Subroutine" calls (see below) such as (?2) or (?&X) are permitted in + lookbehinds, as long as the subpattern matches a fixed-length string. Recursion, however, is not supported. - Possessive quantifiers can be used in conjunction with lookbehind + Possessive quantifiers can be used in conjunction with lookbehind assertions to specify efficient matching of fixed-length strings at the end of subject strings. Consider a simple pattern such as abcd$ - when applied to a long string that does not match. Because matching + when applied to a long string that does not match. Because matching proceeds from left to right, PCRE will look for each "a" in the subject - and then see if what follows matches the rest of the pattern. If the + and then see if what follows matches the rest of the pattern. If the pattern is specified as ^.*abcd$ - the initial .* matches the entire string at first, but when this fails + the initial .* matches the entire string at first, but when this fails (because there is no following "a"), it backtracks to match all but the - last character, then all but the last two characters, and so on. Once - again the search for "a" covers the entire string, from right to left, + last character, then all but the last two characters, and so on. Once + again the search for "a" covers the entire string, from right to left, so we are no better off. However, if the pattern is written as ^.*+(?<=abcd) - there can be no backtracking for the .*+ item; it can match only the - entire string. The subsequent lookbehind assertion does a single test - on the last four characters. If it fails, the match fails immediately. - For long strings, this approach makes a significant difference to the + there can be no backtracking for the .*+ item; it can match only the + entire string. The subsequent lookbehind assertion does a single test + on the last four characters. If it fails, the match fails immediately. + For long strings, this approach makes a significant difference to the processing time. Using multiple assertions @@ -6727,18 +6751,18 @@ ASSERTIONS (?<=\d{3})(?<!999)foo - matches "foo" preceded by three digits that are not "999". Notice that - each of the assertions is applied independently at the same point in - the subject string. First there is a check that the previous three - characters are all digits, and then there is a check that the same + matches "foo" preceded by three digits that are not "999". Notice that + each of the assertions is applied independently at the same point in + the subject string. First there is a check that the previous three + characters are all digits, and then there is a check that the same three characters are not "999". This pattern does not match "foo" pre- - ceded by six characters, the first of which are digits and the last - three of which are not "999". For example, it doesn't match "123abc- + ceded by six characters, the first of which are digits and the last + three of which are not "999". For example, it doesn't match "123abc- foo". A pattern to do that is (?<=\d{3}...)(?<!999)foo - This time the first assertion looks at the preceding six characters, + This time the first assertion looks at the preceding six characters, checking that the first three are digits, and then the second assertion checks that the preceding three characters are not "999". @@ -6746,29 +6770,29 @@ ASSERTIONS (?<=(?<!foo)bar)baz - matches an occurrence of "baz" that is preceded by "bar" which in turn + matches an occurrence of "baz" that is preceded by "bar" which in turn is not preceded by "foo", while (?<=\d{3}(?!999)...)foo - is another pattern that matches "foo" preceded by three digits and any + is another pattern that matches "foo" preceded by three digits and any three characters that are not "999". CONDITIONAL SUBPATTERNS - It is possible to cause the matching process to obey a subpattern con- - ditionally or to choose between two alternative subpatterns, depending - on the result of an assertion, or whether a specific capturing subpat- - tern has already been matched. The two possible forms of conditional + It is possible to cause the matching process to obey a subpattern con- + ditionally or to choose between two alternative subpatterns, depending + on the result of an assertion, or whether a specific capturing subpat- + tern has already been matched. The two possible forms of conditional subpattern are: (?(condition)yes-pattern) (?(condition)yes-pattern|no-pattern) - If the condition is satisfied, the yes-pattern is used; otherwise the - no-pattern (if present) is used. If there are more than two alterna- - tives in the subpattern, a compile-time error occurs. Each of the two + If the condition is satisfied, the yes-pattern is used; otherwise the + no-pattern (if present) is used. If there are more than two alterna- + tives in the subpattern, a compile-time error occurs. Each of the two alternatives may itself contain nested subpatterns of any form, includ- ing conditional subpatterns; the restriction to two alternatives applies only at the level of the condition. This pattern fragment is an @@ -6777,68 +6801,68 @@ CONDITIONAL SUBPATTERNS (?(1) (A|B|C) | (D | (?(2)E|F) | E) ) - There are four kinds of condition: references to subpatterns, refer- + There are four kinds of condition: references to subpatterns, refer- ences to recursion, a pseudo-condition called DEFINE, and assertions. Checking for a used subpattern by number - If the text between the parentheses consists of a sequence of digits, + If the text between the parentheses consists of a sequence of digits, the condition is true if a capturing subpattern of that number has pre- - viously matched. If there is more than one capturing subpattern with - the same number (see the earlier section about duplicate subpattern - numbers), the condition is true if any of them have matched. An alter- - native notation is to precede the digits with a plus or minus sign. In - this case, the subpattern number is relative rather than absolute. The - most recently opened parentheses can be referenced by (?(-1), the next - most recent by (?(-2), and so on. Inside loops it can also make sense + viously matched. If there is more than one capturing subpattern with + the same number (see the earlier section about duplicate subpattern + numbers), the condition is true if any of them have matched. An alter- + native notation is to precede the digits with a plus or minus sign. In + this case, the subpattern number is relative rather than absolute. The + most recently opened parentheses can be referenced by (?(-1), the next + most recent by (?(-2), and so on. Inside loops it can also make sense to refer to subsequent groups. The next parentheses to be opened can be - referenced as (?(+1), and so on. (The value zero in any of these forms + referenced as (?(+1), and so on. (The value zero in any of these forms is not used; it provokes a compile-time error.) - Consider the following pattern, which contains non-significant white + Consider the following pattern, which contains non-significant white space to make it more readable (assume the PCRE_EXTENDED option) and to divide it into three parts for ease of discussion: ( \( )? [^()]+ (?(1) \) ) - The first part matches an optional opening parenthesis, and if that + The first part matches an optional opening parenthesis, and if that character is present, sets it as the first captured substring. The sec- - ond part matches one or more characters that are not parentheses. The - third part is a conditional subpattern that tests whether or not the - first set of parentheses matched. If they did, that is, if subject - started with an opening parenthesis, the condition is true, and so the - yes-pattern is executed and a closing parenthesis is required. Other- - wise, since no-pattern is not present, the subpattern matches nothing. - In other words, this pattern matches a sequence of non-parentheses, + ond part matches one or more characters that are not parentheses. The + third part is a conditional subpattern that tests whether or not the + first set of parentheses matched. If they did, that is, if subject + started with an opening parenthesis, the condition is true, and so the + yes-pattern is executed and a closing parenthesis is required. Other- + wise, since no-pattern is not present, the subpattern matches nothing. + In other words, this pattern matches a sequence of non-parentheses, optionally enclosed in parentheses. - If you were embedding this pattern in a larger one, you could use a + If you were embedding this pattern in a larger one, you could use a relative reference: ...other stuff... ( \( )? [^()]+ (?(-1) \) ) ... - This makes the fragment independent of the parentheses in the larger + This makes the fragment independent of the parentheses in the larger pattern. Checking for a used subpattern by name - Perl uses the syntax (?(<name>)...) or (?('name')...) to test for a - used subpattern by name. For compatibility with earlier versions of - PCRE, which had this facility before Perl, the syntax (?(name)...) is + Perl uses the syntax (?(<name>)...) or (?('name')...) to test for a + used subpattern by name. For compatibility with earlier versions of + PCRE, which had this facility before Perl, the syntax (?(name)...) is also recognized. Rewriting the above example to use a named subpattern gives this: (?<OPEN> \( )? [^()]+ (?(<OPEN>) \) ) - If the name used in a condition of this kind is a duplicate, the test - is applied to all subpatterns of the same name, and is true if any one + If the name used in a condition of this kind is a duplicate, the test + is applied to all subpatterns of the same name, and is true if any one of them has matched. Checking for pattern recursion If the condition is the string (R), and there is no subpattern with the - name R, the condition is true if a recursive call to the whole pattern + name R, the condition is true if a recursive call to the whole pattern or any subpattern has been made. If digits or a name preceded by amper- sand follow the letter R, for example: @@ -6846,51 +6870,51 @@ CONDITIONAL SUBPATTERNS the condition is true if the most recent recursion is into a subpattern whose number or name is given. This condition does not check the entire - recursion stack. If the name used in a condition of this kind is a + recursion stack. If the name used in a condition of this kind is a duplicate, the test is applied to all subpatterns of the same name, and is true if any one of them is the most recent recursion. - At "top level", all these recursion test conditions are false. The + At "top level", all these recursion test conditions are false. The syntax for recursive patterns is described below. Defining subpatterns for use by reference only - If the condition is the string (DEFINE), and there is no subpattern - with the name DEFINE, the condition is always false. In this case, - there may be only one alternative in the subpattern. It is always - skipped if control reaches this point in the pattern; the idea of - DEFINE is that it can be used to define subroutines that can be refer- - enced from elsewhere. (The use of subroutines is described below.) For - example, a pattern to match an IPv4 address such as "192.168.23.245" + If the condition is the string (DEFINE), and there is no subpattern + with the name DEFINE, the condition is always false. In this case, + there may be only one alternative in the subpattern. It is always + skipped if control reaches this point in the pattern; the idea of + DEFINE is that it can be used to define subroutines that can be refer- + enced from elsewhere. (The use of subroutines is described below.) For + example, a pattern to match an IPv4 address such as "192.168.23.245" could be written like this (ignore white space and line breaks): (?(DEFINE) (?<byte> 2[0-4]\d | 25[0-5] | 1\d\d | [1-9]?\d) ) \b (?&byte) (\.(?&byte)){3} \b - The first part of the pattern is a DEFINE group inside which a another - group named "byte" is defined. This matches an individual component of - an IPv4 address (a number less than 256). When matching takes place, - this part of the pattern is skipped because DEFINE acts like a false - condition. The rest of the pattern uses references to the named group - to match the four dot-separated components of an IPv4 address, insist- + The first part of the pattern is a DEFINE group inside which a another + group named "byte" is defined. This matches an individual component of + an IPv4 address (a number less than 256). When matching takes place, + this part of the pattern is skipped because DEFINE acts like a false + condition. The rest of the pattern uses references to the named group + to match the four dot-separated components of an IPv4 address, insist- ing on a word boundary at each end. Assertion conditions - If the condition is not in any of the above formats, it must be an - assertion. This may be a positive or negative lookahead or lookbehind - assertion. Consider this pattern, again containing non-significant + If the condition is not in any of the above formats, it must be an + assertion. This may be a positive or negative lookahead or lookbehind + assertion. Consider this pattern, again containing non-significant white space, and with the two alternatives on the second line: (?(?=[^a-z]*[a-z]) \d{2}-[a-z]{3}-\d{2} | \d{2}-\d{2}-\d{2} ) - The condition is a positive lookahead assertion that matches an - optional sequence of non-letters followed by a letter. In other words, - it tests for the presence of at least one letter in the subject. If a - letter is found, the subject is matched against the first alternative; - otherwise it is matched against the second. This pattern matches - strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are + The condition is a positive lookahead assertion that matches an + optional sequence of non-letters followed by a letter. In other words, + it tests for the presence of at least one letter in the subject. If a + letter is found, the subject is matched against the first alternative; + otherwise it is matched against the second. This pattern matches + strings in one of the two forms dd-aaa-dd or dd-dd-dd, where aaa are letters and dd are digits. @@ -6899,41 +6923,41 @@ COMMENTS There are two ways of including comments in patterns that are processed by PCRE. In both cases, the start of the comment must not be in a char- acter class, nor in the middle of any other sequence of related charac- - ters such as (?: or a subpattern name or number. The characters that + ters such as (?: or a subpattern name or number. The characters that make up a comment play no part in the pattern matching. - The sequence (?# marks the start of a comment that continues up to the - next closing parenthesis. Nested parentheses are not permitted. If the + The sequence (?# marks the start of a comment that continues up to the + next closing parenthesis. Nested parentheses are not permitted. If the PCRE_EXTENDED option is set, an unescaped # character also introduces a - comment, which in this case continues to immediately after the next - newline character or character sequence in the pattern. Which charac- + comment, which in this case continues to immediately after the next + newline character or character sequence in the pattern. Which charac- ters are interpreted as newlines is controlled by the options passed to - a compiling function or by a special sequence at the start of the pat- + a compiling function or by a special sequence at the start of the pat- tern, as described in the section entitled "Newline conventions" above. Note that the end of this type of comment is a literal newline sequence - in the pattern; escape sequences that happen to represent a newline do - not count. For example, consider this pattern when PCRE_EXTENDED is + in the pattern; escape sequences that happen to represent a newline do + not count. For example, consider this pattern when PCRE_EXTENDED is set, and the default newline convention is in force: abc #comment \n still comment - On encountering the # character, pcre_compile() skips along, looking - for a newline in the pattern. The sequence \n is still literal at this - stage, so it does not terminate the comment. Only an actual character + On encountering the # character, pcre_compile() skips along, looking + for a newline in the pattern. The sequence \n is still literal at this + stage, so it does not terminate the comment. Only an actual character with the code value 0x0a (the default newline) does so. RECURSIVE PATTERNS - Consider the problem of matching a string in parentheses, allowing for - unlimited nested parentheses. Without the use of recursion, the best - that can be done is to use a pattern that matches up to some fixed - depth of nesting. It is not possible to handle an arbitrary nesting + Consider the problem of matching a string in parentheses, allowing for + unlimited nested parentheses. Without the use of recursion, the best + that can be done is to use a pattern that matches up to some fixed + depth of nesting. It is not possible to handle an arbitrary nesting depth. For some time, Perl has provided a facility that allows regular expres- - sions to recurse (amongst other things). It does this by interpolating - Perl code in the expression at run time, and the code can refer to the + sions to recurse (amongst other things). It does this by interpolating + Perl code in the expression at run time, and the code can refer to the expression itself. A Perl pattern using code interpolation to solve the parentheses problem can be created like this: @@ -6943,201 +6967,201 @@ RECURSIVE PATTERNS refers recursively to the pattern in which it appears. Obviously, PCRE cannot support the interpolation of Perl code. Instead, - it supports special syntax for recursion of the entire pattern, and - also for individual subpattern recursion. After its introduction in - PCRE and Python, this kind of recursion was subsequently introduced + it supports special syntax for recursion of the entire pattern, and + also for individual subpattern recursion. After its introduction in + PCRE and Python, this kind of recursion was subsequently introduced into Perl at release 5.10. - A special item that consists of (? followed by a number greater than - zero and a closing parenthesis is a recursive subroutine call of the - subpattern of the given number, provided that it occurs inside that - subpattern. (If not, it is a non-recursive subroutine call, which is - described in the next section.) The special item (?R) or (?0) is a + A special item that consists of (? followed by a number greater than + zero and a closing parenthesis is a recursive subroutine call of the + subpattern of the given number, provided that it occurs inside that + subpattern. (If not, it is a non-recursive subroutine call, which is + described in the next section.) The special item (?R) or (?0) is a recursive call of the entire regular expression. - This PCRE pattern solves the nested parentheses problem (assume the + This PCRE pattern solves the nested parentheses problem (assume the PCRE_EXTENDED option is set so that white space is ignored): \( ( [^()]++ | (?R) )* \) - First it matches an opening parenthesis. Then it matches any number of - substrings which can either be a sequence of non-parentheses, or a - recursive match of the pattern itself (that is, a correctly parenthe- + First it matches an opening parenthesis. Then it matches any number of + substrings which can either be a sequence of non-parentheses, or a + recursive match of the pattern itself (that is, a correctly parenthe- sized substring). Finally there is a closing parenthesis. Note the use of a possessive quantifier to avoid backtracking into sequences of non- parentheses. - If this were part of a larger pattern, you would not want to recurse + If this were part of a larger pattern, you would not want to recurse the entire pattern, so instead you could use this: ( \( ( [^()]++ | (?1) )* \) ) - We have put the pattern into parentheses, and caused the recursion to + We have put the pattern into parentheses, and caused the recursion to refer to them instead of the whole pattern. - In a larger pattern, keeping track of parenthesis numbers can be - tricky. This is made easier by the use of relative references. Instead + In a larger pattern, keeping track of parenthesis numbers can be + tricky. This is made easier by the use of relative references. Instead of (?1) in the pattern above you can write (?-2) to refer to the second - most recently opened parentheses preceding the recursion. In other - words, a negative number counts capturing parentheses leftwards from + most recently opened parentheses preceding the recursion. In other + words, a negative number counts capturing parentheses leftwards from the point at which it is encountered. - It is also possible to refer to subsequently opened parentheses, by - writing references such as (?+2). However, these cannot be recursive - because the reference is not inside the parentheses that are refer- - enced. They are always non-recursive subroutine calls, as described in + It is also possible to refer to subsequently opened parentheses, by + writing references such as (?+2). However, these cannot be recursive + because the reference is not inside the parentheses that are refer- + enced. They are always non-recursive subroutine calls, as described in the next section. - An alternative approach is to use named parentheses instead. The Perl - syntax for this is (?&name); PCRE's earlier syntax (?P>name) is also + An alternative approach is to use named parentheses instead. The Perl + syntax for this is (?&name); PCRE's earlier syntax (?P>name) is also supported. We could rewrite the above example as follows: (?<pn> \( ( [^()]++ | (?&pn) )* \) ) - If there is more than one subpattern with the same name, the earliest + If there is more than one subpattern with the same name, the earliest one is used. - This particular example pattern that we have been looking at contains + This particular example pattern that we have been looking at contains nested unlimited repeats, and so the use of a possessive quantifier for matching strings of non-parentheses is important when applying the pat- - tern to strings that do not match. For example, when this pattern is + tern to strings that do not match. For example, when this pattern is applied to (aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa() - it yields "no match" quickly. However, if a possessive quantifier is - not used, the match runs for a very long time indeed because there are - so many different ways the + and * repeats can carve up the subject, + it yields "no match" quickly. However, if a possessive quantifier is + not used, the match runs for a very long time indeed because there are + so many different ways the + and * repeats can carve up the subject, and all have to be tested before failure can be reported. - At the end of a match, the values of capturing parentheses are those - from the outermost level. If you want to obtain intermediate values, a - callout function can be used (see below and the pcrecallout documenta- + At the end of a match, the values of capturing parentheses are those + from the outermost level. If you want to obtain intermediate values, a + callout function can be used (see below and the pcrecallout documenta- tion). If the pattern above is matched against (ab(cd)ef) - the value for the inner capturing parentheses (numbered 2) is "ef", - which is the last value taken on at the top level. If a capturing sub- - pattern is not matched at the top level, its final captured value is - unset, even if it was (temporarily) set at a deeper level during the + the value for the inner capturing parentheses (numbered 2) is "ef", + which is the last value taken on at the top level. If a capturing sub- + pattern is not matched at the top level, its final captured value is + unset, even if it was (temporarily) set at a deeper level during the matching process. - If there are more than 15 capturing parentheses in a pattern, PCRE has - to obtain extra memory to store data during a recursion, which it does + If there are more than 15 capturing parentheses in a pattern, PCRE has + to obtain extra memory to store data during a recursion, which it does by using pcre_malloc, freeing it via pcre_free afterwards. If no memory can be obtained, the match fails with the PCRE_ERROR_NOMEMORY error. - Do not confuse the (?R) item with the condition (R), which tests for - recursion. Consider this pattern, which matches text in angle brack- - ets, allowing for arbitrary nesting. Only digits are allowed in nested - brackets (that is, when recursing), whereas any characters are permit- + Do not confuse the (?R) item with the condition (R), which tests for + recursion. Consider this pattern, which matches text in angle brack- + ets, allowing for arbitrary nesting. Only digits are allowed in nested + brackets (that is, when recursing), whereas any characters are permit- ted at the outer level. < (?: (?(R) \d++ | [^<>]*+) | (?R)) * > - In this pattern, (?(R) is the start of a conditional subpattern, with - two different alternatives for the recursive and non-recursive cases. + In this pattern, (?(R) is the start of a conditional subpattern, with + two different alternatives for the recursive and non-recursive cases. The (?R) item is the actual recursive call. Differences in recursion processing between PCRE and Perl - Recursion processing in PCRE differs from Perl in two important ways. - In PCRE (like Python, but unlike Perl), a recursive subpattern call is + Recursion processing in PCRE differs from Perl in two important ways. + In PCRE (like Python, but unlike Perl), a recursive subpattern call is always treated as an atomic group. That is, once it has matched some of the subject string, it is never re-entered, even if it contains untried - alternatives and there is a subsequent matching failure. This can be - illustrated by the following pattern, which purports to match a palin- - dromic string that contains an odd number of characters (for example, + alternatives and there is a subsequent matching failure. This can be + illustrated by the following pattern, which purports to match a palin- + dromic string that contains an odd number of characters (for example, "a", "aba", "abcba", "abcdcba"): ^(.|(.)(?1)\2)$ The idea is that it either matches a single character, or two identical - characters surrounding a sub-palindrome. In Perl, this pattern works; - in PCRE it does not if the pattern is longer than three characters. + characters surrounding a sub-palindrome. In Perl, this pattern works; + in PCRE it does not if the pattern is longer than three characters. Consider the subject string "abcba": - At the top level, the first character is matched, but as it is not at + At the top level, the first character is matched, but as it is not at the end of the string, the first alternative fails; the second alterna- tive is taken and the recursion kicks in. The recursive call to subpat- - tern 1 successfully matches the next character ("b"). (Note that the + tern 1 successfully matches the next character ("b"). (Note that the beginning and end of line tests are not part of the recursion). - Back at the top level, the next character ("c") is compared with what - subpattern 2 matched, which was "a". This fails. Because the recursion - is treated as an atomic group, there are now no backtracking points, - and so the entire match fails. (Perl is able, at this point, to re- - enter the recursion and try the second alternative.) However, if the + Back at the top level, the next character ("c") is compared with what + subpattern 2 matched, which was "a". This fails. Because the recursion + is treated as an atomic group, there are now no backtracking points, + and so the entire match fails. (Perl is able, at this point, to re- + enter the recursion and try the second alternative.) However, if the pattern is written with the alternatives in the other order, things are different: ^((.)(?1)\2|.)$ - This time, the recursing alternative is tried first, and continues to - recurse until it runs out of characters, at which point the recursion - fails. But this time we do have another alternative to try at the - higher level. That is the big difference: in the previous case the + This time, the recursing alternative is tried first, and continues to + recurse until it runs out of characters, at which point the recursion + fails. But this time we do have another alternative to try at the + higher level. That is the big difference: in the previous case the remaining alternative is at a deeper recursion level, which PCRE cannot use. - To change the pattern so that it matches all palindromic strings, not - just those with an odd number of characters, it is tempting to change + To change the pattern so that it matches all palindromic strings, not + just those with an odd number of characters, it is tempting to change the pattern to this: ^((.)(?1)\2|.?)$ - Again, this works in Perl, but not in PCRE, and for the same reason. - When a deeper recursion has matched a single character, it cannot be - entered again in order to match an empty string. The solution is to - separate the two cases, and write out the odd and even cases as alter- + Again, this works in Perl, but not in PCRE, and for the same reason. + When a deeper recursion has matched a single character, it cannot be + entered again in order to match an empty string. The solution is to + separate the two cases, and write out the odd and even cases as alter- natives at the higher level: ^(?:((.)(?1)\2|)|((.)(?3)\4|.)) - If you want to match typical palindromic phrases, the pattern has to + If you want to match typical palindromic phrases, the pattern has to ignore all non-word characters, which can be done like this: ^\W*+(?:((.)\W*+(?1)\W*+\2|)|((.)\W*+(?3)\W*+\4|\W*+.\W*+))\W*+$ If run with the PCRE_CASELESS option, this pattern matches phrases such as "A man, a plan, a canal: Panama!" and it works well in both PCRE and - Perl. Note the use of the possessive quantifier *+ to avoid backtrack- - ing into sequences of non-word characters. Without this, PCRE takes a - great deal longer (ten times or more) to match typical phrases, and + Perl. Note the use of the possessive quantifier *+ to avoid backtrack- + ing into sequences of non-word characters. Without this, PCRE takes a + great deal longer (ten times or more) to match typical phrases, and Perl takes so long that you think it has gone into a loop. - WARNING: The palindrome-matching patterns above work only if the sub- - ject string does not start with a palindrome that is shorter than the - entire string. For example, although "abcba" is correctly matched, if - the subject is "ababa", PCRE finds the palindrome "aba" at the start, - then fails at top level because the end of the string does not follow. - Once again, it cannot jump back into the recursion to try other alter- + WARNING: The palindrome-matching patterns above work only if the sub- + ject string does not start with a palindrome that is shorter than the + entire string. For example, although "abcba" is correctly matched, if + the subject is "ababa", PCRE finds the palindrome "aba" at the start, + then fails at top level because the end of the string does not follow. + Once again, it cannot jump back into the recursion to try other alter- natives, so the entire match fails. - The second way in which PCRE and Perl differ in their recursion pro- - cessing is in the handling of captured values. In Perl, when a subpat- - tern is called recursively or as a subpattern (see the next section), - it has no access to any values that were captured outside the recur- - sion, whereas in PCRE these values can be referenced. Consider this + The second way in which PCRE and Perl differ in their recursion pro- + cessing is in the handling of captured values. In Perl, when a subpat- + tern is called recursively or as a subpattern (see the next section), + it has no access to any values that were captured outside the recur- + sion, whereas in PCRE these values can be referenced. Consider this pattern: ^(.)(\1|a(?2)) - In PCRE, this pattern matches "bab". The first capturing parentheses - match "b", then in the second group, when the back reference \1 fails - to match "b", the second alternative matches "a" and then recurses. In - the recursion, \1 does now match "b" and so the whole match succeeds. - In Perl, the pattern fails to match because inside the recursive call + In PCRE, this pattern matches "bab". The first capturing parentheses + match "b", then in the second group, when the back reference \1 fails + to match "b", the second alternative matches "a" and then recurses. In + the recursion, \1 does now match "b" and so the whole match succeeds. + In Perl, the pattern fails to match because inside the recursive call \1 cannot access the externally set value. SUBPATTERNS AS SUBROUTINES - If the syntax for a recursive subpattern call (either by number or by - name) is used outside the parentheses to which it refers, it operates - like a subroutine in a programming language. The called subpattern may - be defined before or after the reference. A numbered reference can be + If the syntax for a recursive subpattern call (either by number or by + name) is used outside the parentheses to which it refers, it operates + like a subroutine in a programming language. The called subpattern may + be defined before or after the reference. A numbered reference can be absolute or relative, as in these examples: (...(absolute)...)...(?2)... @@ -7148,79 +7172,79 @@ SUBPATTERNS AS SUBROUTINES (sens|respons)e and \1ibility - matches "sense and sensibility" and "response and responsibility", but + matches "sense and sensibility" and "response and responsibility", but not "sense and responsibility". If instead the pattern (sens|respons)e and (?1)ibility - is used, it does match "sense and responsibility" as well as the other - two strings. Another example is given in the discussion of DEFINE + is used, it does match "sense and responsibility" as well as the other + two strings. Another example is given in the discussion of DEFINE above. - All subroutine calls, whether recursive or not, are always treated as - atomic groups. That is, once a subroutine has matched some of the sub- + All subroutine calls, whether recursive or not, are always treated as + atomic groups. That is, once a subroutine has matched some of the sub- ject string, it is never re-entered, even if it contains untried alter- - natives and there is a subsequent matching failure. Any capturing - parentheses that are set during the subroutine call revert to their + natives and there is a subsequent matching failure. Any capturing + parentheses that are set during the subroutine call revert to their previous values afterwards. - Processing options such as case-independence are fixed when a subpat- - tern is defined, so if it is used as a subroutine, such options cannot + Processing options such as case-independence are fixed when a subpat- + tern is defined, so if it is used as a subroutine, such options cannot be changed for different calls. For example, consider this pattern: (abc)(?i:(?-1)) - It matches "abcabc". It does not match "abcABC" because the change of + It matches "abcabc". It does not match "abcABC" because the change of processing option does not affect the called subpattern. ONIGURUMA SUBROUTINE SYNTAX - For compatibility with Oniguruma, the non-Perl syntax \g followed by a + For compatibility with Oniguruma, the non-Perl syntax \g followed by a name or a number enclosed either in angle brackets or single quotes, is - an alternative syntax for referencing a subpattern as a subroutine, - possibly recursively. Here are two of the examples used above, rewrit- + an alternative syntax for referencing a subpattern as a subroutine, + possibly recursively. Here are two of the examples used above, rewrit- ten using this syntax: (?<pn> \( ( (?>[^()]+) | \g<pn> )* \) ) (sens|respons)e and \g'1'ibility - PCRE supports an extension to Oniguruma: if a number is preceded by a + PCRE supports an extension to Oniguruma: if a number is preceded by a plus or a minus sign it is taken as a relative reference. For example: (abc)(?i:\g<-1>) - Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not - synonymous. The former is a back reference; the latter is a subroutine + Note that \g{...} (Perl syntax) and \g<...> (Oniguruma syntax) are not + synonymous. The former is a back reference; the latter is a subroutine call. CALLOUTS Perl has a feature whereby using the sequence (?{...}) causes arbitrary - Perl code to be obeyed in the middle of matching a regular expression. + Perl code to be obeyed in the middle of matching a regular expression. This makes it possible, amongst other things, to extract different sub- strings that match the same pair of parentheses when there is a repeti- tion. PCRE provides a similar feature, but of course it cannot obey arbitrary Perl code. The feature is called "callout". The caller of PCRE provides - an external function by putting its entry point in the global variable - pcre_callout (8-bit library) or pcre[16|32]_callout (16-bit or 32-bit - library). By default, this variable contains NULL, which disables all + an external function by putting its entry point in the global variable + pcre_callout (8-bit library) or pcre[16|32]_callout (16-bit or 32-bit + library). By default, this variable contains NULL, which disables all calling out. - Within a regular expression, (?C) indicates the points at which the - external function is to be called. If you want to identify different - callout points, you can put a number less than 256 after the letter C. - The default value is zero. For example, this pattern has two callout + Within a regular expression, (?C) indicates the points at which the + external function is to be called. If you want to identify different + callout points, you can put a number less than 256 after the letter C. + The default value is zero. For example, this pattern has two callout points: (?C1)abc(?C2)def - If the PCRE_AUTO_CALLOUT flag is passed to a compiling function, call- - outs are automatically installed before each item in the pattern. They - are all numbered 255. If there is a conditional group in the pattern + If the PCRE_AUTO_CALLOUT flag is passed to a compiling function, call- + outs are automatically installed before each item in the pattern. They + are all numbered 255. If there is a conditional group in the pattern whose condition is an assertion, an additional callout is inserted just before the condition. An explicit callout may also be set at this posi- tion, as in this example: @@ -7230,120 +7254,120 @@ CALLOUTS Note that this applies only to assertion conditions, not to other types of condition. - During matching, when PCRE reaches a callout point, the external func- - tion is called. It is provided with the number of the callout, the - position in the pattern, and, optionally, one item of data originally - supplied by the caller of the matching function. The callout function + During matching, when PCRE reaches a callout point, the external func- + tion is called. It is provided with the number of the callout, the + position in the pattern, and, optionally, one item of data originally + supplied by the caller of the matching function. The callout function may cause matching to proceed, to backtrack, or to fail altogether. - By default, PCRE implements a number of optimizations at compile time - and matching time, and one side-effect is that sometimes callouts are - skipped. If you need all possible callouts to happen, you need to set - options that disable the relevant optimizations. More details, and a - complete description of the interface to the callout function, are + By default, PCRE implements a number of optimizations at compile time + and matching time, and one side-effect is that sometimes callouts are + skipped. If you need all possible callouts to happen, you need to set + options that disable the relevant optimizations. More details, and a + complete description of the interface to the callout function, are given in the pcrecallout documentation. BACKTRACKING CONTROL - Perl 5.10 introduced a number of "Special Backtracking Control Verbs", - which are still described in the Perl documentation as "experimental - and subject to change or removal in a future version of Perl". It goes - on to say: "Their usage in production code should be noted to avoid - problems during upgrades." The same remarks apply to the PCRE features + Perl 5.10 introduced a number of "Special Backtracking Control Verbs", + which are still described in the Perl documentation as "experimental + and subject to change or removal in a future version of Perl". It goes + on to say: "Their usage in production code should be noted to avoid + problems during upgrades." The same remarks apply to the PCRE features described in this section. - The new verbs make use of what was previously invalid syntax: an open- + The new verbs make use of what was previously invalid syntax: an open- ing parenthesis followed by an asterisk. They are generally of the form - (*VERB) or (*VERB:NAME). Some may take either form, possibly behaving - differently depending on whether or not a name is present. A name is + (*VERB) or (*VERB:NAME). Some may take either form, possibly behaving + differently depending on whether or not a name is present. A name is any sequence of characters that does not include a closing parenthesis. The maximum length of name is 255 in the 8-bit library and 65535 in the - 16-bit and 32-bit libraries. If the name is empty, that is, if the - closing parenthesis immediately follows the colon, the effect is as if - the colon were not there. Any number of these verbs may occur in a + 16-bit and 32-bit libraries. If the name is empty, that is, if the + closing parenthesis immediately follows the colon, the effect is as if + the colon were not there. Any number of these verbs may occur in a pattern. - Since these verbs are specifically related to backtracking, most of - them can be used only when the pattern is to be matched using one of - the traditional matching functions, because these use a backtracking - algorithm. With the exception of (*FAIL), which behaves like a failing - negative assertion, the backtracking control verbs cause an error if + Since these verbs are specifically related to backtracking, most of + them can be used only when the pattern is to be matched using one of + the traditional matching functions, because these use a backtracking + algorithm. With the exception of (*FAIL), which behaves like a failing + negative assertion, the backtracking control verbs cause an error if encountered by a DFA matching function. - The behaviour of these verbs in repeated groups, assertions, and in + The behaviour of these verbs in repeated groups, assertions, and in subpatterns called as subroutines (whether or not recursively) is docu- mented below. Optimizations that affect backtracking verbs - PCRE contains some optimizations that are used to speed up matching by + PCRE contains some optimizations that are used to speed up matching by running some checks at the start of each match attempt. For example, it - may know the minimum length of matching subject, or that a particular + may know the minimum length of matching subject, or that a particular character must be present. When one of these optimizations bypasses the - running of a match, any included backtracking verbs will not, of + running of a match, any included backtracking verbs will not, of course, be processed. You can suppress the start-of-match optimizations - by setting the PCRE_NO_START_OPTIMIZE option when calling pcre_com- + by setting the PCRE_NO_START_OPTIMIZE option when calling pcre_com- pile() or pcre_exec(), or by starting the pattern with (*NO_START_OPT). There is more discussion of this option in the section entitled "Option bits for pcre_exec()" in the pcreapi documentation. - Experiments with Perl suggest that it too has similar optimizations, + Experiments with Perl suggest that it too has similar optimizations, sometimes leading to anomalous results. Verbs that act immediately - The following verbs act as soon as they are encountered. They may not + The following verbs act as soon as they are encountered. They may not be followed by a name. (*ACCEPT) - This verb causes the match to end successfully, skipping the remainder - of the pattern. However, when it is inside a subpattern that is called - as a subroutine, only that subpattern is ended successfully. Matching + This verb causes the match to end successfully, skipping the remainder + of the pattern. However, when it is inside a subpattern that is called + as a subroutine, only that subpattern is ended successfully. Matching then continues at the outer level. If (*ACCEPT) in triggered in a posi- - tive assertion, the assertion succeeds; in a negative assertion, the + tive assertion, the assertion succeeds; in a negative assertion, the assertion fails. - If (*ACCEPT) is inside capturing parentheses, the data so far is cap- + If (*ACCEPT) is inside capturing parentheses, the data so far is cap- tured. For example: A((?:A|B(*ACCEPT)|C)D) - This matches "AB", "AAD", or "ACD"; when it matches "AB", "B" is cap- + This matches "AB", "AAD", or "ACD"; when it matches "AB", "B" is cap- tured by the outer parentheses. (*FAIL) or (*F) - This verb causes a matching failure, forcing backtracking to occur. It - is equivalent to (?!) but easier to read. The Perl documentation notes - that it is probably useful only when combined with (?{}) or (??{}). - Those are, of course, Perl features that are not present in PCRE. The - nearest equivalent is the callout feature, as for example in this pat- + This verb causes a matching failure, forcing backtracking to occur. It + is equivalent to (?!) but easier to read. The Perl documentation notes + that it is probably useful only when combined with (?{}) or (??{}). + Those are, of course, Perl features that are not present in PCRE. The + nearest equivalent is the callout feature, as for example in this pat- tern: a+(?C)(*FAIL) - A match with the string "aaaa" always fails, but the callout is taken + A match with the string "aaaa" always fails, but the callout is taken before each backtrack happens (in this example, 10 times). Recording which path was taken - There is one verb whose main purpose is to track how a match was - arrived at, though it also has a secondary use in conjunction with + There is one verb whose main purpose is to track how a match was + arrived at, though it also has a secondary use in conjunction with advancing the match starting point (see (*SKIP) below). (*MARK:NAME) or (*:NAME) - A name is always required with this verb. There may be as many - instances of (*MARK) as you like in a pattern, and their names do not + A name is always required with this verb. There may be as many + instances of (*MARK) as you like in a pattern, and their names do not have to be unique. - When a match succeeds, the name of the last-encountered (*MARK:NAME), - (*PRUNE:NAME), or (*THEN:NAME) on the matching path is passed back to - the caller as described in the section entitled "Extra data for - pcre_exec()" in the pcreapi documentation. Here is an example of - pcretest output, where the /K modifier requests the retrieval and out- + When a match succeeds, the name of the last-encountered (*MARK:NAME), + (*PRUNE:NAME), or (*THEN:NAME) on the matching path is passed back to + the caller as described in the section entitled "Extra data for + pcre_exec()" in the pcreapi documentation. Here is an example of + pcretest output, where the /K modifier requests the retrieval and out- putting of (*MARK) data: re> /X(*MARK:A)Y|X(*MARK:B)Z/K @@ -7355,73 +7379,73 @@ BACKTRACKING CONTROL MK: B The (*MARK) name is tagged with "MK:" in this output, and in this exam- - ple it indicates which of the two alternatives matched. This is a more - efficient way of obtaining this information than putting each alterna- + ple it indicates which of the two alternatives matched. This is a more + efficient way of obtaining this information than putting each alterna- tive in its own capturing parentheses. - If a verb with a name is encountered in a positive assertion that is - true, the name is recorded and passed back if it is the last-encoun- + If a verb with a name is encountered in a positive assertion that is + true, the name is recorded and passed back if it is the last-encoun- tered. This does not happen for negative assertions or failing positive assertions. - After a partial match or a failed match, the last encountered name in + After a partial match or a failed match, the last encountered name in the entire match process is returned. For example: re> /X(*MARK:A)Y|X(*MARK:B)Z/K data> XP No match, mark = B - Note that in this unanchored example the mark is retained from the + Note that in this unanchored example the mark is retained from the match attempt that started at the letter "X" in the subject. Subsequent match attempts starting at "P" and then with an empty string do not get as far as the (*MARK) item, but nevertheless do not reset it. - If you are interested in (*MARK) values after failed matches, you - should probably set the PCRE_NO_START_OPTIMIZE option (see above) to + If you are interested in (*MARK) values after failed matches, you + should probably set the PCRE_NO_START_OPTIMIZE option (see above) to ensure that the match is always attempted. Verbs that act after backtracking The following verbs do nothing when they are encountered. Matching con- - tinues with what follows, but if there is no subsequent match, causing - a backtrack to the verb, a failure is forced. That is, backtracking - cannot pass to the left of the verb. However, when one of these verbs + tinues with what follows, but if there is no subsequent match, causing + a backtrack to the verb, a failure is forced. That is, backtracking + cannot pass to the left of the verb. However, when one of these verbs appears inside an atomic group or an assertion that is true, its effect - is confined to that group, because once the group has been matched, - there is never any backtracking into it. In this situation, backtrack- - ing can "jump back" to the left of the entire atomic group or asser- - tion. (Remember also, as stated above, that this localization also + is confined to that group, because once the group has been matched, + there is never any backtracking into it. In this situation, backtrack- + ing can "jump back" to the left of the entire atomic group or asser- + tion. (Remember also, as stated above, that this localization also applies in subroutine calls.) - These verbs differ in exactly what kind of failure occurs when back- - tracking reaches them. The behaviour described below is what happens - when the verb is not in a subroutine or an assertion. Subsequent sec- + These verbs differ in exactly what kind of failure occurs when back- + tracking reaches them. The behaviour described below is what happens + when the verb is not in a subroutine or an assertion. Subsequent sec- tions cover these special cases. (*COMMIT) - This verb, which may not be followed by a name, causes the whole match + This verb, which may not be followed by a name, causes the whole match to fail outright if there is a later matching failure that causes back- - tracking to reach it. Even if the pattern is unanchored, no further + tracking to reach it. Even if the pattern is unanchored, no further attempts to find a match by advancing the starting point take place. If - (*COMMIT) is the only backtracking verb that is encountered, once it + (*COMMIT) is the only backtracking verb that is encountered, once it has been passed pcre_exec() is committed to finding a match at the cur- rent starting point, or not at all. For example: a+(*COMMIT)b - This matches "xxaab" but not "aacaab". It can be thought of as a kind + This matches "xxaab" but not "aacaab". It can be thought of as a kind of dynamic anchor, or "I've started, so I must finish." The name of the - most recently passed (*MARK) in the path is passed back when (*COMMIT) + most recently passed (*MARK) in the path is passed back when (*COMMIT) forces a match failure. - If there is more than one backtracking verb in a pattern, a different - one that follows (*COMMIT) may be triggered first, so merely passing + If there is more than one backtracking verb in a pattern, a different + one that follows (*COMMIT) may be triggered first, so merely passing (*COMMIT) during a match does not always guarantee that a match must be at this starting point. - Note that (*COMMIT) at the start of a pattern is not the same as an - anchor, unless PCRE's start-of-match optimizations are turned off, as + Note that (*COMMIT) at the start of a pattern is not the same as an + anchor, unless PCRE's start-of-match optimizations are turned off, as shown in this output from pcretest: re> /(*COMMIT)abc/ @@ -7432,207 +7456,207 @@ BACKTRACKING CONTROL For this pattern, PCRE knows that any match must start with "a", so the optimization skips along the subject to "a" before applying the pattern - to the first set of data. The match attempt then succeeds. In the sec- - ond set of data, the escape sequence \Y is interpreted by the pcretest - program. It causes the PCRE_NO_START_OPTIMIZE option to be set when + to the first set of data. The match attempt then succeeds. In the sec- + ond set of data, the escape sequence \Y is interpreted by the pcretest + program. It causes the PCRE_NO_START_OPTIMIZE option to be set when pcre_exec() is called. This disables the optimization that skips along to the first character. The pattern is now applied starting at "x", and - so the (*COMMIT) causes the match to fail without trying any other + so the (*COMMIT) causes the match to fail without trying any other starting points. (*PRUNE) or (*PRUNE:NAME) - This verb causes the match to fail at the current starting position in + This verb causes the match to fail at the current starting position in the subject if there is a later matching failure that causes backtrack- - ing to reach it. If the pattern is unanchored, the normal "bumpalong" - advance to the next starting character then happens. Backtracking can - occur as usual to the left of (*PRUNE), before it is reached, or when - matching to the right of (*PRUNE), but if there is no match to the - right, backtracking cannot cross (*PRUNE). In simple cases, the use of - (*PRUNE) is just an alternative to an atomic group or possessive quan- + ing to reach it. If the pattern is unanchored, the normal "bumpalong" + advance to the next starting character then happens. Backtracking can + occur as usual to the left of (*PRUNE), before it is reached, or when + matching to the right of (*PRUNE), but if there is no match to the + right, backtracking cannot cross (*PRUNE). In simple cases, the use of + (*PRUNE) is just an alternative to an atomic group or possessive quan- tifier, but there are some uses of (*PRUNE) that cannot be expressed in - any other way. In an anchored pattern (*PRUNE) has the same effect as + any other way. In an anchored pattern (*PRUNE) has the same effect as (*COMMIT). The behaviour of (*PRUNE:NAME) is the not the same as - (*MARK:NAME)(*PRUNE). It is like (*MARK:NAME) in that the name is - remembered for passing back to the caller. However, (*SKIP:NAME) + (*MARK:NAME)(*PRUNE). It is like (*MARK:NAME) in that the name is + remembered for passing back to the caller. However, (*SKIP:NAME) searches only for names set with (*MARK). (*SKIP) - This verb, when given without a name, is like (*PRUNE), except that if - the pattern is unanchored, the "bumpalong" advance is not to the next + This verb, when given without a name, is like (*PRUNE), except that if + the pattern is unanchored, the "bumpalong" advance is not to the next character, but to the position in the subject where (*SKIP) was encoun- - tered. (*SKIP) signifies that whatever text was matched leading up to + tered. (*SKIP) signifies that whatever text was matched leading up to it cannot be part of a successful match. Consider: a+(*SKIP)b - If the subject is "aaaac...", after the first match attempt fails - (starting at the first character in the string), the starting point + If the subject is "aaaac...", after the first match attempt fails + (starting at the first character in the string), the starting point skips on to start the next attempt at "c". Note that a possessive quan- - tifer does not have the same effect as this example; although it would - suppress backtracking during the first match attempt, the second - attempt would start at the second character instead of skipping on to + tifer does not have the same effect as this example; although it would + suppress backtracking during the first match attempt, the second + attempt would start at the second character instead of skipping on to "c". (*SKIP:NAME) When (*SKIP) has an associated name, its behaviour is modified. When it is triggered, the previous path through the pattern is searched for the - most recent (*MARK) that has the same name. If one is found, the + most recent (*MARK) that has the same name. If one is found, the "bumpalong" advance is to the subject position that corresponds to that (*MARK) instead of to where (*SKIP) was encountered. If no (*MARK) with a matching name is found, the (*SKIP) is ignored. - Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It + Note that (*SKIP:NAME) searches only for names set by (*MARK:NAME). It ignores names that are set by (*PRUNE:NAME) or (*THEN:NAME). (*THEN) or (*THEN:NAME) - This verb causes a skip to the next innermost alternative when back- - tracking reaches it. That is, it cancels any further backtracking - within the current alternative. Its name comes from the observation + This verb causes a skip to the next innermost alternative when back- + tracking reaches it. That is, it cancels any further backtracking + within the current alternative. Its name comes from the observation that it can be used for a pattern-based if-then-else block: ( COND1 (*THEN) FOO | COND2 (*THEN) BAR | COND3 (*THEN) BAZ ) ... - If the COND1 pattern matches, FOO is tried (and possibly further items - after the end of the group if FOO succeeds); on failure, the matcher - skips to the second alternative and tries COND2, without backtracking - into COND1. If that succeeds and BAR fails, COND3 is tried. If subse- - quently BAZ fails, there are no more alternatives, so there is a back- - track to whatever came before the entire group. If (*THEN) is not + If the COND1 pattern matches, FOO is tried (and possibly further items + after the end of the group if FOO succeeds); on failure, the matcher + skips to the second alternative and tries COND2, without backtracking + into COND1. If that succeeds and BAR fails, COND3 is tried. If subse- + quently BAZ fails, there are no more alternatives, so there is a back- + track to whatever came before the entire group. If (*THEN) is not inside an alternation, it acts like (*PRUNE). - The behaviour of (*THEN:NAME) is the not the same as - (*MARK:NAME)(*THEN). It is like (*MARK:NAME) in that the name is - remembered for passing back to the caller. However, (*SKIP:NAME) + The behaviour of (*THEN:NAME) is the not the same as + (*MARK:NAME)(*THEN). It is like (*MARK:NAME) in that the name is + remembered for passing back to the caller. However, (*SKIP:NAME) searches only for names set with (*MARK). - A subpattern that does not contain a | character is just a part of the - enclosing alternative; it is not a nested alternation with only one - alternative. The effect of (*THEN) extends beyond such a subpattern to - the enclosing alternative. Consider this pattern, where A, B, etc. are - complex pattern fragments that do not contain any | characters at this + A subpattern that does not contain a | character is just a part of the + enclosing alternative; it is not a nested alternation with only one + alternative. The effect of (*THEN) extends beyond such a subpattern to + the enclosing alternative. Consider this pattern, where A, B, etc. are + complex pattern fragments that do not contain any | characters at this level: A (B(*THEN)C) | D - If A and B are matched, but there is a failure in C, matching does not + If A and B are matched, but there is a failure in C, matching does not backtrack into A; instead it moves to the next alternative, that is, D. - However, if the subpattern containing (*THEN) is given an alternative, + However, if the subpattern containing (*THEN) is given an alternative, it behaves differently: A (B(*THEN)C | (*FAIL)) | D - The effect of (*THEN) is now confined to the inner subpattern. After a + The effect of (*THEN) is now confined to the inner subpattern. After a failure in C, matching moves to (*FAIL), which causes the whole subpat- - tern to fail because there are no more alternatives to try. In this + tern to fail because there are no more alternatives to try. In this case, matching does now backtrack into A. - Note that a conditional subpattern is not considered as having two - alternatives, because only one is ever used. In other words, the | + Note that a conditional subpattern is not considered as having two + alternatives, because only one is ever used. In other words, the | character in a conditional subpattern has a different meaning. Ignoring white space, consider: ^.*? (?(?=a) a | b(*THEN)c ) - If the subject is "ba", this pattern does not match. Because .*? is - ungreedy, it initially matches zero characters. The condition (?=a) - then fails, the character "b" is matched, but "c" is not. At this - point, matching does not backtrack to .*? as might perhaps be expected - from the presence of the | character. The conditional subpattern is + If the subject is "ba", this pattern does not match. Because .*? is + ungreedy, it initially matches zero characters. The condition (?=a) + then fails, the character "b" is matched, but "c" is not. At this + point, matching does not backtrack to .*? as might perhaps be expected + from the presence of the | character. The conditional subpattern is part of the single alternative that comprises the whole pattern, and so - the match fails. (If there was a backtrack into .*?, allowing it to + the match fails. (If there was a backtrack into .*?, allowing it to match "b", the match would succeed.) - The verbs just described provide four different "strengths" of control + The verbs just described provide four different "strengths" of control when subsequent matching fails. (*THEN) is the weakest, carrying on the - match at the next alternative. (*PRUNE) comes next, failing the match - at the current starting position, but allowing an advance to the next - character (for an unanchored pattern). (*SKIP) is similar, except that + match at the next alternative. (*PRUNE) comes next, failing the match + at the current starting position, but allowing an advance to the next + character (for an unanchored pattern). (*SKIP) is similar, except that the advance may be more than one character. (*COMMIT) is the strongest, causing the entire match to fail. More than one backtracking verb - If more than one backtracking verb is present in a pattern, the one - that is backtracked onto first acts. For example, consider this pat- + If more than one backtracking verb is present in a pattern, the one + that is backtracked onto first acts. For example, consider this pat- tern, where A, B, etc. are complex pattern fragments: (A(*COMMIT)B(*THEN)C|ABD) - If A matches but B fails, the backtrack to (*COMMIT) causes the entire + If A matches but B fails, the backtrack to (*COMMIT) causes the entire match to fail. However, if A and B match, but C fails, the backtrack to - (*THEN) causes the next alternative (ABD) to be tried. This behaviour - is consistent, but is not always the same as Perl's. It means that if - two or more backtracking verbs appear in succession, all the the last + (*THEN) causes the next alternative (ABD) to be tried. This behaviour + is consistent, but is not always the same as Perl's. It means that if + two or more backtracking verbs appear in succession, all the the last of them has no effect. Consider this example: ...(*COMMIT)(*PRUNE)... If there is a matching failure to the right, backtracking onto (*PRUNE) - causes it to be triggered, and its action is taken. There can never be + causes it to be triggered, and its action is taken. There can never be a backtrack onto (*COMMIT). Backtracking verbs in repeated groups - PCRE differs from Perl in its handling of backtracking verbs in + PCRE differs from Perl in its handling of backtracking verbs in repeated groups. For example, consider: /(a(*COMMIT)b)+ac/ - If the subject is "abac", Perl matches, but PCRE fails because the + If the subject is "abac", Perl matches, but PCRE fails because the (*COMMIT) in the second repeat of the group acts. Backtracking verbs in assertions - (*FAIL) in an assertion has its normal effect: it forces an immediate + (*FAIL) in an assertion has its normal effect: it forces an immediate backtrack. (*ACCEPT) in a positive assertion causes the assertion to succeed with- - out any further processing. In a negative assertion, (*ACCEPT) causes + out any further processing. In a negative assertion, (*ACCEPT) causes the assertion to fail without any further processing. - The other backtracking verbs are not treated specially if they appear - in a positive assertion. In particular, (*THEN) skips to the next - alternative in the innermost enclosing group that has alternations, + The other backtracking verbs are not treated specially if they appear + in a positive assertion. In particular, (*THEN) skips to the next + alternative in the innermost enclosing group that has alternations, whether or not this is within the assertion. - Negative assertions are, however, different, in order to ensure that - changing a positive assertion into a negative assertion changes its + Negative assertions are, however, different, in order to ensure that + changing a positive assertion into a negative assertion changes its result. Backtracking into (*COMMIT), (*SKIP), or (*PRUNE) causes a neg- ative assertion to be true, without considering any further alternative branches in the assertion. Backtracking into (*THEN) causes it to skip - to the next enclosing alternative within the assertion (the normal be- - haviour), but if the assertion does not have such an alternative, + to the next enclosing alternative within the assertion (the normal be- + haviour), but if the assertion does not have such an alternative, (*THEN) behaves like (*PRUNE). Backtracking verbs in subroutines - These behaviours occur whether or not the subpattern is called recur- + These behaviours occur whether or not the subpattern is called recur- sively. Perl's treatment of subroutines is different in some cases. - (*FAIL) in a subpattern called as a subroutine has its normal effect: + (*FAIL) in a subpattern called as a subroutine has its normal effect: it forces an immediate backtrack. - (*ACCEPT) in a subpattern called as a subroutine causes the subroutine - match to succeed without any further processing. Matching then contin- + (*ACCEPT) in a subpattern called as a subroutine causes the subroutine + match to succeed without any further processing. Matching then contin- ues after the subroutine call. (*COMMIT), (*SKIP), and (*PRUNE) in a subpattern called as a subroutine cause the subroutine match to fail. - (*THEN) skips to the next alternative in the innermost enclosing group - within the subpattern that has alternatives. If there is no such group + (*THEN) skips to the next alternative in the innermost enclosing group + within the subpattern that has alternatives. If there is no such group within the subpattern, (*THEN) causes the subroutine match to fail. SEE ALSO - pcreapi(3), pcrecallout(3), pcrematching(3), pcresyntax(3), pcre(3), + pcreapi(3), pcrecallout(3), pcrematching(3), pcresyntax(3), pcre(3), pcre16(3), pcre32(3). @@ -7645,8 +7669,8 @@ AUTHOR REVISION - Last updated: 08 January 2014 - Copyright (c) 1997-2014 University of Cambridge. + Last updated: 14 June 2015 + Copyright (c) 1997-2015 University of Cambridge. ------------------------------------------------------------------------------ diff --git a/ext/pcre/pcrelib/pcre.h b/ext/pcre/pcrelib/pcre.h index 58ed46a2a3..bf6351f883 100644 --- a/ext/pcre/pcrelib/pcre.h +++ b/ext/pcre/pcrelib/pcre.h @@ -42,9 +42,9 @@ POSSIBILITY OF SUCH DAMAGE. /* The current PCRE version information. */ #define PCRE_MAJOR 8 -#define PCRE_MINOR 37 +#define PCRE_MINOR 38 #define PCRE_PRERELEASE -#define PCRE_DATE 2015-04-28 +#define PCRE_DATE 2015-11-23 /* When an application links to a PCRE DLL in Windows, the symbols that are imported have to be identified as such. When building PCRE, the appropriate diff --git a/ext/pcre/pcrelib/pcre_compile.c b/ext/pcre/pcrelib/pcre_compile.c index 9a32becb50..11a9d26ff6 100644 --- a/ext/pcre/pcrelib/pcre_compile.c +++ b/ext/pcre/pcrelib/pcre_compile.c @@ -172,7 +172,7 @@ static const short int escapes[] = { -ESC_Z, CHAR_LEFT_SQUARE_BRACKET, CHAR_BACKSLASH, CHAR_RIGHT_SQUARE_BRACKET, CHAR_CIRCUMFLEX_ACCENT, CHAR_UNDERSCORE, - CHAR_GRAVE_ACCENT, 7, + CHAR_GRAVE_ACCENT, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, @@ -200,9 +200,9 @@ static const short int escapes[] = { /* 68 */ 0, 0, '|', ',', '%', '_', '>', '?', /* 70 */ 0, 0, 0, 0, 0, 0, 0, 0, /* 78 */ 0, '`', ':', '#', '@', '\'', '=', '"', -/* 80 */ 0, 7, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, +/* 80 */ 0, ESC_a, -ESC_b, 0, -ESC_d, ESC_e, ESC_f, 0, /* 88 */-ESC_h, 0, 0, '{', 0, 0, 0, 0, -/* 90 */ 0, 0, -ESC_k, 'l', 0, ESC_n, 0, -ESC_p, +/* 90 */ 0, 0, -ESC_k, 0, 0, ESC_n, 0, -ESC_p, /* 98 */ 0, ESC_r, 0, '}', 0, 0, 0, 0, /* A0 */ 0, '~', -ESC_s, ESC_tee, 0,-ESC_v, -ESC_w, 0, /* A8 */ 0,-ESC_z, 0, 0, 0, '[', 0, 0, @@ -217,6 +217,12 @@ static const short int escapes[] = { /* F0 */ 0, 0, 0, 0, 0, 0, 0, 0, /* F8 */ 0, 0, 0, 0, 0, 0, 0, 0 }; + +/* We also need a table of characters that may follow \c in an EBCDIC +environment for characters 0-31. */ + +static unsigned char ebcdic_escape_c[] = "@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"; + #endif @@ -456,7 +462,7 @@ static const char error_texts[] = "range out of order in character class\0" "nothing to repeat\0" /* 10 */ - "operand of unlimited repeat could match the empty string\0" /** DEAD **/ + "internal error: invalid forward reference offset\0" "internal error: unexpected repeat\0" "unrecognized character after (? or (?-\0" "POSIX named classes are supported only within a class\0" @@ -525,7 +531,11 @@ static const char error_texts[] = "different names for subpatterns of the same number are not allowed\0" "(*MARK) must have an argument\0" "this version of PCRE is not compiled with Unicode property support\0" +#ifndef EBCDIC "\\c must be followed by an ASCII character\0" +#else + "\\c must be followed by a letter or one of [\\]^_?\0" +#endif "\\k is not followed by a braced, angle-bracketed, or quoted name\0" /* 70 */ "internal error: unknown opcode in find_fixedlength()\0" @@ -1423,7 +1433,16 @@ else c ^= 0x40; #else /* EBCDIC coding */ if (c >= CHAR_a && c <= CHAR_z) c += 64; - c ^= 0xC0; + if (c == CHAR_QUESTION_MARK) + c = ('\\' == 188 && '`' == 74)? 0x5f : 0xff; + else + { + for (i = 0; i < 32; i++) + { + if (c == ebcdic_escape_c[i]) break; + } + if (i < 32) c = i; else *errorcodeptr = ERR68; + } #endif break; @@ -1797,7 +1816,7 @@ for (;;) case OP_ASSERTBACK: case OP_ASSERTBACK_NOT: do cc += GET(cc, 1); while (*cc == OP_ALT); - cc += PRIV(OP_lengths)[*cc]; + cc += 1 + LINK_SIZE; break; /* Skip over things that don't match chars */ @@ -2485,7 +2504,7 @@ for (code = first_significant_code(code + PRIV(OP_lengths)[*code], TRUE); if (c == OP_BRA || c == OP_BRAPOS || c == OP_CBRA || c == OP_CBRAPOS || c == OP_ONCE || c == OP_ONCE_NC || - c == OP_COND) + c == OP_COND || c == OP_SCOND) { BOOL empty_branch; if (GET(code, 1) == 0) return TRUE; /* Hit unclosed bracket */ @@ -3884,11 +3903,11 @@ didn't consider this to be a POSIX class. Likewise for [:1234:]. The problem in trying to be exactly like Perl is in the handling of escapes. We have to be sure that [abc[:x\]pqr] is *not* treated as containing a POSIX class, but [abc[:x\]pqr:]] is (so that an error can be generated). The code -below handles the special case of \], but does not try to do any other escape -processing. This makes it different from Perl for cases such as [:l\ower:] -where Perl recognizes it as the POSIX class "lower" but PCRE does not recognize -"l\ower". This is a lesser evil than not diagnosing bad classes when Perl does, -I think. +below handles the special cases \\ and \], but does not try to do any other +escape processing. This makes it different from Perl for cases such as +[:l\ower:] where Perl recognizes it as the POSIX class "lower" but PCRE does +not recognize "l\ower". This is a lesser evil than not diagnosing bad classes +when Perl does, I think. A user pointed out that PCRE was rejecting [:a[:digit:]] whereas Perl was not. It seems that the appearance of a nested POSIX class supersedes an apparent @@ -3915,21 +3934,16 @@ pcre_uchar terminator; /* Don't combine these lines; the Solaris cc */ terminator = *(++ptr); /* compiler warns about "non-constant" initializer. */ for (++ptr; *ptr != CHAR_NULL; ptr++) { - if (*ptr == CHAR_BACKSLASH && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) + if (*ptr == CHAR_BACKSLASH && + (ptr[1] == CHAR_RIGHT_SQUARE_BRACKET || + ptr[1] == CHAR_BACKSLASH)) ptr++; - else if (*ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE; - else + else if ((*ptr == CHAR_LEFT_SQUARE_BRACKET && ptr[1] == terminator) || + *ptr == CHAR_RIGHT_SQUARE_BRACKET) return FALSE; + else if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) { - if (*ptr == terminator && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) - { - *endptr = ptr; - return TRUE; - } - if (*ptr == CHAR_LEFT_SQUARE_BRACKET && - (ptr[1] == CHAR_COLON || ptr[1] == CHAR_DOT || - ptr[1] == CHAR_EQUALS_SIGN) && - check_posix_syntax(ptr, endptr)) - return FALSE; + *endptr = ptr; + return TRUE; } } return FALSE; @@ -3983,11 +3997,12 @@ have their offsets adjusted. That one of the jobs of this function. Before it is called, the partially compiled regex must be temporarily terminated with OP_END. -This function has been extended with the possibility of forward references for -recursions and subroutine calls. It must also check the list of such references -for the group we are dealing with. If it finds that one of the recursions in -the current group is on this list, it adjusts the offset in the list, not the -value in the reference (which is a group number). +This function has been extended to cope with forward references for recursions +and subroutine calls. It must check the list of such references for the +group we are dealing with. If it finds that one of the recursions in the +current group is on this list, it does not adjust the value in the reference +(which is a group number). After the group has been scanned, all the offsets in +the forward reference list for the group are adjusted. Arguments: group points to the start of the group @@ -4003,29 +4018,21 @@ static void adjust_recurse(pcre_uchar *group, int adjust, BOOL utf, compile_data *cd, size_t save_hwm_offset) { +int offset; +pcre_uchar *hc; pcre_uchar *ptr = group; while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL) { - int offset; - pcre_uchar *hc; - - /* See if this recursion is on the forward reference list. If so, adjust the - reference. */ - for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; hc += LINK_SIZE) { offset = (int)GET(hc, 0); - if (cd->start_code + offset == ptr + 1) - { - PUT(hc, 0, offset + adjust); - break; - } + if (cd->start_code + offset == ptr + 1) break; } - /* Otherwise, adjust the recursion offset if it's after the start of this - group. */ + /* If we have not found this recursion on the forward reference list, adjust + the recursion's offset if it's after the start of this group. */ if (hc >= cd->hwm) { @@ -4035,6 +4042,15 @@ while ((ptr = (pcre_uchar *)find_recurse(ptr, utf)) != NULL) ptr += 1 + LINK_SIZE; } + +/* Now adjust all forward reference offsets for the group. */ + +for (hc = (pcre_uchar *)cd->start_workspace + save_hwm_offset; hc < cd->hwm; + hc += LINK_SIZE) + { + offset = (int)GET(hc, 0); + PUT(hc, 0, offset + adjust); + } } @@ -4463,7 +4479,7 @@ const pcre_uchar *tempptr; const pcre_uchar *nestptr = NULL; pcre_uchar *previous = NULL; pcre_uchar *previous_callout = NULL; -size_t save_hwm_offset = 0; +size_t item_hwm_offset = 0; pcre_uint8 classbits[32]; /* We can fish out the UTF-8 setting once and for all into a BOOL, but we @@ -4621,8 +4637,7 @@ for (;; ptr++) /* In the real compile phase, just check the workspace used by the forward reference list. */ - else if (cd->hwm > cd->start_workspace + cd->workspace_size - - WORK_SIZE_SAFETY_MARGIN) + else if (cd->hwm > cd->start_workspace + cd->workspace_size) { *errorcodeptr = ERR52; goto FAILED; @@ -4765,6 +4780,7 @@ for (;; ptr++) zeroreqchar = reqchar; zeroreqcharflags = reqcharflags; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_DOTALL) != 0)? OP_ALLANY: OP_ANY; break; @@ -4816,6 +4832,7 @@ for (;; ptr++) /* Handle a real character class. */ previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; /* PCRE supports POSIX class stuff inside a class. Perl gives an error if they are encountered at the top level, so we'll do that too. */ @@ -4921,9 +4938,10 @@ for (;; ptr++) (which is on the stack). We have to remember that there was XCLASS data, however. */ + if (class_uchardata > class_uchardata_base) xclass = TRUE; + if (lengthptr != NULL && class_uchardata > class_uchardata_base) { - xclass = TRUE; *lengthptr += (int)(class_uchardata - class_uchardata_base); class_uchardata = class_uchardata_base; } @@ -5026,10 +5044,26 @@ for (;; ptr++) ptr = tempptr + 1; continue; - /* For all other POSIX classes, no special action is taken in UCP - mode. Fall through to the non_UCP case. */ + /* For the other POSIX classes (ascii, xdigit) we are going to fall + through to the non-UCP case and build a bit map for characters with + code points less than 256. If we are in a negated POSIX class + within a non-negated overall class, characters with code points + greater than 255 must all match. In the special case where we have + not yet generated any xclass data, and this is the final item in + the overall class, we need do nothing: later on, the opcode + OP_NCLASS will be used to indicate that characters greater than 255 + are acceptable. If we have already seen an xclass item or one may + follow (we have to assume that it might if this is not the end of + the class), explicitly match all wide codepoints. */ default: + if (!negate_class && local_negate && + (xclass || tempptr[2] != CHAR_RIGHT_SQUARE_BRACKET)) + { + *class_uchardata++ = XCL_RANGE; + class_uchardata += PRIV(ord2utf)(0x100, class_uchardata); + class_uchardata += PRIV(ord2utf)(0x10ffff, class_uchardata); + } break; } } @@ -5193,9 +5227,9 @@ for (;; ptr++) cd, PRIV(vspace_list)); continue; -#ifdef SUPPORT_UCP case ESC_p: case ESC_P: +#ifdef SUPPORT_UCP { BOOL negated; unsigned int ptype = 0, pdata = 0; @@ -5209,6 +5243,9 @@ for (;; ptr++) class_has_8bitchar--; /* Undo! */ continue; } +#else + *errorcodeptr = ERR45; + goto FAILED; #endif /* Unrecognized escapes are faulted if PCRE is running in its strict mode. By default, for compatibility with Perl, they are @@ -5365,16 +5402,20 @@ for (;; ptr++) CLASS_SINGLE_CHARACTER: if (class_one_char < 2) class_one_char++; - /* If class_one_char is 1, we have the first single character in the - class, and there have been no prior ranges, or XCLASS items generated by - escapes. If this is the final character in the class, we can optimize by - turning the item into a 1-character OP_CHAR[I] if it's positive, or - OP_NOT[I] if it's negative. In the positive case, it can cause firstchar - to be set. Otherwise, there can be no first char if this item is first, - whatever repeat count may follow. In the case of reqchar, save the - previous value for reinstating. */ + /* If xclass_has_prop is false and class_one_char is 1, we have the first + single character in the class, and there have been no prior ranges, or + XCLASS items generated by escapes. If this is the final character in the + class, we can optimize by turning the item into a 1-character OP_CHAR[I] + if it's positive, or OP_NOT[I] if it's negative. In the positive case, it + can cause firstchar to be set. Otherwise, there can be no first char if + this item is first, whatever repeat count may follow. In the case of + reqchar, save the previous value for reinstating. */ - if (!inescq && class_one_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) + if (!inescq && +#ifdef SUPPORT_UCP + !xclass_has_prop && +#endif + class_one_char == 1 && ptr[1] == CHAR_RIGHT_SQUARE_BRACKET) { ptr++; zeroreqchar = reqchar; @@ -5490,9 +5531,10 @@ for (;; ptr++) actual compiled code. */ #ifdef SUPPORT_UTF - if (xclass && (!should_flip_negation || (options & PCRE_UCP) != 0)) + if (xclass && (xclass_has_prop || !should_flip_negation || + (options & PCRE_UCP) != 0)) #elif !defined COMPILE_PCRE8 - if (xclass && !should_flip_negation) + if (xclass && (xclass_has_prop || !should_flip_negation)) #endif #if defined SUPPORT_UTF || !defined COMPILE_PCRE8 { @@ -5928,7 +5970,7 @@ for (;; ptr++) { register int i; int len = (int)(code - previous); - size_t base_hwm_offset = save_hwm_offset; + size_t base_hwm_offset = item_hwm_offset; pcre_uchar *bralink = NULL; pcre_uchar *brazeroptr = NULL; @@ -5983,7 +6025,7 @@ for (;; ptr++) if (repeat_max <= 1) /* Covers 0, 1, and unlimited */ { *code = OP_END; - adjust_recurse(previous, 1, utf, cd, save_hwm_offset); + adjust_recurse(previous, 1, utf, cd, item_hwm_offset); memmove(previous + 1, previous, IN_UCHARS(len)); code++; if (repeat_max == 0) @@ -6007,7 +6049,7 @@ for (;; ptr++) { int offset; *code = OP_END; - adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(previous, 2 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(previous + 2 + LINK_SIZE, previous, IN_UCHARS(len)); code += 2 + LINK_SIZE; *previous++ = OP_BRAZERO + repeat_type; @@ -6252,6 +6294,12 @@ for (;; ptr++) while (*scode == OP_ALT); } + /* A conditional group with only one branch has an implicit empty + alternative branch. */ + + if (*bracode == OP_COND && bracode[GET(bracode,1)] != OP_ALT) + *bracode = OP_SCOND; + /* Handle possessive quantifiers. */ if (possessive_quantifier) @@ -6265,11 +6313,11 @@ for (;; ptr++) { int nlen = (int)(code - bracode); *code = OP_END; - adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(bracode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(bracode + 1 + LINK_SIZE, bracode, IN_UCHARS(nlen)); code += 1 + LINK_SIZE; nlen += 1 + LINK_SIZE; - *bracode = OP_BRAPOS; + *bracode = (*bracode == OP_COND)? OP_BRAPOS : OP_SBRAPOS; *code++ = OP_KETRPOS; PUTINC(code, 0, nlen); PUT(bracode, 1, nlen); @@ -6399,7 +6447,7 @@ for (;; ptr++) else { *code = OP_END; - adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); code += 1 + LINK_SIZE; len += 1 + LINK_SIZE; @@ -6448,7 +6496,7 @@ for (;; ptr++) default: *code = OP_END; - adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, save_hwm_offset); + adjust_recurse(tempcode, 1 + LINK_SIZE, utf, cd, item_hwm_offset); memmove(tempcode + 1 + LINK_SIZE, tempcode, IN_UCHARS(len)); code += 1 + LINK_SIZE; len += 1 + LINK_SIZE; @@ -6584,9 +6632,17 @@ for (;; ptr++) goto FAILED; } setverb = *code++ = verbs[i].op_arg; - *code++ = arglen; - memcpy(code, arg, IN_UCHARS(arglen)); - code += arglen; + if (lengthptr != NULL) /* In pass 1 just add in the length */ + { /* to avoid potential workspace */ + *lengthptr += arglen; /* overflow. */ + *code++ = 0; + } + else + { + *code++ = arglen; + memcpy(code, arg, IN_UCHARS(arglen)); + code += arglen; + } *code++ = 0; } @@ -6621,7 +6677,7 @@ for (;; ptr++) newoptions = options; skipbytes = 0; bravalue = OP_CBRA; - save_hwm_offset = cd->hwm - cd->start_workspace; + item_hwm_offset = cd->hwm - cd->start_workspace; reset_bracount = FALSE; /* Deal with the extended parentheses; all are introduced by '?', and the @@ -6639,6 +6695,7 @@ for (;; ptr++) /* ------------------------------------------------------------ */ case CHAR_VERTICAL_LINE: /* Reset capture count for each branch */ reset_bracount = TRUE; + cd->dupgroups = TRUE; /* Record (?| encountered */ /* Fall through */ /* ------------------------------------------------------------ */ @@ -6739,6 +6796,12 @@ for (;; ptr++) { while (IS_DIGIT(*ptr)) { + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + while (IS_DIGIT(*ptr)) ptr++; + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + (int)(*ptr - CHAR_0); ptr++; } @@ -6767,7 +6830,7 @@ for (;; ptr++) ptr++; } namelen = (int)(ptr - name); - if (lengthptr != NULL) *lengthptr += IMM2_SIZE; + if (lengthptr != NULL) skipbytes += IMM2_SIZE; } /* Check the terminator */ @@ -6873,6 +6936,11 @@ for (;; ptr++) *errorcodeptr = ERR15; goto FAILED; } + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + name[i] - CHAR_0; } if (recno == 0) recno = RREF_ANY; @@ -7149,6 +7217,7 @@ for (;; ptr++) if (lengthptr != NULL) { named_group *ng; + recno = 0; if (namelen == 0) { @@ -7166,20 +7235,6 @@ for (;; ptr++) goto FAILED; } - /* The name table does not exist in the first pass; instead we must - scan the list of names encountered so far in order to get the - number. If the name is not found, set the value to 0 for a forward - reference. */ - - ng = cd->named_groups; - for (i = 0; i < cd->names_found; i++, ng++) - { - if (namelen == ng->length && - STRNCMP_UC_UC(name, ng->name, namelen) == 0) - break; - } - recno = (i < cd->names_found)? ng->number : 0; - /* Count named back references. */ if (!is_recurse) cd->namedrefcount++; @@ -7189,6 +7244,56 @@ for (;; ptr++) 16-bit data item. */ *lengthptr += IMM2_SIZE; + + /* If this is a forward reference and we are within a (?|...) group, + the reference may end up as the number of a group which we are + currently inside, that is, it could be a recursive reference. In the + real compile this will be picked up and the reference wrapped with + OP_ONCE to make it atomic, so we must space in case this occurs. */ + + /* In fact, this can happen for a non-forward reference because + another group with the same number might be created later. This + issue is fixed "properly" in PCRE2. As PCRE1 is now in maintenance + only mode, we finesse the bug by allowing more memory always. */ + + *lengthptr += 2 + 2*LINK_SIZE; + + /* It is even worse than that. The current reference may be to an + existing named group with a different number (so apparently not + recursive) but which later on is also attached to a group with the + current number. This can only happen if $(| has been previous + encountered. In that case, we allow yet more memory, just in case. + (Again, this is fixed "properly" in PCRE2. */ + + if (cd->dupgroups) *lengthptr += 4 + 4*LINK_SIZE; + + /* Otherwise, check for recursion here. The name table does not exist + in the first pass; instead we must scan the list of names encountered + so far in order to get the number. If the name is not found, leave + the value of recno as 0 for a forward reference. */ + + else + { + ng = cd->named_groups; + for (i = 0; i < cd->names_found; i++, ng++) + { + if (namelen == ng->length && + STRNCMP_UC_UC(name, ng->name, namelen) == 0) + { + open_capitem *oc; + recno = ng->number; + if (is_recurse) break; + for (oc = cd->open_caps; oc != NULL; oc = oc->next) + { + if (oc->number == recno) + { + oc->flag = TRUE; + break; + } + } + } + } + } } /* In the real compile, search the name table. We check the name @@ -7235,8 +7340,6 @@ for (;; ptr++) for (i++; i < cd->names_found; i++) { if (STRCMP_UC_UC(slot + IMM2_SIZE, cslot + IMM2_SIZE) != 0) break; - - count++; cslot += cd->name_entry_size; } @@ -7245,6 +7348,7 @@ for (;; ptr++) { if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_CASELESS) != 0)? OP_DNREFI : OP_DNREF; PUT2INC(code, 0, index); PUT2INC(code, 0, count); @@ -7282,9 +7386,14 @@ for (;; ptr++) /* ------------------------------------------------------------ */ - case CHAR_R: /* Recursion */ - ptr++; /* Same as (?0) */ - /* Fall through */ + case CHAR_R: /* Recursion, same as (?0) */ + recno = 0; + if (*(++ptr) != CHAR_RIGHT_PARENTHESIS) + { + *errorcodeptr = ERR29; + goto FAILED; + } + goto HANDLE_RECURSION; /* ------------------------------------------------------------ */ @@ -7321,7 +7430,15 @@ for (;; ptr++) recno = 0; while(IS_DIGIT(*ptr)) + { + if (recno > INT_MAX / 10 - 1) /* Integer overflow */ + { + while (IS_DIGIT(*ptr)) ptr++; + *errorcodeptr = ERR61; + goto FAILED; + } recno = recno * 10 + *ptr++ - CHAR_0; + } if (*ptr != (pcre_uchar)terminator) { @@ -7358,6 +7475,7 @@ for (;; ptr++) HANDLE_RECURSION: previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; called = cd->start_code; /* When we are actually compiling, find the bracket that is being @@ -7559,7 +7677,11 @@ for (;; ptr++) previous = NULL; cd->iscondassert = FALSE; } - else previous = code; + else + { + previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; + } *code = bravalue; tempcode = code; @@ -7807,7 +7929,7 @@ for (;; ptr++) const pcre_uchar *p; pcre_uint32 cf; - save_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */ + item_hwm_offset = cd->hwm - cd->start_workspace; /* Normally this is set when '(' is read */ terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? CHAR_GREATER_THAN_SIGN : CHAR_APOSTROPHE; @@ -7836,7 +7958,7 @@ for (;; ptr++) if (*p != (pcre_uchar)terminator) { *errorcodeptr = ERR57; - break; + goto FAILED; } ptr++; goto HANDLE_NUMERICAL_RECURSION; @@ -7851,7 +7973,7 @@ for (;; ptr++) ptr[1] != CHAR_APOSTROPHE && ptr[1] != CHAR_LEFT_CURLY_BRACKET)) { *errorcodeptr = ERR69; - break; + goto FAILED; } is_recurse = FALSE; terminator = (*(++ptr) == CHAR_LESS_THAN_SIGN)? @@ -7875,6 +7997,7 @@ for (;; ptr++) HANDLE_REFERENCE: if (firstcharflags == REQ_UNSET) firstcharflags = REQ_NONE; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((options & PCRE_CASELESS) != 0)? OP_REFI : OP_REF; PUT2INC(code, 0, recno); cd->backref_map |= (recno < 32)? (1 << recno) : 1; @@ -7904,6 +8027,7 @@ for (;; ptr++) if (!get_ucp(&ptr, &negated, &ptype, &pdata, errorcodeptr)) goto FAILED; previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = ((escape == ESC_p) != negated)? OP_PROP : OP_NOTPROP; *code++ = ptype; *code++ = pdata; @@ -7944,6 +8068,7 @@ for (;; ptr++) { previous = (escape > ESC_b && escape < ESC_Z)? code : NULL; + item_hwm_offset = cd->hwm - cd->start_workspace; *code++ = (!utf && escape == ESC_C)? OP_ALLANY : escape; } } @@ -7987,6 +8112,7 @@ for (;; ptr++) ONE_CHAR: previous = code; + item_hwm_offset = cd->hwm - cd->start_workspace; /* For caseless UTF-8 mode when UCP support is available, check whether this character has more than one other case. If so, generate a special @@ -9162,6 +9288,7 @@ cd->names_found = 0; cd->name_entry_size = 0; cd->name_table = NULL; cd->dupnames = FALSE; +cd->dupgroups = FALSE; cd->namedrefcount = 0; cd->start_code = cworkspace; cd->hwm = cworkspace; @@ -9334,6 +9461,16 @@ if (cd->hwm > cd->start_workspace) int offset, recno; cd->hwm -= LINK_SIZE; offset = GET(cd->hwm, 0); + + /* Check that the hwm handling hasn't gone wrong. This whole area is + rewritten in PCRE2 because there are some obscure cases. */ + + if (offset == 0 || codestart[offset-1] != OP_RECURSE) + { + errorcode = ERR10; + break; + } + recno = GET(codestart, offset); if (recno != prev_recno) { @@ -9364,7 +9501,7 @@ used in this code because at least one compiler gives a warning about loss of "const" attribute if the cast (pcre_uchar *)codestart is used directly in the function call. */ -if ((options & PCRE_NO_AUTO_POSSESS) == 0) +if (errorcode == 0 && (options & PCRE_NO_AUTO_POSSESS) == 0) { pcre_uchar *temp = (pcre_uchar *)codestart; auto_possessify(temp, utf, cd); @@ -9378,7 +9515,7 @@ OP_RECURSE that are not fixed length get a diagnosic with a useful offset. The exceptional ones forgo this. We scan the pattern to check that they are fixed length, and set their lengths. */ -if (cd->check_lookbehind) +if (errorcode == 0 && cd->check_lookbehind) { pcre_uchar *cc = (pcre_uchar *)codestart; @@ -9591,4 +9728,3 @@ return (pcre32 *)re; } /* End of pcre_compile.c */ - diff --git a/ext/pcre/pcrelib/pcre_exec.c b/ext/pcre/pcrelib/pcre_exec.c index f64a1410cd..c783ff6e7e 100644 --- a/ext/pcre/pcrelib/pcre_exec.c +++ b/ext/pcre/pcrelib/pcre_exec.c @@ -686,7 +686,7 @@ the alternative names that are used. */ #define foc number #define save_mark data -/* These statements are here to stop the compiler complaining about uninitialized +/* These statements are here to stop the compiler complaining about unitialized variables. */ #ifdef SUPPORT_UCP @@ -6683,7 +6683,8 @@ if (md->offset_vector != NULL) register int *iend = iptr - re->top_bracket; if (iend < md->offset_vector + 2) iend = md->offset_vector + 2; while (--iptr >= iend) *iptr = -1; - md->offset_vector[0] = md->offset_vector[1] = -1; + if (offsetcount > 0) md->offset_vector[0] = -1; + if (offsetcount > 1) md->offset_vector[1] = -1; } /* Set up the first character to match, if available. The first_char value is diff --git a/ext/pcre/pcrelib/pcre_internal.h b/ext/pcre/pcrelib/pcre_internal.h index dd0ac7fc91..f7a5ee7aa6 100644 --- a/ext/pcre/pcrelib/pcre_internal.h +++ b/ext/pcre/pcrelib/pcre_internal.h @@ -984,7 +984,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ #ifndef EBCDIC #define HSPACE_LIST \ - CHAR_HT, CHAR_SPACE, 0xa0, \ + CHAR_HT, CHAR_SPACE, CHAR_NBSP, \ 0x1680, 0x180e, 0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005, \ 0x2006, 0x2007, 0x2008, 0x2009, 0x200A, 0x202f, 0x205f, 0x3000, \ NOTACHAR @@ -1010,7 +1010,7 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ #define HSPACE_BYTE_CASES \ case CHAR_HT: \ case CHAR_SPACE: \ - case 0xa0 /* NBSP */ + case CHAR_NBSP #define HSPACE_CASES \ HSPACE_BYTE_CASES: \ @@ -1037,11 +1037,12 @@ other. NOTE: The values also appear in pcre_jit_compile.c. */ /* ------ EBCDIC environments ------ */ #else -#define HSPACE_LIST CHAR_HT, CHAR_SPACE +#define HSPACE_LIST CHAR_HT, CHAR_SPACE, CHAR_NBSP, NOTACHAR #define HSPACE_BYTE_CASES \ case CHAR_HT: \ - case CHAR_SPACE + case CHAR_SPACE: \ + case CHAR_NBSP #define HSPACE_CASES HSPACE_BYTE_CASES @@ -1215,6 +1216,7 @@ same code point. */ #define CHAR_ESC '\047' #define CHAR_DEL '\007' +#define CHAR_NBSP '\x41' #define STR_ESC "\047" #define STR_DEL "\007" @@ -1229,6 +1231,7 @@ a positive value. */ #define CHAR_NEL ((unsigned char)'\x85') #define CHAR_ESC '\033' #define CHAR_DEL '\177' +#define CHAR_NBSP ((unsigned char)'\xa0') #define STR_LF "\n" #define STR_NL STR_LF @@ -1606,6 +1609,7 @@ only. */ #define CHAR_VERTICAL_LINE '\174' #define CHAR_RIGHT_CURLY_BRACKET '\175' #define CHAR_TILDE '\176' +#define CHAR_NBSP ((unsigned char)'\xa0') #define STR_HT "\011" #define STR_VT "\013" @@ -1762,6 +1766,10 @@ only. */ /* Escape items that are just an encoding of a particular data value. */ +#ifndef ESC_a +#define ESC_a CHAR_BEL +#endif + #ifndef ESC_e #define ESC_e CHAR_ESC #endif @@ -2446,6 +2454,7 @@ typedef struct compile_data { BOOL had_pruneorskip; /* (*PRUNE) or (*SKIP) encountered */ BOOL check_lookbehind; /* Lookbehinds need later checking */ BOOL dupnames; /* Duplicate names exist */ + BOOL dupgroups; /* Duplicate groups exist: (?| found */ BOOL iscondassert; /* Next assert is a condition */ int nltype; /* Newline type */ int nllen; /* Newline string length */ diff --git a/ext/pcre/pcrelib/pcre_jit_compile.c b/ext/pcre/pcrelib/pcre_jit_compile.c index debdf6ef45..445de0cbef 100644 --- a/ext/pcre/pcrelib/pcre_jit_compile.c +++ b/ext/pcre/pcrelib/pcre_jit_compile.c @@ -1064,6 +1064,7 @@ pcre_uchar *alternative; pcre_uchar *end = NULL; int private_data_ptr = *private_data_start; int space, size, bracketlen; +BOOL repeat_check = TRUE; while (cc < ccend) { @@ -1071,9 +1072,10 @@ while (cc < ccend) size = 0; bracketlen = 0; if (private_data_ptr > SLJIT_MAX_LOCAL_SIZE) - return; + break; - if (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND) + if (repeat_check && (*cc == OP_ONCE || *cc == OP_ONCE_NC || *cc == OP_BRA || *cc == OP_CBRA || *cc == OP_COND)) + { if (detect_repeat(common, cc)) { /* These brackets are converted to repeats, so no global @@ -1081,6 +1083,8 @@ while (cc < ccend) if (cc >= end) end = bracketend(cc); } + } + repeat_check = TRUE; switch(*cc) { @@ -1136,6 +1140,13 @@ while (cc < ccend) bracketlen = 1 + LINK_SIZE + IMM2_SIZE; break; + case OP_BRAZERO: + case OP_BRAMINZERO: + case OP_BRAPOSZERO: + repeat_check = FALSE; + size = 1; + break; + CASE_ITERATOR_PRIVATE_DATA_1 space = 1; size = -2; @@ -1162,12 +1173,17 @@ while (cc < ccend) size = 1; break; - CASE_ITERATOR_TYPE_PRIVATE_DATA_2B + case OP_TYPEUPTO: if (cc[1 + IMM2_SIZE] != OP_ANYNL && cc[1 + IMM2_SIZE] != OP_EXTUNI) space = 2; size = 1 + IMM2_SIZE; break; + case OP_TYPEMINUPTO: + space = 2; + size = 1 + IMM2_SIZE; + break; + case OP_CLASS: case OP_NCLASS: size += 1 + 32 / sizeof(pcre_uchar); @@ -1316,6 +1332,13 @@ while (cc < ccend) cc += 1 + LINK_SIZE + IMM2_SIZE; break; + case OP_THEN: + stack_restore = TRUE; + if (common->control_head_ptr != 0) + *needs_control_head = TRUE; + cc ++; + break; + default: stack_restore = TRUE; /* Fall through. */ @@ -2220,6 +2243,7 @@ while (current != NULL) SLJIT_ASSERT_STOP(); break; } + SLJIT_ASSERT(current > (sljit_sw*)current[-1]); current = (sljit_sw*)current[-1]; } return -1; @@ -3209,7 +3233,7 @@ bytes[len] = byte; bytes[0] = len; } -static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars) +static int scan_prefix(compiler_common *common, pcre_uchar *cc, pcre_uint32 *chars, pcre_uint8 *bytes, int max_chars, pcre_uint32 *rec_count) { /* Recursive function, which scans prefix literals. */ BOOL last, any, caseless; @@ -3227,9 +3251,14 @@ pcre_uchar othercase[1]; repeat = 1; while (TRUE) { + if (*rec_count == 0) + return 0; + (*rec_count)--; + last = TRUE; any = FALSE; caseless = FALSE; + switch (*cc) { case OP_CHARI: @@ -3291,7 +3320,7 @@ while (TRUE) #ifdef SUPPORT_UTF if (common->utf && HAS_EXTRALEN(*cc)) len += GET_EXTRALEN(*cc); #endif - max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars); + max_chars = scan_prefix(common, cc + len, chars, bytes, max_chars, rec_count); if (max_chars == 0) return consumed; last = FALSE; @@ -3314,7 +3343,7 @@ while (TRUE) alternative = cc + GET(cc, 1); while (*alternative == OP_ALT) { - max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars); + max_chars = scan_prefix(common, alternative + 1 + LINK_SIZE, chars, bytes, max_chars, rec_count); if (max_chars == 0) return consumed; alternative += GET(alternative, 1); @@ -3556,6 +3585,7 @@ int i, max, from; int range_right = -1, range_len = 3 - 1; sljit_ub *update_table = NULL; BOOL in_range; +pcre_uint32 rec_count; for (i = 0; i < MAX_N_CHARS; i++) { @@ -3564,7 +3594,8 @@ for (i = 0; i < MAX_N_CHARS; i++) bytes[i * MAX_N_BYTES] = 0; } -max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS); +rec_count = 10000; +max = scan_prefix(common, common->start, chars, bytes, MAX_N_CHARS, &rec_count); if (max <= 1) return FALSE; @@ -4311,8 +4342,10 @@ switch(length) case 4: if ((ranges[1] - ranges[0]) == (ranges[3] - ranges[2]) && (ranges[0] | (ranges[2] - ranges[0])) == ranges[2] + && (ranges[1] & (ranges[2] - ranges[0])) == 0 && is_powerof2(ranges[2] - ranges[0])) { + SLJIT_ASSERT((ranges[0] & (ranges[2] - ranges[0])) == 0 && (ranges[2] & ranges[3] & (ranges[2] - ranges[0])) != 0); OP2(SLJIT_OR, TMP1, 0, TMP1, 0, SLJIT_IMM, ranges[2] - ranges[0]); if (ranges[2] + 1 != ranges[3]) { @@ -4900,9 +4933,10 @@ else if ((cc[-1] & XCL_MAP) != 0) if (!check_class_ranges(common, (const pcre_uint8 *)cc, FALSE, TRUE, list)) { #ifdef COMPILE_PCRE8 - SLJIT_ASSERT(common->utf); + jump = NULL; + if (common->utf) #endif - jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); + jump = CMP(SLJIT_GREATER, TMP1, 0, SLJIT_IMM, 255); OP2(SLJIT_AND, TMP2, 0, TMP1, 0, SLJIT_IMM, 0x7); OP2(SLJIT_LSHR, TMP1, 0, TMP1, 0, SLJIT_IMM, 3); @@ -4911,7 +4945,10 @@ else if ((cc[-1] & XCL_MAP) != 0) OP2(SLJIT_AND | SLJIT_SET_E, SLJIT_UNUSED, 0, TMP1, 0, TMP2, 0); add_jump(compiler, list, JUMP(SLJIT_NOT_ZERO)); - JUMPHERE(jump); +#ifdef COMPILE_PCRE8 + if (common->utf) +#endif + JUMPHERE(jump); } OP1(SLJIT_MOV, TMP1, 0, TMP3, 0); @@ -5219,7 +5256,7 @@ while (*cc != XCL_END) OP_FLAGS(SLJIT_MOV, TMP2, 0, SLJIT_UNUSED, 0, SLJIT_LESS_EQUAL); SET_CHAR_OFFSET(0); - OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0xff); + OP2(SLJIT_SUB | SLJIT_SET_U, SLJIT_UNUSED, 0, TMP1, 0, SLJIT_IMM, 0x7f); OP_FLAGS(SLJIT_AND, TMP2, 0, TMP2, 0, SLJIT_LESS_EQUAL); SET_TYPE_OFFSET(ucp_Pc); @@ -7665,6 +7702,10 @@ while (*cc != OP_KETRPOS) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(0), STR_PTR, 0); } + /* Even if the match is empty, we need to reset the control head. */ + if (needs_control_head) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); + if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0)); @@ -7692,6 +7733,10 @@ while (*cc != OP_KETRPOS) OP1(SLJIT_MOV, SLJIT_MEM1(TMP2), (framesize + 1) * sizeof(sljit_sw), STR_PTR, 0); } + /* Even if the match is empty, we need to reset the control head. */ + if (needs_control_head) + OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); + if (opcode == OP_SBRAPOS || opcode == OP_SCBRAPOS) add_jump(compiler, &emptymatch, CMP(SLJIT_EQUAL, TMP1, 0, STR_PTR, 0)); @@ -7704,9 +7749,6 @@ while (*cc != OP_KETRPOS) } } - if (needs_control_head) - OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), common->control_head_ptr, SLJIT_MEM1(STACK_TOP), STACK(stack)); - JUMPTO(SLJIT_JUMP, loop); flush_stubs(common); @@ -8441,8 +8483,7 @@ while (cc < ccend) OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(1), STR_PTR, 0); } BACKTRACK_AS(braminzero_backtrack)->matchingpath = LABEL(); - if (cc[1] > OP_ASSERTBACK_NOT) - count_match(common); + count_match(common); break; case OP_ONCE: @@ -9624,7 +9665,7 @@ static SLJIT_INLINE void compile_recurse(compiler_common *common) DEFINE_COMPILER; pcre_uchar *cc = common->start + common->currententry->start; pcre_uchar *ccbegin = cc + 1 + LINK_SIZE + (*cc == OP_BRA ? 0 : IMM2_SIZE); -pcre_uchar *ccend = bracketend(cc); +pcre_uchar *ccend = bracketend(cc) - (1 + LINK_SIZE); BOOL needs_control_head; int framesize = get_framesize(common, cc, NULL, TRUE, &needs_control_head); int private_data_size = get_private_data_copy_length(common, ccbegin, ccend, needs_control_head); @@ -9648,6 +9689,7 @@ set_jumps(common->currententry->calls, common->currententry->entry); sljit_emit_fast_enter(compiler, TMP2, 0); allocate_stack(common, private_data_size + framesize + alternativesize); +count_match(common); OP1(SLJIT_MOV, SLJIT_MEM1(STACK_TOP), STACK(private_data_size + framesize + alternativesize - 1), TMP2, 0); copy_private_data(common, ccbegin, ccend, TRUE, private_data_size + framesize + alternativesize, framesize + alternativesize, needs_control_head); if (needs_control_head) @@ -9992,6 +10034,7 @@ OP1(SLJIT_MOV, TMP2, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, stack)); OP1(SLJIT_MOV_UI, TMP1, 0, SLJIT_MEM1(TMP1), SLJIT_OFFSETOF(jit_arguments, limit_match)); OP1(SLJIT_MOV, STACK_TOP, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, base)); OP1(SLJIT_MOV, STACK_LIMIT, 0, SLJIT_MEM1(TMP2), SLJIT_OFFSETOF(struct sljit_stack, limit)); +OP2(SLJIT_ADD, TMP1, 0, TMP1, 0, SLJIT_IMM, 1); OP1(SLJIT_MOV, SLJIT_MEM1(SLJIT_SP), LIMIT_MATCH, TMP1, 0); if (mode == JIT_PARTIAL_SOFT_COMPILE) diff --git a/ext/pcre/pcrelib/pcre_study.c b/ext/pcre/pcrelib/pcre_study.c index cc20b28c5c..38ab820853 100644 --- a/ext/pcre/pcrelib/pcre_study.c +++ b/ext/pcre/pcrelib/pcre_study.c @@ -69,6 +69,7 @@ Arguments: startcode pointer to start of the whole pattern's code options the compiling options recurses chain of recurse_check to catch mutual recursion + countptr pointer to call count (to catch over complexity) Returns: the minimum length -1 if \C in UTF-8 mode or (*ACCEPT) was encountered @@ -78,7 +79,8 @@ Returns: the minimum length static int find_minlength(const REAL_PCRE *re, const pcre_uchar *code, - const pcre_uchar *startcode, int options, recurse_check *recurses) + const pcre_uchar *startcode, int options, recurse_check *recurses, + int *countptr) { int length = -1; /* PCRE_UTF16 has the same value as PCRE_UTF8. */ @@ -88,6 +90,8 @@ recurse_check this_recurse; register int branchlength = 0; register pcre_uchar *cc = (pcre_uchar *)code + 1 + LINK_SIZE; +if ((*countptr)++ > 1000) return -1; /* too complex */ + if (*code == OP_CBRA || *code == OP_SCBRA || *code == OP_CBRAPOS || *code == OP_SCBRAPOS) cc += IMM2_SIZE; @@ -129,7 +133,7 @@ for (;;) case OP_SBRAPOS: case OP_ONCE: case OP_ONCE_NC: - d = find_minlength(re, cc, startcode, options, recurses); + d = find_minlength(re, cc, startcode, options, recurses, countptr); if (d < 0) return d; branchlength += d; do cc += GET(cc, 1); while (*cc == OP_ALT); @@ -413,7 +417,8 @@ for (;;) int dd; this_recurse.prev = recurses; this_recurse.group = cs; - dd = find_minlength(re, cs, startcode, options, &this_recurse); + dd = find_minlength(re, cs, startcode, options, &this_recurse, + countptr); if (dd < d) d = dd; } } @@ -449,7 +454,8 @@ for (;;) { this_recurse.prev = recurses; this_recurse.group = cs; - d = find_minlength(re, cs, startcode, options, &this_recurse); + d = find_minlength(re, cs, startcode, options, &this_recurse, + countptr); } } } @@ -512,7 +518,7 @@ for (;;) this_recurse.prev = recurses; this_recurse.group = cs; branchlength += find_minlength(re, cs, startcode, options, - &this_recurse); + &this_recurse, countptr); } } cc += 1 + LINK_SIZE; @@ -1451,6 +1457,7 @@ pcre32_study(const pcre32 *external_re, int options, const char **errorptr) #endif { int min; +int count = 0; BOOL bits_set = FALSE; pcre_uint8 start_bits[32]; PUBL(extra) *extra = NULL; @@ -1537,7 +1544,7 @@ if ((re->options & PCRE_ANCHORED) == 0 && /* Find the minimum length of subject string. */ -switch(min = find_minlength(re, code, code, re->options, NULL)) +switch(min = find_minlength(re, code, code, re->options, NULL, &count)) { case -2: *errorptr = "internal error: missing capturing bracket"; return NULL; case -3: *errorptr = "internal error: opcode not recognized"; return NULL; diff --git a/ext/pcre/pcrelib/pcre_xclass.c b/ext/pcre/pcrelib/pcre_xclass.c index 6f800c20a9..782748f241 100644 --- a/ext/pcre/pcrelib/pcre_xclass.c +++ b/ext/pcre/pcrelib/pcre_xclass.c @@ -244,7 +244,7 @@ while ((t = *data++) != XCL_END) case PT_PXPUNCT: if ((PRIV(ucp_gentype)[prop->chartype] == ucp_P || - (c < 256 && PRIV(ucp_gentype)[prop->chartype] == ucp_S)) == isprop) + (c < 128 && PRIV(ucp_gentype)[prop->chartype] == ucp_S)) == isprop) return !negated; break; diff --git a/ext/pcre/pcrelib/sljit/sljitConfig.h b/ext/pcre/pcrelib/sljit/sljitConfig.h index 10364c3b60..1c8a521aa8 100644 --- a/ext/pcre/pcrelib/sljit/sljitConfig.h +++ b/ext/pcre/pcrelib/sljit/sljitConfig.h @@ -96,6 +96,15 @@ #define SLJIT_EXECUTABLE_ALLOCATOR 1 #endif +/* Force cdecl calling convention even if a better calling + convention (e.g. fastcall) is supported by the C compiler. + If this option is enabled, C functions without + SLJIT_CALL can also be called from JIT code. */ +#ifndef SLJIT_USE_CDECL_CALLING_CONVENTION +/* Disabled by default */ +#define SLJIT_USE_CDECL_CALLING_CONVENTION 0 +#endif + /* Return with error when an invalid argument is passed. */ #ifndef SLJIT_ARGUMENT_CHECKS /* Disabled by default */ diff --git a/ext/pcre/pcrelib/sljit/sljitConfigInternal.h b/ext/pcre/pcrelib/sljit/sljitConfigInternal.h index 3284012f19..16e3547c93 100644 --- a/ext/pcre/pcrelib/sljit/sljitConfigInternal.h +++ b/ext/pcre/pcrelib/sljit/sljitConfigInternal.h @@ -468,7 +468,12 @@ typedef double sljit_d; #ifndef SLJIT_CALL -#if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) +#if (defined SLJIT_USE_CDECL_CALLING_CONVENTION && SLJIT_USE_CDECL_CALLING_CONVENTION) + +/* Force cdecl. */ +#define SLJIT_CALL + +#elif (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) #if defined(__GNUC__) && !defined(__APPLE__) @@ -608,6 +613,12 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_free_unused_memory_exec(void); #define SLJIT_LOCALS_OFFSET_BASE ((23 + 1) * sizeof(sljit_sw)) #endif +#elif (defined SLJIT_CONFIG_TILEGX && SLJIT_CONFIG_TILEGX) + +#define SLJIT_NUMBER_OF_REGISTERS 10 +#define SLJIT_NUMBER_OF_SAVED_REGISTERS 5 +#define SLJIT_LOCALS_OFFSET_BASE 0 + #elif (defined SLJIT_CONFIG_UNSUPPORTED && SLJIT_CONFIG_UNSUPPORTED) #define SLJIT_NUMBER_OF_REGISTERS 0 diff --git a/ext/pcre/pcrelib/sljit/sljitLir.c b/ext/pcre/pcrelib/sljit/sljitLir.c index 5039a7e04e..0f1b1c9cce 100644 --- a/ext/pcre/pcrelib/sljit/sljitLir.c +++ b/ext/pcre/pcrelib/sljit/sljitLir.c @@ -845,8 +845,8 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_compiler_verbose(struct sljit_compiler *comp } static SLJIT_CONST char* op0_names[] = { - (char*)"breakpoint", (char*)"nop", - (char*)"lumul", (char*)"lsmul", (char*)"ludiv", (char*)"lsdiv", + (char*)"breakpoint", (char*)"nop", (char*)"lumul", (char*)"lsmul", + (char*)"udivmod", (char*)"sdivmod", (char*)"udivi", (char*)"sdivi" }; static SLJIT_CONST char* op1_names[] = { @@ -1036,7 +1036,7 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op0(struct sljit_compiler { #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) CHECK_ARGUMENT((op >= SLJIT_BREAKPOINT && op <= SLJIT_LSMUL) - || ((op & ~SLJIT_INT_OP) >= SLJIT_LUDIV && (op & ~SLJIT_INT_OP) <= SLJIT_LSDIV)); + || ((op & ~SLJIT_INT_OP) >= SLJIT_UDIVMOD && (op & ~SLJIT_INT_OP) <= SLJIT_SDIVI)); CHECK_ARGUMENT(op < SLJIT_LUMUL || compiler->scratches >= 2); #endif #if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) @@ -1447,6 +1447,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_op_flags(struct sljit_com static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw offset) { + SLJIT_UNUSED_ARG(offset); + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw); #endif @@ -1462,6 +1464,8 @@ static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_get_local_base(struct sljit_co static SLJIT_INLINE CHECK_RETURN_TYPE check_sljit_emit_const(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw, sljit_sw init_value) { + SLJIT_UNUSED_ARG(init_value); + #if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) FUNCTION_CHECK_DST(dst, dstw); #endif diff --git a/ext/pcre/pcrelib/sljit/sljitLir.h b/ext/pcre/pcrelib/sljit/sljitLir.h index 24c0f60399..2e2e9ac09c 100644 --- a/ext/pcre/pcrelib/sljit/sljitLir.h +++ b/ext/pcre/pcrelib/sljit/sljitLir.h @@ -687,7 +687,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler * #define SLJIT_OP0_BASE 0 /* Flags: - (never set any flags) - Note: breakpoint instruction is not supported by all architectures (namely ppc) + Note: breakpoint instruction is not supported by all architectures (e.g. ppc) It falls back to SLJIT_NOP in those cases. */ #define SLJIT_BREAKPOINT (SLJIT_OP0_BASE + 0) /* Flags: - (never set any flags) @@ -696,24 +696,42 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler * #define SLJIT_NOP (SLJIT_OP0_BASE + 1) /* Flags: - (may destroy flags) Unsigned multiplication of SLJIT_R0 and SLJIT_R1. - Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */ + Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */ #define SLJIT_LUMUL (SLJIT_OP0_BASE + 2) /* Flags: - (may destroy flags) Signed multiplication of SLJIT_R0 and SLJIT_R1. - Result goes to SLJIT_R1:SLJIT_R0 (high:low) word */ + Result is placed into SLJIT_R1:SLJIT_R0 (high:low) word */ #define SLJIT_LSMUL (SLJIT_OP0_BASE + 3) /* Flags: I - (may destroy flags) Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. - The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1. - Note: if SLJIT_R1 contains 0, the behaviour is undefined. */ -#define SLJIT_LUDIV (SLJIT_OP0_BASE + 4) -#define SLJIT_ILUDIV (SLJIT_LUDIV | SLJIT_INT_OP) + The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. + Note: if SLJIT_R1 is 0, the behaviour is undefined. */ +#define SLJIT_UDIVMOD (SLJIT_OP0_BASE + 4) +#define SLJIT_IUDIVMOD (SLJIT_UDIVMOD | SLJIT_INT_OP) /* Flags: I - (may destroy flags) Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. - The result is placed in SLJIT_R0 and the remainder goes to SLJIT_R1. - Note: if SLJIT_R1 contains 0, the behaviour is undefined. */ -#define SLJIT_LSDIV (SLJIT_OP0_BASE + 5) -#define SLJIT_ILSDIV (SLJIT_LSDIV | SLJIT_INT_OP) + The result is placed into SLJIT_R0 and the remainder into SLJIT_R1. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00), + the behaviour is undefined. */ +#define SLJIT_SDIVMOD (SLJIT_OP0_BASE + 5) +#define SLJIT_ISDIVMOD (SLJIT_SDIVMOD | SLJIT_INT_OP) +/* Flags: I - (may destroy flags) + Unsigned divide of the value in SLJIT_R0 by the value in SLJIT_R1. + The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: SLJIT_SDIV is single precision divide. */ +#define SLJIT_UDIVI (SLJIT_OP0_BASE + 6) +#define SLJIT_IUDIVI (SLJIT_UDIVI | SLJIT_INT_OP) +/* Flags: I - (may destroy flags) + Signed divide of the value in SLJIT_R0 by the value in SLJIT_R1. + The result is placed into SLJIT_R0. SLJIT_R1 preserves its value. + Note: if SLJIT_R1 is 0, the behaviour is undefined. + Note: if SLJIT_R1 is -1 and SLJIT_R0 is integer min (0x800..00), + the behaviour is undefined. + Note: SLJIT_SDIV is single precision divide. */ +#define SLJIT_SDIVI (SLJIT_OP0_BASE + 7) +#define SLJIT_ISDIVI (SLJIT_SDIVI | SLJIT_INT_OP) SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op); @@ -851,34 +869,6 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w); -/* The following function is a helper function for sljit_emit_op_custom. - It returns with the real machine register index ( >=0 ) of any SLJIT_R, - SLJIT_S and SLJIT_SP registers. - - Note: it returns with -1 for virtual registers (only on x86-32). */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg); - -/* The following function is a helper function for sljit_emit_op_custom. - It returns with the real machine register index of any SLJIT_FLOAT register. - - Note: the index is always an even number on ARM (except ARM-64), MIPS, and SPARC. */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg); - -/* Any instruction can be inserted into the instruction stream by - sljit_emit_op_custom. It has a similar purpose as inline assembly. - The size parameter must match to the instruction size of the target - architecture: - - x86: 0 < size <= 15. The instruction argument can be byte aligned. - Thumb2: if size == 2, the instruction argument must be 2 byte aligned. - if size == 4, the instruction argument must be 4 byte aligned. - Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */ - -SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler, - void *instruction, sljit_si size); - /* Returns with non-zero if fpu is available. */ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_is_fpu_available(void); @@ -1196,4 +1186,64 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_function_context(void** func_ptr, struct #endif /* !(defined SLJIT_INDIRECT_CALL && SLJIT_INDIRECT_CALL) */ +/* --------------------------------------------------------------------- */ +/* CPU specific functions */ +/* --------------------------------------------------------------------- */ + +/* The following function is a helper function for sljit_emit_op_custom. + It returns with the real machine register index ( >=0 ) of any SLJIT_R, + SLJIT_S and SLJIT_SP registers. + + Note: it returns with -1 for virtual registers (only on x86-32). */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg); + +/* The following function is a helper function for sljit_emit_op_custom. + It returns with the real machine register index of any SLJIT_FLOAT register. + + Note: the index is always an even number on ARM (except ARM-64), MIPS, and SPARC. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_float_register_index(sljit_si reg); + +/* Any instruction can be inserted into the instruction stream by + sljit_emit_op_custom. It has a similar purpose as inline assembly. + The size parameter must match to the instruction size of the target + architecture: + + x86: 0 < size <= 15. The instruction argument can be byte aligned. + Thumb2: if size == 2, the instruction argument must be 2 byte aligned. + if size == 4, the instruction argument must be 4 byte aligned. + Otherwise: size must be 4 and instruction argument must be 4 byte aligned. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, sljit_si size); + +#if (defined SLJIT_CONFIG_X86 && SLJIT_CONFIG_X86) + +/* Returns with non-zero if sse2 is available. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_is_sse2_available(void); + +/* Returns with non-zero if cmov instruction is available. */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_is_cmov_available(void); + +/* Emit a conditional mov instruction on x86 CPUs. This instruction + moves src to destination, if the condition is satisfied. Unlike + other arithmetic instructions, destination must be a register. + Before such instructions are emitted, cmov support should be + checked by sljit_x86_is_cmov_available function. + type must be between SLJIT_EQUAL and SLJIT_S_ORDERED + dst_reg must be a valid register and it can be combined + with SLJIT_INT_OP to perform 32 bit arithmetic + Flags: I - (never set any flags) + */ + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_emit_cmov(struct sljit_compiler *compiler, + sljit_si type, + sljit_si dst_reg, + sljit_si src, sljit_sw srcw); + +#endif + #endif /* _SLJIT_LIR_H_ */ diff --git a/ext/pcre/pcrelib/sljit/sljitNativeARM_32.c b/ext/pcre/pcrelib/sljit/sljitNativeARM_32.c index aca1d31fdf..5cd4c71a29 100644 --- a/ext/pcre/pcrelib/sljit/sljitNativeARM_32.c +++ b/ext/pcre/pcrelib/sljit/sljitNativeARM_32.c @@ -1833,18 +1833,33 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler | (reg_map[SLJIT_R0] << 8) | reg_map[TMP_REG1]); #endif - case SLJIT_LUDIV: - case SLJIT_LSDIV: - if (compiler->scratches >= 3) + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); + SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2, bad_register_mapping); + + if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) { FAIL_IF(push_inst(compiler, 0xe52d2008 /* str r2, [sp, #-8]! */)); + FAIL_IF(push_inst(compiler, 0xe58d1004 /* str r1, [sp, #4] */)); + } + else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3)) + FAIL_IF(push_inst(compiler, 0xe52d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* str r1/r2, [sp, #-8]! */)); + #if defined(__GNUC__) FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, - (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); + ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); #else #error "Software divmod functions are needed" #endif - if (compiler->scratches >= 3) - return push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */); + + if ((op >= SLJIT_UDIVI) && (compiler->scratches >= 3)) { + FAIL_IF(push_inst(compiler, 0xe59d1004 /* ldr r1, [sp, #4] */)); + FAIL_IF(push_inst(compiler, 0xe49d2008 /* ldr r2, [sp], #8 */)); + } + else if ((op >= SLJIT_UDIVI) || (compiler->scratches >= 3)) + return push_inst(compiler, 0xe49d0008 | (op >= SLJIT_UDIVI ? 0x1000 : 0x2000) /* ldr r1/r2, [sp], #8 */); return SLJIT_SUCCESS; } diff --git a/ext/pcre/pcrelib/sljit/sljitNativeARM_64.c b/ext/pcre/pcrelib/sljit/sljitNativeARM_64.c index b66455f756..044a675eee 100644 --- a/ext/pcre/pcrelib/sljit/sljitNativeARM_64.c +++ b/ext/pcre/pcrelib/sljit/sljitNativeARM_64.c @@ -1087,14 +1087,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil saved_regs_size += sizeof(sljit_sw); } local_size -= saved_regs_size + SLJIT_LOCALS_OFFSET; - FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); + if (saved_regs_size > 0) + FAIL_IF(push_inst(compiler, SUBI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); } tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; prev = -1; for (i = SLJIT_S0; i >= tmp; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1104,7 +1110,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, STRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, STP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1112,8 +1123,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil prev = -1; } - if (prev != -1) - FAIL_IF(push_inst(compiler, STRI | RT(prev) | RN(TMP_SP) | (offs >> 5))); + SLJIT_ASSERT(prev == -1); if (compiler->local_size > (63 * sizeof(sljit_sw))) { /* The local_size is already adjusted by the saved registers. */ @@ -1188,7 +1198,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi prev = -1; for (i = SLJIT_S0; i >= tmp; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1198,7 +1213,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { if (prev == -1) { - prev = i; + if (!(offs & (1 << 15))) { + prev = i; + continue; + } + FAIL_IF(push_inst(compiler, LDRI | RT(i) | RN(TMP_SP) | (offs >> 5))); + offs += 1 << 15; continue; } FAIL_IF(push_inst(compiler, LDP | RT(prev) | RT2(i) | RN(TMP_SP) | offs)); @@ -1206,13 +1226,12 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi prev = -1; } - if (prev != -1) - FAIL_IF(push_inst(compiler, LDRI | RT(prev) | RN(TMP_SP) | (offs >> 5))); + SLJIT_ASSERT(prev == -1); if (compiler->local_size <= (63 * sizeof(sljit_sw))) { FAIL_IF(push_inst(compiler, LDP_PST | 29 | RT2(TMP_LR) | RN(TMP_SP) | (((local_size >> 3) & 0x7f) << 15))); - } else { + } else if (saved_regs_size > 0) { FAIL_IF(push_inst(compiler, ADDI | RD(TMP_SP) | RN(TMP_SP) | (saved_regs_size << 10))); } @@ -1242,12 +1261,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler FAIL_IF(push_inst(compiler, ORR | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); FAIL_IF(push_inst(compiler, MADD | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); return push_inst(compiler, (op == SLJIT_LUMUL ? UMULH : SMULH) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: FAIL_IF(push_inst(compiler, (ORR ^ inv_bits) | RD(TMP_REG1) | RN(TMP_ZERO) | RM(SLJIT_R0))); - FAIL_IF(push_inst(compiler, ((op == SLJIT_LUDIV ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1))); + FAIL_IF(push_inst(compiler, ((op == SLJIT_UDIVMOD ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1))); FAIL_IF(push_inst(compiler, (MADD ^ inv_bits) | RD(SLJIT_R1) | RN(SLJIT_R0) | RM(SLJIT_R1) | RT2(TMP_ZERO))); return push_inst(compiler, (SUB ^ inv_bits) | RD(SLJIT_R1) | RN(TMP_REG1) | RM(SLJIT_R1)); + case SLJIT_UDIVI: + case SLJIT_SDIVI: + return push_inst(compiler, ((op == SLJIT_UDIVI ? UDIV : SDIV) ^ inv_bits) | RD(SLJIT_R0) | RN(SLJIT_R0) | RM(SLJIT_R1)); } return SLJIT_SUCCESS; diff --git a/ext/pcre/pcrelib/sljit/sljitNativeARM_T2_32.c b/ext/pcre/pcrelib/sljit/sljitNativeARM_T2_32.c index 6e38cec899..f9803f5d44 100644 --- a/ext/pcre/pcrelib/sljit/sljitNativeARM_T2_32.c +++ b/ext/pcre/pcrelib/sljit/sljitNativeARM_T2_32.c @@ -1239,6 +1239,9 @@ extern int __aeabi_idivmod(int numerator, int denominator); SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) { + sljit_sw saved_reg_list[3]; + sljit_sw saved_reg_count; + CHECK_ERROR(); CHECK(check_sljit_emit_op0(compiler, op)); @@ -1255,24 +1258,53 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler | (reg_map[SLJIT_R0] << 12) | (reg_map[SLJIT_R0] << 16) | reg_map[SLJIT_R1]); - case SLJIT_LUDIV: - case SLJIT_LSDIV: - if (compiler->scratches >= 4) { - FAIL_IF(push_inst32(compiler, 0xf84d2d04 /* str r2, [sp, #-4]! */)); - FAIL_IF(push_inst32(compiler, 0xf84dcd04 /* str ip, [sp, #-4]! */)); - } else if (compiler->scratches >= 3) - FAIL_IF(push_inst32(compiler, 0xf84d2d08 /* str r2, [sp, #-8]! */)); + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); + SLJIT_COMPILE_ASSERT(reg_map[2] == 1 && reg_map[3] == 2 && reg_map[4] == 12, bad_register_mapping); + + saved_reg_count = 0; + if (compiler->scratches >= 4) + saved_reg_list[saved_reg_count++] = 12; + if (compiler->scratches >= 3) + saved_reg_list[saved_reg_count++] = 2; + if (op >= SLJIT_UDIVI) + saved_reg_list[saved_reg_count++] = 1; + + if (saved_reg_count > 0) { + FAIL_IF(push_inst32(compiler, 0xf84d0d00 | (saved_reg_count >= 3 ? 16 : 8) + | (saved_reg_list[0] << 12) /* str rX, [sp, #-8/-16]! */)); + if (saved_reg_count >= 2) { + SLJIT_ASSERT(saved_reg_list[1] < 8); + FAIL_IF(push_inst16(compiler, 0x9001 | (saved_reg_list[1] << 8) /* str rX, [sp, #4] */)); + } + if (saved_reg_count >= 3) { + SLJIT_ASSERT(saved_reg_list[2] < 8); + FAIL_IF(push_inst16(compiler, 0x9002 | (saved_reg_list[2] << 8) /* str rX, [sp, #8] */)); + } + } + #if defined(__GNUC__) FAIL_IF(sljit_emit_ijump(compiler, SLJIT_FAST_CALL, SLJIT_IMM, - (op == SLJIT_LUDIV ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); + ((op | 0x2) == SLJIT_UDIVI ? SLJIT_FUNC_OFFSET(__aeabi_uidivmod) : SLJIT_FUNC_OFFSET(__aeabi_idivmod)))); #else #error "Software divmod functions are needed" #endif - if (compiler->scratches >= 4) { - FAIL_IF(push_inst32(compiler, 0xf85dcb04 /* ldr ip, [sp], #4 */)); - return push_inst32(compiler, 0xf85d2b04 /* ldr r2, [sp], #4 */); - } else if (compiler->scratches >= 3) - return push_inst32(compiler, 0xf85d2b08 /* ldr r2, [sp], #8 */); + + if (saved_reg_count > 0) { + if (saved_reg_count >= 3) { + SLJIT_ASSERT(saved_reg_list[2] < 8); + FAIL_IF(push_inst16(compiler, 0x9802 | (saved_reg_list[2] << 8) /* ldr rX, [sp, #8] */)); + } + if (saved_reg_count >= 2) { + SLJIT_ASSERT(saved_reg_list[1] < 8); + FAIL_IF(push_inst16(compiler, 0x9801 | (saved_reg_list[1] << 8) /* ldr rX, [sp, #4] */)); + } + return push_inst32(compiler, 0xf85d0b00 | (saved_reg_count >= 3 ? 16 : 8) + | (saved_reg_list[0] << 12) /* ldr rX, [sp], #8/16 */); + } return SLJIT_SUCCESS; } diff --git a/ext/pcre/pcrelib/sljit/sljitNativeMIPS_common.c b/ext/pcre/pcrelib/sljit/sljitNativeMIPS_common.c index 3e2c9f0232..cf3535f81a 100644 --- a/ext/pcre/pcrelib/sljit/sljitNativeMIPS_common.c +++ b/ext/pcre/pcrelib/sljit/sljitNativeMIPS_common.c @@ -1053,8 +1053,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #endif FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); #if !(defined SLJIT_MIPS_R1 && SLJIT_MIPS_R1) FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); FAIL_IF(push_inst(compiler, NOP, UNMOVABLE_INS)); @@ -1062,15 +1065,15 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #if (defined SLJIT_CONFIG_MIPS_64 && SLJIT_CONFIG_MIPS_64) if (int_op) - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); else - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DDIVU : DDIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); #else - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? DIVU : DIV) | S(SLJIT_R0) | T(SLJIT_R1), MOVABLE_INS)); #endif FAIL_IF(push_inst(compiler, MFLO | D(SLJIT_R0), DR(SLJIT_R0))); - return push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); + return (op >= SLJIT_UDIVI) ? SLJIT_SUCCESS : push_inst(compiler, MFHI | D(SLJIT_R1), DR(SLJIT_R1)); } return SLJIT_SUCCESS; diff --git a/ext/pcre/pcrelib/sljit/sljitNativePPC_common.c b/ext/pcre/pcrelib/sljit/sljitNativePPC_common.c index 08d5356f5a..b6a043f4e4 100644 --- a/ext/pcre/pcrelib/sljit/sljitNativePPC_common.c +++ b/ext/pcre/pcrelib/sljit/sljitNativePPC_common.c @@ -1267,22 +1267,23 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); return push_inst(compiler, (op == SLJIT_LUMUL ? MULHWU : MULHW) | D(SLJIT_R1) | A(TMP_REG1) | B(SLJIT_R1)); #endif - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: FAIL_IF(push_inst(compiler, OR | S(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R0))); #if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) - if (int_op) { - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); - FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); - } else { - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVDU : DIVD) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); - FAIL_IF(push_inst(compiler, MULLD | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); - } - return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1)); + FAIL_IF(push_inst(compiler, (int_op ? (op == SLJIT_UDIVMOD ? DIVWU : DIVW) : (op == SLJIT_UDIVMOD ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1))); + FAIL_IF(push_inst(compiler, (int_op ? MULLW : MULLD) | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); #else - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? DIVWU : DIVW) | D(SLJIT_R0) | A(TMP_REG1) | B(SLJIT_R1))); + FAIL_IF(push_inst(compiler, (op == SLJIT_UDIVMOD ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1))); FAIL_IF(push_inst(compiler, MULLW | D(SLJIT_R1) | A(SLJIT_R0) | B(SLJIT_R1))); +#endif return push_inst(compiler, SUBF | D(SLJIT_R1) | A(SLJIT_R1) | B(TMP_REG1)); + case SLJIT_UDIVI: + case SLJIT_SDIVI: +#if (defined SLJIT_CONFIG_PPC_64 && SLJIT_CONFIG_PPC_64) + return push_inst(compiler, (int_op ? (op == SLJIT_UDIVI ? DIVWU : DIVW) : (op == SLJIT_UDIVI ? DIVDU : DIVD)) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); +#else + return push_inst(compiler, (op == SLJIT_UDIVI ? DIVWU : DIVW) | D(SLJIT_R0) | A(SLJIT_R0) | B(SLJIT_R1)); #endif } diff --git a/ext/pcre/pcrelib/sljit/sljitNativeSPARC_common.c b/ext/pcre/pcrelib/sljit/sljitNativeSPARC_common.c index 0b1927a824..327c4267be 100644 --- a/ext/pcre/pcrelib/sljit/sljitNativeSPARC_common.c +++ b/ext/pcre/pcrelib/sljit/sljitNativeSPARC_common.c @@ -777,20 +777,25 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #else #error "Implementation required" #endif - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); #if (defined SLJIT_CONFIG_SPARC_32 && SLJIT_CONFIG_SPARC_32) - if (op == SLJIT_LUDIV) + if ((op | 0x2) == SLJIT_UDIVI) FAIL_IF(push_inst(compiler, WRY | S1(0), MOVABLE_INS)); else { FAIL_IF(push_inst(compiler, SRA | D(TMP_REG1) | S1(SLJIT_R0) | IMM(31), DR(TMP_REG1))); FAIL_IF(push_inst(compiler, WRY | S1(TMP_REG1), MOVABLE_INS)); } - FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2))); - FAIL_IF(push_inst(compiler, (op == SLJIT_LUDIV ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0))); + if (op <= SLJIT_SDIVMOD) + FAIL_IF(push_inst(compiler, OR | D(TMP_REG2) | S1(0) | S2(SLJIT_R0), DR(TMP_REG2))); + FAIL_IF(push_inst(compiler, ((op | 0x2) == SLJIT_UDIVI ? UDIV : SDIV) | D(SLJIT_R0) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R0))); + if (op >= SLJIT_UDIVI) + return SLJIT_SUCCESS; FAIL_IF(push_inst(compiler, SMUL | D(SLJIT_R1) | S1(SLJIT_R0) | S2(SLJIT_R1), DR(SLJIT_R1))); - FAIL_IF(push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1))); - return SLJIT_SUCCESS; + return push_inst(compiler, SUB | D(SLJIT_R1) | S1(TMP_REG2) | S2(SLJIT_R1), DR(SLJIT_R1)); #else #error "Implementation required" #endif diff --git a/ext/pcre/pcrelib/sljit/sljitNativeTILEGX_64.c b/ext/pcre/pcrelib/sljit/sljitNativeTILEGX_64.c index 1d6aa5a110..4d40392fa8 100644 --- a/ext/pcre/pcrelib/sljit/sljitNativeTILEGX_64.c +++ b/ext/pcre/pcrelib/sljit/sljitNativeTILEGX_64.c @@ -35,21 +35,21 @@ #define SIMM_16BIT_MIN (-0x8000) #define SIMM_17BIT_MAX (0xffff) #define SIMM_17BIT_MIN (-0x10000) -#define SIMM_32BIT_MIN (-0x80000000) #define SIMM_32BIT_MAX (0x7fffffff) -#define SIMM_48BIT_MIN (0x800000000000L) +#define SIMM_32BIT_MIN (-0x7fffffff - 1) #define SIMM_48BIT_MAX (0x7fffffff0000L) +#define SIMM_48BIT_MIN (-0x800000000000L) #define IMM16(imm) ((imm) & 0xffff) #define UIMM_16BIT_MAX (0xffff) -#define TMP_REG1 (SLJIT_NO_REGISTERS + 1) -#define TMP_REG2 (SLJIT_NO_REGISTERS + 2) -#define TMP_REG3 (SLJIT_NO_REGISTERS + 3) -#define ADDR_TMP (SLJIT_NO_REGISTERS + 4) +#define TMP_REG1 (SLJIT_NUMBER_OF_REGISTERS + 2) +#define TMP_REG2 (SLJIT_NUMBER_OF_REGISTERS + 3) +#define TMP_REG3 (SLJIT_NUMBER_OF_REGISTERS + 4) +#define ADDR_TMP (SLJIT_NUMBER_OF_REGISTERS + 5) #define PIC_ADDR_REG TMP_REG2 -static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { +static SLJIT_CONST sljit_ub reg_map[SLJIT_NUMBER_OF_REGISTERS + 6] = { 63, 0, 1, 2, 3, 4, 30, 31, 32, 33, 34, 54, 5, 16, 6, 7 }; @@ -58,11 +58,6 @@ static SLJIT_CONST sljit_ub reg_map[SLJIT_NO_REGISTERS + 5] = { #define TMP_REG2_mapped 16 #define TMP_REG3_mapped 6 #define ADDR_TMP_mapped 7 -#define SLJIT_SAVED_REG1_mapped 30 -#define SLJIT_SAVED_REG2_mapped 31 -#define SLJIT_SAVED_REG3_mapped 32 -#define SLJIT_SAVED_EREG1_mapped 33 -#define SLJIT_SAVED_EREG2_mapped 34 /* Flags are keept in volatile registers. */ #define EQUAL_FLAG 8 @@ -399,6 +394,9 @@ static sljit_si push_inst(struct sljit_compiler *compiler, sljit_ins ins) #define SUB(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_SUB, dst, srca, srcb, __LINE__) +#define MUL(dst, srca, srcb) \ + push_3_buffer(compiler, TILEGX_OPC_MULX, dst, srca, srcb, __LINE__) + #define NOR(dst, srca, srcb) \ push_3_buffer(compiler, TILEGX_OPC_NOR, dst, srca, srcb, __LINE__) @@ -547,8 +545,8 @@ const struct Format* compute_format() const struct Format* match = NULL; const struct Format *b = NULL; - unsigned int i = 0; - for (i; i < sizeof formats / sizeof formats[0]; i++) { + unsigned int i; + for (i = 0; i < sizeof formats / sizeof formats[0]; i++) { b = &formats[i]; if ((b->pipe_mask & compatible_pipes) == b->pipe_mask) { match = b; @@ -625,7 +623,6 @@ tilegx_bundle_bits get_bundle_bit(struct jit_instr *inst) static sljit_si update_buffer(struct sljit_compiler *compiler) { - int count; int i; int orig_index = inst_buf_index; struct jit_instr inst0 = inst_buf[0]; @@ -738,8 +735,10 @@ static sljit_si update_buffer(struct sljit_compiler *compiler) static sljit_si flush_buffer(struct sljit_compiler *compiler) { - while (inst_buf_index != 0) - update_buffer(compiler); + while (inst_buf_index != 0) { + FAIL_IF(update_buffer(compiler)); + } + return SLJIT_SUCCESS; } static sljit_si push_4_buffer(struct sljit_compiler *compiler, tilegx_mnemonic opc, int op0, int op1, int op2, int op3, int line) @@ -787,6 +786,7 @@ static sljit_si push_3_buffer(struct sljit_compiler *compiler, tilegx_mnemonic o case TILEGX_OPC_ADD: case TILEGX_OPC_AND: case TILEGX_OPC_SUB: + case TILEGX_OPC_MULX: case TILEGX_OPC_OR: case TILEGX_OPC_XOR: case TILEGX_OPC_NOR: @@ -905,7 +905,6 @@ static SLJIT_INLINE sljit_ins * detect_jump_type(struct sljit_jump *jump, sljit_ sljit_sw diff; sljit_uw target_addr; sljit_ins *inst; - sljit_ins saved_inst; if (jump->flags & SLJIT_REWRITABLE_JUMP) return code_ptr; @@ -1009,7 +1008,7 @@ SLJIT_API_FUNC_ATTRIBUTE void * sljit_generate_code(struct sljit_compiler *compi struct sljit_const *const_; CHECK_ERROR_PTR(); - check_sljit_generate_code(compiler); + CHECK_PTR(check_sljit_generate_code(compiler)); reverse_buf(compiler); code = (sljit_ins *)SLJIT_MALLOC_EXEC(compiler->size * sizeof(sljit_ins)); @@ -1178,13 +1177,13 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil sljit_si fscratches, sljit_si fsaveds, sljit_si local_size) { sljit_ins base; - sljit_ins bundle = 0; - + sljit_si i, tmp; + CHECK_ERROR(); - check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK(check_sljit_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); set_emit_enter(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); - local_size += (saveds + 1) * sizeof(sljit_sw); + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); local_size = (local_size + 7) & ~7; compiler->local_size = local_size; @@ -1200,56 +1199,52 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_enter(struct sljit_compiler *compil local_size = 0; } + /* Save the return address. */ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8)); FAIL_IF(ST_ADD(ADDR_TMP_mapped, RA, -8)); - if (saveds >= 1) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG1_mapped, -8)); - - if (saveds >= 2) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG2_mapped, -8)); - - if (saveds >= 3) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_REG3_mapped, -8)); - - if (saveds >= 4) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG1_mapped, -8)); - - if (saveds >= 5) - FAIL_IF(ST_ADD(ADDR_TMP_mapped, SLJIT_SAVED_EREG2_mapped, -8)); - - if (args >= 1) - FAIL_IF(ADD(SLJIT_SAVED_REG1_mapped, 0, ZERO)); + /* Save the S registers. */ + tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; + for (i = SLJIT_S0; i >= tmp; i--) { + FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8)); + } - if (args >= 2) - FAIL_IF(ADD(SLJIT_SAVED_REG2_mapped, 1, ZERO)); + /* Save the R registers that need to be reserved. */ + for (i = scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + FAIL_IF(ST_ADD(ADDR_TMP_mapped, reg_map[i], -8)); + } - if (args >= 3) - FAIL_IF(ADD(SLJIT_SAVED_REG3_mapped, 2, ZERO)); + /* Move the arguments to S registers. */ + for (i = 0; i < args; i++) { + FAIL_IF(ADD(reg_map[SLJIT_S0 - i], i, ZERO)); + } return SLJIT_SUCCESS; } -SLJIT_API_FUNC_ATTRIBUTE void sljit_set_context(struct sljit_compiler *compiler, +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_set_context(struct sljit_compiler *compiler, sljit_si options, sljit_si args, sljit_si scratches, sljit_si saveds, sljit_si fscratches, sljit_si fsaveds, sljit_si local_size) { - CHECK_ERROR_VOID(); - check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); + CHECK_ERROR(); + CHECK(check_sljit_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size)); set_set_context(compiler, options, args, scratches, saveds, fscratches, fsaveds, local_size); - local_size += (saveds + 1) * sizeof(sljit_sw); + local_size += GET_SAVED_REGISTERS_SIZE(scratches, saveds, 1); compiler->local_size = (local_size + 7) & ~7; + + return SLJIT_SUCCESS; } SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compiler, sljit_si op, sljit_si src, sljit_sw srcw) { sljit_si local_size; sljit_ins base; - int addr_initialized = 0; + sljit_si i, tmp; + sljit_si saveds; CHECK_ERROR(); - check_sljit_emit_return(compiler, op, src, srcw); + CHECK(check_sljit_emit_return(compiler, op, src, srcw)); FAIL_IF(emit_mov_before_return(compiler, op, src, srcw)); @@ -1263,50 +1258,20 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_return(struct sljit_compiler *compi local_size = 0; } + /* Restore the return address. */ FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 8)); - FAIL_IF(LD(RA, ADDR_TMP_mapped)); - - if (compiler->saveds >= 5) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 48)); - addr_initialized = 1; + FAIL_IF(LD_ADD(RA, ADDR_TMP_mapped, -8)); - FAIL_IF(LD_ADD(SLJIT_SAVED_EREG2_mapped, ADDR_TMP_mapped, 8)); + /* Restore the S registers. */ + saveds = compiler->saveds; + tmp = saveds < SLJIT_NUMBER_OF_SAVED_REGISTERS ? (SLJIT_S0 + 1 - saveds) : SLJIT_FIRST_SAVED_REG; + for (i = SLJIT_S0; i >= tmp; i--) { + FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8)); } - if (compiler->saveds >= 4) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 40)); - addr_initialized = 1; - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_EREG1_mapped, ADDR_TMP_mapped, 8)); - } - - if (compiler->saveds >= 3) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 32)); - addr_initialized = 1; - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_REG3_mapped, ADDR_TMP_mapped, 8)); - } - - if (compiler->saveds >= 2) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 24)); - addr_initialized = 1; - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_REG2_mapped, ADDR_TMP_mapped, 8)); - } - - if (compiler->saveds >= 1) { - if (addr_initialized == 0) { - FAIL_IF(ADDLI(ADDR_TMP_mapped, base, local_size - 16)); - /* addr_initialized = 1; no need to initialize as it's the last one. */ - } - - FAIL_IF(LD_ADD(SLJIT_SAVED_REG1_mapped, ADDR_TMP_mapped, 8)); + /* Restore the R registers that need to be reserved. */ + for (i = compiler->scratches; i >= SLJIT_FIRST_SAVED_REG; i--) { + FAIL_IF(LD_ADD(reg_map[i], ADDR_TMP_mapped, -8)); } if (compiler->local_size <= SIMM_16BIT_MAX) @@ -1585,7 +1550,7 @@ static SLJIT_INLINE sljit_si emit_op_mem2(struct sljit_compiler *compiler, sljit SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *compiler, sljit_si dst, sljit_sw dstw) { CHECK_ERROR(); - check_sljit_emit_fast_enter(compiler, dst, dstw); + CHECK(check_sljit_emit_fast_enter(compiler, dst, dstw)); ADJUST_LOCAL_OFFSET(dst, dstw); /* For UNUSED dst. Uncommon, but possible. */ @@ -1602,7 +1567,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_enter(struct sljit_compiler *c SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_fast_return(struct sljit_compiler *compiler, sljit_si src, sljit_sw srcw) { CHECK_ERROR(); - check_sljit_emit_fast_return(compiler, src, srcw); + CHECK(check_sljit_emit_fast_return(compiler, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) @@ -1636,9 +1601,11 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj if (op == SLJIT_MOV_SI) return BFEXTS(reg_map[dst], reg_map[src2], 0, 31); - return BFEXTU(reg_map[dst], reg_map[src2], 0, 31); - } else if (dst != src2) - SLJIT_ASSERT_STOP(); + return BFEXTU(reg_map[dst], reg_map[src2], 0, 31); + } else if (dst != src2) { + SLJIT_ASSERT(src2 == 0); + return ADD(reg_map[dst], reg_map[src2], ZERO); + } return SLJIT_SUCCESS; @@ -1650,8 +1617,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj return BFEXTS(reg_map[dst], reg_map[src2], 0, 7); return BFEXTU(reg_map[dst], reg_map[src2], 0, 7); - } else if (dst != src2) - SLJIT_ASSERT_STOP(); + } else if (dst != src2) { + SLJIT_ASSERT(src2 == 0); + return ADD(reg_map[dst], reg_map[src2], ZERO); + } return SLJIT_SUCCESS; @@ -1663,8 +1632,10 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj return BFEXTS(reg_map[dst], reg_map[src2], 0, 15); return BFEXTU(reg_map[dst], reg_map[src2], 0, 15); - } else if (dst != src2) - SLJIT_ASSERT_STOP(); + } else if (dst != src2) { + SLJIT_ASSERT(src2 == 0); + return ADD(reg_map[dst], reg_map[src2], ZERO); + } return SLJIT_SUCCESS; @@ -1811,7 +1782,6 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj else { /* Rare ocasion. */ FAIL_IF(ADD(TMP_EREG2, reg_map[src1], ZERO)); - overflow_ra = TMP_EREG2; } } @@ -1903,6 +1873,17 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj return SLJIT_SUCCESS; + case SLJIT_MUL: + if (flags & SRC2_IMM) { + FAIL_IF(load_immediate(compiler, TMP_REG2_mapped, src2)); + src2 = TMP_REG2; + flags &= ~SRC2_IMM; + } + + FAIL_IF(MUL(reg_map[dst], reg_map[src1], reg_map[src2])); + + return SLJIT_SUCCESS; + #define EMIT_LOGICAL(op_imm, op_norm) \ if (flags & SRC2_IMM) { \ FAIL_IF(load_immediate(compiler, ADDR_TMP_mapped, src2)); \ @@ -1950,8 +1931,8 @@ static SLJIT_INLINE sljit_si emit_single_op(struct sljit_compiler *compiler, slj } else { \ if (op & SLJIT_SET_E) \ FAIL_IF(push_3_buffer( \ - compiler, op_imm, reg_map[dst], reg_map[src1], \ - src2 & 0x3F, __LINE__)); \ + compiler, op_norm, EQUAL_FLAG, reg_map[src1], \ + reg_map[src2], __LINE__)); \ if (CHECK_FLAGS(SLJIT_SET_E)) \ FAIL_IF(push_3_buffer( \ compiler, op_norm, reg_map[dst], reg_map[src1], \ @@ -2105,66 +2086,61 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com { sljit_si sugg_dst_ar, dst_ar; sljit_si flags = GET_ALL_FLAGS(op); + sljit_si mem_type = (op & SLJIT_INT_OP) ? (INT_DATA | SIGNED_DATA) : WORD_DATA; CHECK_ERROR(); - check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type); + CHECK(check_sljit_emit_op_flags(compiler, op, dst, dstw, src, srcw, type)); ADJUST_LOCAL_OFFSET(dst, dstw); if (dst == SLJIT_UNUSED) return SLJIT_SUCCESS; op = GET_OPCODE(op); + if (op == SLJIT_MOV_SI || op == SLJIT_MOV_UI) + mem_type = INT_DATA | SIGNED_DATA; sugg_dst_ar = reg_map[(op < SLJIT_ADD && FAST_IS_REG(dst)) ? dst : TMP_REG2]; compiler->cache_arg = 0; compiler->cache_argw = 0; if (op >= SLJIT_ADD && (src & SLJIT_MEM)) { ADJUST_LOCAL_OFFSET(src, srcw); - FAIL_IF(emit_op_mem2(compiler, WORD_DATA | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw)); + FAIL_IF(emit_op_mem2(compiler, mem_type | LOAD_DATA, TMP_REG1_mapped, src, srcw, dst, dstw)); src = TMP_REG1; srcw = 0; } - switch (type) { - case SLJIT_C_EQUAL: - case SLJIT_C_NOT_EQUAL: + switch (type & 0xff) { + case SLJIT_EQUAL: + case SLJIT_NOT_EQUAL: FAIL_IF(CMPLTUI(sugg_dst_ar, EQUAL_FLAG, 1)); dst_ar = sugg_dst_ar; break; - case SLJIT_C_LESS: - case SLJIT_C_GREATER_EQUAL: - case SLJIT_C_FLOAT_LESS: - case SLJIT_C_FLOAT_GREATER_EQUAL: + case SLJIT_LESS: + case SLJIT_GREATER_EQUAL: dst_ar = ULESS_FLAG; break; - case SLJIT_C_GREATER: - case SLJIT_C_LESS_EQUAL: - case SLJIT_C_FLOAT_GREATER: - case SLJIT_C_FLOAT_LESS_EQUAL: + case SLJIT_GREATER: + case SLJIT_LESS_EQUAL: dst_ar = UGREATER_FLAG; break; - case SLJIT_C_SIG_LESS: - case SLJIT_C_SIG_GREATER_EQUAL: + case SLJIT_SIG_LESS: + case SLJIT_SIG_GREATER_EQUAL: dst_ar = LESS_FLAG; break; - case SLJIT_C_SIG_GREATER: - case SLJIT_C_SIG_LESS_EQUAL: + case SLJIT_SIG_GREATER: + case SLJIT_SIG_LESS_EQUAL: dst_ar = GREATER_FLAG; break; - case SLJIT_C_OVERFLOW: - case SLJIT_C_NOT_OVERFLOW: + case SLJIT_OVERFLOW: + case SLJIT_NOT_OVERFLOW: dst_ar = OVERFLOW_FLAG; break; - case SLJIT_C_MUL_OVERFLOW: - case SLJIT_C_MUL_NOT_OVERFLOW: + case SLJIT_MUL_OVERFLOW: + case SLJIT_MUL_NOT_OVERFLOW: FAIL_IF(CMPLTUI(sugg_dst_ar, OVERFLOW_FLAG, 1)); dst_ar = sugg_dst_ar; type ^= 0x1; /* Flip type bit for the XORI below. */ break; - case SLJIT_C_FLOAT_EQUAL: - case SLJIT_C_FLOAT_NOT_EQUAL: - dst_ar = EQUAL_FLAG; - break; default: SLJIT_ASSERT_STOP(); @@ -2180,11 +2156,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com if (op >= SLJIT_ADD) { if (TMP_REG2_mapped != dst_ar) FAIL_IF(ADD(TMP_REG2_mapped, dst_ar, ZERO)); - return emit_op(compiler, op | flags, CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0); + return emit_op(compiler, op | flags, mem_type | CUMULATIVE_OP | LOGICAL_OP | IMM_OP | ALT_KEEP_CACHE, dst, dstw, src, srcw, TMP_REG2, 0); } if (dst & SLJIT_MEM) - return emit_op_mem(compiler, WORD_DATA, dst_ar, dst, dstw); + return emit_op_mem(compiler, mem_type, dst_ar, dst, dstw); if (sugg_dst_ar != dst_ar) return ADD(sugg_dst_ar, dst_ar, ZERO); @@ -2194,7 +2170,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_flags(struct sljit_compiler *com SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler, sljit_si op) { CHECK_ERROR(); - check_sljit_emit_op0(compiler, op); + CHECK(check_sljit_emit_op0(compiler, op)); op = GET_OPCODE(op); switch (op) { @@ -2204,10 +2180,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler case SLJIT_BREAKPOINT: return PI(BPT); - case SLJIT_UMUL: - case SLJIT_SMUL: - case SLJIT_UDIV: - case SLJIT_SDIV: + case SLJIT_LUMUL: + case SLJIT_LSMUL: + case SLJIT_UDIVI: + case SLJIT_SDIVI: SLJIT_ASSERT_STOP(); } @@ -2217,7 +2193,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src, sljit_sw srcw) { CHECK_ERROR(); - check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw); + CHECK(check_sljit_emit_op1(compiler, op, dst, dstw, src, srcw)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src, srcw); @@ -2273,7 +2249,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler return emit_op(compiler, SLJIT_SUB | GET_ALL_FLAGS(op), IMM_OP, dst, dstw, SLJIT_IMM, 0, src, srcw); case SLJIT_CLZ: - return emit_op(compiler, op, 0, dst, dstw, TMP_REG1, 0, src, srcw); + return emit_op(compiler, op, (op & SLJIT_INT_OP) ? INT_DATA : WORD_DATA, dst, dstw, TMP_REG1, 0, src, srcw); } return SLJIT_SUCCESS; @@ -2282,7 +2258,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op1(struct sljit_compiler *compiler SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op2(struct sljit_compiler *compiler, sljit_si op, sljit_si dst, sljit_sw dstw, sljit_si src1, sljit_sw src1w, sljit_si src2, sljit_sw src2w) { CHECK_ERROR(); - check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w); + CHECK(check_sljit_emit_op2(compiler, op, dst, dstw, src1, src1w, src2, src2w)); ADJUST_LOCAL_OFFSET(dst, dstw); ADJUST_LOCAL_OFFSET(src1, src1w); ADJUST_LOCAL_OFFSET(src2, src2w); @@ -2325,7 +2301,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_label * sljit_emit_label(struct sljit_comp flush_buffer(compiler); CHECK_ERROR_PTR(); - check_sljit_emit_label(compiler); + CHECK_PTR(check_sljit_emit_label(compiler)); if (compiler->last_label && compiler->last_label->size == compiler->size) return compiler->last_label; @@ -2344,7 +2320,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil flush_buffer(compiler); CHECK_ERROR(); - check_sljit_emit_ijump(compiler, type, src, srcw); + CHECK(check_sljit_emit_ijump(compiler, type, src, srcw)); ADJUST_LOCAL_OFFSET(src, srcw); if (FAST_IS_REG(src)) { @@ -2404,8 +2380,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_ijump(struct sljit_compiler *compil return SLJIT_SUCCESS; - } else if (src & SLJIT_MEM) + } else if (src & SLJIT_MEM) { FAIL_IF(emit_op(compiler, SLJIT_MOV, WORD_DATA, TMP_REG2, 0, TMP_REG1, 0, src, srcw)); + flush_buffer(compiler); + } FAIL_IF(JR_SOLO(reg_map[src_r])); @@ -2432,7 +2410,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil flush_buffer(compiler); CHECK_ERROR_PTR(); - check_sljit_emit_jump(compiler, type); + CHECK_PTR(check_sljit_emit_jump(compiler, type)); jump = (struct sljit_jump *)ensure_abuf(compiler, sizeof(struct sljit_jump)); PTR_FAIL_IF(!jump); @@ -2440,48 +2418,42 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_jump * sljit_emit_jump(struct sljit_compil type &= 0xff; switch (type) { - case SLJIT_C_EQUAL: - case SLJIT_C_FLOAT_NOT_EQUAL: + case SLJIT_EQUAL: BR_NZ(EQUAL_FLAG); break; - case SLJIT_C_NOT_EQUAL: - case SLJIT_C_FLOAT_EQUAL: + case SLJIT_NOT_EQUAL: BR_Z(EQUAL_FLAG); break; - case SLJIT_C_LESS: - case SLJIT_C_FLOAT_LESS: + case SLJIT_LESS: BR_Z(ULESS_FLAG); break; - case SLJIT_C_GREATER_EQUAL: - case SLJIT_C_FLOAT_GREATER_EQUAL: + case SLJIT_GREATER_EQUAL: BR_NZ(ULESS_FLAG); break; - case SLJIT_C_GREATER: - case SLJIT_C_FLOAT_GREATER: + case SLJIT_GREATER: BR_Z(UGREATER_FLAG); break; - case SLJIT_C_LESS_EQUAL: - case SLJIT_C_FLOAT_LESS_EQUAL: + case SLJIT_LESS_EQUAL: BR_NZ(UGREATER_FLAG); break; - case SLJIT_C_SIG_LESS: + case SLJIT_SIG_LESS: BR_Z(LESS_FLAG); break; - case SLJIT_C_SIG_GREATER_EQUAL: + case SLJIT_SIG_GREATER_EQUAL: BR_NZ(LESS_FLAG); break; - case SLJIT_C_SIG_GREATER: + case SLJIT_SIG_GREATER: BR_Z(GREATER_FLAG); break; - case SLJIT_C_SIG_LESS_EQUAL: + case SLJIT_SIG_LESS_EQUAL: BR_NZ(GREATER_FLAG); break; - case SLJIT_C_OVERFLOW: - case SLJIT_C_MUL_OVERFLOW: + case SLJIT_OVERFLOW: + case SLJIT_MUL_OVERFLOW: BR_Z(OVERFLOW_FLAG); break; - case SLJIT_C_NOT_OVERFLOW: - case SLJIT_C_MUL_NOT_OVERFLOW: + case SLJIT_NOT_OVERFLOW: + case SLJIT_MUL_NOT_OVERFLOW: BR_NZ(OVERFLOW_FLAG); break; default: @@ -2536,7 +2508,7 @@ SLJIT_API_FUNC_ATTRIBUTE struct sljit_const * sljit_emit_const(struct sljit_comp flush_buffer(compiler); CHECK_ERROR_PTR(); - check_sljit_emit_const(compiler, dst, dstw, init_value); + CHECK_PTR(check_sljit_emit_const(compiler, dst, dstw, init_value)); ADJUST_LOCAL_OFFSET(dst, dstw); const_ = (struct sljit_const *)ensure_abuf(compiler, sizeof(struct sljit_const)); @@ -2572,3 +2544,18 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta inst[3] = (inst[3] & ~(0xFFFFL << 43)) | ((new_constant & 0xFFFFL) << 43); SLJIT_CACHE_FLUSH(inst, inst + 4); } + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_get_register_index(sljit_si reg) +{ + CHECK_REG_INDEX(check_sljit_get_register_index(reg)); + return reg_map[reg]; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op_custom(struct sljit_compiler *compiler, + void *instruction, sljit_si size) +{ + CHECK_ERROR(); + CHECK(check_sljit_emit_op_custom(compiler, instruction, size)); + return SLJIT_ERR_UNSUPPORTED; +} + diff --git a/ext/pcre/pcrelib/sljit/sljitNativeX86_common.c b/ext/pcre/pcrelib/sljit/sljitNativeX86_common.c index 22a163fcc6..416c15afaf 100644 --- a/ext/pcre/pcrelib/sljit/sljitNativeX86_common.c +++ b/ext/pcre/pcrelib/sljit/sljitNativeX86_common.c @@ -273,7 +273,9 @@ static sljit_si cpu_has_sse2 = -1; #endif static sljit_si cpu_has_cmov = -1; -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifdef _WIN32_WCE +#include <cmnintrin.h> +#elif defined(_MSC_VER) && _MSC_VER >= 1400 #include <intrin.h> #endif @@ -742,8 +744,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler break; case SLJIT_LUMUL: case SLJIT_LSMUL: - case SLJIT_LUDIV: - case SLJIT_LSDIV: + case SLJIT_UDIVMOD: + case SLJIT_SDIVMOD: + case SLJIT_UDIVI: + case SLJIT_SDIVI: compiler->flags_saved = 0; #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) #ifdef _WIN64 @@ -761,9 +765,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler #endif compiler->mode32 = op & SLJIT_INT_OP; #endif + SLJIT_COMPILE_ASSERT((SLJIT_UDIVMOD & 0x2) == 0 && SLJIT_UDIVI - 0x2 == SLJIT_UDIVMOD, bad_div_opcode_assignments); op = GET_OPCODE(op); - if (op == SLJIT_LUDIV) { + if ((op | 0x2) == SLJIT_UDIVI) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0); inst = emit_x86_instruction(compiler, 1, SLJIT_R1, 0, SLJIT_R1, 0); @@ -774,7 +779,7 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler *inst = XOR_r_rm; } - if (op == SLJIT_LSDIV) { + if ((op | 0x2) == SLJIT_SDIVI) { #if (defined SLJIT_CONFIG_X86_32 && SLJIT_CONFIG_X86_32) || defined(_WIN64) EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_R1, 0); #endif @@ -805,10 +810,10 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler FAIL_IF(!inst); INC_SIZE(2); *inst++ = GROUP_F7; - *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]); + *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_map[TMP_REG1] : reg_map[SLJIT_R1]); #else #ifdef _WIN64 - size = (!compiler->mode32 || op >= SLJIT_LUDIV) ? 3 : 2; + size = (!compiler->mode32 || op >= SLJIT_UDIVMOD) ? 3 : 2; #else size = (!compiler->mode32) ? 3 : 2; #endif @@ -817,11 +822,11 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler INC_SIZE(size); #ifdef _WIN64 if (!compiler->mode32) - *inst++ = REX_W | ((op >= SLJIT_LUDIV) ? REX_B : 0); - else if (op >= SLJIT_LUDIV) + *inst++ = REX_W | ((op >= SLJIT_UDIVMOD) ? REX_B : 0); + else if (op >= SLJIT_UDIVMOD) *inst++ = REX_B; *inst++ = GROUP_F7; - *inst = MOD_REG | ((op >= SLJIT_LUDIV) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]); + *inst = MOD_REG | ((op >= SLJIT_UDIVMOD) ? reg_lmap[TMP_REG1] : reg_lmap[SLJIT_R1]); #else if (!compiler->mode32) *inst++ = REX_W; @@ -836,15 +841,21 @@ SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_emit_op0(struct sljit_compiler *compiler case SLJIT_LSMUL: *inst |= IMUL; break; - case SLJIT_LUDIV: + case SLJIT_UDIVMOD: + case SLJIT_UDIVI: *inst |= DIV; break; - case SLJIT_LSDIV: + case SLJIT_SDIVMOD: + case SLJIT_SDIVI: *inst |= IDIV; break; } #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) && !defined(_WIN64) - EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); + if (op <= SLJIT_SDIVMOD) + EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); +#else + if (op >= SLJIT_UDIVI) + EMIT_MOV(compiler, SLJIT_R1, 0, TMP_REG1, 0); #endif break; } @@ -1905,60 +1916,62 @@ static sljit_si emit_test_binary(struct sljit_compiler *compiler, return SLJIT_SUCCESS; } - if (FAST_IS_REG(src1)) { + if (!(src1 & SLJIT_IMM)) { if (src2 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src2w) || compiler->mode32) { - inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0); + inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w); FAIL_IF(!inst); *inst = GROUP_F7; } else { FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src2w)); - inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, 0); + inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src1, src1w); FAIL_IF(!inst); *inst = TEST_rm_r; } #else - inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, 0); + inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src2w, src1, src1w); FAIL_IF(!inst); *inst = GROUP_F7; #endif + return SLJIT_SUCCESS; } - else { + else if (FAST_IS_REG(src1)) { inst = emit_x86_instruction(compiler, 1, src1, 0, src2, src2w); FAIL_IF(!inst); *inst = TEST_rm_r; + return SLJIT_SUCCESS; } - return SLJIT_SUCCESS; } - if (FAST_IS_REG(src2)) { + if (!(src2 & SLJIT_IMM)) { if (src1 & SLJIT_IMM) { #if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) if (IS_HALFWORD(src1w) || compiler->mode32) { - inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, 0); + inst = emit_x86_instruction(compiler, 1, SLJIT_IMM, src1w, src2, src2w); FAIL_IF(!inst); *inst = GROUP_F7; } else { FAIL_IF(emit_load_imm64(compiler, TMP_REG2, src1w)); - inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, 0); + inst = emit_x86_instruction(compiler, 1, TMP_REG2, 0, src2, src2w); FAIL_IF(!inst); *inst = TEST_rm_r; } #else - inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, 0); + inst = emit_x86_instruction(compiler, 1, src1, src1w, src2, src2w); FAIL_IF(!inst); *inst = GROUP_F7; #endif + return SLJIT_SUCCESS; } - else { + else if (FAST_IS_REG(src2)) { inst = emit_x86_instruction(compiler, 1, src2, 0, src1, src1w); FAIL_IF(!inst); *inst = TEST_rm_r; + return SLJIT_SUCCESS; } - return SLJIT_SUCCESS; } EMIT_MOV(compiler, TMP_REG1, 0, src1, src1w); @@ -2923,3 +2936,69 @@ SLJIT_API_FUNC_ATTRIBUTE void sljit_set_const(sljit_uw addr, sljit_sw new_consta { *(sljit_sw*)addr = new_constant; } + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_is_sse2_available(void) +{ +#if (defined SLJIT_DETECT_SSE2 && SLJIT_DETECT_SSE2) + if (cpu_has_sse2 == -1) + get_cpu_features(); + return cpu_has_sse2; +#else + return 1; +#endif +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_is_cmov_available(void) +{ + if (cpu_has_cmov == -1) + get_cpu_features(); + return cpu_has_cmov; +} + +SLJIT_API_FUNC_ATTRIBUTE sljit_si sljit_x86_emit_cmov(struct sljit_compiler *compiler, + sljit_si type, + sljit_si dst_reg, + sljit_si src, sljit_sw srcw) +{ + sljit_ub* inst; + + CHECK_ERROR(); +#if (defined SLJIT_ARGUMENT_CHECKS && SLJIT_ARGUMENT_CHECKS) + CHECK_ARGUMENT(sljit_x86_is_cmov_available()); + CHECK_ARGUMENT(!(type & ~(0xff | SLJIT_INT_OP))); + CHECK_ARGUMENT((type & 0xff) >= SLJIT_EQUAL && (type & 0xff) <= SLJIT_D_ORDERED); + CHECK_ARGUMENT(FUNCTION_CHECK_IS_REG(dst_reg & ~SLJIT_INT_OP)); + FUNCTION_CHECK_SRC(src, srcw); +#endif +#if (defined SLJIT_VERBOSE && SLJIT_VERBOSE) + if (SLJIT_UNLIKELY(!!compiler->verbose)) { + fprintf(compiler->verbose, " x86_cmov%s %s%s, ", + !(dst_reg & SLJIT_INT_OP) ? "" : ".i", + JUMP_PREFIX(type), jump_names[type & 0xff]); + sljit_verbose_reg(compiler, dst_reg & ~SLJIT_INT_OP); + fprintf(compiler->verbose, ", "); + sljit_verbose_param(compiler, src, srcw); + fprintf(compiler->verbose, "\n"); + } +#endif + + ADJUST_LOCAL_OFFSET(src, srcw); + CHECK_EXTRA_REGS(src, srcw, (void)0); + +#if (defined SLJIT_CONFIG_X86_64 && SLJIT_CONFIG_X86_64) + compiler->mode32 = dst_reg & SLJIT_INT_OP; +#endif + dst_reg &= ~SLJIT_INT_OP; + + if (SLJIT_UNLIKELY(src & SLJIT_IMM)) { + EMIT_MOV(compiler, TMP_REG1, 0, SLJIT_IMM, srcw); + src = TMP_REG1; + srcw = 0; + } + + inst = emit_x86_instruction(compiler, 2, dst_reg, 0, src, srcw); + FAIL_IF(!inst); + *inst++ = GROUP_0F; + *inst = get_jump_code(type & 0xff) - 0x40; + return SLJIT_SUCCESS; +} diff --git a/ext/pcre/pcrelib/testdata/grepoutput b/ext/pcre/pcrelib/testdata/grepoutput index 9bf9d9d62e..f23dac7693 100644 --- a/ext/pcre/pcrelib/testdata/grepoutput +++ b/ext/pcre/pcrelib/testdata/grepoutput @@ -743,3 +743,15 @@ RC=0 ---------------------------- Test 106 ----------------------------- a RC=0 +---------------------------- Test 107 ----------------------------- +1:0,1 +2:0,1 +2:1,1 +2:2,1 +2:3,1 +2:4,1 +RC=0 +---------------------------- Test 108 ------------------------------ +RC=0 +---------------------------- Test 109 ----------------------------- +RC=0 diff --git a/ext/pcre/pcrelib/testdata/testinput1 b/ext/pcre/pcrelib/testdata/testinput1 index 123e3d3cfd..8379ce04d5 100644 --- a/ext/pcre/pcrelib/testdata/testinput1 +++ b/ext/pcre/pcrelib/testdata/testinput1 @@ -5720,4 +5720,17 @@ AbcdCBefgBhiBqz /[\Q]a\E]+/ aa]] +/(?:((abcd))|(((?:(?:(?:(?:abc|(?:abcdef))))b)abcdefghi)abc)|((*ACCEPT)))/ + 1234abcd + +/(\2)(\1)/ + +"Z*(|d*){216}" + +"(?1)(?#?'){8}(a)" + baaaaaaaaac + +"(?|(\k'Pm')|(?'Pm'))" + abcd + /-- End of testinput1 --/ diff --git a/ext/pcre/pcrelib/testdata/testinput11 b/ext/pcre/pcrelib/testdata/testinput11 index 7e8e54221d..ac9d228985 100644 --- a/ext/pcre/pcrelib/testdata/testinput11 +++ b/ext/pcre/pcrelib/testdata/testinput11 @@ -134,4 +134,8 @@ is required for these tests. --/ /(((a\2)|(a*)\g<-1>))*a?/B +/((?+1)(\1))/B + +/.((?2)(?R)\1)()/B + /-- End of testinput11 --/ diff --git a/ext/pcre/pcrelib/testdata/testinput12 b/ext/pcre/pcrelib/testdata/testinput12 index 5d727af26a..944be6943f 100644 --- a/ext/pcre/pcrelib/testdata/testinput12 +++ b/ext/pcre/pcrelib/testdata/testinput12 @@ -8,6 +8,8 @@ and a couple of things that are different with JIT. --/ /(?(?C1)(?=a)a)/S!+I +/b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*/S+I + /abc/S+I>testsavedregex <testsavedregex @@ -87,4 +89,19 @@ and a couple of things that are different with JIT. --/ /^12345678abcd/mS++ 12345678abcd +/-- Test pattern compilation --/ + +/(?:a|b|c|d|e)(?R)/S++ + +/(?:a|b|c|d|e)(?R)(?R)/S++ + +/(a(?:a|b|c|d|e)b){8,16}/S++ + +/(?:|a|){100}x/S++ + +/(x(?1)){4}/S++ + +/(.|.)*?bx/ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabax + /-- End of testinput12 --/ diff --git a/ext/pcre/pcrelib/testdata/testinput14 b/ext/pcre/pcrelib/testdata/testinput14 index 325ed9e361..192b8d64d5 100644 --- a/ext/pcre/pcrelib/testdata/testinput14 +++ b/ext/pcre/pcrelib/testdata/testinput14 @@ -340,4 +340,6 @@ not matter. --/ /[^\s]*\s* [^\W]+\W+ [^\d]*?\d0 [^\d\w]{4,6}?\w*A/BZ +/(?'ABC'[bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar](*THEN:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))/ + /-- End of testinput14 --/ diff --git a/ext/pcre/pcrelib/testdata/testinput17 b/ext/pcre/pcrelib/testdata/testinput17 index 1d933c7942..c48e77f97f 100644 --- a/ext/pcre/pcrelib/testdata/testinput17 +++ b/ext/pcre/pcrelib/testdata/testinput17 @@ -304,4 +304,6 @@ /^[\x{1234}\x{4321}]{2,4}?/ \x{1234}\x{1234}\x{1234} +/(*THEN:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)/ + /-- End of testinput17 --/ diff --git a/ext/pcre/pcrelib/testdata/testinput2 b/ext/pcre/pcrelib/testdata/testinput2 index c6816bf322..e2e520f740 100644 --- a/ext/pcre/pcrelib/testdata/testinput2 +++ b/ext/pcre/pcrelib/testdata/testinput2 @@ -1380,6 +1380,8 @@ 1X 123456\P +//KF>testsavedregex + /abc/IS>testsavedregex <testsavedregex abc @@ -4078,4 +4080,141 @@ backtracking verbs. --/ /\x{whatever}/ +"((?=(?(?=(?(?=(?(?=()))))))))" + a + +"(?(?=)==)(((((((((?=)))))))))" + a + +/^(?:(a)|b)(?(1)A|B)/I + aA123\O3 + aA123\O6 + +'^(?:(?<AA>a)|b)(?(<AA>)A|B)' + aA123\O3 + aA123\O6 + +'^(?<AA>)(?:(?<AA>a)|b)(?(<AA>)A|B)'J + aA123\O3 + aA123\O6 + +'^(?:(?<AA>X)|)(?:(?<AA>a)|b)\k{AA}'J + aa123\O3 + aa123\O6 + +/(?<N111>(?J)(?<N111>1(111111)11|)1|1|)(?(<N111>)1)/ + +/(?(?=0)?)+/ + +/(?(?=0)(?=00)?00765)/ + 00765 + +/(?(?=0)(?=00)?00765|(?!3).56)/ + 00765 + 456 + ** Failers + 356 + +'^(a)*+(\w)' + g + g\O3 + +'^(?:a)*+(\w)' + g + g\O3 + +//C + \O\C+ + +"((?2){0,1999}())?" + +/((?+1)(\1))/BZ + +/(?(?!)a|b)/ + bbb + aaa + +"((?2)+)((?1))" + +"(?(?<E>.*!.*)?)" + +"X((?2)()*+){2}+"BZ + +"X((?2)()*+){2}"BZ + +"(?<=((?2))((?1)))" + +/(?<=\Ka)/g+ + aaaaa + +/(?<=\Ka)/G+ + aaaaa + +/((?2){73}(?2))((?1))/ + +/.((?2)(?R)\1)()/BZ + +/(?1)()((((((\1++))\x85)+)|))/ + +/(\9*+(?2);\3++()2|)++{/ + +/\V\x85\9*+((?2)\3++()2)*:2/ + +/(((?(R)){0,2}) (?''((?'R')((?'R')))))/J + +/(((?(X)){0,2}) (?''((?'X')((?'X')))))/J + +/(((?(R)){0,2}) (?''((?'X')((?'R')))))/ + +"(?J)(?'d'(?'d'\g{d}))" + +".*?\h.+.\.+\R*?\xd(?i)(?=!(?=b`b`b`\`b\xa9b!)`\a`bbbbbbbbbbbbb`bbbbbbbbbbbb*R\x85bbbbbbb\C?{((?2)(?))(( +\H){8(?<=(?1){29}\xa8bbbb\x16\xd\xc6^($(?<! )(\xa9H4){4}h}1)B))\x15')" + +"(?J:(?|(?'R')(\k'R')|((?'R'))))" + +/(?<=|(\,\$(?73591620449005828816)\xa8.{7}){6}\x09)/ + +// +\O1 + +/^(?:(?(1)x|)+)+$()/BZ + +/(?=di(?<=(?1))|(?=(.))))/ + +/(?(R))*+/BZ + +/[[:\\](?'abc')[a:]/ + +"[[[.\xe8Nq\xffq\xff\xe0\x2|||::Nq\xffq\xff\xe0\x6\x2|||::[[[:[::::::[[[[[::::::::[:[[[:[:::[[[[[[[[[[[[:::::::::::::::::[[.\xe8Nq\xffq\xff\xe0\x2|||::Nq\xffq\xff\xe0\x6\x2|||::[[[:[::::::[[[[[::::::::[:[[[:[:::[[[[[[[[[[[[[[:::E[[[:[:[[:[:::[[:::E[[[:[:[[:'[:::::E[[[:[::::::[[[:[[[[[[[::E[[[:[::::::[[[:[[[[[[[[:[[::[::::[[:::::::[[:[[[[[[[:[[::[:[[:[~" + +/()(?(R)0)*+/BZ + +/(?R-:(?</ + +/(?1){3918}(((((0(\k'R'))))(?J)(?'R'(?'R'\3){99})))/I + +/(?J:(?|(:(?|(?'R')(\k'R')|((?'R')))H'Rk'Rf)|s(?'R')))/ + +/0(?0)|(1)(*THEN)(*SKIP:0)(*FAIL)/ + 01 + +/((?(R8000000000)))/ + +/(?(8000000000/ + +/(?:ab)?(?:ab)(?:ab)/ + abab + ababab + aba + +/((*MARK:A))++a(*SKIP:B)b/ + aacb + +/(?J:(?|(:(?|(?'R')(\z(?|(?'R')(\k'R')|((?'R')))k'R')|((?'R')))H'Ak'Rf)|s(?'R')))/ + +/(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?<a>1)/ + +/a[[:punct:]b]/BZ + /-- End of testinput2 --/ diff --git a/ext/pcre/pcrelib/testdata/testinput4 b/ext/pcre/pcrelib/testdata/testinput4 index 0110267bd8..8bdbdac4c2 100644 --- a/ext/pcre/pcrelib/testdata/testinput4 +++ b/ext/pcre/pcrelib/testdata/testinput4 @@ -722,4 +722,9 @@ /^#[^\x{ffff}]#[^\x{ffff}]#[^\x{ffff}]#/8 #\x{10000}#\x{100}#\x{10ffff}# +"[\S\V\H]"8 + +/\C(\W?Å¿)'?{{/8 + \\C(\\W?Å¿)'?{{ + /-- End of testinput4 --/ diff --git a/ext/pcre/pcrelib/testdata/testinput5 b/ext/pcre/pcrelib/testdata/testinput5 index e36b09d637..28561a9357 100644 --- a/ext/pcre/pcrelib/testdata/testinput5 +++ b/ext/pcre/pcrelib/testdata/testinput5 @@ -790,4 +790,12 @@ /[b-d\x{200}-\x{250}]*[ae-h]?#[\x{200}-\x{250}]{0,8}[\x00-\xff]*#[\x{200}-\x{250}]+[a-z]/8BZ +/[^\xff]*PRUNE:\x{100}abc(xyz(?1))/8DZ + +/(?<=\K\x{17f})/8g+ + \x{17f}\x{17f}\x{17f}\x{17f}\x{17f} + +/(?<=\K\x{17f})/8G+ + \x{17f}\x{17f}\x{17f}\x{17f}\x{17f} + /-- End of testinput5 --/ diff --git a/ext/pcre/pcrelib/testdata/testinput6 b/ext/pcre/pcrelib/testdata/testinput6 index 82c3ed5c77..aeb62a073f 100644 --- a/ext/pcre/pcrelib/testdata/testinput6 +++ b/ext/pcre/pcrelib/testdata/testinput6 @@ -1496,4 +1496,61 @@ /^s?c/mi8 scat +/[A-`]/i8 + abcdefghijklmno + +/\C\X*QT/8 + Ó…\x0aT + +/[\pS#moq]/ + = + +/[[:punct:]]/8W + \xc2\xb4 + \x{b4} + +/[[:^ascii:]]/8W + \x{100} + \x{200} + \x{300} + \x{37e} + a + 9 + g + +/[[:^ascii:]\w]/8W + a + 9 + g + \x{100} + \x{200} + \x{300} + \x{37e} + +/[\w[:^ascii:]]/8W + a + 9 + g + \x{100} + \x{200} + \x{300} + \x{37e} + +/[^[:ascii:]\W]/8W + a + 9 + g + \x{100} + \x{200} + \x{300} + \x{37e} + +/[[:^ascii:]a]/8W + a + 9 + g + \x{100} + \x{200} + \x{37e} + /-- End of testinput6 --/ diff --git a/ext/pcre/pcrelib/testdata/testinput7 b/ext/pcre/pcrelib/testdata/testinput7 index 7a66025434..e411a4b842 100644 --- a/ext/pcre/pcrelib/testdata/testinput7 +++ b/ext/pcre/pcrelib/testdata/testinput7 @@ -838,4 +838,19 @@ of case for anything other than the ASCII letters. --/ /^s?c/mi8I scat +/[\W\p{Any}]/BZ + abc + 123 + +/[\W\pL]/BZ + abc + ** Failers + 123 + +/a[[:punct:]b]/WBZ + +/a[[:punct:]b]/8WBZ + +/a[b[:punct:]]/8WBZ + /-- End of testinput7 --/ diff --git a/ext/pcre/pcrelib/testdata/testinput8 b/ext/pcre/pcrelib/testdata/testinput8 index 06334cd36e..931dd717e7 100644 --- a/ext/pcre/pcrelib/testdata/testinput8 +++ b/ext/pcre/pcrelib/testdata/testinput8 @@ -4837,4 +4837,8 @@ '\A(?:[^\"]++|\"(?:[^\"]++|\"\")*+\")++' NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED +/(?(?!)a|b)/ + bbb + aaa + /-- End of testinput8 --/ diff --git a/ext/pcre/pcrelib/testdata/testinputEBC b/ext/pcre/pcrelib/testdata/testinputEBC index 56efcd00aa..378755d3b9 100644 --- a/ext/pcre/pcrelib/testdata/testinputEBC +++ b/ext/pcre/pcrelib/testdata/testinputEBC @@ -29,13 +29,16 @@ in EBCDIC, but can be specified as escapes. --/ /^A\ˆ/ A B + A\x41B /-- Test \H --/ /^A\È/ AB + A\x42B ** Fail A B + A\x41B /-- Test \R --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput1 b/ext/pcre/pcrelib/testdata/testoutput1 index 5e719002ed..e852ab9544 100644 --- a/ext/pcre/pcrelib/testdata/testoutput1 +++ b/ext/pcre/pcrelib/testdata/testoutput1 @@ -9411,4 +9411,27 @@ No match aa]] 0: aa]] +/(?:((abcd))|(((?:(?:(?:(?:abc|(?:abcdef))))b)abcdefghi)abc)|((*ACCEPT)))/ + 1234abcd + 0: + 1: <unset> + 2: <unset> + 3: <unset> + 4: <unset> + 5: + +/(\2)(\1)/ + +"Z*(|d*){216}" + +"(?1)(?#?'){8}(a)" + baaaaaaaaac + 0: aaaaaaaaa + 1: a + +"(?|(\k'Pm')|(?'Pm'))" + abcd + 0: + 1: + /-- End of testinput1 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput11-16 b/ext/pcre/pcrelib/testdata/testoutput11-16 index a1db3f3422..9a0a12d509 100644 --- a/ext/pcre/pcrelib/testdata/testoutput11-16 +++ b/ext/pcre/pcrelib/testdata/testoutput11-16 @@ -231,7 +231,7 @@ Memory allocation (code space): 73 ------------------------------------------------------------------ /(?P<a>a)...(?P=a)bbb(?P>a)d/BM -Memory allocation (code space): 57 +Memory allocation (code space): 77 ------------------------------------------------------------------ 0 24 Bra 2 5 CBra 1 @@ -650,18 +650,18 @@ Memory allocation (code space): 14 /[[:^alpha:][:^cntrl:]]+/8WB ------------------------------------------------------------------ - 0 26 Bra - 2 [ -~\x80-\xff\P{L}]++ - 26 26 Ket - 28 End + 0 30 Bra + 2 [ -~\x80-\xff\P{L}\x{100}-\x{10ffff}]++ + 30 30 Ket + 32 End ------------------------------------------------------------------ /[[:^cntrl:][:^alpha:]]+/8WB ------------------------------------------------------------------ - 0 26 Bra - 2 [ -~\x80-\xff\P{L}]++ - 26 26 Ket - 28 End + 0 30 Bra + 2 [ -~\x80-\xff\x{100}-\x{10ffff}\P{L}]++ + 30 30 Ket + 32 End ------------------------------------------------------------------ /[[:alpha:]]+/8WB @@ -733,4 +733,36 @@ Memory allocation (code space): 14 41 End ------------------------------------------------------------------ +/((?+1)(\1))/B +------------------------------------------------------------------ + 0 20 Bra + 2 16 Once + 4 12 CBra 1 + 7 9 Recurse + 9 5 CBra 2 + 12 \1 + 14 5 Ket + 16 12 Ket + 18 16 Ket + 20 20 Ket + 22 End +------------------------------------------------------------------ + +/.((?2)(?R)\1)()/B +------------------------------------------------------------------ + 0 23 Bra + 2 Any + 3 13 Once + 5 9 CBra 1 + 8 18 Recurse + 10 0 Recurse + 12 \1 + 14 9 Ket + 16 13 Ket + 18 3 CBra 2 + 21 3 Ket + 23 23 Ket + 25 End +------------------------------------------------------------------ + /-- End of testinput11 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput11-32 b/ext/pcre/pcrelib/testdata/testoutput11-32 index 7b7b030fdc..57e5da0279 100644 --- a/ext/pcre/pcrelib/testdata/testoutput11-32 +++ b/ext/pcre/pcrelib/testdata/testoutput11-32 @@ -231,7 +231,7 @@ Memory allocation (code space): 155 ------------------------------------------------------------------ /(?P<a>a)...(?P=a)bbb(?P>a)d/BM -Memory allocation (code space): 117 +Memory allocation (code space): 157 ------------------------------------------------------------------ 0 24 Bra 2 5 CBra 1 @@ -650,18 +650,18 @@ Memory allocation (code space): 28 /[[:^alpha:][:^cntrl:]]+/8WB ------------------------------------------------------------------ - 0 18 Bra - 2 [ -~\x80-\xff\P{L}]++ - 18 18 Ket - 20 End + 0 21 Bra + 2 [ -~\x80-\xff\P{L}\x{100}-\x{10ffff}]++ + 21 21 Ket + 23 End ------------------------------------------------------------------ /[[:^cntrl:][:^alpha:]]+/8WB ------------------------------------------------------------------ - 0 18 Bra - 2 [ -~\x80-\xff\P{L}]++ - 18 18 Ket - 20 End + 0 21 Bra + 2 [ -~\x80-\xff\x{100}-\x{10ffff}\P{L}]++ + 21 21 Ket + 23 End ------------------------------------------------------------------ /[[:alpha:]]+/8WB @@ -733,4 +733,36 @@ Memory allocation (code space): 28 41 End ------------------------------------------------------------------ +/((?+1)(\1))/B +------------------------------------------------------------------ + 0 20 Bra + 2 16 Once + 4 12 CBra 1 + 7 9 Recurse + 9 5 CBra 2 + 12 \1 + 14 5 Ket + 16 12 Ket + 18 16 Ket + 20 20 Ket + 22 End +------------------------------------------------------------------ + +/.((?2)(?R)\1)()/B +------------------------------------------------------------------ + 0 23 Bra + 2 Any + 3 13 Once + 5 9 CBra 1 + 8 18 Recurse + 10 0 Recurse + 12 \1 + 14 9 Ket + 16 13 Ket + 18 3 CBra 2 + 21 3 Ket + 23 23 Ket + 25 End +------------------------------------------------------------------ + /-- End of testinput11 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput11-8 b/ext/pcre/pcrelib/testdata/testoutput11-8 index f5ec652af8..748548a5ab 100644 --- a/ext/pcre/pcrelib/testdata/testoutput11-8 +++ b/ext/pcre/pcrelib/testdata/testoutput11-8 @@ -231,7 +231,7 @@ Memory allocation (code space): 45 ------------------------------------------------------------------ /(?P<a>a)...(?P=a)bbb(?P>a)d/BM -Memory allocation (code space): 34 +Memory allocation (code space): 50 ------------------------------------------------------------------ 0 30 Bra 3 7 CBra 1 @@ -650,18 +650,18 @@ Memory allocation (code space): 10 /[[:^alpha:][:^cntrl:]]+/8WB ------------------------------------------------------------------ - 0 44 Bra - 3 [ -~\x80-\xff\P{L}]++ - 44 44 Ket - 47 End + 0 51 Bra + 3 [ -~\x80-\xff\P{L}\x{100}-\x{10ffff}]++ + 51 51 Ket + 54 End ------------------------------------------------------------------ /[[:^cntrl:][:^alpha:]]+/8WB ------------------------------------------------------------------ - 0 44 Bra - 3 [ -~\x80-\xff\P{L}]++ - 44 44 Ket - 47 End + 0 51 Bra + 3 [ -~\x80-\xff\x{100}-\x{10ffff}\P{L}]++ + 51 51 Ket + 54 End ------------------------------------------------------------------ /[[:alpha:]]+/8WB @@ -733,4 +733,36 @@ Memory allocation (code space): 10 60 End ------------------------------------------------------------------ +/((?+1)(\1))/B +------------------------------------------------------------------ + 0 31 Bra + 3 25 Once + 6 19 CBra 1 + 11 14 Recurse + 14 8 CBra 2 + 19 \1 + 22 8 Ket + 25 19 Ket + 28 25 Ket + 31 31 Ket + 34 End +------------------------------------------------------------------ + +/.((?2)(?R)\1)()/B +------------------------------------------------------------------ + 0 35 Bra + 3 Any + 4 20 Once + 7 14 CBra 1 + 12 27 Recurse + 15 0 Recurse + 18 \1 + 21 14 Ket + 24 20 Ket + 27 5 CBra 2 + 32 5 Ket + 35 35 Ket + 38 End +------------------------------------------------------------------ + /-- End of testinput11 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput12 b/ext/pcre/pcrelib/testdata/testoutput12 index 67ad2c8aec..87911086f4 100644 --- a/ext/pcre/pcrelib/testdata/testoutput12 +++ b/ext/pcre/pcrelib/testdata/testoutput12 @@ -30,6 +30,15 @@ Subject length lower bound = -1 No starting char list JIT study was not successful +/b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*b*/S+I +Capturing subpattern count = 0 +May match empty string +No options +No first char +No need char +Study returned NULL +JIT study was not successful + /abc/S+I>testsavedregex Capturing subpattern count = 0 No options @@ -176,4 +185,20 @@ No match, mark = m (JIT) 12345678abcd 0: 12345678abcd (JIT) +/-- Test pattern compilation --/ + +/(?:a|b|c|d|e)(?R)/S++ + +/(?:a|b|c|d|e)(?R)(?R)/S++ + +/(a(?:a|b|c|d|e)b){8,16}/S++ + +/(?:|a|){100}x/S++ + +/(x(?1)){4}/S++ + +/(.|.)*?bx/ + aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabax +Error -8 (match limit exceeded) + /-- End of testinput12 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput14 b/ext/pcre/pcrelib/testdata/testoutput14 index ae85681e0e..020f51e3a2 100644 --- a/ext/pcre/pcrelib/testdata/testoutput14 +++ b/ext/pcre/pcrelib/testdata/testoutput14 @@ -527,4 +527,6 @@ Failed: character value in \u.... sequence is too large at offset 6 End ------------------------------------------------------------------ +/(?'ABC'[bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar]([bar](*THEN:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))/ + /-- End of testinput14 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput17 b/ext/pcre/pcrelib/testdata/testoutput17 index 1a3b492fb4..9ef6c7279f 100644 --- a/ext/pcre/pcrelib/testdata/testoutput17 +++ b/ext/pcre/pcrelib/testdata/testoutput17 @@ -555,4 +555,6 @@ MK: 0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789AB \x{1234}\x{1234}\x{1234} 0: \x{1234}\x{1234} +/(*THEN:AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA)/ + /-- End of testinput17 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput2 b/ext/pcre/pcrelib/testdata/testoutput2 index 1e87026cc6..85c565d132 100644 --- a/ext/pcre/pcrelib/testdata/testoutput2 +++ b/ext/pcre/pcrelib/testdata/testoutput2 @@ -561,7 +561,7 @@ Failed: assertion expected after (?( at offset 3 Failed: reference to non-existent subpattern at offset 7 /(?(?<ab))/ -Failed: syntax error in subpattern name (missing terminator) at offset 7 +Failed: assertion expected after (?( at offset 3 /((?s)blah)\s+\1/I Capturing subpattern count = 1 @@ -1566,30 +1566,35 @@ Need char = 'b' /a(?(1)b)(.)/I Capturing subpattern count = 1 +Max back reference = 1 No options First char = 'a' No need char /a(?(1)bag|big)(.)/I Capturing subpattern count = 1 +Max back reference = 1 No options First char = 'a' Need char = 'g' /a(?(1)bag|big)*(.)/I Capturing subpattern count = 1 +Max back reference = 1 No options First char = 'a' No need char /a(?(1)bag|big)+(.)/I Capturing subpattern count = 1 +Max back reference = 1 No options First char = 'a' Need char = 'g' /a(?(1)b..|b..)(.)/I Capturing subpattern count = 1 +Max back reference = 1 No options First char = 'a' Need char = 'b' @@ -3379,24 +3384,28 @@ Need char = 'a' /(?(1)ab|ac)(.)/I Capturing subpattern count = 1 +Max back reference = 1 No options First char = 'a' No need char /(?(1)abz|acz)(.)/I Capturing subpattern count = 1 +Max back reference = 1 No options First char = 'a' Need char = 'z' /(?(1)abz)(.)/I Capturing subpattern count = 1 +Max back reference = 1 No options No first char No need char /(?(1)abz)(1)23/I Capturing subpattern count = 1 +Max back reference = 1 No options No first char Need char = '3' @@ -5605,6 +5614,10 @@ No match 123456\P No match +//KF>testsavedregex +Compiled pattern written to testsavedregex +Study data written to testsavedregex + /abc/IS>testsavedregex Capturing subpattern count = 0 No options @@ -6336,6 +6349,7 @@ No need char /^(?P<A>a)?(?(A)a|b)/I Capturing subpattern count = 1 +Max back reference = 1 Named capturing subpatterns: A 1 Options: anchored @@ -6353,6 +6367,7 @@ No match /(?:(?(ZZ)a|b)(?P<ZZ>X))+/I Capturing subpattern count = 1 +Max back reference = 1 Named capturing subpatterns: ZZ 1 No options @@ -6370,6 +6385,7 @@ Failed: reference to non-existent subpattern at offset 9 /(?:(?(ZZ)a|b)(?(ZZ)a|b)(?P<ZZ>X))+/I Capturing subpattern count = 1 +Max back reference = 1 Named capturing subpatterns: ZZ 1 No options @@ -6381,6 +6397,7 @@ Need char = 'X' /(?:(?(ZZ)a|\(b\))\\(?P<ZZ>X))+/I Capturing subpattern count = 1 +Max back reference = 1 Named capturing subpatterns: ZZ 1 No options @@ -9118,10 +9135,10 @@ Failed: subpattern name expected at offset 3 Failed: subpattern name expected at offset 3 /\k/ -Failed: \k is not followed by a braced, angle-bracketed, or quoted name at offset 2 +Failed: \k is not followed by a braced, angle-bracketed, or quoted name at offset 1 /\kabc/ -Failed: \k is not followed by a braced, angle-bracketed, or quoted name at offset 5 +Failed: \k is not followed by a braced, angle-bracketed, or quoted name at offset 1 /(?P=)/ Failed: subpattern name expected at offset 4 @@ -9169,7 +9186,7 @@ Failed: unknown POSIX class name at offset 6 Failed: unknown POSIX class name at offset 3 /(^(a|b\g<-1'c))/ -Failed: \g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number at offset 15 +Failed: \g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number at offset 8 /^(?+1)(?<a>x|y){0}z/ xzxx @@ -10226,6 +10243,7 @@ No starting char list (?(1)|.) # check that there was an empty component /xiIS Capturing subpattern count = 1 +Max back reference = 1 Options: anchored caseless extended No first char Need char = ':' @@ -10255,6 +10273,7 @@ Failed: different names for subpatterns of the same number are not allowed at of b(?<quote> (?<apostrophe>')|(?<realquote>")) ) (?('quote')[a-z]+|[0-9]+)/JIx Capturing subpattern count = 6 +Max back reference = 1 Named capturing subpatterns: apostrophe 2 apostrophe 5 @@ -10317,6 +10336,7 @@ No match End ------------------------------------------------------------------ Capturing subpattern count = 4 +Max back reference = 4 Named capturing subpatterns: D 4 D 1 @@ -10364,6 +10384,7 @@ No match End ------------------------------------------------------------------ Capturing subpattern count = 4 +Max back reference = 1 Named capturing subpatterns: A 1 A 4 @@ -10486,6 +10507,7 @@ No starting char list /()i(?(1)a)/SI Capturing subpattern count = 1 +Max back reference = 1 No options No first char Need char = 'i' @@ -14076,10 +14098,10 @@ Failed: group name must start with a non-digit at offset 3 Failed: group name must start with a non-digit at offset 4 /\g'3gh'/ -Failed: \g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number at offset 7 +Failed: \g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number at offset 2 /\g<5fg>/ -Failed: \g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number at offset 7 +Failed: \g is not followed by a braced, angle-bracketed, or quoted name/number or by a plain number at offset 2 /(?(<4gh>)abc)/ Failed: group name must start with a non-digit at offset 4 @@ -14206,4 +14228,350 @@ Failed: digits missing in \x{} or \o{} at offset 3 /\x{whatever}/ Failed: non-hex character in \x{} (closing brace missing?) at offset 3 +"((?=(?(?=(?(?=(?(?=()))))))))" + a + 0: + 1: + 2: + +"(?(?=)==)(((((((((?=)))))))))" + a +No match + +/^(?:(a)|b)(?(1)A|B)/I +Capturing subpattern count = 1 +Max back reference = 1 +Options: anchored +No first char +No need char + aA123\O3 +Matched, but too many substrings + 0: aA + aA123\O6 + 0: aA + 1: a + +'^(?:(?<AA>a)|b)(?(<AA>)A|B)' + aA123\O3 +Matched, but too many substrings + 0: aA + aA123\O6 + 0: aA + 1: a + +'^(?<AA>)(?:(?<AA>a)|b)(?(<AA>)A|B)'J + aA123\O3 +Matched, but too many substrings + 0: aA + aA123\O6 +Matched, but too many substrings + 0: aA + 1: + +'^(?:(?<AA>X)|)(?:(?<AA>a)|b)\k{AA}'J + aa123\O3 +Matched, but too many substrings + 0: aa + aa123\O6 +Matched, but too many substrings + 0: aa + 1: <unset> + +/(?<N111>(?J)(?<N111>1(111111)11|)1|1|)(?(<N111>)1)/ + +/(?(?=0)?)+/ +Failed: nothing to repeat at offset 7 + +/(?(?=0)(?=00)?00765)/ + 00765 + 0: 00765 + +/(?(?=0)(?=00)?00765|(?!3).56)/ + 00765 + 0: 00765 + 456 + 0: 456 + ** Failers +No match + 356 +No match + +'^(a)*+(\w)' + g + 0: g + 1: <unset> + 2: g + g\O3 +Matched, but too many substrings + 0: g + +'^(?:a)*+(\w)' + g + 0: g + 1: g + g\O3 +Matched, but too many substrings + 0: g + +//C + \O\C+ +Callout 255: last capture = -1 +---> + +0 ^ +Matched, but too many substrings + +"((?2){0,1999}())?" + +/((?+1)(\1))/BZ +------------------------------------------------------------------ + Bra + Once + CBra 1 + Recurse + CBra 2 + \1 + Ket + Ket + Ket + Ket + End +------------------------------------------------------------------ + +/(?(?!)a|b)/ + bbb + 0: b + aaa +No match + +"((?2)+)((?1))" + +"(?(?<E>.*!.*)?)" +Failed: assertion expected after (?( at offset 3 + +"X((?2)()*+){2}+"BZ +------------------------------------------------------------------ + Bra + X + Once + CBra 1 + Recurse + Braposzero + SCBraPos 2 + KetRpos + Ket + CBra 1 + Recurse + Braposzero + SCBraPos 2 + KetRpos + Ket + Ket + Ket + End +------------------------------------------------------------------ + +"X((?2)()*+){2}"BZ +------------------------------------------------------------------ + Bra + X + CBra 1 + Recurse + Braposzero + SCBraPos 2 + KetRpos + Ket + CBra 1 + Recurse + Braposzero + SCBraPos 2 + KetRpos + Ket + Ket + End +------------------------------------------------------------------ + +"(?<=((?2))((?1)))" +Failed: lookbehind assertion is not fixed length at offset 17 + +/(?<=\Ka)/g+ + aaaaa + 0: a + 0+ aaaa + 0: a + 0+ aaaa + 0: a + 0+ aaa + 0: a + 0+ aa + 0: a + 0+ a + 0: a + 0+ + +/(?<=\Ka)/G+ + aaaaa + 0: a + 0+ aaaa + 0: a + 0+ aaa + 0: a + 0+ aa + 0: a + 0+ a + 0: a + 0+ + +/((?2){73}(?2))((?1))/ + +/.((?2)(?R)\1)()/BZ +------------------------------------------------------------------ + Bra + Any + Once + CBra 1 + Recurse + Recurse + \1 + Ket + Ket + CBra 2 + Ket + Ket + End +------------------------------------------------------------------ + +/(?1)()((((((\1++))\x85)+)|))/ + +/(\9*+(?2);\3++()2|)++{/ +Failed: reference to non-existent subpattern at offset 22 + +/\V\x85\9*+((?2)\3++()2)*:2/ +Failed: reference to non-existent subpattern at offset 26 + +/(((?(R)){0,2}) (?''((?'R')((?'R')))))/J + +/(((?(X)){0,2}) (?''((?'X')((?'X')))))/J + +/(((?(R)){0,2}) (?''((?'X')((?'R')))))/ + +"(?J)(?'d'(?'d'\g{d}))" + +".*?\h.+.\.+\R*?\xd(?i)(?=!(?=b`b`b`\`b\xa9b!)`\a`bbbbbbbbbbbbb`bbbbbbbbbbbb*R\x85bbbbbbb\C?{((?2)(?))(( +\H){8(?<=(?1){29}\xa8bbbb\x16\xd\xc6^($(?<! )(\xa9H4){4}h}1)B))\x15')" + +"(?J:(?|(?'R')(\k'R')|((?'R'))))" + +/(?<=|(\,\$(?73591620449005828816)\xa8.{7}){6}\x09)/ +Failed: number is too big at offset 32 + +// +\O1 +Matched, but too many substrings + +/^(?:(?(1)x|)+)+$()/BZ +------------------------------------------------------------------ + Bra + ^ + SBra + SCond + 1 Cond ref + x + Alt + KetRmax + KetRmax + $ + CBra 1 + Ket + Ket + End +------------------------------------------------------------------ + +/(?=di(?<=(?1))|(?=(.))))/ +Failed: unmatched parentheses at offset 23 + +/(?(R))*+/BZ +------------------------------------------------------------------ + Bra + Braposzero + SBraPos + SCond + Cond recurse any + Ket + KetRpos + Ket + End +------------------------------------------------------------------ + +/[[:\\](?'abc')[a:]/ + +"[[[.\xe8Nq\xffq\xff\xe0\x2|||::Nq\xffq\xff\xe0\x6\x2|||::[[[:[::::::[[[[[::::::::[:[[[:[:::[[[[[[[[[[[[:::::::::::::::::[[.\xe8Nq\xffq\xff\xe0\x2|||::Nq\xffq\xff\xe0\x6\x2|||::[[[:[::::::[[[[[::::::::[:[[[:[:::[[[[[[[[[[[[[[:::E[[[:[:[[:[:::[[:::E[[[:[:[[:'[:::::E[[[:[::::::[[[:[[[[[[[::E[[[:[::::::[[[:[[[[[[[[:[[::[::::[[:::::::[[:[[[[[[[:[[::[:[[:[~" +Failed: missing terminating ] for character class at offset 353 + +/()(?(R)0)*+/BZ +------------------------------------------------------------------ + Bra + CBra 1 + Ket + Braposzero + SBraPos + SCond + Cond recurse any + 0 + Ket + KetRpos + Ket + End +------------------------------------------------------------------ + +/(?R-:(?</ +Failed: (?R or (?[+-]digits must be followed by ) at offset 3 + +/(?1){3918}(((((0(\k'R'))))(?J)(?'R'(?'R'\3){99})))/I +Capturing subpattern count = 8 +Max back reference = 8 +Named capturing subpatterns: + R 7 + R 8 +No options +Duplicate name status changes +No first char +Need char = '0' + +/(?J:(?|(:(?|(?'R')(\k'R')|((?'R')))H'Rk'Rf)|s(?'R')))/ + +/0(?0)|(1)(*THEN)(*SKIP:0)(*FAIL)/ + 01 +No match + +/((?(R8000000000)))/ +Failed: number is too big at offset 16 + +/(?(8000000000/ +Failed: number is too big at offset 13 + +/(?:ab)?(?:ab)(?:ab)/ + abab + 0: abab + ababab + 0: ababab + aba +No match + +/((*MARK:A))++a(*SKIP:B)b/ + aacb +No match + +/(?J:(?|(:(?|(?'R')(\z(?|(?'R')(\k'R')|((?'R')))k'R')|((?'R')))H'Ak'Rf)|s(?'R')))/ + +/(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?&a)(?<a>1)/ + +/a[[:punct:]b]/BZ +------------------------------------------------------------------ + Bra + a + [!-/:-@[-`b{-~] + Ket + End +------------------------------------------------------------------ + /-- End of testinput2 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput4 b/ext/pcre/pcrelib/testdata/testoutput4 index dcf13b0850..d43c12392d 100644 --- a/ext/pcre/pcrelib/testdata/testoutput4 +++ b/ext/pcre/pcrelib/testdata/testoutput4 @@ -1271,4 +1271,10 @@ No match #\x{10000}#\x{100}#\x{10ffff}# 0: #\x{10000}#\x{100}#\x{10ffff}# +"[\S\V\H]"8 + +/\C(\W?Å¿)'?{{/8 + \\C(\\W?Å¿)'?{{ +No match + /-- End of testinput4 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput5 b/ext/pcre/pcrelib/testdata/testoutput5 index 5c098e650b..bab989ca7e 100644 --- a/ext/pcre/pcrelib/testdata/testoutput5 +++ b/ext/pcre/pcrelib/testdata/testoutput5 @@ -1897,4 +1897,49 @@ Failed: disallowed Unicode code point (>= 0xd800 && <= 0xdfff) at offset 5 End ------------------------------------------------------------------ +/[^\xff]*PRUNE:\x{100}abc(xyz(?1))/8DZ +------------------------------------------------------------------ + Bra + [^\x{ff}]* + PRUNE:\x{100}abc + CBra 1 + xyz + Recurse + Ket + Ket + End +------------------------------------------------------------------ +Capturing subpattern count = 1 +Options: utf +No first char +Need char = 'z' + +/(?<=\K\x{17f})/8g+ + \x{17f}\x{17f}\x{17f}\x{17f}\x{17f} + 0: \x{17f} + 0+ \x{17f}\x{17f}\x{17f}\x{17f} + 0: \x{17f} + 0+ \x{17f}\x{17f}\x{17f}\x{17f} + 0: \x{17f} + 0+ \x{17f}\x{17f}\x{17f} + 0: \x{17f} + 0+ \x{17f}\x{17f} + 0: \x{17f} + 0+ \x{17f} + 0: \x{17f} + 0+ + +/(?<=\K\x{17f})/8G+ + \x{17f}\x{17f}\x{17f}\x{17f}\x{17f} + 0: \x{17f} + 0+ \x{17f}\x{17f}\x{17f}\x{17f} + 0: \x{17f} + 0+ \x{17f}\x{17f}\x{17f} + 0: \x{17f} + 0+ \x{17f}\x{17f} + 0: \x{17f} + 0+ \x{17f} + 0: \x{17f} + 0+ + /-- End of testinput5 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput6 b/ext/pcre/pcrelib/testdata/testoutput6 index a990ba13eb..beb85aaa0b 100644 --- a/ext/pcre/pcrelib/testdata/testoutput6 +++ b/ext/pcre/pcrelib/testdata/testoutput6 @@ -2461,4 +2461,100 @@ No match scat 0: sc +/[A-`]/i8 + abcdefghijklmno + 0: a + +/\C\X*QT/8 + Ó…\x0aT +No match + +/[\pS#moq]/ + = + 0: = + +/[[:punct:]]/8W + \xc2\xb4 +No match + \x{b4} +No match + +/[[:^ascii:]]/8W + \x{100} + 0: \x{100} + \x{200} + 0: \x{200} + \x{300} + 0: \x{300} + \x{37e} + 0: \x{37e} + a +No match + 9 +No match + g +No match + +/[[:^ascii:]\w]/8W + a + 0: a + 9 + 0: 9 + g + 0: g + \x{100} + 0: \x{100} + \x{200} + 0: \x{200} + \x{300} + 0: \x{300} + \x{37e} + 0: \x{37e} + +/[\w[:^ascii:]]/8W + a + 0: a + 9 + 0: 9 + g + 0: g + \x{100} + 0: \x{100} + \x{200} + 0: \x{200} + \x{300} + 0: \x{300} + \x{37e} + 0: \x{37e} + +/[^[:ascii:]\W]/8W + a +No match + 9 +No match + g +No match + \x{100} + 0: \x{100} + \x{200} + 0: \x{200} + \x{300} +No match + \x{37e} +No match + +/[[:^ascii:]a]/8W + a + 0: a + 9 +No match + g +No match + \x{100} + 0: \x{100} + \x{200} + 0: \x{200} + \x{37e} + 0: \x{37e} + /-- End of testinput6 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput7 b/ext/pcre/pcrelib/testdata/testoutput7 index ee46bdbb5a..cc9ebdd558 100644 --- a/ext/pcre/pcrelib/testdata/testoutput7 +++ b/ext/pcre/pcrelib/testdata/testoutput7 @@ -949,7 +949,7 @@ No match /[[:^alpha:][:^cntrl:]]+/8WBZ ------------------------------------------------------------------ Bra - [ -~\x80-\xff\P{L}]++ + [ -~\x80-\xff\P{L}\x{100}-\x{10ffff}]++ Ket End ------------------------------------------------------------------ @@ -961,7 +961,7 @@ No match /[[:^cntrl:][:^alpha:]]+/8WBZ ------------------------------------------------------------------ Bra - [ -~\x80-\xff\P{L}]++ + [ -~\x80-\xff\x{100}-\x{10ffff}\P{L}]++ Ket End ------------------------------------------------------------------ @@ -2295,4 +2295,57 @@ Need char = 'c' (caseless) scat 0: sc +/[\W\p{Any}]/BZ +------------------------------------------------------------------ + Bra + [\x00-/:-@[-^`{-\xff\p{Any}] + Ket + End +------------------------------------------------------------------ + abc + 0: a + 123 + 0: 1 + +/[\W\pL]/BZ +------------------------------------------------------------------ + Bra + [\x00-/:-@[-^`{-\xff\p{L}] + Ket + End +------------------------------------------------------------------ + abc + 0: a + ** Failers + 0: * + 123 +No match + +/a[[:punct:]b]/WBZ +------------------------------------------------------------------ + Bra + a + [b[:punct:]] + Ket + End +------------------------------------------------------------------ + +/a[[:punct:]b]/8WBZ +------------------------------------------------------------------ + Bra + a + [b[:punct:]] + Ket + End +------------------------------------------------------------------ + +/a[b[:punct:]]/8WBZ +------------------------------------------------------------------ + Bra + a + [b[:punct:]] + Ket + End +------------------------------------------------------------------ + /-- End of testinput7 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutput8 b/ext/pcre/pcrelib/testdata/testoutput8 index 95c4e4db1b..e4fa497756 100644 --- a/ext/pcre/pcrelib/testdata/testoutput8 +++ b/ext/pcre/pcrelib/testdata/testoutput8 @@ -7785,4 +7785,10 @@ Matched, but offsets vector is too small to show all matches NON QUOTED \"QUOT\"\"ED\" AFTER \"NOT MATCHED 0: NON QUOTED "QUOT""ED" AFTER +/(?(?!)a|b)/ + bbb + 0: b + aaa +No match + /-- End of testinput8 --/ diff --git a/ext/pcre/pcrelib/testdata/testoutputEBC b/ext/pcre/pcrelib/testdata/testoutputEBC index abbfdc43fc..72b6fa3edf 100644 --- a/ext/pcre/pcrelib/testdata/testoutputEBC +++ b/ext/pcre/pcrelib/testdata/testoutputEBC @@ -41,16 +41,22 @@ No match /^A\ˆ/ A B 0: A\x20 + A\x41B + 0: AA /-- Test \H --/ /^A\È/ AB 0: AB + A\x42B + 0: AB ** Fail No match A B No match + A\x41B +No match /-- Test \R --/ diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index ee3e36b6ab..93bfc00052 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -1350,7 +1350,6 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *subject, int limit, int is_callable_replace, int *replace_count) { zval *regex_entry, - *replace_entry = NULL, *replace_value, empty_replace; zend_string *result; @@ -1372,25 +1371,26 @@ static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *sub /* For each entry in the regex array, get the entry */ ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(regex), regex_entry) { + zval replace_str; /* Make sure we're dealing with strings. */ zend_string *regex_str = zval_get_string(regex_entry); + ZVAL_UNDEF(&replace_str); /* If replace is an array and not a callable construct */ if (Z_TYPE_P(replace) == IS_ARRAY && !is_callable_replace) { /* Get current entry */ - replace_entry = NULL; while (replace_idx < Z_ARRVAL_P(replace)->nNumUsed) { if (Z_TYPE(Z_ARRVAL_P(replace)->arData[replace_idx].val) != IS_UNDEF) { - replace_entry = &Z_ARRVAL_P(replace)->arData[replace_idx].val; + ZVAL_COPY(&replace_str, &Z_ARRVAL_P(replace)->arData[replace_idx].val); break; } replace_idx++; } - if (replace_entry != NULL) { + if (!Z_ISUNDEF(replace_str)) { if (!is_callable_replace) { - convert_to_string_ex(replace_entry); + convert_to_string(&replace_str); } - replace_value = replace_entry; + replace_value = &replace_str; replace_idx++; } else { /* We've run out of replacement strings, so use an empty one */ @@ -1413,10 +1413,12 @@ static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *sub } else { zend_string_release(subject_str); zend_string_release(regex_str); + zval_dtor(&replace_str); return NULL; } zend_string_release(regex_str); + zval_dtor(&replace_str); } ZEND_HASH_FOREACH_END(); return subject_str; diff --git a/ext/pcre/tests/backtrack_limit.phpt b/ext/pcre/tests/backtrack_limit.phpt index 419e6c2009..3f0d8e6446 100644 --- a/ext/pcre/tests/backtrack_limit.phpt +++ b/ext/pcre/tests/backtrack_limit.phpt @@ -8,6 +8,7 @@ if (@preg_match_all('/\p{N}/', '0123456789', $dummy) === false) { ?> --INI-- pcre.backtrack_limit=2 +pcre.jit=0 --FILE-- <?php diff --git a/ext/pcre/tests/bug71537.phpt b/ext/pcre/tests/bug71537.phpt new file mode 100644 index 0000000000..cdc2928a28 --- /dev/null +++ b/ext/pcre/tests/bug71537.phpt @@ -0,0 +1,9 @@ +--TEST-- +Fixed bug #71537 (PCRE segfault from Opcache) +--FILE-- +<?php + +var_dump(preg_replace(array("/Monkey/"), array(2016), "Happy Year of Monkey")); +?> +--EXPECT-- +string(18) "Happy Year of 2016" diff --git a/ext/pdo/Makefile.frag b/ext/pdo/Makefile.frag index dc25c9f70b..58125ed872 100644 --- a/ext/pdo/Makefile.frag +++ b/ext/pdo/Makefile.frag @@ -10,7 +10,7 @@ $(srcdir)/pdo_sql_parser.c: $(srcdir)/pdo_sql_parser.re (cd $(top_srcdir); $(RE2C) --no-generation-date -o ext/pdo/pdo_sql_parser.c ext/pdo/pdo_sql_parser.re) install-pdo-headers: - @echo "Installing PDO headers: $(INSTALL_ROOT)$(phpincludedir)/ext/pdo/" + @echo "Installing PDO headers: $(INSTALL_ROOT)$(phpincludedir)/ext/pdo/" @$(mkinstalldirs) $(INSTALL_ROOT)$(phpincludedir)/ext/pdo @for f in $(PDO_HEADER_FILES); do \ if test -f "$(top_srcdir)/$$f"; then \ diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c index 77366f817d..e0fc9d74f2 100644 --- a/ext/pdo/pdo.c +++ b/ext/pdo/pdo.c @@ -32,8 +32,7 @@ #include "php_pdo_driver.h" #include "php_pdo_int.h" #include "zend_exceptions.h" - -static zend_class_entry *spl_ce_RuntimeException; +#include "ext/spl/spl_exceptions.h" zend_class_entry *pdo_dbh_ce, *pdo_dbstmt_ce, *pdo_row_ce; @@ -79,20 +78,9 @@ PDO_API char *php_pdo_str_tolower_dup(const char *src, int len) /* {{{ */ PDO_API zend_class_entry *php_pdo_get_exception_base(int root) /* {{{ */ { -#if defined(HAVE_SPL) if (!root) { - if (!spl_ce_RuntimeException) { - zend_class_entry *pce; - - if ((pce = zend_hash_str_find_ptr(CG(class_table), "runtimeexception", sizeof("RuntimeException") - 1))) { - spl_ce_RuntimeException = pce; - return pce; - } - } else { - return spl_ce_RuntimeException; - } + return spl_ce_RuntimeException; } -#endif return zend_ce_exception; } /* }}} */ @@ -128,14 +116,10 @@ const zend_function_entry pdo_functions[] = { /* }}} */ /* {{{ pdo_functions[] */ -#if ZEND_MODULE_API_NO >= 20050922 static const zend_module_dep pdo_deps[] = { -#ifdef HAVE_SPL ZEND_MOD_REQUIRED("spl") -#endif ZEND_MOD_END }; -#endif /* }}} */ /* {{{ pdo_module_entry */ @@ -351,8 +335,6 @@ PHP_MINIT_FUNCTION(pdo) { zend_class_entry ce; - spl_ce_RuntimeException = NULL; - if (FAILURE == pdo_sqlstate_init_error_table()) { return FAILURE; } diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index cc6346bf15..0b2053d0d3 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -1274,8 +1274,7 @@ static void cls_method_pdtor(zval *el) /* {{{ */ { int pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind) { const zend_function_entry *funcs; - zend_function func; - zend_internal_function *ifunc = (zend_internal_function*)&func; + zend_internal_function func; size_t namelen; char *lc_name; pdo_dbh_t *dbh = dbh_obj->inner; @@ -1294,41 +1293,43 @@ int pdo_hash_methods(pdo_dbh_object_t *dbh_obj, int kind) zend_hash_init_ex(dbh->cls_methods[kind], 8, NULL, dbh->is_persistent? cls_method_pdtor : cls_method_dtor, dbh->is_persistent, 0); + memset(&func, 0, sizeof(func)); + while (funcs->fname) { - ifunc->type = ZEND_INTERNAL_FUNCTION; - ifunc->handler = funcs->handler; - ifunc->function_name = zend_string_init(funcs->fname, strlen(funcs->fname), dbh->is_persistent); - ifunc->scope = dbh_obj->std.ce; - ifunc->prototype = NULL; + func.type = ZEND_INTERNAL_FUNCTION; + func.handler = funcs->handler; + func.function_name = zend_string_init(funcs->fname, strlen(funcs->fname), dbh->is_persistent); + func.scope = dbh_obj->std.ce; + func.prototype = NULL; if (funcs->flags) { - ifunc->fn_flags = funcs->flags | ZEND_ACC_NEVER_CACHE; + func.fn_flags = funcs->flags | ZEND_ACC_NEVER_CACHE; } else { - ifunc->fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_NEVER_CACHE; + func.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_NEVER_CACHE; } if (funcs->arg_info) { zend_internal_function_info *info = (zend_internal_function_info*)funcs->arg_info; - ifunc->arg_info = (zend_internal_arg_info*)funcs->arg_info + 1; - ifunc->num_args = funcs->num_args; + func.arg_info = (zend_internal_arg_info*)funcs->arg_info + 1; + func.num_args = funcs->num_args; if (info->required_num_args == -1) { - ifunc->required_num_args = funcs->num_args; + func.required_num_args = funcs->num_args; } else { - ifunc->required_num_args = info->required_num_args; + func.required_num_args = info->required_num_args; } if (info->return_reference) { - ifunc->fn_flags |= ZEND_ACC_RETURN_REFERENCE; + func.fn_flags |= ZEND_ACC_RETURN_REFERENCE; } if (funcs->arg_info[funcs->num_args].is_variadic) { - ifunc->fn_flags |= ZEND_ACC_VARIADIC; + func.fn_flags |= ZEND_ACC_VARIADIC; /* Don't count the variadic argument */ - ifunc->num_args--; + func.num_args--; } } else { - ifunc->arg_info = NULL; - ifunc->num_args = 0; - ifunc->required_num_args = 0; + func.arg_info = NULL; + func.num_args = 0; + func.required_num_args = 0; } - zend_set_function_arg_flags((zend_function*)ifunc); + zend_set_function_arg_flags((zend_function*)&func); namelen = strlen(funcs->fname); lc_name = emalloc(namelen+1); zend_str_tolower_copy(lc_name, funcs->fname, namelen); @@ -1431,9 +1432,7 @@ void pdo_dbh_init(void) REGISTER_PDO_CLASS_CONST_LONG("FETCH_KEY_PAIR", (zend_long)PDO_FETCH_KEY_PAIR); REGISTER_PDO_CLASS_CONST_LONG("FETCH_CLASSTYPE", (zend_long)PDO_FETCH_CLASSTYPE); -#if PHP_VERSION_ID >= 50100 REGISTER_PDO_CLASS_CONST_LONG("FETCH_SERIALIZE",(zend_long)PDO_FETCH_SERIALIZE); -#endif REGISTER_PDO_CLASS_CONST_LONG("FETCH_PROPS_LATE", (zend_long)PDO_FETCH_PROPS_LATE); REGISTER_PDO_CLASS_CONST_LONG("FETCH_NAMED", (zend_long)PDO_FETCH_NAMED); diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index 5ca20fcd5b..6019c39aba 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2107,9 +2107,9 @@ static PHP_METHOD(PDOStatement, debugDumpParams) RETURN_FALSE; } - php_stream_printf(out, "SQL: [%d] %.*s\n", + php_stream_printf(out, "SQL: [%zd] %.*s\n", stmt->query_stringlen, - stmt->query_stringlen, stmt->query_string); + (int) stmt->query_stringlen, stmt->query_string); php_stream_printf(out, "Params: %d\n", stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0); @@ -2119,13 +2119,14 @@ static PHP_METHOD(PDOStatement, debugDumpParams) zend_string *key = NULL; ZEND_HASH_FOREACH_KEY_PTR(stmt->bound_params, num, key, param) { if (key) { - php_stream_printf(out, "Key: Name: [%d] %.*s\n", ZSTR_LEN(key), ZSTR_LEN(key), ZSTR_VAL(key)); + php_stream_printf(out, "Key: Name: [%zd] %.*s\n", + ZSTR_LEN(key), (int) ZSTR_LEN(key), ZSTR_VAL(key)); } else { php_stream_printf(out, "Key: Position #%pd:\n", num); } - php_stream_printf(out, "paramno=%pd\nname=[%d] \"%.*s\"\nis_param=%d\nparam_type=%d\n", - param->paramno, param->name? ZSTR_LEN(param->name) : 0, param->name? ZSTR_LEN(param->name) : 0, + php_stream_printf(out, "paramno=%pd\nname=[%zd] \"%.*s\"\nis_param=%d\nparam_type=%d\n", + param->paramno, param->name ? ZSTR_LEN(param->name) : 0, param->name ? (int) ZSTR_LEN(param->name) : 0, param->name ? ZSTR_VAL(param->name) : "", param->is_param, param->param_type); diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c index cfb386fa0d..dcbaf55a3f 100644 --- a/ext/pdo_dblib/dblib_driver.c +++ b/ext/pdo_dblib/dblib_driver.c @@ -331,9 +331,7 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options) ,{"auto",0} /* Only works with FreeTDS. Other drivers will bork */ }; - - nvers = sizeof(tdsver)/sizeof(tdsver[0]); - + struct pdo_data_src_parser vars[] = { { "charset", NULL, 0 } ,{ "appname", "PHP " PDO_DBLIB_FLAVOUR, 0 } @@ -344,7 +342,8 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options) }; nvars = sizeof(vars)/sizeof(vars[0]); - + nvers = sizeof(tdsver)/sizeof(tdsver[0]); + php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, nvars); if (driver_options) { diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c index 484bfbb560..0eff4945dd 100644 --- a/ext/pdo_dblib/dblib_stmt.c +++ b/ext/pdo_dblib/dblib_stmt.c @@ -102,7 +102,7 @@ static int pdo_dblib_stmt_cursor_closer(pdo_stmt_t *stmt) /* Cancel any pending results */ dbcancel(H->link); - + return 1; } @@ -268,6 +268,25 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, *ptr = tmp_ptr; break; } + case SQLDATETIM4: + case SQLDATETIME: { + DBDATETIME dt; + DBDATEREC di; + + dbconvert(H->link, coltype, (BYTE*) *ptr, -1, SQLDATETIME, (LPBYTE) &dt, -1); + dbdatecrack(H->link, &di, &dt); + + *len = spprintf((char**) &tmp_ptr, 20, "%d-%02d-%02d %02d:%02d:%02d", +#ifdef PHP_DBLIB_IS_MSSQL || MSDBLIB + di.year, di.month, di.day, di.hour, di.minute, di.second +#else + di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond +#endif + ); + + *ptr = (char*) tmp_ptr; + break; + } default: if (dbwillconvert(coltype, SQLCHAR)) { tmp_len = 32 + (2 * (*len)); /* FIXME: We allocate more than we need here */ diff --git a/ext/pdo_dblib/pdo_dblib.c b/ext/pdo_dblib/pdo_dblib.c index 8025187196..0b64bce8a7 100644 --- a/ext/pdo_dblib/pdo_dblib.c +++ b/ext/pdo_dblib/pdo_dblib.c @@ -39,24 +39,18 @@ const zend_function_entry pdo_dblib_functions[] = { PHP_FE_END }; -#if ZEND_MODULE_API_NO >= 20050922 static const zend_module_dep pdo_dblib_deps[] = { ZEND_MOD_REQUIRED("pdo") ZEND_MOD_END }; -#endif #if PDO_DBLIB_IS_MSSQL zend_module_entry pdo_mssql_module_entry = { #else zend_module_entry pdo_dblib_module_entry = { #endif -#if ZEND_MODULE_API_NO >= 20050922 STANDARD_MODULE_HEADER_EX, NULL, pdo_dblib_deps, -#else - STANDARD_MODULE_HEADER, -#endif #if PDO_DBLIB_IS_MSSQL "pdo_mssql", #elif defined(PHP_WIN32) diff --git a/ext/pdo_dblib/tests/bug_45876.phpt b/ext/pdo_dblib/tests/bug_45876.phpt index 920905830a..5b595519f2 100644 --- a/ext/pdo_dblib/tests/bug_45876.phpt +++ b/ext/pdo_dblib/tests/bug_45876.phpt @@ -15,7 +15,7 @@ var_dump($stmt->getColumnMeta(0)); $stmt = null; ?> --EXPECT-- -array(8) { +array(10) { ["max_length"]=> int(255) ["precision"]=> @@ -26,6 +26,10 @@ array(8) { string(13) "TABLE_CATALOG" ["native_type"]=> string(4) "char" + ["native_type_id"]=> + int(47) + ["native_usertype_id"]=> + int(2) ["name"]=> string(13) "TABLE_CATALOG" ["len"]=> diff --git a/ext/pdo_dblib/tests/bug_54648.phpt b/ext/pdo_dblib/tests/bug_54648.phpt new file mode 100644 index 0000000000..aa9f292669 --- /dev/null +++ b/ext/pdo_dblib/tests/bug_54648.phpt @@ -0,0 +1,26 @@ +--TEST-- +PDO_DBLIB: Does not force correct dateformat +--SKIPIF-- +<?php +if (!extension_loaded('pdo_dblib')) die('skip not loaded'); +require dirname(__FILE__) . '/config.inc'; +?> +--FILE-- +<?php +require dirname(__FILE__) . '/config.inc'; +$db->query('set dateformat ymd'); +$rs = $db->query("select cast('1950-01-18 23:00:00' as smalldatetime) as sdt, cast('2030-01-01 23:59:59' as datetime) as dt"); +var_dump($rs->fetchAll(PDO::FETCH_ASSOC)); +echo "Done.\n"; +?> +--EXPECT-- +array(1) { + [0]=> + array(2) { + ["sdt"]=> + string(19) "1950-01-18 23:00:00" + ["dt"]=> + string(19) "2030-01-01 23:59:59" + } +} +Done. diff --git a/ext/pdo_dblib/tests/bug_68957.phpt b/ext/pdo_dblib/tests/bug_68957.phpt new file mode 100644 index 0000000000..3d6e2fd13d --- /dev/null +++ b/ext/pdo_dblib/tests/bug_68957.phpt @@ -0,0 +1,29 @@ +--TEST-- +PDO_DBLIB bug #68957 PDO::query doesn't support several queries +--SKIPIF-- +<?php +if (!extension_loaded('pdo_dblib')) die('skip not loaded'); +require dirname(__FILE__) . '/config.inc'; +?> +--FILE-- +<?php +require dirname(__FILE__) . '/config.inc'; + +$query = "declare @myInt int = 1; select @myInt;"; +$stmt = $db->query($query); +$stmt->nextRowset(); // Added line +$rows = $stmt->fetchAll(); +print_r($rows); + +?> +--EXPECT-- +Array +( + [0] => Array + ( + [computed0] => 1 + [0] => 1 + ) + +) + diff --git a/ext/pdo_mysql/mysql_driver.c b/ext/pdo_mysql/mysql_driver.c index f09bc05314..1b1d1abbea 100644 --- a/ext/pdo_mysql/mysql_driver.c +++ b/ext/pdo_mysql/mysql_driver.c @@ -630,12 +630,7 @@ static int pdo_mysql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) } #ifndef PDO_USE_MYSQLND -#if PHP_API_VERSION < 20100412 - if ((PG(open_basedir) && PG(open_basedir)[0] != '\0') || PG(safe_mode)) -#else - if (PG(open_basedir) && PG(open_basedir)[0] != '\0') -#endif - { + if (PG(open_basedir) && PG(open_basedir)[0] != '\0') { local_infile = 0; } #endif diff --git a/ext/pdo_mysql/pdo_mysql.c b/ext/pdo_mysql/pdo_mysql.c index 546514435e..5eedc6bd07 100644 --- a/ext/pdo_mysql/pdo_mysql.c +++ b/ext/pdo_mysql/pdo_mysql.c @@ -229,7 +229,6 @@ const zend_function_entry pdo_mysql_functions[] = { /* }}} */ /* {{{ pdo_mysql_deps[] */ -#if ZEND_MODULE_API_NO >= 20050922 static const zend_module_dep pdo_mysql_deps[] = { ZEND_MOD_REQUIRED("pdo") #ifdef PDO_USE_MYSQLND @@ -237,7 +236,6 @@ static const zend_module_dep pdo_mysql_deps[] = { #endif ZEND_MOD_END }; -#endif /* }}} */ /* {{{ pdo_mysql_module_entry */ diff --git a/ext/pdo_mysql/tests/bug71569.phpt b/ext/pdo_mysql/tests/bug71569.phpt new file mode 100644 index 0000000000..32c14b4622 --- /dev/null +++ b/ext/pdo_mysql/tests/bug71569.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #71569 (#70389 fix causes segmentation fault) +--SKIPIF-- +<?php +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc'); +require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc'); +MySQLPDOTest::skip(); +?> +--FILE-- +<?php +require(dirname(__FILE__). DIRECTORY_SEPARATOR . 'config.inc'); + +try { + new PDO(PDO_MYSQL_TEST_DSN, PDO_MYSQL_TEST_USER, PDO_MYSQL_TEST_PASS, [ + PDO::MYSQL_ATTR_INIT_COMMAND => null, + ]); +} catch (PDOException $e) { + echo $e->getMessage(); +} + +?> +--EXPECT-- +SQLSTATE[42000] [1065] Query was empty diff --git a/ext/pdo_oci/pdo_oci.c b/ext/pdo_oci/pdo_oci.c index 9753f5fce3..0c0cf84574 100644 --- a/ext/pdo_oci/pdo_oci.c +++ b/ext/pdo_oci/pdo_oci.c @@ -38,12 +38,10 @@ const zend_function_entry pdo_oci_functions[] = { /* {{{ pdo_oci_module_entry */ -#if ZEND_MODULE_API_NO >= 20050922 static const zend_module_dep pdo_oci_deps[] = { ZEND_MOD_REQUIRED("pdo") ZEND_MOD_END }; -#endif zend_module_entry pdo_oci_module_entry = { STANDARD_MODULE_HEADER_EX, NULL, diff --git a/ext/pdo_odbc/pdo_odbc.c b/ext/pdo_odbc/pdo_odbc.c index 04326a4a87..0c76ccc25e 100644 --- a/ext/pdo_odbc/pdo_odbc.c +++ b/ext/pdo_odbc/pdo_odbc.c @@ -37,12 +37,10 @@ const zend_function_entry pdo_odbc_functions[] = { /* }}} */ /* {{{ pdo_odbc_deps[] */ -#if ZEND_MODULE_API_NO >= 20050922 static const zend_module_dep pdo_odbc_deps[] = { ZEND_MOD_REQUIRED("pdo") ZEND_MOD_END }; -#endif /* }}} */ /* {{{ pdo_odbc_module_entry */ diff --git a/ext/pdo_pgsql/pdo_pgsql.c b/ext/pdo_pgsql/pdo_pgsql.c index f9b0c62eba..1661fbe2d6 100644 --- a/ext/pdo_pgsql/pdo_pgsql.c +++ b/ext/pdo_pgsql/pdo_pgsql.c @@ -47,12 +47,10 @@ const zend_function_entry pdo_pgsql_functions[] = { /* {{{ pdo_sqlite_deps */ -#if ZEND_MODULE_API_NO >= 20050922 static const zend_module_dep pdo_pgsql_deps[] = { ZEND_MOD_REQUIRED("pdo") ZEND_MOD_END }; -#endif /* }}} */ /* {{{ pdo_pgsql_module_entry */ diff --git a/ext/pdo_sqlite/pdo_sqlite.c b/ext/pdo_sqlite/pdo_sqlite.c index a26d55494b..ca077092a3 100644 --- a/ext/pdo_sqlite/pdo_sqlite.c +++ b/ext/pdo_sqlite/pdo_sqlite.c @@ -39,12 +39,10 @@ const zend_function_entry pdo_sqlite_functions[] = { /* {{{ pdo_sqlite_deps */ -#if ZEND_MODULE_API_NO >= 20050922 static const zend_module_dep pdo_sqlite_deps[] = { ZEND_MOD_REQUIRED("pdo") ZEND_MOD_END }; -#endif /* }}} */ /* {{{ pdo_sqlite_module_entry diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index d7ef097d5f..5c82fd8b43 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -2319,7 +2319,7 @@ PHP_FUNCTION(pg_last_notice) zval *pgsql_link = NULL; zval *notice, *notices; PGconn *pg_link; - long option = PGSQL_NOTICE_LAST; + zend_long option = PGSQL_NOTICE_LAST; if (zend_parse_parameters(ZEND_NUM_ARGS(), "r|l", &pgsql_link, &option) == FAILURE) { return; @@ -2358,7 +2358,8 @@ PHP_FUNCTION(pg_last_notice) RETURN_TRUE; break; default: - php_error_docref(NULL, E_WARNING, "Invalid option specified (%d)", option); + php_error_docref(NULL, E_WARNING, + "Invalid option specified (" ZEND_LONG_FMT ")", option); } RETURN_FALSE; } @@ -3073,7 +3074,7 @@ static void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type) RETVAL_LONG(PQgetlength(pgsql_result, pgsql_row, field_offset)); break; case PHP_PG_DATA_ISNULL: - RETVAL_LONG(PQgetisnull(pgsql_result, pgsql_row, field_offset)) + RETVAL_LONG(PQgetisnull(pgsql_result, pgsql_row, field_offset)); break; } } diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index ce6bffecbd..33dfffc3c0 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -199,13 +199,14 @@ static php_stream *phar_make_dirstream(char *dir, HashTable *manifest) /* {{{ */ zend_hash_internal_pointer_reset(manifest); while (FAILURE != zend_hash_has_more_elements(manifest)) { + keylen = 0; if (HASH_KEY_NON_EXISTENT == zend_hash_get_current_key(manifest, &str_key, &unused)) { break; } keylen = ZSTR_LEN(str_key); if (keylen <= (uint)dirlen) { - if (keylen < (uint)dirlen || !strncmp(ZSTR_VAL(str_key), dir, dirlen)) { + if (keylen == 0 || keylen < (uint)dirlen || !strncmp(ZSTR_VAL(str_key), dir, dirlen)) { if (SUCCESS != zend_hash_move_forward(manifest)) { break; } diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 0ed34dbfcd..71498b6a13 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -516,15 +516,15 @@ void phar_entry_remove(phar_entry_data *idata, char **error) /* {{{ */ memcpy(&var, buffer, sizeof(var)); \ buffer += 4 # define PHAR_GET_16(buffer, var) \ - var = *(php_uint16*)(buffer); \ + var = *(uint16_t*)(buffer); \ buffer += 2 #endif -#define PHAR_ZIP_16(var) ((php_uint16)((((php_uint16)var[0]) & 0xff) | \ - (((php_uint16)var[1]) & 0xff) << 8)) -#define PHAR_ZIP_32(var) ((php_uint32)((((php_uint32)var[0]) & 0xff) | \ - (((php_uint32)var[1]) & 0xff) << 8 | \ - (((php_uint32)var[2]) & 0xff) << 16 | \ - (((php_uint32)var[3]) & 0xff) << 24)) +#define PHAR_ZIP_16(var) ((uint16_t)((((uint16_t)var[0]) & 0xff) | \ + (((uint16_t)var[1]) & 0xff) << 8)) +#define PHAR_ZIP_32(var) ((uint32_t)((((uint32_t)var[0]) & 0xff) | \ + (((uint32_t)var[1]) & 0xff) << 8 | \ + (((uint32_t)var[2]) & 0xff) << 16 | \ + (((uint32_t)var[3]) & 0xff) << 24)) /** * Open an already loaded phar @@ -604,7 +604,7 @@ int phar_open_parsed_phar(char *fname, int fname_len, char *alias, int alias_len * * data is the serialized zval */ -int phar_parse_metadata(char **buffer, zval *metadata, php_uint32 zip_metadata_len) /* {{{ */ +int phar_parse_metadata(char **buffer, zval *metadata, uint32_t zip_metadata_len) /* {{{ */ { php_unserialize_data_t var_hash; @@ -649,14 +649,14 @@ int phar_parse_metadata(char **buffer, zval *metadata, php_uint32 zip_metadata_l * This is used by phar_open_from_filename to process the manifest, but can be called * directly. */ -static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, zend_long halt_offset, phar_archive_data** pphar, php_uint32 compression, char **error) /* {{{ */ +static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char *alias, int alias_len, zend_long halt_offset, phar_archive_data** pphar, uint32_t compression, char **error) /* {{{ */ { char b32[4], *buffer, *endbuffer, *savebuf; phar_archive_data *mydata = NULL; phar_entry_info entry; - php_uint32 manifest_len, manifest_count, manifest_flags, manifest_index, tmp_len, sig_flags; - php_uint16 manifest_ver; - php_uint32 len; + uint32_t manifest_len, manifest_count, manifest_flags, manifest_index, tmp_len, sig_flags; + uint16_t manifest_ver; + uint32_t len; zend_long offset; int sig_len, register_alias = 0, temp_alias = 0; char *signature = NULL; @@ -778,7 +778,7 @@ static int phar_parse_pharfile(php_stream *fp, char *fname, int fname_len, char switch(sig_flags) { case PHAR_SIG_OPENSSL: { - php_uint32 signature_len; + uint32_t signature_len; char *sig; zend_off_t whence; @@ -1326,11 +1326,6 @@ int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int a if (!pphar) { pphar = &mydata; } -#if PHP_API_VERSION < 20100412 - if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) { - return FAILURE; - } -#endif if (php_check_open_basedir(fname)) { return FAILURE; } @@ -1490,11 +1485,6 @@ int phar_open_from_filename(char *fname, int fname_len, char *alias, int alias_l } else if (error && *error) { return FAILURE; } -#if PHP_API_VERSION < 20100412 - if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) { - return FAILURE; - } -#endif if (php_check_open_basedir(fname)) { return FAILURE; } @@ -1575,7 +1565,7 @@ static int phar_open_from_fp(php_stream* fp, char *fname, int fname_len, char *a const zend_long tokenlen = sizeof(token) - 1; zend_long halt_offset; size_t got; - php_uint32 compression = PHAR_FILE_COMPRESSED_NONE; + uint32_t compression = PHAR_FILE_COMPRESSED_NONE; if (error) { *error = NULL; @@ -1794,8 +1784,11 @@ static int phar_analyze_path(const char *fname, const char *ext, int ext_len, in #ifdef PHP_WIN32 phar_unixify_path_separators(realpath, strlen(realpath)); #endif - slash = strstr(realpath, filename) + ((ext - fname) + ext_len); - *slash = '\0'; + slash = strstr(realpath, filename); + if (slash) { + slash += ((ext - fname) + ext_len); + *slash = '\0'; + } slash = strrchr(realpath, '/'); if (slash) { @@ -2285,13 +2278,6 @@ int phar_open_executed_filename(char *alias, int alias_len, char **error) /* {{{ return FAILURE; } - -#if PHP_API_VERSION < 20100412 - if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) { - return FAILURE; - } -#endif - if (php_check_open_basedir(fname)) { return FAILURE; } @@ -2326,9 +2312,9 @@ int phar_open_executed_filename(char *alias, int alias_len, char **error) /* {{{ /** * Validate the CRC32 of a file opened from within the phar */ -int phar_postprocess_file(phar_entry_data *idata, php_uint32 crc32, char **error, int process_zip) /* {{{ */ +int phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip) /* {{{ */ { - php_uint32 crc = ~0; + uint32_t crc = ~0; int len = idata->internal_file->uncompressed_filesize; php_stream *fp = idata->fp; phar_entry_info *entry = idata->internal_file; @@ -2493,8 +2479,8 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv zend_off_t manifest_ftell; zend_long offset; size_t wrote; - php_uint32 manifest_len, mytime, loc, new_manifest_count; - php_uint32 newcrc32; + uint32_t manifest_len, mytime, loc, new_manifest_count; + uint32_t newcrc32; php_stream *file, *oldfile, *newfile, *stubfile; php_stream_filter *filter; php_serialize_data_t metadata_hash; @@ -2826,7 +2812,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv php_stream_flush(entry->cfp); php_stream_filter_remove(filter, 1); php_stream_seek(entry->cfp, 0, SEEK_END); - entry->compressed_filesize = (php_uint32) php_stream_tell(entry->cfp); + entry->compressed_filesize = (uint32_t) php_stream_tell(entry->cfp); /* generate crc on compressed file */ php_stream_rewind(entry->cfp); entry->old_flags = entry->flags; @@ -3581,9 +3567,7 @@ static const zend_module_dep phar_deps[] = { #if defined(HAVE_HASH) && !defined(COMPILE_DL_HASH) ZEND_MOD_REQUIRED("hash") #endif -#if HAVE_SPL ZEND_MOD_REQUIRED("spl") -#endif ZEND_MOD_END }; diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 1e7ab7a324..610482b290 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -55,13 +55,11 @@ #include "TSRM/tsrm_strtok_r.h" #endif #include "Zend/zend_virtual_cwd.h" -#if HAVE_SPL #include "ext/spl/spl_array.h" #include "ext/spl/spl_directory.h" #include "ext/spl/spl_engine.h" #include "ext/spl/spl_exceptions.h" #include "ext/spl/spl_iterators.h" -#endif #include "php_phar.h" #ifdef PHAR_HASH_OK #include "ext/hash/php_hash.h" @@ -201,19 +199,10 @@ ZEND_EXTERN_MODULE_GLOBALS(phar) ZEND_TSRMLS_CACHE_EXTERN(); #endif -#ifndef php_uint16 -# if SIZEOF_SHORT == 2 -# define php_uint16 unsigned short -# else -# define php_uint16 uint16_t -# endif -#endif #include "pharzip.h" -#if HAVE_SPL typedef union _phar_archive_object phar_archive_object; typedef union _phar_entry_object phar_entry_object; -#endif /* * used in phar_entry_info->fp_type to @@ -233,17 +222,17 @@ enum phar_fp_type { /* entry for one file in a phar file */ typedef struct _phar_entry_info { /* first bytes are exactly as in file */ - php_uint32 uncompressed_filesize; - php_uint32 timestamp; - php_uint32 compressed_filesize; - php_uint32 crc32; - php_uint32 flags; + uint32_t uncompressed_filesize; + uint32_t timestamp; + uint32_t compressed_filesize; + uint32_t crc32; + uint32_t flags; /* remainder */ /* when changing compression, save old flags in case fp is NULL */ - php_uint32 old_flags; + uint32_t old_flags; zval metadata; int metadata_len; /* only used for cached manifests */ - php_uint32 filename_len; + uint32_t filename_len; char *filename; enum phar_fp_type fp_type; /* offset within original phar file of the file contents */ @@ -299,14 +288,14 @@ struct _phar_archive_data { HashTable virtual_dirs; /* hash of mounted directory paths */ HashTable mounted_dirs; - php_uint32 flags; - php_uint32 min_timestamp; - php_uint32 max_timestamp; + uint32_t flags; + uint32_t min_timestamp; + uint32_t max_timestamp; php_stream *fp; /* decompressed file contents are stored here */ php_stream *ufp; int refcount; - php_uint32 sig_flags; + uint32_t sig_flags; int sig_len; char *signature; zval metadata; @@ -473,21 +462,17 @@ typedef struct _phar_entry_data { phar_entry_info *internal_file; } phar_entry_data; -#if HAVE_SPL /* archive php object */ union _phar_archive_object { spl_filesystem_object spl; phar_archive_data *archive; }; -#endif -#if HAVE_SPL /* entry php object */ union _phar_entry_object { spl_filesystem_object spl; phar_entry_info *entry; }; -#endif #ifndef PHAR_MAIN extern zend_string *(*phar_save_resolve_path)(const char *filename, int filename_len); @@ -544,7 +529,7 @@ void phar_object_init(void); void phar_destroy_phar_data(phar_archive_data *phar); int phar_open_entry_file(phar_archive_data *phar, phar_entry_info *entry, char **error); -int phar_postprocess_file(phar_entry_data *idata, php_uint32 crc32, char **error, int process_zip); +int phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip); int phar_open_from_filename(char *fname, int fname_len, char *alias, int alias_len, int options, phar_archive_data** pphar, char **error); int phar_open_or_create_filename(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error); int phar_create_or_parse_filename(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error); @@ -552,7 +537,7 @@ int phar_open_executed_filename(char *alias, int alias_len, char **error); int phar_free_alias(phar_archive_data *phar, char *alias, int alias_len); int phar_get_archive(phar_archive_data **archive, char *fname, int fname_len, char *alias, int alias_len, char **error); int phar_open_parsed_phar(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error); -int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_type, char *sig, int sig_len, char *fname, char **signature, int *signature_len, char **error); +int phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, int sig_len, char *fname, char **signature, int *signature_len, char **error); int phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, int *signature_length, char **error); /* utility functions */ @@ -566,7 +551,7 @@ int phar_mount_entry(phar_archive_data *phar, char *filename, int filename_len, zend_string *phar_find_in_include_path(char *file, int file_len, phar_archive_data **pphar); char *phar_fix_filepath(char *path, int *new_len, int use_cwd); phar_entry_info * phar_open_jit(phar_archive_data *phar, phar_entry_info *entry, char **error); -int phar_parse_metadata(char **buffer, zval *metadata, php_uint32 zip_metadata_len); +int phar_parse_metadata(char **buffer, zval *metadata, uint32_t zip_metadata_len); void destroy_phar_manifest_entry(zval *zv); int phar_seek_efp(phar_entry_info *entry, zend_off_t offset, int whence, zend_off_t position, int follow_links); php_stream *phar_get_efp(phar_entry_info *entry, int follow_links); @@ -580,7 +565,7 @@ int phar_copy_on_write(phar_archive_data **pphar); /* tar functions in tar.c */ int phar_is_tar(char *buf, char *fname); -int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, phar_archive_data** pphar, int is_data, php_uint32 compression, char **error); +int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, phar_archive_data** pphar, int is_data, uint32_t compression, char **error); int phar_open_or_create_tar(char *fname, int fname_len, char *alias, int alias_len, int is_data, int options, phar_archive_data** pphar, char **error); int phar_tar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int defaultstub, char **error); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 22404dddbc..249fbff4de 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -25,16 +25,7 @@ static zend_class_entry *phar_ce_archive; static zend_class_entry *phar_ce_data; static zend_class_entry *phar_ce_PharException; - -#if HAVE_SPL static zend_class_entry *phar_ce_entry; -#endif - -#if PHP_VERSION_ID >= 50300 -# define PHAR_ARG_INFO -#else -# define PHAR_ARG_INFO static -#endif static int phar_file_type(HashTable *mimes, char *file, char **mime_type) /* {{{ */ { @@ -1071,7 +1062,6 @@ PHP_METHOD(Phar, isValidPharFilename) } /* }}} */ -#if HAVE_SPL /** * from spl_directory */ @@ -1104,7 +1094,6 @@ static spl_other_handler phar_spl_foreign_handler = { phar_spl_foreign_dtor, phar_spl_foreign_clone }; -#endif /* HAVE_SPL */ /* {{{ proto void Phar::__construct(string fname [, int flags [, string alias]]) * Construct a Phar archive object @@ -1117,9 +1106,6 @@ static spl_other_handler phar_spl_foreign_handler = { */ PHP_METHOD(Phar, __construct) { -#if !HAVE_SPL - zend_throw_exception_ex(zend_ce_exception, 0, "Cannot instantiate Phar object without SPL extension"); -#else char *fname, *alias = NULL, *error, *arch = NULL, *entry = NULL, *save_fname; size_t fname_len, alias_len = 0; int arch_len, entry_len, is_data; @@ -1244,7 +1230,6 @@ PHP_METHOD(Phar, __construct) phar_obj->spl.info_class = phar_ce_entry; efree(fname); -#endif /* HAVE_SPL */ } /* }}} */ @@ -1363,8 +1348,6 @@ PHP_METHOD(Phar, unlinkArchive) } /* }}} */ -#if HAVE_SPL - #define PHAR_ARCHIVE_OBJECT() \ zval *zobj = getThis(); \ phar_archive_object *phar_obj = (phar_archive_object*)((char*)Z_OBJ_P(zobj) - Z_OBJ_P(zobj)->handlers->offset); \ @@ -1588,21 +1571,6 @@ phar_spl_fileinfo: return ZEND_HASH_APPLY_STOP; } } -#if PHP_API_VERSION < 20100412 - if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) { - zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned a path \"%s\" that safe mode prevents opening", ZSTR_VAL(ce->name), fname); - - if (save) { - efree(save); - } - - if (temp) { - efree(temp); - } - - return ZEND_HASH_APPLY_STOP; - } -#endif if (php_check_open_basedir(fname)) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Iterator %v returned a path \"%s\" that open_basedir prevents opening", ZSTR_VAL(ce->name), fname); @@ -2196,7 +2164,7 @@ its_ok: } /* }}} */ -static zend_object *phar_convert_to_other(phar_archive_data *source, int convert, char *ext, php_uint32 flags) /* {{{ */ +static zend_object *phar_convert_to_other(phar_archive_data *source, int convert, char *ext, uint32_t flags) /* {{{ */ { phar_archive_data *phar; phar_entry_info *entry, newentry; @@ -2320,7 +2288,7 @@ PHP_METHOD(Phar, convertToExecutable) char *ext = NULL; int is_data; size_t ext_len = 0; - php_uint32 flags; + uint32_t flags; zend_object *ret; /* a number that is not 0, 1 or 2 (Which is also Greg's birthday, so there) */ zend_long format = 9021976, method = 9021976; @@ -2424,7 +2392,7 @@ PHP_METHOD(Phar, convertToData) char *ext = NULL; int is_data; size_t ext_len = 0; - php_uint32 flags; + uint32_t flags; zend_object *ret; /* a number that is not 0, 1 or 2 (Which is also Greg's birthday so there) */ zend_long format = 9021976, method = 9021976; @@ -3098,7 +3066,7 @@ PHP_METHOD(Phar, getModified) static int phar_set_compression(zval *zv, void *argument) /* {{{ */ { phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv); - php_uint32 compress = *(php_uint32 *)argument; + uint32_t compress = *(uint32_t *)argument; if (entry->is_deleted) { return ZEND_HASH_APPLY_KEEP; @@ -3136,7 +3104,7 @@ static int phar_test_compression(zval *zv, void *argument) /* {{{ */ } /* }}} */ -static void pharobj_set_compression(HashTable *manifest, php_uint32 compress) /* {{{ */ +static void pharobj_set_compression(HashTable *manifest, uint32_t compress) /* {{{ */ { zend_hash_apply_with_argument(manifest, phar_set_compression, &compress); } @@ -3162,7 +3130,7 @@ PHP_METHOD(Phar, compress) zend_long method; char *ext = NULL; size_t ext_len = 0; - php_uint32 flags; + uint32_t flags; zend_object *ret; PHAR_ARCHIVE_OBJECT(); @@ -3271,7 +3239,7 @@ PHP_METHOD(Phar, decompress) PHP_METHOD(Phar, compressFiles) { char *error; - php_uint32 flags; + uint32_t flags; zend_long method; PHAR_ARCHIVE_OBJECT(); @@ -3800,13 +3768,6 @@ PHP_METHOD(Phar, addFile) return; } -#if PHP_API_VERSION < 20100412 - if (PG(safe_mode) && (!php_checkuid(fname, NULL, CHECKUID_ALLOW_ONLY_FILE))) { - zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive, safe_mode restrictions prevent this", fname); - return; - } -#endif - if (!strstr(fname, "://") && php_check_open_basedir(fname)) { zend_throw_exception_ex(spl_ce_RuntimeException, 0, "phar error: unable to open file \"%s\" to add to phar archive, open_basedir restrictions prevent this", fname); return; @@ -4052,13 +4013,6 @@ PHP_METHOD(Phar, delMetadata) } } /* }}} */ -#if PHP_API_VERSION < 20100412 -#define PHAR_OPENBASEDIR_CHECKPATH(filename) \ - (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename) -#else -#define PHAR_OPENBASEDIR_CHECKPATH(filename) \ - php_check_open_basedir(filename) -#endif static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *dest, int dest_len, char **error) /* {{{ */ { @@ -4137,7 +4091,7 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char * return FAILURE; } - if (PHAR_OPENBASEDIR_CHECKPATH(fullpath)) { + if (php_check_open_basedir(fullpath)) { spprintf(error, 4096, "Cannot extract \"%s\" to \"%s\", openbasedir/safe mode restrictions in effect", entry->filename, fullpath); efree(fullpath); efree(new_state.cwd); @@ -4193,11 +4147,7 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char * return SUCCESS; } -#if PHP_API_VERSION < 20100412 - fp = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS|ENFORCE_SAFE_MODE, NULL); -#else fp = php_stream_open_wrapper(fullpath, "w+b", REPORT_ERRORS, NULL); -#endif if (!fp) { spprintf(error, 4096, "Cannot extract \"%s\", could not open for writing \"%s\"", entry->filename, fullpath); @@ -5043,10 +4993,7 @@ PHP_METHOD(PharFileInfo, decompress) } /* }}} */ -#endif /* HAVE_SPL */ - /* {{{ phar methods */ -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar___construct, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, flags) @@ -5054,47 +5001,39 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_phar___construct, 0, 0, 1) ZEND_ARG_INFO(0, fileformat) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_createDS, 0, 0, 0) ZEND_ARG_INFO(0, index) ZEND_ARG_INFO(0, webindex) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_cancompress, 0, 0, 0) ZEND_ARG_INFO(0, method) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_isvalidpharfilename, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, executable) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_loadPhar, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, alias) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mapPhar, 0, 0, 0) ZEND_ARG_INFO(0, alias) ZEND_ARG_INFO(0, offset) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mount, 0, 0, 2) ZEND_ARG_INFO(0, inphar) ZEND_ARG_INFO(0, externalfile) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_mungServer, 0, 0, 1) ZEND_ARG_INFO(0, munglist) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_webPhar, 0, 0, 0) ZEND_ARG_INFO(0, alias) ZEND_ARG_INFO(0, index) @@ -5103,141 +5042,112 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_webPhar, 0, 0, 0) ZEND_ARG_INFO(0, rewrites) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_running, 0, 0, 1) ZEND_ARG_INFO(0, retphar) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_ua, 0, 0, 1) ZEND_ARG_INFO(0, archive) ZEND_END_ARG_INFO() -#if HAVE_SPL -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_build, 0, 0, 1) ZEND_ARG_INFO(0, iterator) ZEND_ARG_INFO(0, base_directory) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_conv, 0, 0, 0) ZEND_ARG_INFO(0, format) ZEND_ARG_INFO(0, compression_type) ZEND_ARG_INFO(0, file_ext) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_comps, 0, 0, 1) ZEND_ARG_INFO(0, compression_type) ZEND_ARG_INFO(0, file_ext) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_decomp, 0, 0, 0) ZEND_ARG_INFO(0, file_ext) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_comp, 0, 0, 1) ZEND_ARG_INFO(0, compression_type) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_compo, 0, 0, 0) ZEND_ARG_INFO(0, compression_type) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_copy, 0, 0, 2) ZEND_ARG_INFO(0, newfile) ZEND_ARG_INFO(0, oldfile) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_delete, 0, 0, 1) ZEND_ARG_INFO(0, entry) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_fromdir, 0, 0, 1) ZEND_ARG_INFO(0, base_dir) ZEND_ARG_INFO(0, regex) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetExists, 0, 0, 1) ZEND_ARG_INFO(0, entry) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_offsetSet, 0, 0, 2) ZEND_ARG_INFO(0, entry) ZEND_ARG_INFO(0, value) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setAlias, 0, 0, 1) ZEND_ARG_INFO(0, alias) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setMetadata, 0, 0, 1) ZEND_ARG_INFO(0, metadata) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setSigAlgo, 0, 0, 1) ZEND_ARG_INFO(0, algorithm) ZEND_ARG_INFO(0, privatekey) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_setStub, 0, 0, 1) ZEND_ARG_INFO(0, newstub) ZEND_ARG_INFO(0, maxlen) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_emptydir, 0, 0, 0) ZEND_ARG_INFO(0, dirname) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_extract, 0, 0, 1) ZEND_ARG_INFO(0, pathto) ZEND_ARG_INFO(0, files) ZEND_ARG_INFO(0, overwrite) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_addfile, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_ARG_INFO(0, localname) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_fromstring, 0, 0, 1) ZEND_ARG_INFO(0, localname) ZEND_ARG_INFO(0, contents) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_phar_isff, 0, 0, 1) ZEND_ARG_INFO(0, fileformat) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO(arginfo_phar__void, 0) ZEND_END_ARG_INFO() -#endif /* HAVE_SPL */ - zend_function_entry php_archive_methods[] = { -#if !HAVE_SPL - PHP_ME(Phar, __construct, arginfo_phar___construct, ZEND_ACC_PRIVATE) -#else PHP_ME(Phar, __construct, arginfo_phar___construct, ZEND_ACC_PUBLIC) PHP_ME(Phar, __destruct, arginfo_phar__void, ZEND_ACC_PUBLIC) PHP_ME(Phar, addEmptyDir, arginfo_phar_emptydir, ZEND_ACC_PUBLIC) @@ -5279,7 +5189,6 @@ zend_function_entry php_archive_methods[] = { PHP_ME(Phar, setStub, arginfo_phar_setStub, ZEND_ACC_PUBLIC) PHP_ME(Phar, startBuffering, arginfo_phar__void, ZEND_ACC_PUBLIC) PHP_ME(Phar, stopBuffering, arginfo_phar__void, ZEND_ACC_PUBLIC) -#endif /* static member functions */ PHP_ME(Phar, apiVersion, arginfo_phar__void, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) PHP_ME(Phar, canCompress, arginfo_phar_cancompress, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC|ZEND_ACC_FINAL) @@ -5299,13 +5208,10 @@ zend_function_entry php_archive_methods[] = { PHP_FE_END }; -#if HAVE_SPL -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_entry___construct, 0, 0, 1) ZEND_ARG_INFO(0, filename) ZEND_END_ARG_INFO() -PHAR_ARG_INFO ZEND_BEGIN_ARG_INFO_EX(arginfo_entry_chmod, 0, 0, 1) ZEND_ARG_INFO(0, perms) ZEND_END_ARG_INFO() @@ -5328,7 +5234,6 @@ zend_function_entry php_entry_methods[] = { PHP_ME(PharFileInfo, setMetadata, arginfo_phar_setMetadata, ZEND_ACC_PUBLIC) PHP_FE_END }; -#endif /* HAVE_SPL */ zend_function_entry phar_exception_methods[] = { PHP_FE_END @@ -5345,7 +5250,6 @@ void phar_object_init(void) /* {{{ */ INIT_CLASS_ENTRY(ce, "PharException", phar_exception_methods); phar_ce_PharException = zend_register_internal_class_ex(&ce, zend_ce_exception); -#if HAVE_SPL INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods); phar_ce_archive = zend_register_internal_class_ex(&ce, spl_ce_RecursiveDirectoryIterator); @@ -5358,15 +5262,6 @@ void phar_object_init(void) /* {{{ */ INIT_CLASS_ENTRY(ce, "PharFileInfo", php_entry_methods); phar_ce_entry = zend_register_internal_class_ex(&ce, spl_ce_SplFileInfo); -#else - INIT_CLASS_ENTRY(ce, "Phar", php_archive_methods); - phar_ce_archive = zend_register_internal_class(&ce); - phar_ce_archive->ce_flags |= ZEND_ACC_FINAL; - - INIT_CLASS_ENTRY(ce, "PharData", php_archive_methods); - phar_ce_data = zend_register_internal_class(&ce); - phar_ce_data->ce_flags |= ZEND_ACC_FINAL; -#endif REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "BZ2", PHAR_ENT_COMPRESSED_BZ2) REGISTER_PHAR_CLASS_CONST_LONG(phar_ce_archive, "GZ", PHAR_ENT_COMPRESSED_GZ) diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 5182633513..3b7373f6fa 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -19,9 +19,9 @@ #include "phar_internal.h" -static php_uint32 phar_tar_number(char *buf, int len) /* {{{ */ +static uint32_t phar_tar_number(char *buf, int len) /* {{{ */ { - php_uint32 num = 0; + uint32_t num = 0; int i = 0; while (i < len && buf[i] == ' ') { @@ -62,7 +62,7 @@ static php_uint32 phar_tar_number(char *buf, int len) /* {{{ */ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -static int phar_tar_octal(char *buf, php_uint32 val, int len) /* {{{ */ +static int phar_tar_octal(char *buf, uint32_t val, int len) /* {{{ */ { char *p = buf; int s = len; @@ -84,9 +84,9 @@ static int phar_tar_octal(char *buf, php_uint32 val, int len) /* {{{ */ } /* }}} */ -static php_uint32 phar_tar_checksum(char *buf, int len) /* {{{ */ +static uint32_t phar_tar_checksum(char *buf, int len) /* {{{ */ { - php_uint32 sum = 0; + uint32_t sum = 0; char *end = buf + len; while (buf != end) { @@ -100,8 +100,8 @@ static php_uint32 phar_tar_checksum(char *buf, int len) /* {{{ */ int phar_is_tar(char *buf, char *fname) /* {{{ */ { tar_header *header = (tar_header *) buf; - php_uint32 checksum = phar_tar_number(header->checksum, sizeof(header->checksum)); - php_uint32 ret; + uint32_t checksum = phar_tar_number(header->checksum, sizeof(header->checksum)); + uint32_t ret; char save[sizeof(header->checksum)], *bname; /* assume that the first filename in a tar won't begin with <?php */ @@ -195,15 +195,23 @@ static int phar_tar_process_metadata(phar_entry_info *entry, php_stream *fp) /* } /* }}} */ -int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, phar_archive_data** pphar, int is_data, php_uint32 compression, char **error) /* {{{ */ +#if !HAVE_STRNLEN +static size_t strnlen(const char *s, size_t maxlen) { + char *r = (char *)memchr(s, '\0', maxlen); + return r ? r-s : maxlen; +} +#endif + +int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, int alias_len, phar_archive_data** pphar, int is_data, uint32_t compression, char **error) /* {{{ */ { char buf[512], *actual_alias = NULL, *p; phar_entry_info entry = {0}; size_t pos = 0, read, totalsize; tar_header *hdr; - php_uint32 sum1, sum2, size, old; + uint32_t sum1, sum2, size, old; phar_archive_data *myphar, *actual; int last_was_longlink = 0; + int linkname_len; if (error) { *error = NULL; @@ -264,7 +272,7 @@ int phar_parse_tarfile(php_stream* fp, char *fname, int fname_len, char *alias, goto next; } - if (((!old && hdr->prefix[0] == 0) || old) && strlen(hdr->name) == sizeof(".phar/signature.bin")-1 && !strncmp(hdr->name, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) { + if (((!old && hdr->prefix[0] == 0) || old) && strnlen(hdr->name, 100) == sizeof(".phar/signature.bin")-1 && !strncmp(hdr->name, ".phar/signature.bin", sizeof(".phar/signature.bin")-1)) { zend_off_t curloc; if (size > 511) { @@ -291,7 +299,7 @@ bail: | ((((unsigned char*)(buffer))[1]) << 8) \ | (((unsigned char*)(buffer))[0])) #else -# define PHAR_GET_32(buffer) (php_uint32) *(buffer) +# define PHAR_GET_32(buffer) (uint32_t) *(buffer) #endif myphar->sig_flags = PHAR_GET_32(buf); if (FAILURE == phar_verify_signature(fp, php_stream_tell(fp) - size - 512, myphar->sig_flags, buf + 8, size - 8, fname, &myphar->signature, &myphar->sig_len, error)) { @@ -348,7 +356,7 @@ bail: entry.filename_len = entry.uncompressed_filesize; /* Check for overflow - bug 61065 */ - if (entry.filename_len == UINT_MAX) { + if (entry.filename_len == UINT_MAX || entry.filename_len == 0) { if (error) { spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file (invalid entry size)", fname); } @@ -472,20 +480,22 @@ bail: } entry.link = NULL; - + /* link field is null-terminated unless it has 100 non-null chars. + * Thus we can not use strlen. */ + linkname_len = strnlen(hdr->linkname, 100); if (entry.tar_type == TAR_LINK) { - if (!zend_hash_str_exists(&myphar->manifest, hdr->linkname, strlen(hdr->linkname))) { + if (!zend_hash_str_exists(&myphar->manifest, hdr->linkname, linkname_len)) { if (error) { - spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file - hard link to non-existent file \"%s\"", fname, hdr->linkname); + spprintf(error, 4096, "phar error: \"%s\" is a corrupted tar file - hard link to non-existent file \"%.*s\"", fname, linkname_len, hdr->linkname); } pefree(entry.filename, entry.is_persistent); php_stream_close(fp); phar_destroy_phar_data(myphar); return FAILURE; } - entry.link = estrdup(hdr->linkname); + entry.link = estrndup(hdr->linkname, linkname_len); } else if (entry.tar_type == TAR_SYMLINK) { - entry.link = estrdup(hdr->linkname); + entry.link = estrndup(hdr->linkname, linkname_len); } phar_set_inode(&entry); if ((newentry = zend_hash_str_add_mem(&myphar->manifest, entry.filename, entry.filename_len, (void*)&entry, sizeof(phar_entry_info))) == NULL) { @@ -1225,12 +1235,12 @@ nostub: } #ifdef WORDS_BIGENDIAN # define PHAR_SET_32(var, buffer) \ - *(php_uint32 *)(var) = (((((unsigned char*)&(buffer))[3]) << 24) \ + *(uint32_t *)(var) = (((((unsigned char*)&(buffer))[3]) << 24) \ | ((((unsigned char*)&(buffer))[2]) << 16) \ | ((((unsigned char*)&(buffer))[1]) << 8) \ | (((unsigned char*)&(buffer))[0])) #else -# define PHAR_SET_32(var, buffer) *(php_uint32 *)(var) = (php_uint32) (buffer) +# define PHAR_SET_32(var, buffer) *(uint32_t *)(var) = (uint32_t) (buffer) #endif PHAR_SET_32(sigbuf, phar->sig_flags); PHAR_SET_32(sigbuf + 4, signature_length); diff --git a/ext/phar/tests/bug71331.phpt b/ext/phar/tests/bug71331.phpt new file mode 100644 index 0000000000..0026c406e8 --- /dev/null +++ b/ext/phar/tests/bug71331.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #71331 (Uninitialized pointer in phar_make_dirstream()) +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip"); ?> +--FILE-- +<?php +$p = new PharData(__DIR__."/bug71331.tar"); +?> +DONE +--EXPECTF-- +Fatal error: Uncaught UnexpectedValueException: phar error: "%s%ebug71331.tar" is a corrupted tar file (invalid entry size) in %s%ebug71331.php:2 +Stack trace: +#0 %s%ebug71331.php(2): PharData->__construct('%s') +#1 {main} + thrown in %s%ebug71331.php on line 2 diff --git a/ext/phar/tests/bug71331.tar b/ext/phar/tests/bug71331.tar Binary files differnew file mode 100644 index 0000000000..14eec28781 --- /dev/null +++ b/ext/phar/tests/bug71331.tar diff --git a/ext/phar/tests/bug71354.phpt b/ext/phar/tests/bug71354.phpt new file mode 100644 index 0000000000..43230f1520 --- /dev/null +++ b/ext/phar/tests/bug71354.phpt @@ -0,0 +1,13 @@ +--TEST-- +Phar: bug #71354: Heap corruption in tar/zip/phar parser. +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip"); ?> +--FILE-- +<?php +$p = new PharData(__DIR__."/bug71354.tar"); +var_dump($p['aaaa']->getContent()); +?> +DONE +--EXPECT-- +string(0) "" +DONE
\ No newline at end of file diff --git a/ext/phar/tests/bug71354.tar b/ext/phar/tests/bug71354.tar Binary files differnew file mode 100644 index 0000000000..b0bd992b9e --- /dev/null +++ b/ext/phar/tests/bug71354.tar diff --git a/ext/phar/tests/bug71391.phpt b/ext/phar/tests/bug71391.phpt new file mode 100644 index 0000000000..b8d84f5375 --- /dev/null +++ b/ext/phar/tests/bug71391.phpt @@ -0,0 +1,18 @@ +--TEST-- +Phar: bug #71391: NULL Pointer Dereference in phar_tar_setupmetadata() +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip"); ?> +--FILE-- +<?php +// duplicate since the tar will change +copy(__DIR__."/bug71391.tar", __DIR__."/bug71391.test.tar"); +$p = new PharData(__DIR__."/bug71391.test.tar"); +$p->delMetaData(); +?> +DONE +--CLEAN-- +<?php +unlink(__DIR__."/bug71391.test.tar"); +?> +--EXPECT-- +DONE
\ No newline at end of file diff --git a/ext/phar/tests/bug71391.tar b/ext/phar/tests/bug71391.tar Binary files differnew file mode 100644 index 0000000000..a5b155ac87 --- /dev/null +++ b/ext/phar/tests/bug71391.tar diff --git a/ext/phar/tests/bug71488.phpt b/ext/phar/tests/bug71488.phpt new file mode 100644 index 0000000000..05fdd8f481 --- /dev/null +++ b/ext/phar/tests/bug71488.phpt @@ -0,0 +1,16 @@ +--TEST-- +Phar: bug #71488: Stack overflow when decompressing tar archives +--SKIPIF-- +<?php if (!extension_loaded("phar")) die("skip"); ?> +--FILE-- +<?php +$p = new PharData(__DIR__."/bug71488.tar"); +$newp = $p->decompress("test"); +?> +DONE +--CLEAN-- +<?php +@unlink(__DIR__."/bug71488.test"); +?> +--EXPECT-- +DONE
\ No newline at end of file diff --git a/ext/phar/tests/bug71488.tar b/ext/phar/tests/bug71488.tar Binary files differnew file mode 100644 index 0000000000..6e14195025 --- /dev/null +++ b/ext/phar/tests/bug71488.tar diff --git a/ext/phar/tests/bug71625.phpt b/ext/phar/tests/bug71625.phpt new file mode 100644 index 0000000000..8e6c31f462 --- /dev/null +++ b/ext/phar/tests/bug71625.phpt @@ -0,0 +1,25 @@ +--TEST-- +Phar - Bug #71625 - Crash in php7.dll +--INI-- +phar.readonly=0 +--SKIPIF-- +<?php + +if (!extension_loaded("phar") || !extension_loaded("zlib")) die("skip"); +if(substr(PHP_OS, 0, 3) != 'WIN' ) { + die('skip windows only test'); +} + +?> +--FILE-- +<?php +$phar = new Phar("A:A:.phar"); +$phar["hello_habr.txt"] = '<? Hello Habr!?>'; +?> +DONE +--EXPECTF-- +Fatal error: Uncaught UnexpectedValueException: Cannot create phar 'A:A:.phar', file extension (or combination) not recognised or the directory does not exist in %sbug71625.php:%d +Stack trace: +#0 %sbug71625.php(%d): Phar->__construct('A:A:.phar') +#1 {main} + thrown in %sbug71625.php on line %d diff --git a/ext/phar/util.c b/ext/phar/util.c index eca33efc38..39ecf399ae 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -199,13 +199,6 @@ int phar_mount_entry(phar_archive_data *phar, char *filename, int filename_len, entry.tmp = estrndup(filename, filename_len); } } -#if PHP_API_VERSION < 20100412 - if (PG(safe_mode) && !is_phar && (!php_checkuid(entry.tmp, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { - efree(entry.tmp); - efree(entry.filename); - return FAILURE; - } -#endif filename = entry.tmp; /* only check openbasedir for files, not for phar streams */ @@ -1184,7 +1177,7 @@ char * phar_compress_filter(phar_entry_info * entry, int return_unknown) /* {{{ */ char * phar_decompress_filter(phar_entry_info * entry, int return_unknown) /* {{{ */ { - php_uint32 flags; + uint32_t flags; if (entry->is_modified) { flags = entry->old_flags; @@ -1480,7 +1473,7 @@ static int phar_call_openssl_signverify(int is_sign, php_stream *fp, zend_off_t /* }}} */ #endif /* #ifndef PHAR_HAVE_OPENSSL */ -int phar_verify_signature(php_stream *fp, size_t end_of_phar, php_uint32 sig_type, char *sig, int sig_len, char *fname, char **signature, int *signature_len, char **error) /* {{{ */ +int phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, int sig_len, char *fname, char **signature, int *signature_len, char **error) /* {{{ */ { int read_size, len; zend_off_t read_len; diff --git a/ext/phar/zip.c b/ext/phar/zip.c index bd088cf4fa..4994dd0e04 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -18,28 +18,28 @@ #include "phar_internal.h" -#define PHAR_GET_16(var) ((php_uint16)((((php_uint16)var[0]) & 0xff) | \ - (((php_uint16)var[1]) & 0xff) << 8)) -#define PHAR_GET_32(var) ((php_uint32)((((php_uint32)var[0]) & 0xff) | \ - (((php_uint32)var[1]) & 0xff) << 8 | \ - (((php_uint32)var[2]) & 0xff) << 16 | \ - (((php_uint32)var[3]) & 0xff) << 24)) -static inline void phar_write_32(char buffer[4], php_uint32 value) +#define PHAR_GET_16(var) ((uint16_t)((((uint16_t)var[0]) & 0xff) | \ + (((uint16_t)var[1]) & 0xff) << 8)) +#define PHAR_GET_32(var) ((uint32_t)((((uint32_t)var[0]) & 0xff) | \ + (((uint32_t)var[1]) & 0xff) << 8 | \ + (((uint32_t)var[2]) & 0xff) << 16 | \ + (((uint32_t)var[3]) & 0xff) << 24)) +static inline void phar_write_32(char buffer[4], uint32_t value) { buffer[3] = (unsigned char) ((value & 0xff000000) >> 24); buffer[2] = (unsigned char) ((value & 0xff0000) >> 16); buffer[1] = (unsigned char) ((value & 0xff00) >> 8); buffer[0] = (unsigned char) (value & 0xff); } -static inline void phar_write_16(char buffer[2], php_uint32 value) +static inline void phar_write_16(char buffer[2], uint32_t value) { buffer[1] = (unsigned char) ((value & 0xff00) >> 8); buffer[0] = (unsigned char) (value & 0xff); } -# define PHAR_SET_32(var, value) phar_write_32(var, (php_uint32) (value)); -# define PHAR_SET_16(var, value) phar_write_16(var, (php_uint16) (value)); +# define PHAR_SET_32(var, value) phar_write_32(var, (uint32_t) (value)); +# define PHAR_SET_16(var, value) phar_write_16(var, (uint16_t) (value)); -static int phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, php_uint16 len) /* {{{ */ +static int phar_zip_process_extra(php_stream *fp, phar_entry_info *entry, uint16_t len) /* {{{ */ { union { phar_zip_extra_field_header header; @@ -143,7 +143,7 @@ static time_t phar_zip_d2u_time(char *cdtime, char *cddate) /* {{{ */ static void phar_zip_u2d_time(time_t time, char *dtime, char *ddate) /* {{{ */ { - php_uint16 ctime, cdate; + uint16_t ctime, cdate; struct tm *tm, tmbuf; tm = php_localtime_r(&time, &tmbuf); @@ -168,7 +168,7 @@ int phar_parse_zipfile(php_stream *fp, char *fname, int fname_len, char *alias, phar_zip_dir_end locator; char buf[sizeof(locator) + 65536]; zend_long size; - php_uint16 i; + uint16_t i; phar_archive_data *mydata = NULL; phar_entry_info entry = {0}; char *p = buf, *ext, *actual_alias = NULL; @@ -791,7 +791,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ phar_zip_unix3 perms; phar_zip_central_dir_file central; struct _phar_zip_pass *p; - php_uint32 newcrc32; + uint32_t newcrc32; zend_off_t offset; int not_really_modified = 0; p = (struct _phar_zip_pass*) arg; @@ -822,7 +822,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ PHAR_SET_16(perms.size, sizeof(perms) - 4); PHAR_SET_16(perms.perms, entry->flags & PHAR_ENT_PERM_MASK); { - php_uint32 crc = (php_uint32) ~0; + uint32_t crc = (uint32_t) ~0; CRC32(crc, perms.perms[0]); CRC32(crc, perms.perms[1]); PHAR_SET_32(perms.crc32, ~crc); @@ -848,7 +848,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ /* do extra field for perms later */ if (entry->is_modified) { - php_uint32 loc; + uint32_t loc; php_stream_filter *filter; php_stream *efp; @@ -936,7 +936,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{ php_stream_flush(entry->cfp); php_stream_filter_remove(filter, 1); php_stream_seek(entry->cfp, 0, SEEK_END); - entry->compressed_filesize = (php_uint32) php_stream_tell(entry->cfp); + entry->compressed_filesize = (uint32_t) php_stream_tell(entry->cfp); PHAR_SET_32(central.compsize, entry->compressed_filesize); PHAR_SET_32(local.compsize, entry->compressed_filesize); /* generate crc on compressed file */ @@ -1194,7 +1194,7 @@ int phar_zip_flush(phar_archive_data *phar, char *user_stub, zend_long len, int char *temperr = NULL; struct _phar_zip_pass pass; phar_zip_dir_end eocd; - php_uint32 cdir_size, cdir_offset; + uint32_t cdir_size, cdir_offset; pass.error = &temperr; entry.flags = PHAR_ENT_PERM_DEF_FILE; diff --git a/ext/readline/config.w32 b/ext/readline/config.w32 new file mode 100644 index 0000000000..482c99cc04 --- /dev/null +++ b/ext/readline/config.w32 @@ -0,0 +1,16 @@ +// $Id$ +// vim:ft=javascript + +ARG_WITH("readline", "Readline support", "yes"); + +if (PHP_READLINE != "no") { + if (CHECK_LIB("edit_a.lib;edit.lib", "readline", PHP_READLINE) && + CHECK_HEADER_ADD_INCLUDE("editline/readline.h", "CFLAGS_READLINE")) { + EXTENSION("readline", "readline.c readline_cli.c"); + ADD_FLAG("CFLAGS_READLINE", "/D HAVE_LIBEDIT"); + ADD_FLAG("CFLAGS_READLINE", "/D HAVE_RL_COMPLETION_MATCHES"); + } else { + WARNING("readline not enabled; libraries and headers not found"); + } +} + diff --git a/ext/readline/php_readline.h b/ext/readline/php_readline.h index 52dabdadeb..e3a0aba676 100644 --- a/ext/readline/php_readline.h +++ b/ext/readline/php_readline.h @@ -22,9 +22,11 @@ #define PHP_READLINE_H #if HAVE_LIBREADLINE || HAVE_LIBEDIT +#ifndef PHP_WIN32 #ifdef ZTS #warning Readline module will *NEVER* be thread-safe #endif +#endif extern zend_module_entry readline_module_entry; #define phpext_readline_ptr &readline_module_entry diff --git a/ext/readline/readline.c b/ext/readline/readline.c index ad9b01a946..0e6f849444 100644 --- a/ext/readline/readline.c +++ b/ext/readline/readline.c @@ -251,7 +251,9 @@ PHP_FUNCTION(readline_info) array_init(return_value); add_assoc_string(return_value,"line_buffer",SAFE_STRING(rl_line_buffer)); add_assoc_long(return_value,"point",rl_point); +#ifndef PHP_WIN32 add_assoc_long(return_value,"end",rl_end); +#endif #ifdef HAVE_LIBREADLINE add_assoc_long(return_value,"mark",rl_mark); add_assoc_long(return_value,"done",rl_done); @@ -262,7 +264,9 @@ PHP_FUNCTION(readline_info) #if HAVE_ERASE_EMPTY_LINE add_assoc_long(return_value,"erase_empty_line",rl_erase_empty_line); #endif +#ifndef PHP_WIN32 add_assoc_string(return_value,"library_version",(char *)SAFE_STRING(rl_library_version)); +#endif add_assoc_string(return_value,"readline_name",(char *)SAFE_STRING(rl_readline_name)); add_assoc_long(return_value,"attempted_completion_over",rl_attempted_completion_over); } else { @@ -276,8 +280,10 @@ PHP_FUNCTION(readline_info) RETVAL_STRING(SAFE_STRING(oldstr)); } else if (!strcasecmp(what, "point")) { RETVAL_LONG(rl_point); +#ifndef PHP_WIN32 } else if (!strcasecmp(what, "end")) { RETVAL_LONG(rl_end); +#endif #ifdef HAVE_LIBREADLINE } else if (!strcasecmp(what, "mark")) { RETVAL_LONG(rl_mark); @@ -309,8 +315,10 @@ PHP_FUNCTION(readline_info) } RETVAL_LONG(oldval); #endif +#ifndef PHP_WIN32 } else if (!strcasecmp(what,"library_version")) { RETVAL_STRING((char *)SAFE_STRING(rl_library_version)); +#endif } else if (!strcasecmp(what, "readline_name")) { oldstr = (char*)rl_readline_name; if (value) { diff --git a/ext/readline/readline_cli.c b/ext/readline/readline_cli.c index 0cdf9f4ae8..6f4e47d42b 100644 --- a/ext/readline/readline_cli.c +++ b/ext/readline/readline_cli.c @@ -19,6 +19,10 @@ /* $Id$ */ +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + #include "php.h" #ifndef HAVE_RL_COMPLETION_MATCHES @@ -63,7 +67,7 @@ #include "sapi/cli/cli.h" #include "readline_cli.h" -#ifdef COMPILE_DL_READLINE +#if defined(COMPILE_DL_READLINE) && !defined(PHP_WIN32) #include <dlfcn.h> #endif @@ -598,9 +602,15 @@ static int readline_shell_run(void) /* {{{ */ zend_execute_scripts(ZEND_REQUIRE, NULL, 1, prepend_file_p); } +#ifndef PHP_WIN32 history_file = tilde_expand("~/.php_history"); +#else + spprintf(&history_file, MAX_PATH, "%s/.php_history", getenv("USERPROFILE")); +#endif rl_attempted_completion_function = cli_code_completion; +#ifndef PHP_WIN32 rl_special_prefixes = "$"; +#endif read_history(history_file); EG(exit_status) = 0; @@ -686,13 +696,33 @@ static int readline_shell_run(void) /* {{{ */ php_last_char = '\0'; } +#ifdef PHP_WIN32 + efree(history_file); +#else free(history_file); +#endif efree(code); zend_string_release(prompt); return EG(exit_status); } /* }}} */ +#ifdef PHP_WIN32 +typedef cli_shell_callbacks_t *(__cdecl *get_cli_shell_callbacks)(void); +#define GET_SHELL_CB(cb) \ + do { \ + get_cli_shell_callbacks get_callbacks; \ + HMODULE hMod = GetModuleHandle("php.exe"); \ + (cb) = NULL; \ + if (strlen(sapi_module.name) >= 3 && 0 == strncmp("cli", sapi_module.name, 3)) { \ + get_callbacks = (get_cli_shell_callbacks)GetProcAddress(hMod, "php_cli_get_shell_callbacks"); \ + if (get_callbacks) { \ + (cb) = get_callbacks(); \ + } \ + } \ + } while(0) + +#else /* #ifdef COMPILE_DL_READLINE This dlsym() is always used as even the CGI SAPI is linked against "CLI"-only @@ -711,6 +741,7 @@ this extension sharedto offer compatibility. /*#else #define GET_SHELL_CB(cb) (cb) = php_cli_get_shell_callbacks() #endif*/ +#endif PHP_MINIT_FUNCTION(cli_readline) { @@ -755,7 +786,11 @@ PHP_MINFO_FUNCTION(cli_readline) { php_info_print_table_start(); php_info_print_table_header(2, "Readline Support", "enabled"); +#ifdef PHP_WIN32 + php_info_print_table_row(2, "Readline library", "WinEditLine"); +#else php_info_print_table_row(2, "Readline library", (rl_library_version ? rl_library_version : "Unknown")); +#endif php_info_print_table_end(); DISPLAY_INI_ENTRIES(); diff --git a/ext/readline/tests/libedit_info_001-win32.phpt b/ext/readline/tests/libedit_info_001-win32.phpt new file mode 100644 index 0000000000..5d43921c60 --- /dev/null +++ b/ext/readline/tests/libedit_info_001-win32.phpt @@ -0,0 +1,42 @@ +--TEST-- +readline_info(): Basic test +--SKIPIF-- +<?php if (!extension_loaded("readline")) die("skip"); +if (READLINE_LIB != "libedit") die("skip libedit only"); +if(substr(PHP_OS, 0, 3) != 'WIN' ) { + die('skip windows only test'); +} +?> +--FILE-- +<?php + +var_dump(readline_info()); +var_dump(readline_info(1)); +var_dump(readline_info(1,1)); +var_dump(readline_info('line_buffer')); +var_dump(readline_info('readline_name')); +var_dump(readline_info('readline_name', 1)); +var_dump(readline_info('readline_name')); +var_dump(readline_info('attempted_completion_over',1)); +var_dump(readline_info('attempted_completion_over')); + +?> +--EXPECTF-- +array(4) { + ["line_buffer"]=> + string(0) "" + ["point"]=> + int(0) + ["readline_name"]=> + string(0) "" + ["attempted_completion_over"]=> + int(0) +} +NULL +NULL +string(0) "" +string(0) "" +string(0) "" +string(1) "1" +int(0) +int(1) diff --git a/ext/readline/tests/libedit_info_001.phpt b/ext/readline/tests/libedit_info_001.phpt index 1d79f4ad0c..33dc144add 100644 --- a/ext/readline/tests/libedit_info_001.phpt +++ b/ext/readline/tests/libedit_info_001.phpt @@ -3,6 +3,9 @@ readline_info(): Basic test --SKIPIF-- <?php if (!extension_loaded("readline")) die("skip"); if (READLINE_LIB != "libedit") die("skip libedit only"); +if(substr(PHP_OS, 0, 3) == 'WIN' ) { + die('skip not for windows'); +} ?> --FILE-- <?php diff --git a/ext/readline/tests/libedit_write_history_001-win32.phpt b/ext/readline/tests/libedit_write_history_001-win32.phpt new file mode 100644 index 0000000000..28af4cbfdd --- /dev/null +++ b/ext/readline/tests/libedit_write_history_001-win32.phpt @@ -0,0 +1,29 @@ +--TEST-- +readline_write_history(): Basic test +--SKIPIF-- +<?php if (!extension_loaded("readline") || !function_exists('readline_add_history')) die("skip"); +if (READLINE_LIB != "libedit") die("skip libedit only"); +if(substr(PHP_OS, 0, 3) != 'WIN' ) { + die('skip windows only test'); +} +?> +--FILE-- +<?php + +$name = tempnam(sys_get_temp_dir(), 'readline.tmp'); + +readline_add_history('foo'); +readline_add_history(''); +readline_add_history(1); +readline_add_history(NULL); +readline_write_history($name); + +var_dump(file_get_contents($name)); + +unlink($name); + +?> +--EXPECT-- +string(6) "foo +1 +" diff --git a/ext/readline/tests/libedit_write_history_001.phpt b/ext/readline/tests/libedit_write_history_001.phpt index e9b6dbee8d..14c3282e6d 100644 --- a/ext/readline/tests/libedit_write_history_001.phpt +++ b/ext/readline/tests/libedit_write_history_001.phpt @@ -3,6 +3,9 @@ readline_write_history(): Basic test --SKIPIF-- <?php if (!extension_loaded("readline") || !function_exists('readline_add_history')) die("skip"); if (READLINE_LIB != "libedit") die("skip libedit only"); +if(substr(PHP_OS, 0, 3) == 'WIN' ) { + die('skip not for windows'); +} ?> --FILE-- <?php diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index 7713137e89..af1e972f60 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -386,7 +386,7 @@ static void _class_string(string *str, zend_class_entry *ce, zval *obj, char *in /* TBD: Repair indenting of doc comment (or is this to be done in the parser?) */ if (ce->type == ZEND_USER_CLASS && ce->info.user.doc_comment) { - string_printf(str, "%s%s", indent, ce->info.user.doc_comment); + string_printf(str, "%s%s", indent, ZSTR_VAL(ce->info.user.doc_comment)); string_write(str, "\n", 1); } @@ -3029,6 +3029,7 @@ ZEND_METHOD(reflection_type, __toString) case _IS_BOOL: RETURN_STRINGL("bool", sizeof("bool") - 1); case IS_LONG: RETURN_STRINGL("int", sizeof("int") - 1); case IS_DOUBLE: RETURN_STRINGL("float", sizeof("float") - 1); + case IS_VOID: RETURN_STRINGL("void", sizeof("void") - 1); EMPTY_SWITCH_DEFAULT_CASE() } } diff --git a/ext/reflection/tests/ReflectionClass_isArray.phpt b/ext/reflection/tests/ReflectionClass_isArray.phpt new file mode 100644 index 0000000000..3eec0dac54 --- /dev/null +++ b/ext/reflection/tests/ReflectionClass_isArray.phpt @@ -0,0 +1,24 @@ +--TEST-- +public bool ReflectionParameter::isArray ( void ); +--CREDITS-- +marcosptf - <marcosptf@yahoo.com.br> - @phpsp - sao paulo - br +--FILE-- +<?php +function testReflectionIsArray($a = null, $b = 0, array $c, $d=true, array $e, $f=1.5, $g="", array $h, $i="#F989898") {} + +$reflection = new ReflectionFunction('testReflectionIsArray'); + +foreach ($reflection->getParameters() as $parameter) { + var_dump($parameter->isArray()); +} +?> +--EXPECT-- +bool(false) +bool(false) +bool(true) +bool(false) +bool(true) +bool(false) +bool(false) +bool(true) +bool(false) diff --git a/ext/reflection/tests/ReflectionType_possible_types.phpt b/ext/reflection/tests/ReflectionType_possible_types.phpt new file mode 100644 index 0000000000..81e08550f2 --- /dev/null +++ b/ext/reflection/tests/ReflectionType_possible_types.phpt @@ -0,0 +1,31 @@ +--TEST-- +ReflectionType possible types +--FILE-- +<?php + +$functions = [ + function(): void {}, + function(): int {}, + function(): float {}, + function(): string {}, + function(): bool {}, + function(): array {}, + function(): callable {}, + function(): StdClass {} +]; + +foreach ($functions as $function) { + $reflectionFunc = new ReflectionFunction($function); + $returnType = $reflectionFunc->getReturnType(); + var_dump($returnType->__toString()); +} +?> +--EXPECTF-- +string(4) "void" +string(3) "int" +string(5) "float" +string(6) "string" +string(4) "bool" +string(5) "array" +string(8) "callable" +string(8) "StdClass" diff --git a/ext/session/mod_mm.c b/ext/session/mod_mm.c index 1978caed3c..3f69897556 100644 --- a/ext/session/mod_mm.c +++ b/ext/session/mod_mm.c @@ -29,6 +29,7 @@ #include <sys/types.h> #include <fcntl.h> +#include "php_stdint.h" #include "php_session.h" #include "mod_mm.h" #include "SAPI.h" @@ -39,14 +40,11 @@ #define PS_MM_FILE "session_mm_" -/* For php_uint32 */ -#include "ext/standard/basic_functions.h" - /* This list holds all data associated with one session. */ typedef struct ps_sd { struct ps_sd *next; - php_uint32 hv; /* hash value of key */ + uint32_t hv; /* hash value of key */ time_t ctime; /* time of last change */ void *data; size_t datalen; /* amount of valid data */ @@ -57,8 +55,8 @@ typedef struct ps_sd { typedef struct { MM *mm; ps_sd **hash; - php_uint32 hash_max; - php_uint32 hash_cnt; + uint32_t hash_max; + uint32_t hash_cnt; pid_t owner; } ps_mm; @@ -70,9 +68,9 @@ static ps_mm *ps_mm_instance = NULL; # define ps_mm_debug(a) #endif -static inline php_uint32 ps_sd_hash(const char *data, int len) +static inline uint32_t ps_sd_hash(const char *data, int len) { - php_uint32 h; + uint32_t h; const char *e = data + len; for (h = 2166136261U; data < e; ) { @@ -85,7 +83,7 @@ static inline php_uint32 ps_sd_hash(const char *data, int len) static void hash_split(ps_mm *data) { - php_uint32 nmax; + uint32_t nmax; ps_sd **nhash; ps_sd **ohash, **ehash; ps_sd *ps, *next; @@ -114,7 +112,7 @@ static void hash_split(ps_mm *data) static ps_sd *ps_sd_new(ps_mm *data, const char *key) { - php_uint32 hv, slot; + uint32_t hv, slot; ps_sd *sd; int keylen; @@ -155,7 +153,7 @@ static ps_sd *ps_sd_new(ps_mm *data, const char *key) static void ps_sd_destroy(ps_mm *data, ps_sd *sd) { - php_uint32 slot; + uint32_t slot; slot = ps_sd_hash(sd->key, strlen(sd->key)) & data->hash_max; @@ -180,7 +178,7 @@ static void ps_sd_destroy(ps_mm *data, ps_sd *sd) static ps_sd *ps_sd_lookup(ps_mm *data, const char *key, int rw) { - php_uint32 hv, slot; + uint32_t hv, slot; ps_sd *ret, *prev; hv = ps_sd_hash(key, strlen(key)); diff --git a/ext/session/mod_user.c b/ext/session/mod_user.c index e6f162855a..c7c09ff781 100644 --- a/ext/session/mod_user.c +++ b/ext/session/mod_user.c @@ -85,7 +85,16 @@ PS_OPEN_FUNC(user) ZVAL_STRING(&args[0], (char*)save_path); ZVAL_STRING(&args[1], (char*)session_name); - ps_call_handler(&PSF(open), 2, args, &retval); + zend_try { + ps_call_handler(&PSF(open), 2, args, &retval); + } zend_catch { + PS(session_status) = php_session_none; + if (!Z_ISUNDEF(retval)) { + zval_ptr_dtor(&retval); + } + zend_bailout(); + } zend_end_try(); + PS(mod_user_implemented) = 1; FINISH; diff --git a/ext/session/mod_user_class.c b/ext/session/mod_user_class.c index 59b44f5f6f..a774d4bf9c 100644 --- a/ext/session/mod_user_class.c +++ b/ext/session/mod_user_class.c @@ -22,6 +22,10 @@ #include "php_session.h" #define PS_SANITY_CHECK \ + if (PS(session_status) != php_session_active) { \ + php_error_docref(NULL, E_WARNING, "Session is not active"); \ + RETURN_FALSE; \ + } \ if (PS(default_mod) == NULL) { \ php_error_docref(NULL, E_CORE_ERROR, "Cannot call default session handler"); \ RETURN_FALSE; \ @@ -40,6 +44,7 @@ PHP_METHOD(SessionHandler, open) { char *save_path = NULL, *session_name = NULL; size_t save_path_len, session_name_len; + int ret; PS_SANITY_CHECK; @@ -48,7 +53,15 @@ PHP_METHOD(SessionHandler, open) } PS(mod_user_is_open) = 1; - RETVAL_BOOL(SUCCESS == PS(default_mod)->s_open(&PS(mod_data), save_path, session_name)); + + zend_try { + ret = PS(default_mod)->s_open(&PS(mod_data), save_path, session_name); + } zend_catch { + PS(session_status) = php_session_none; + zend_bailout(); + } zend_end_try(); + + RETVAL_BOOL(SUCCESS == ret); } /* }}} */ @@ -56,6 +69,8 @@ PHP_METHOD(SessionHandler, open) Wraps the old close handler */ PHP_METHOD(SessionHandler, close) { + int ret; + PS_SANITY_CHECK_IS_OPEN; // don't return on failure, since not closing the default handler @@ -63,7 +78,15 @@ PHP_METHOD(SessionHandler, close) zend_parse_parameters_none(); PS(mod_user_is_open) = 0; - RETVAL_BOOL(SUCCESS == PS(default_mod)->s_close(&PS(mod_data))); + + zend_try { + ret = PS(default_mod)->s_close(&PS(mod_data)); + } zend_catch { + PS(session_status) = php_session_none; + zend_bailout(); + } zend_end_try(); + + RETVAL_BOOL(SUCCESS == ret); } /* }}} */ diff --git a/ext/session/session.c b/ext/session/session.c index 52ba7e300a..866fab68a4 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -97,11 +97,13 @@ zend_class_entry *php_session_update_timestamp_iface_entry; #define APPLY_TRANS_SID (PS(use_trans_sid) && !PS(use_only_cookies)) static void php_session_send_cookie(void); +static void php_session_abort(void); /* Dispatched by RINIT and by php_session_destroy */ 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. */ PS(id) = NULL; PS(session_status) = php_session_none; PS(mod_data) = NULL; @@ -129,10 +131,15 @@ static inline void php_rshutdown_session_globals(void) /* {{{ */ zend_string_release(PS(id)); PS(id) = NULL; } + if (PS(session_vars)) { zend_string_release(PS(session_vars)); PS(session_vars) = NULL; } + + /* User save handlers may end up directly here by misuse, bugs in user script, etc. */ + /* Set session status to prevent error while restoring save handler INI value. */ + PS(session_status) = php_session_none; } /* }}} */ @@ -503,7 +510,10 @@ static void php_session_initialize(void) /* {{{ */ { zend_string *val = NULL; + PS(session_status) = php_session_active; + if (!PS(mod)) { + PS(session_status) = php_session_disabled; php_error_docref(NULL, E_ERROR, "No storage module chosen - failed to initialize session"); return; } @@ -512,14 +522,19 @@ static void php_session_initialize(void) /* {{{ */ if (PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name)) == FAILURE /* || PS(mod_data) == NULL */ /* FIXME: open must set valid PS(mod_data) with success */ ) { + php_session_abort(); php_error_docref(NULL, E_ERROR, "Failed to initialize storage module: %s (path: %s)", PS(mod)->s_name, PS(save_path)); return; } /* If there is no ID, use session module to create one */ - if (!PS(id)) { + if (!PS(id) || !ZSTR_VAL(PS(id))[0]) { + if (PS(id)) { + zend_string_release(PS(id)); + } PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); if (!PS(id)) { + php_session_abort(); php_error_docref(NULL, E_ERROR, "Failed to create session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); return; } @@ -541,20 +556,20 @@ static void php_session_initialize(void) /* {{{ */ } php_session_reset_id(); - PS(session_status) = php_session_active; - - /* GC must be done before read */ - php_session_gc(); /* Read data */ php_session_track_init(); if (PS(mod)->s_read(&PS(mod_data), PS(id), &val, PS(gc_maxlifetime)) == FAILURE) { + php_session_abort(); /* Some broken save handler implementation returns FAILURE for non-existent session ID */ /* It's better to raise error for this, but disabled error for better compatibility */ - /* - php_error_docref(NULL, E_NOTICE, "Failed to read session data: %s (path: %s)", PS(mod)->s_name, PS(save_path)); - */ + php_error_docref(NULL, E_WARNING, "Failed to read session data: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + return; } + + /* GC must be done after read */ + php_session_gc(); + if (PS(session_vars)) { zend_string_release(PS(session_vars)); PS(session_vars) = NULL; @@ -597,11 +612,16 @@ static void php_session_save_current_state(int write) /* {{{ */ } if ((ret == FAILURE) && !EG(exception)) { - php_error_docref(NULL, E_WARNING, "Failed to write session data (%s). Please " - "verify that the current setting of session.save_path " - "is correct (%s)", - PS(mod)->s_name, - PS(save_path)); + if (!PS(mod_user_implemented)) { + php_error_docref(NULL, E_WARNING, "Failed to write session data (%s). Please " + "verify that the current setting of session.save_path " + "is correct (%s)", + PS(mod)->s_name, + PS(save_path)); + } else { + php_error_docref(NULL, E_WARNING, "Failed to write session data using user " + "defined save handler. (session.save_path: %s)", PS(save_path)); + } } } } @@ -1102,7 +1122,7 @@ static ps_serializer ps_serializers[MAX_SERIALIZERS + 1] = { PHPAPI int php_session_register_serializer(const char *name, zend_string *(*encode)(PS_SERIALIZER_ENCODE_ARGS), int (*decode)(PS_SERIALIZER_DECODE_ARGS)) /* {{{ */ { - int ret = -1; + int ret = FAILURE; int i; for (i = 0; i < MAX_SERIALIZERS; i++) { @@ -1111,7 +1131,7 @@ PHPAPI int php_session_register_serializer(const char *name, zend_string *(*enco ps_serializers[i].encode = encode; ps_serializers[i].decode = decode; ps_serializers[i + 1].name = NULL; - ret = 0; + ret = SUCCESS; break; } } @@ -1133,13 +1153,13 @@ static ps_module *ps_modules[MAX_MODULES + 1] = { PHPAPI int php_session_register_module(ps_module *ptr) /* {{{ */ { - int ret = -1; + int ret = FAILURE; int i; for (i = 0; i < MAX_MODULES; i++) { if (!ps_modules[i]) { ps_modules[i] = ptr; - ret = 0; + ret = SUCCESS; break; } } @@ -1288,11 +1308,13 @@ static int php_session_cache_limiter(void) /* {{{ */ php_session_cache_limiter_t *lim; if (PS(cache_limiter)[0] == '\0') return 0; + if (PS(session_status) != php_session_active) return -1; if (SG(headers_sent)) { const char *output_start_filename = php_output_get_start_filename(); int output_start_lineno = php_output_get_start_lineno(); + php_session_abort(); if (output_start_filename) { php_error_docref(NULL, E_WARNING, "Cannot send session cache limiter - headers already sent (output started at %s:%d)", output_start_filename, output_start_lineno); } else { @@ -1652,8 +1674,8 @@ PHPAPI void php_session_start(void) /* {{{ */ static void php_session_flush(int write) /* {{{ */ { if (PS(session_status) == php_session_active) { - PS(session_status) = php_session_none; php_session_save_current_state(write); + PS(session_status) = php_session_none; } } /* }}} */ @@ -1661,10 +1683,10 @@ static void php_session_flush(int write) /* {{{ */ static void php_session_abort(void) /* {{{ */ { if (PS(session_status) == php_session_active) { - PS(session_status) = php_session_none; if (PS(mod_data) || PS(mod_user_implemented)) { PS(mod)->s_close(&PS(mod_data)); } + PS(session_status) = php_session_none; } } /* }}} */ @@ -2039,13 +2061,13 @@ static PHP_FUNCTION(session_regenerate_id) return; } - if (SG(headers_sent) && PS(use_cookies)) { - php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - headers already sent"); + if (PS(session_status) != php_session_active) { + php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - session is not active"); RETURN_FALSE; } - if (PS(session_status) != php_session_active) { - php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - session is not active"); + if (SG(headers_sent) && PS(use_cookies)) { + php_error_docref(NULL, E_WARNING, "Cannot regenerate session id - headers already sent"); RETURN_FALSE; } @@ -2081,15 +2103,18 @@ static PHP_FUNCTION(session_regenerate_id) PS(session_vars) = NULL; } zend_string_release(PS(id)); - PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); - if (!PS(id)) { + PS(id) = NULL; + + if (PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name)) == FAILURE) { PS(session_status) = php_session_none; - php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create new session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to open session: %s (path: %s)", PS(mod)->s_name, PS(save_path)); RETURN_FALSE; } - if (PS(mod)->s_open(&PS(mod_data), PS(save_path), PS(session_name)) == FAILURE) { + + PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); + if (!PS(id)) { PS(session_status) = php_session_none; - php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create(open) session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); + php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create new session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); RETURN_FALSE; } if (PS(use_strict_mode) && PS(mod)->s_validate_sid && @@ -2097,6 +2122,7 @@ static PHP_FUNCTION(session_regenerate_id) zend_string_release(PS(id)); PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); if (!PS(id)) { + PS(mod)->s_close(&PS(mod_data)); PS(session_status) = php_session_none; php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create session ID by collision: %s (path: %s)", PS(mod)->s_name, PS(save_path)); RETURN_FALSE; @@ -2104,6 +2130,7 @@ static PHP_FUNCTION(session_regenerate_id) } /* Read is required to make new session data at this point. */ if (PS(mod)->s_read(&PS(mod_data), PS(id), &data, PS(gc_maxlifetime)) == FAILURE) { + PS(mod)->s_close(&PS(mod_data)); PS(session_status) = php_session_none; php_error_docref(NULL, E_RECOVERABLE_ERROR, "Failed to create(read) session ID: %s (path: %s)", PS(mod)->s_name, PS(save_path)); RETURN_FALSE; @@ -2275,11 +2302,6 @@ static PHP_FUNCTION(session_start) RETURN_FALSE; } - if (PS(id) && !(ZSTR_LEN(PS(id)))) { - php_error_docref(NULL, E_WARNING, "Cannot start session with empty session ID"); - RETURN_FALSE; - } - /* set options */ if (options) { ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(options), num_idx, str_idx, value) { @@ -2941,7 +2963,7 @@ static int php_session_rfc1867_callback(unsigned int event, void *event_data, vo if (name_len == progress->sname_len && memcmp(data->name, PS(session_name), name_len) == 0) { zval_dtor(&progress->sid); ZVAL_STRINGL(&progress->sid, (*data->value), value_len); - } else if (memcmp(data->name, PS(rfc1867_name), name_len + 1) == 0) { + } else if (name_len == strlen(PS(rfc1867_name)) && memcmp(data->name, PS(rfc1867_name), name_len + 1) == 0) { smart_str_free(&progress->key); smart_str_appends(&progress->key, PS(rfc1867_prefix)); smart_str_appendl(&progress->key, *data->value, value_len); diff --git a/ext/session/tests/016.phpt b/ext/session/tests/016.phpt index 82a85d2705..f23605eb47 100644 --- a/ext/session/tests/016.phpt +++ b/ext/session/tests/016.phpt @@ -22,5 +22,5 @@ session_write_close(); print "I live\n"; ?> --EXPECTF-- -Warning: session_write_close(): Failed to write session data (files). Please verify that the current setting of session.save_path is correct (123;:/really%scompletely:::/invalid;;,23123;213) in %s on line %d +Warning: session_start(): Failed to read session data: files (path: 123;:/really%scompletely:::/invalid;;,23123;213) in %s on line %d I live diff --git a/ext/session/tests/bug32330.phpt b/ext/session/tests/bug32330.phpt index fe83cc9504..98d442ae5c 100644 --- a/ext/session/tests/bug32330.phpt +++ b/ext/session/tests/bug32330.phpt @@ -69,17 +69,17 @@ $_SESSION['E'] = 'F'; ?> --EXPECTF-- open: path = /tmp, name = sid -gc: maxlifetime = %d read: id = %s +gc: maxlifetime = %d write: id = %s, data = A|s:1:"B"; close open: path = /tmp, name = sid -gc: maxlifetime = %d read: id = %s +gc: maxlifetime = %d destroy: id = %s close open: path = /tmp, name = sid -gc: maxlifetime = %d read: id = %s +gc: maxlifetime = %d write: id = %s, data = E|s:1:"F"; close diff --git a/ext/session/tests/bug55688.phpt b/ext/session/tests/bug55688.phpt index 8db48384af..b073dc3c5c 100644 --- a/ext/session/tests/bug55688.phpt +++ b/ext/session/tests/bug55688.phpt @@ -12,4 +12,4 @@ $x = new SessionHandler; $x->gc(1); ?> --EXPECTF-- -Warning: SessionHandler::gc(): Parent session handler is not open in %s on line %d +Warning: SessionHandler::gc(): Session is not active in %s on line %d diff --git a/ext/session/tests/bug60634.phpt b/ext/session/tests/bug60634.phpt index 86dcb11526..b2f5076287 100644 --- a/ext/session/tests/bug60634.phpt +++ b/ext/session/tests/bug60634.phpt @@ -39,8 +39,17 @@ session_start(); session_write_close(); echo "um, hi\n"; +/* +FIXME: Since session module try to write/close session data in +RSHUTDOWN, write() is executed twices. This is caused by undefined +function error and zend_bailout(). Current session module codes +depends on this behavior. These codes should be modified to remove +multiple write(). +*/ + ?> --EXPECTF-- write: goodbye cruel world +write: goodbye cruel world close: goodbye cruel world diff --git a/ext/session/tests/bug60634_error_1.phpt b/ext/session/tests/bug60634_error_1.phpt index d0733f5a5a..fa76ff522a 100644 --- a/ext/session/tests/bug60634_error_1.phpt +++ b/ext/session/tests/bug60634_error_1.phpt @@ -41,6 +41,11 @@ session_start(); session_write_close(); echo "um, hi\n"; +/* +FIXME: Something wrong. It should try to close after error, otherwise session +may keep "open" state. +*/ + ?> --EXPECTF-- write: goodbye cruel world @@ -51,3 +56,4 @@ Stack trace: #1 %s(%d): session_write_close() #2 {main} thrown in %s on line %d + diff --git a/ext/session/tests/bug61728.phpt b/ext/session/tests/bug61728.phpt index 3f8dbeb58a..2780d7b7e2 100644 --- a/ext/session/tests/bug61728.phpt +++ b/ext/session/tests/bug61728.phpt @@ -8,32 +8,34 @@ function output_html($ext) { return strlen($ext); } -function open ($save_path, $session_name) { +function open ($save_path, $session_name) { return true; -} +} -function close() { +function close() { return true; -} +} -function read ($id) { -} +function read ($id) { + return ''; +} -function write ($id, $sess_data) { +function write ($id, $sess_data) { ob_start("output_html"); echo "laruence"; ob_end_flush(); return true; -} +} -function destroy ($id) { -} +function destroy ($id) { + return true; +} -function gc ($maxlifetime) { - return true; -} +function gc ($maxlifetime) { + return true; +} -session_set_save_handler ("open", "close", "read", "write", "destroy", "gc"); +session_set_save_handler ("open", "close", "read", "write", "destroy", "gc"); session_start(); --EXPECTF-- 8 diff --git a/ext/session/tests/bug67972.phpt b/ext/session/tests/bug67972.phpt index 63ed3a95b8..92c3044ac5 100644 --- a/ext/session/tests/bug67972.phpt +++ b/ext/session/tests/bug67972.phpt @@ -7,4 +7,5 @@ Bug #67972: SessionHandler Invalid memory read create_sid() (new SessionHandler)->create_sid(); --EXPECTF-- -Fatal error: SessionHandler::create_sid(): Cannot call default session handler in %s on line %d +Warning: SessionHandler::create_sid(): Session is not active in %s on line %d + diff --git a/ext/session/tests/bug68063.phpt b/ext/session/tests/bug68063.phpt index d3da470d06..ec3a70d156 100644 --- a/ext/session/tests/bug68063.phpt +++ b/ext/session/tests/bug68063.phpt @@ -3,18 +3,22 @@ Bug #68063 (Empty session IDs do still start sessions) --SKIPIF-- <?php include('skipif.inc'); ?> --INI-- +session.use_strict_mode=0 +session.hash_function=1 +session.hash_bits_per_character=4 --FILE-- <?php +// Empty session ID may happen by browser bugs + // Could also be set with a cookie like "PHPSESSID=; path=/" session_id(''); -// Will still start the session and return true +// Start the session with empty string should result in new session ID var_dump(session_start()); -// Returns an empty string +// Returns newly created session ID var_dump(session_id()); ?> --EXPECTF-- -Warning: session_start(): Cannot start session with empty session ID in %s on line %d -bool(false) -string(0) "" +bool(true) +string(40) "%s" diff --git a/ext/session/tests/bug69111.phpt b/ext/session/tests/bug69111.phpt new file mode 100644 index 0000000000..75b78f01ac --- /dev/null +++ b/ext/session/tests/bug69111.phpt @@ -0,0 +1,22 @@ +--TEST-- +Bug #69111 Crash in SessionHandler::read() +--SKIPIF-- +--XFAIL-- +It is still a leak +<?php include('skipif.inc'); ?> +--FILE-- +<?php +$sh = new SessionHandler; +session_set_save_handler($sh); + +$savePath = ini_get('session.save_path'); +$sessionName = ini_get('session.name'); + +// session_start(); // Uncommenting this makes it not crash when reading the session (see below), but it will not return any data. + +$sh->open($savePath, $sessionName); +$sh->write("foo", "bar"); +var_dump($sh->read(@$id)); +?> +--EXPECTF-- +bool(false) diff --git a/ext/session/tests/bug70133.phpt b/ext/session/tests/bug70133.phpt new file mode 100644 index 0000000000..3e019e483b --- /dev/null +++ b/ext/session/tests/bug70133.phpt @@ -0,0 +1,41 @@ +--TEST-- +Bug #70133 (Extended SessionHandler::read is ignoring $session_id when calling parent) +--SKIPIF-- +<?php include('skipif.inc'); ?> +--INI-- +session.save_handler=files +session.save_path= +session.use_strict_mode=0 +--FILE-- +<?php + +class CustomReadHandler extends \SessionHandler { + + public function read($session_id) { + return parent::read('mycustomsession'); + } +} + +ob_start(); + +session_set_save_handler(new CustomReadHandler(), true); + +session_id('mycustomsession'); +session_start(); +$_SESSION['foo'] = 'hoge'; +var_dump(session_id()); +session_commit(); + +session_id('otherid'); +session_start(); +var_dump($_SESSION); +var_dump(session_id()); + +?> +--EXPECT-- +string(15) "mycustomsession" +array(1) { + ["foo"]=> + string(4) "hoge" +} +string(7) "otherid" diff --git a/ext/session/tests/bug71186.phpt b/ext/session/tests/bug71186.phpt new file mode 100644 index 0000000000..5eeba6035f --- /dev/null +++ b/ext/session/tests/bug71186.phpt @@ -0,0 +1,32 @@ +--TEST-- +Bug #71186 session.hash_function - algorithm changes +--SKIPIF-- +<?php include('skipif.inc'); ?> +--INI-- +session.hash_function=sha512 +session.save_handler=files +--FILE-- +<?php +ob_start(); +ini_set('session.use_strict_mode', 1); + +session_start(); +$orig = session_id(); +session_regenerate_id(); +$new = session_id(); +var_dump(strlen($orig),strlen($new)); +session_commit(); + +ini_set('session.hash_function','sha1'); +session_id('invalid'); +session_start(); +$orig = session_id(); +session_regenerate_id(); +$new = session_id(); +var_dump(strlen($orig),strlen($new)); +?> +--EXPECT-- +int(128) +int(128) +int(40) +int(40) diff --git a/ext/session/tests/rfc1867_sid_invalid.phpt b/ext/session/tests/rfc1867_sid_invalid.phpt index 4dd8f1f979..a9114e3e1d 100644 --- a/ext/session/tests/rfc1867_sid_invalid.phpt +++ b/ext/session/tests/rfc1867_sid_invalid.phpt @@ -47,13 +47,13 @@ session_destroy(); --EXPECTF-- Warning: Unknown: The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in Unknown on line 0 -Warning: Unknown: The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in Unknown on line 0 +Warning: Unknown: Failed to read session data: files (path: ) in Unknown on line 0 Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct () in Unknown on line 0 Warning: Unknown: The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in Unknown on line 0 -Warning: Unknown: The session id is too long or contains illegal characters, valid characters are a-z, A-Z, 0-9 and '-,' in Unknown on line 0 +Warning: Unknown: Failed to read session data: files (path: ) in Unknown on line 0 Warning: Unknown: Failed to write session data (files). Please verify that the current setting of session.save_path is correct () in Unknown on line 0 string(%d) "%s" diff --git a/ext/session/tests/session_save_path_variation2.phpt b/ext/session/tests/session_save_path_variation2.phpt index 4cf44b75a4..60675aec3c 100644 --- a/ext/session/tests/session_save_path_variation2.phpt +++ b/ext/session/tests/session_save_path_variation2.phpt @@ -33,8 +33,12 @@ ob_end_flush(); string(5) "/blah" Warning: session_start(): open(%sblah%e%s, O_RDWR) failed: No such file or directory (2) in %s on line %d -bool(true) + +Warning: session_start(): Failed to read session data: files (path: %sblah) in %s on line %d +bool(false) string(5) "/blah" -bool(true) + +Warning: session_destroy(): Trying to destroy uninitialized session in %s on line %d +bool(false) string(5) "/blah" Done diff --git a/ext/session/tests/session_save_path_variation3.phpt b/ext/session/tests/session_save_path_variation3.phpt index b064f30183..1d290d95b3 100644 --- a/ext/session/tests/session_save_path_variation3.phpt +++ b/ext/session/tests/session_save_path_variation3.phpt @@ -33,8 +33,12 @@ ob_end_flush(); string(5) "/blah" Warning: session_start(): open(%s, O_RDWR) failed: No such file or directory (2) in %s on line %d -bool(true) + +Warning: session_start(): Failed to read session data: files (path: %sblah) in %s on line %d +bool(false) string(5) "/blah" -bool(true) + +Warning: session_destroy(): Trying to destroy uninitialized session in %s on line %d +bool(false) string(5) "/blah" Done diff --git a/ext/session/tests/session_set_save_handler_class_002.phpt b/ext/session/tests/session_set_save_handler_class_002.phpt index b75a7e6390..880bc33425 100644 --- a/ext/session/tests/session_set_save_handler_class_002.phpt +++ b/ext/session/tests/session_set_save_handler_class_002.phpt @@ -34,7 +34,7 @@ class MySession2 extends SessionHandler { } public function read($id) { - return @file_get_contents($this->path . $id); + return (string)@file_get_contents($this->path . $id); } public function write($id, $data) { diff --git a/ext/session/tests/session_set_save_handler_class_005.phpt b/ext/session/tests/session_set_save_handler_class_005.phpt index 5be735306a..1b8c1ce645 100644 --- a/ext/session/tests/session_set_save_handler_class_005.phpt +++ b/ext/session/tests/session_set_save_handler_class_005.phpt @@ -33,7 +33,7 @@ class MySession6 extends SessionHandler { $handler = new MySession6; session_set_save_handler($handler); -session_start(); +var_dump(session_start()); var_dump(session_id(), ini_get('session.save_handler'), $_SESSION); @@ -45,13 +45,12 @@ session_unset(); *** Testing session_set_save_handler() : incomplete implementation *** Warning: SessionHandler::read(): Parent session handler is not open in %ssession_set_save_handler_class_005.php on line %d + +Warning: SessionHandler::close(): Parent session handler is not open in %ssession_set_save_handler_class_005.php on line %d + +Warning: session_start(): Failed to read session data: user (%s) in %ssession_set_save_handler_class_005.php on line %d +bool(false) string(%d) "%s" string(4) "user" array(0) { } - -Warning: SessionHandler::write(): Parent session handler is not open in %ssession_set_save_handler_class_005.php on line %d - -Warning: session_write_close(): Failed to write session data %s in %ssession_set_save_handler_class_005.php on line %d - -Warning: SessionHandler::close(): Parent session handler is not open in %ssession_set_save_handler_class_005.php on line %d diff --git a/ext/session/tests/session_set_save_handler_class_012.phpt b/ext/session/tests/session_set_save_handler_class_012.phpt index 91e751bdfc..0ce03f865e 100644 --- a/ext/session/tests/session_set_save_handler_class_012.phpt +++ b/ext/session/tests/session_set_save_handler_class_012.phpt @@ -38,7 +38,7 @@ class MySession extends SessionHandler { $oldHandler = ini_get('session.save_handler'); $handler = new MySession; session_set_save_handler($handler); -session_start(); +var_dump(session_start()); var_dump(session_id(), $oldHandler, ini_get('session.save_handler'), $handler->i, $_SESSION); @@ -50,15 +50,14 @@ Warning: SessionHandler::open() expects exactly 2 parameters, 0 given in %s on l Read %s Warning: SessionHandler::read(): Parent session handler is not open in %s on line %d + +Warning: SessionHandler::close(): Parent session handler is not open in %s on line %d + +Warning: session_start(): Failed to read session data: user (%s) in %s on line %d +bool(false) string(%d) "%s" string(5) "files" string(4) "user" int(2) array(0) { } - -Warning: SessionHandler::write(): Parent session handler is not open in Unknown on line 0 - -Warning: session_write_close(): Failed to write session data %s in %s on line %d - -Warning: SessionHandler::close(): Parent session handler is not open in Unknown on line 0 diff --git a/ext/session/tests/session_set_save_handler_class_016.phpt b/ext/session/tests/session_set_save_handler_class_016.phpt index 521bd86f31..4095813c9d 100644 --- a/ext/session/tests/session_set_save_handler_class_016.phpt +++ b/ext/session/tests/session_set_save_handler_class_016.phpt @@ -10,10 +10,10 @@ session.name=PHPSESSID ob_start(); -/* +/* * Prototype : bool session_set_save_handler(SessionHandlerInterface $handler [, bool $register_shutdown_function = true]) * Description : Sets user-level session storage functions - * Source code : ext/session/session.c + * Source code : ext/session/session.c */ echo "*** Testing session_set_save_handler() function: class with create_sid ***\n"; @@ -34,7 +34,7 @@ class MySession2 extends SessionHandler { } public function read($id) { - return @file_get_contents($this->path . $id); + return (string)@file_get_contents($this->path . $id); } public function write($id, $data) { diff --git a/ext/session/tests/session_set_save_handler_class_017.phpt b/ext/session/tests/session_set_save_handler_class_017.phpt index 6f42d7809a..b8e7d7a7ad 100644 --- a/ext/session/tests/session_set_save_handler_class_017.phpt +++ b/ext/session/tests/session_set_save_handler_class_017.phpt @@ -34,7 +34,7 @@ class MySession2 extends SessionHandler { } public function read($id) { - return @file_get_contents($this->path . $id); + return (string)@file_get_contents($this->path . $id); } public function write($id, $data) { diff --git a/ext/session/tests/session_set_save_handler_error4.phpt b/ext/session/tests/session_set_save_handler_error4.phpt index be3429b084..4267195ee1 100644 --- a/ext/session/tests/session_set_save_handler_error4.phpt +++ b/ext/session/tests/session_set_save_handler_error4.phpt @@ -24,7 +24,7 @@ session_set_save_handler("callback", "callback", "callback", "echo", "callback", session_set_save_handler("callback", "callback", "callback", "callback", "echo", "callback"); session_set_save_handler("callback", "callback", "callback", "callback", "callback", "echo"); session_set_save_handler("callback", "callback", "callback", "callback", "callback", "callback"); -session_start(); +var_dump(session_start()); ob_end_flush(); ?> --EXPECTF-- @@ -39,3 +39,6 @@ Warning: session_set_save_handler(): Argument 4 is not a valid callback in %s on Warning: session_set_save_handler(): Argument 5 is not a valid callback in %s on line %d Warning: session_set_save_handler(): Argument 6 is not a valid callback in %s on line %d + +Warning: session_start(): Failed to read session data: user (%s) in %s on line %d +bool(false) diff --git a/ext/session/tests/session_set_save_handler_iface_001.phpt b/ext/session/tests/session_set_save_handler_iface_001.phpt index 03ee42865c..6943d59cbe 100644 --- a/ext/session/tests/session_set_save_handler_iface_001.phpt +++ b/ext/session/tests/session_set_save_handler_iface_001.phpt @@ -34,7 +34,7 @@ class MySession2 implements SessionHandlerInterface { } public function read($id) { - return @file_get_contents($this->path . $id); + return (string)@file_get_contents($this->path . $id); } public function write($id, $data) { diff --git a/ext/session/tests/session_set_save_handler_iface_002.phpt b/ext/session/tests/session_set_save_handler_iface_002.phpt index 40c9ac6825..204d88c785 100644 --- a/ext/session/tests/session_set_save_handler_iface_002.phpt +++ b/ext/session/tests/session_set_save_handler_iface_002.phpt @@ -43,7 +43,7 @@ class MySession2 implements MySessionHandlerInterface { } public function read($id) { - return @file_get_contents($this->path . $id); + return (string)@file_get_contents($this->path . $id); } public function write($id, $data) { diff --git a/ext/session/tests/session_set_save_handler_variation4.phpt b/ext/session/tests/session_set_save_handler_variation4.phpt index 67aa70c4af..a711fdea59 100644 --- a/ext/session/tests/session_set_save_handler_variation4.phpt +++ b/ext/session/tests/session_set_save_handler_variation4.phpt @@ -52,9 +52,9 @@ ob_end_flush(); *** Testing session_set_save_handler() : variation *** Open [%s,PHPSESSID] +Read [%s,%s] GC [0] 1 deleted -Read [%s,%s] array(3) { ["Blah"]=> string(12) "Hello World!" @@ -67,12 +67,20 @@ Write [%s,%s,Blah|s:12:"Hello World!";Foo|b:0;Guff|i:1234567890;] Close [%s,PHPSESSID] NULL Open [%s,PHPSESSID] +Read [%s,%s] GC [0] 1 deleted -Read [%s,%s] -array(0) { +array(3) { + ["Blah"]=> + string(12) "Hello World!" + ["Foo"]=> + bool(false) + ["Guff"]=> + int(1234567890) } Destroy [%s,%s] + +Warning: unlink(%s): No such file or directory in %s on line %s Close [%s,PHPSESSID] bool(true) diff --git a/ext/session/tests/session_set_save_handler_variation5.phpt b/ext/session/tests/session_set_save_handler_variation5.phpt index 4c1687cac6..6ad600e4d1 100644 --- a/ext/session/tests/session_set_save_handler_variation5.phpt +++ b/ext/session/tests/session_set_save_handler_variation5.phpt @@ -62,9 +62,9 @@ string(0) "" bool(true) Open [%s,PHPSESSID] CreateID [PHPT-%d] +Read [%s,PHPT-%d] GC [0] 1 deleted -Read [%s,PHPT-%d] bool(true) string(%d) "PHPT-%d" Write [%s,PHPT-%d,] @@ -76,9 +76,9 @@ string(%d) "PHPT-%d" bool(true) Open [%s,PHPSESSID] ValidateID [%s,PHPT-%d] +Read [%s,PHPT-%d] GC [0] 1 deleted -Read [%s,PHPT-%d] bool(true) Write [%s,PHPT-%d,] Close [%s,PHPSESSID] @@ -88,10 +88,12 @@ string(%d) "PHPT-%d" string(%d) "PHPT-%d" Open [%s,PHPSESSID] ValidateID [%s,PHPT-%d] +Read [%s,PHPT-%d] GC [0] 1 deleted -Read [%s,PHPT-%d] bool(true) Destroy [%s,PHPT-%d] + +Warning: unlink(%s): No such file or directory in %s on line %d Close [%s,PHPSESSID] bool(true) diff --git a/ext/session/tests/sessionhandler_open_001.phpt b/ext/session/tests/sessionhandler_open_001.phpt index 6ade9e00a5..e6e913a6a5 100644 --- a/ext/session/tests/sessionhandler_open_001.phpt +++ b/ext/session/tests/sessionhandler_open_001.phpt @@ -16,4 +16,11 @@ print "Done!\n"; ?> --EXPECTF-- +Warning: SessionHandler::open(): Session is not active in %s on line 5 + +Warning: SessionHandler::open(): Session is not active in %s on line 6 + +Warning: SessionHandler::open(): Session is not active in %s on line 7 + +Warning: SessionHandler::open(): Session is not active in %s on line 8 Done! diff --git a/ext/simplexml/php_simplexml.h b/ext/simplexml/php_simplexml.h index a6d5ffc7ff..ea29f1399c 100644 --- a/ext/simplexml/php_simplexml.h +++ b/ext/simplexml/php_simplexml.h @@ -45,9 +45,6 @@ extern zend_module_entry simplexml_module_entry; PHP_MINIT_FUNCTION(simplexml); PHP_MSHUTDOWN_FUNCTION(simplexml); -#ifdef HAVE_SPL -PHP_RINIT_FUNCTION(simplexml); -#endif PHP_MINFO_FUNCTION(simplexml); typedef enum { diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index be8888c348..d6a5680e7d 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -33,10 +33,7 @@ #include "php_snmp.h" #include "zend_exceptions.h" - -#if HAVE_SPL #include "ext/spl/spl_exceptions.h" -#endif #if HAVE_SNMP @@ -2414,11 +2411,7 @@ PHP_MINIT_FUNCTION(snmp) /* Register SNMPException class */ INIT_CLASS_ENTRY(cex, "SNMPException", NULL); -#ifdef HAVE_SPL php_snmp_exception_ce = zend_register_internal_class_ex(&cex, spl_ce_RuntimeException); -#else - php_snmp_exception_ce = zend_register_internal_class_ex(&cex, zend_ce_exception); -#endif return SUCCESS; } @@ -2450,14 +2443,10 @@ PHP_MINFO_FUNCTION(snmp) /* {{{ snmp_module_deps[] */ -#if ZEND_MODULE_API_NO >= 20050922 static const zend_module_dep snmp_module_deps[] = { -#ifdef HAVE_SPL ZEND_MOD_REQUIRED("spl") -#endif ZEND_MOD_END }; -#endif /* }}} */ /* {{{ snmp_module_entry diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 5d9064af70..1fdc5a8788 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -3014,7 +3014,11 @@ static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodeP xmlFreeNode(dummy); } ZEND_HASH_FOREACH_END(); smart_str_0(&list); - xmlNodeSetContentLen(ret, BAD_CAST(ZSTR_VAL(list.s)), ZSTR_LEN(list.s)); + if (list.s) { + xmlNodeSetContentLen(ret, BAD_CAST(ZSTR_VAL(list.s)), ZSTR_LEN(list.s)); + } else { + xmlNodeSetContentLen(ret, BAD_CAST(""), 0); + } smart_str_free(&list); } else { zval tmp; @@ -3054,7 +3058,11 @@ static xmlNodePtr to_xml_list(encodeTypePtr enc, zval *data, int style, xmlNodeP start = next; } smart_str_0(&list); - xmlNodeSetContentLen(ret, BAD_CAST(ZSTR_VAL(list.s)), ZSTR_LEN(list.s)); + if (list.s) { + xmlNodeSetContentLen(ret, BAD_CAST(ZSTR_VAL(list.s)), ZSTR_LEN(list.s)); + } else { + xmlNodeSetContentLen(ret, BAD_CAST(""), 0); + } smart_str_free(&list); efree(str); if (data == &tmp) {zval_dtor(&tmp);} diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 49fc72d68f..ee41ff908f 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -2135,7 +2135,7 @@ static void soap_error_handler(int error_num, const char *error_filename, const _old_http_response_code = SG(sapi_headers).http_response_code; _old_http_status_line = SG(sapi_headers).http_status_line; - if (!SOAP_GLOBAL(use_soap_error_handler) || !EG(objects_store).object_buckets) { + if (!PG(modules_activated) || !SOAP_GLOBAL(use_soap_error_handler) || !EG(objects_store).object_buckets) { call_old_error_handler(error_num, error_filename, error_lineno, format, args); return; } diff --git a/ext/sockets/tests/socket_clear_error-win32.phpt b/ext/sockets/tests/socket_clear_error-win32.phpt new file mode 100644 index 0000000000..3a0b1ea162 --- /dev/null +++ b/ext/sockets/tests/socket_clear_error-win32.phpt @@ -0,0 +1,32 @@ +--TEST-- +void socket_clear_error ([ resource $socket ] ) ; +--CREDITS-- +marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao paulo - br +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} +if(substr(PHP_OS, 0, 3) != 'WIN' ) { + die('skip windows only test'); +} +?> +--FILE-- +<?php +$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); +$socketConn = socket_connect($socket, "127.0.0.1", 21248); +var_dump(socket_last_error($socket)); +socket_clear_error($socket); +var_dump(socket_last_error($socket)); +?> +--CLEAN-- +<?php +socket_close($socket); +unset($socket); +unset($socketConn); +?> +--EXPECTF-- +Warning: socket_connect(): unable to connect [%d]: No connection could be made because the target machine actively refused it. + in %s on line %d +int(%d) +int(%d) diff --git a/ext/sockets/tests/socket_clear_error.phpt b/ext/sockets/tests/socket_clear_error.phpt index af9acaa9bf..273f7a0ca8 100644 --- a/ext/sockets/tests/socket_clear_error.phpt +++ b/ext/sockets/tests/socket_clear_error.phpt @@ -7,6 +7,9 @@ marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao p if (!extension_loaded('sockets')) { die('SKIP sockets extension not available.'); } +if(substr(PHP_OS, 0, 3) == 'WIN' ) { + die('skip windows only test'); +} ?> --FILE-- <?php diff --git a/ext/sockets/tests/socket_send.phpt b/ext/sockets/tests/socket_send.phpt index 1411868c4b..ceeb397979 100644 --- a/ext/sockets/tests/socket_send.phpt +++ b/ext/sockets/tests/socket_send.phpt @@ -7,6 +7,9 @@ marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao p if (!extension_loaded('sockets')) { die('SKIP sockets extension not available.'); } +if(substr(PHP_OS, 0, 3) == 'WIN' ) { + die('skip not for windows'); +} ?> --FILE-- <?php diff --git a/ext/sockets/tests/socket_send_win32.phpt b/ext/sockets/tests/socket_send_win32.phpt new file mode 100644 index 0000000000..04a985c781 --- /dev/null +++ b/ext/sockets/tests/socket_send_win32.phpt @@ -0,0 +1,43 @@ +--TEST-- +int socket_send ( resource $socket , string $buf , int $len , int $flags ); +--CREDITS-- +marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao paulo - br +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} +if(substr(PHP_OS, 0, 3) != 'WIN' ) { + die('skip windows only test'); +} +?> +--FILE-- +<?php +$port = 80; +$host = "yahoo.com"; +$stringSocket = "send_socket_to_connected_socket"; +$stringSocketLenght = strlen($stringSocket); + +$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); +$socketConn = socket_connect($socket, $host, $port); + +if(socket_send($socket, $stringSocket, $stringSocketLenght, MSG_OOB)===$stringSocketLenght){ + print("okey\n"); +} + +if(socket_send($socket, $stringSocket, $stringSocketLenght, MSG_DONTROUTE)===$stringSocketLenght){ + print("okey\n"); +} +?> +<?php +socket_close($socket); +unset($port); +unset($host); +unset($stringSocket); +unset($stringSocketLenght); +unset($socket); +unset($socketConn); +?> +--EXPECTF-- +okey +okey diff --git a/ext/sockets/tests/socket_shutdown-win32.phpt b/ext/sockets/tests/socket_shutdown-win32.phpt new file mode 100644 index 0000000000..6280e61044 --- /dev/null +++ b/ext/sockets/tests/socket_shutdown-win32.phpt @@ -0,0 +1,59 @@ +--TEST-- +bool socket_shutdown ( resource $socket [, int $how = 2 ] ) ; +--CREDITS-- +marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao paulo - br +--SKIPIF-- +<?php +if (!extension_loaded('sockets')) { + die('SKIP sockets extension not available.'); +} +if(substr(PHP_OS, 0, 3) != 'WIN' ) { + die('skip windows only test'); +} +?> +--FILE-- +<?php +$host = "yahoo.com"; +$port = 80; + +$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); +$socketConn = socket_connect($socket, $host, $port); +var_dump(socket_shutdown($socket,0)); +socket_close($socket); + +$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); +$socketConn = socket_connect($socket, $host, $port); +var_dump(socket_shutdown($socket,1)); +socket_close($socket); + +$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); +$socketConn = socket_connect($socket, $host, $port); +var_dump(socket_shutdown($socket,2)); +socket_close($socket); + +$socket = socket_create(AF_INET, SOCK_STREAM, SOL_TCP); +var_dump(socket_shutdown($socket,0)); + +$socketConn = socket_connect($socket, $host, $port); +var_dump(socket_shutdown($socket,-1)); +socket_close($socket); +?> +--CLEAN-- +<?php +unset($host); +unset($port); +unset($socket); +unset($socketConn); +?> +--EXPECTF-- +bool(true) +bool(true) +bool(true) + +Warning: socket_shutdown(): unable to shutdown socket [%d]: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied. + in %s on line %d +bool(false) + +Warning: socket_shutdown(): unable to shutdown socket [%d]: An invalid argument was supplied. + in %s on line %d +bool(false) diff --git a/ext/sockets/tests/socket_shutdown.phpt b/ext/sockets/tests/socket_shutdown.phpt index 09f5ac73fc..77cbc8f32c 100644 --- a/ext/sockets/tests/socket_shutdown.phpt +++ b/ext/sockets/tests/socket_shutdown.phpt @@ -7,6 +7,9 @@ marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao p if (!extension_loaded('sockets')) { die('SKIP sockets extension not available.'); } +if(substr(PHP_OS, 0, 3) == 'WIN' ) { + die('skip not for windows'); +} ?> --FILE-- <?php diff --git a/ext/spl/php_spl.c b/ext/spl/php_spl.c index 57e43d4fae..9c7611d117 100644 --- a/ext/spl/php_spl.c +++ b/ext/spl/php_spl.c @@ -777,7 +777,7 @@ PHPAPI zend_string *php_spl_object_hash(zval *obj) /* {{{*/ } hash_handle = SPL_G(hash_mask_handle)^(intptr_t)Z_OBJ_HANDLE_P(obj); - hash_handlers = SPL_G(hash_mask_handlers)^(intptr_t)Z_OBJ_HT_P(obj); + hash_handlers = SPL_G(hash_mask_handlers); return strpprintf(32, "%016lx%016lx", hash_handle, hash_handlers); } diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 1f4cad1f15..685dd27092 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -82,19 +82,29 @@ static inline spl_array_object *spl_array_from_obj(zend_object *obj) /* {{{ */ { #define Z_SPLARRAY_P(zv) spl_array_from_obj(Z_OBJ_P((zv))) -static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props) { /* {{{ */ - if (intern->ar_flags & SPL_ARRAY_IS_SELF - || (check_std_props && (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST)) - ) { +static inline HashTable *spl_array_get_hash_table(spl_array_object* intern) { /* {{{ */ + //??? TODO: Delay duplication for arrays; only duplicate for write operations + if (intern->ar_flags & SPL_ARRAY_IS_SELF) { if (!intern->std.properties) { rebuild_object_properties(&intern->std); } return intern->std.properties; } else if (intern->ar_flags & SPL_ARRAY_USE_OTHER) { spl_array_object *other = Z_SPLARRAY_P(&intern->array); - return spl_array_get_hash_table(other, check_std_props); + return spl_array_get_hash_table(other); + } else if (Z_TYPE(intern->array) == IS_ARRAY) { + return Z_ARRVAL(intern->array); } else { - return HASH_OF(&intern->array); + zend_object *obj = Z_OBJ(intern->array); + if (!obj->properties) { + rebuild_object_properties(obj); + } else if (GC_REFCOUNT(obj->properties) > 1) { + if (EXPECTED(!(GC_FLAGS(obj->properties) & IS_ARRAY_IMMUTABLE))) { + GC_REFCOUNT(obj->properties)--; + } + obj->properties = zend_array_dup(obj->properties); + } + return obj->properties; } } /* }}} */ @@ -167,10 +177,12 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zval * if (other->ar_flags & SPL_ARRAY_IS_SELF) { ZVAL_UNDEF(&intern->array); } else if (Z_OBJ_HT_P(orig) == &spl_handler_ArrayObject) { - ZVAL_ARR(&intern->array, zend_array_dup(HASH_OF(&other->array))); + ZVAL_ARR(&intern->array, + zend_array_dup(spl_array_get_hash_table(other))); } else { ZEND_ASSERT(Z_OBJ_HT_P(orig) == &spl_handler_ArrayIterator); - ZVAL_COPY(&intern->array, &other->array); + ZVAL_COPY(&intern->array, orig); + intern->ar_flags |= SPL_ARRAY_USE_OTHER; } } else { ZVAL_COPY(&intern->array, orig); @@ -269,13 +281,13 @@ static zval *spl_array_get_dimension_ptr(int check_inherited, zval *object, zval zend_long index; zend_string *offset_key; spl_array_object *intern = Z_SPLARRAY_P(object); - HashTable *ht = spl_array_get_hash_table(intern, 0); + HashTable *ht = spl_array_get_hash_table(intern); if (!offset || Z_ISUNDEF_P(offset)) { return &EG(uninitialized_zval); } - if ((type == BP_VAR_W || type == BP_VAR_RW) && (ht->u.v.nApplyCount > 0)) { + if ((type == BP_VAR_W || type == BP_VAR_RW) && intern->nApplyCount > 0) { zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); return &EG(error_zval); } @@ -434,16 +446,8 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval return; } - if (!offset) { - ht = spl_array_get_hash_table(intern, 0); - if (ht->u.v.nApplyCount > 0) { - zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); - return; - } - if (Z_REFCOUNTED_P(value)) { - Z_ADDREF_P(value); - } - zend_hash_next_index_insert(ht, value); + if (intern->nApplyCount > 0) { + zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); return; } @@ -451,14 +455,16 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval Z_ADDREF_P(value); } + if (!offset) { + ht = spl_array_get_hash_table(intern); + zend_hash_next_index_insert(ht, value); + return; + } + try_again: switch (Z_TYPE_P(offset)) { case IS_STRING: - ht = spl_array_get_hash_table(intern, 0); - if (ht->u.v.nApplyCount > 0) { - zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); - return; - } + ht = spl_array_get_hash_table(intern); zend_symtable_update_ind(ht, Z_STR_P(offset), value); return; case IS_DOUBLE: @@ -476,19 +482,11 @@ try_again: case IS_LONG: index = Z_LVAL_P(offset); num_index: - ht = spl_array_get_hash_table(intern, 0); - if (ht->u.v.nApplyCount > 0) { - zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); - return; - } + ht = spl_array_get_hash_table(intern); zend_hash_index_update(ht, index, value); return; case IS_NULL: - ht = spl_array_get_hash_table(intern, 0); - if (ht->u.v.nApplyCount > 0) { - zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); - return; - } + ht = spl_array_get_hash_table(intern); zend_hash_next_index_insert(ht, value); return; case IS_REFERENCE: @@ -496,6 +494,7 @@ num_index: goto try_again; default: zend_error(E_WARNING, "Illegal offset type"); + zval_ptr_dtor(value); return; } } /* }}} */ @@ -518,14 +517,15 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval return; } + if (intern->nApplyCount > 0) { + zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); + return; + } + try_again: switch (Z_TYPE_P(offset)) { case IS_STRING: - ht = spl_array_get_hash_table(intern, 0); - if (ht->u.v.nApplyCount > 0) { - zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); - return; - } + ht = spl_array_get_hash_table(intern); if (ht == &EG(symbol_table)) { if (zend_delete_global_variable(Z_STR_P(offset))) { zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset)); @@ -570,11 +570,7 @@ try_again: case IS_LONG: index = Z_LVAL_P(offset); num_index: - ht = spl_array_get_hash_table(intern, 0); - if (ht->u.v.nApplyCount > 0) { - zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); - return; - } + ht = spl_array_get_hash_table(intern); if (zend_hash_index_del(ht, index) == FAILURE) { zend_error(E_NOTICE,"Undefined offset: %pd", index); } @@ -618,7 +614,7 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o } if (!value) { - HashTable *ht = spl_array_get_hash_table(intern, 0); + HashTable *ht = spl_array_get_hash_table(intern); try_again: switch (Z_TYPE_P(offset)) { @@ -744,7 +740,7 @@ SPL_METHOD(Array, offsetSet) void spl_array_iterator_append(zval *object, zval *append_value) /* {{{ */ { spl_array_object *intern = Z_SPLARRAY_P(object); - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); if (!aht) { php_error_docref(NULL, E_NOTICE, "Array was modified outside object and is no longer an array"); @@ -792,22 +788,21 @@ SPL_METHOD(Array, getArrayCopy) zval *object = getThis(); spl_array_object *intern = Z_SPLARRAY_P(object); - RETURN_ARR(zend_array_dup(spl_array_get_hash_table(intern, 0))); + RETURN_ARR(zend_array_dup(spl_array_get_hash_table(intern))); } /* }}} */ static HashTable *spl_array_get_properties(zval *object) /* {{{ */ { spl_array_object *intern = Z_SPLARRAY_P(object); - HashTable *result; - if (intern->nApplyCount > 1) { - php_error_docref(NULL, E_ERROR, "Nesting level too deep - recursive dependency?"); + if (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST) { + if (!intern->std.properties) { + rebuild_object_properties(&intern->std); + } + return intern->std.properties; } - intern->nApplyCount++; - result = spl_array_get_hash_table(intern, 1); - intern->nApplyCount--; - return result; + return spl_array_get_hash_table(intern); } /* }}} */ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp) /* {{{ */ @@ -922,8 +917,8 @@ static int spl_array_compare_objects(zval *o1, zval *o2) /* {{{ */ intern1 = Z_SPLARRAY_P(o1); intern2 = Z_SPLARRAY_P(o2); - ht1 = spl_array_get_hash_table(intern1, 0); - ht2 = spl_array_get_hash_table(intern2, 0); + ht1 = spl_array_get_hash_table(intern1); + ht2 = spl_array_get_hash_table(intern2); result = zend_compare_symbol_tables(ht1, ht2); /* if we just compared std.properties, don't do it again */ @@ -978,7 +973,7 @@ static int spl_array_next_ex(spl_array_object *intern, HashTable *aht) /* {{{ */ static int spl_array_next(spl_array_object *intern) /* {{{ */ { - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); return spl_array_next_ex(intern, aht); @@ -994,7 +989,7 @@ static void spl_array_it_dtor(zend_object_iterator *iter) /* {{{ */ static int spl_array_it_valid(zend_object_iterator *iter) /* {{{ */ { spl_array_object *object = Z_SPLARRAY_P(&iter->data); - HashTable *aht = spl_array_get_hash_table(object, 0); + HashTable *aht = spl_array_get_hash_table(object); if (object->ar_flags & SPL_ARRAY_OVERLOADED_VALID) { return zend_user_it_valid(iter); @@ -1011,7 +1006,7 @@ static int spl_array_it_valid(zend_object_iterator *iter) /* {{{ */ static zval *spl_array_it_get_current_data(zend_object_iterator *iter) /* {{{ */ { spl_array_object *object = Z_SPLARRAY_P(&iter->data); - HashTable *aht = spl_array_get_hash_table(object, 0); + HashTable *aht = spl_array_get_hash_table(object); if (object->ar_flags & SPL_ARRAY_OVERLOADED_CURRENT) { return zend_user_it_get_current_data(iter); @@ -1028,7 +1023,7 @@ static zval *spl_array_it_get_current_data(zend_object_iterator *iter) /* {{{ */ static void spl_array_it_get_current_key(zend_object_iterator *iter, zval *key) /* {{{ */ { spl_array_object *object = Z_SPLARRAY_P(&iter->data); - HashTable *aht = spl_array_get_hash_table(object, 0); + HashTable *aht = spl_array_get_hash_table(object); if (object->ar_flags & SPL_ARRAY_OVERLOADED_KEY) { zend_user_it_get_current_key(iter, key); @@ -1045,7 +1040,7 @@ static void spl_array_it_get_current_key(zend_object_iterator *iter, zval *key) static void spl_array_it_move_forward(zend_object_iterator *iter) /* {{{ */ { spl_array_object *object = Z_SPLARRAY_P(&iter->data); - HashTable *aht = spl_array_get_hash_table(object, 0); + HashTable *aht = spl_array_get_hash_table(object); if (object->ar_flags & SPL_ARRAY_OVERLOADED_NEXT) { zend_user_it_move_forward(iter); @@ -1063,7 +1058,7 @@ static void spl_array_it_move_forward(zend_object_iterator *iter) /* {{{ */ static void spl_array_rewind(spl_array_object *intern) /* {{{ */ { - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); if (!aht) { php_error_docref(NULL, E_NOTICE, "ArrayIterator::rewind(): Array was modified outside object and is no longer an array"); @@ -1099,13 +1094,13 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar return; } - zval_ptr_dtor(&intern->array); - if (Z_TYPE_P(array) == IS_ARRAY) { //??? TODO: try to avoid array duplication + zval_ptr_dtor(&intern->array); ZVAL_DUP(&intern->array, array); } else { if (Z_OBJ_HT_P(array) == &spl_handler_ArrayObject || Z_OBJ_HT_P(array) == &spl_handler_ArrayIterator) { + zval_ptr_dtor(&intern->array); if (just_array) { spl_array_object *other = Z_SPLARRAY_P(array); ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK; @@ -1119,18 +1114,13 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar } } else { zend_object_get_properties_t handler = Z_OBJ_HANDLER_P(array, get_properties); - if (handler != std_object_handlers.get_properties - || !spl_array_get_hash_table(intern, 0)) { - ZVAL_UNDEF(&intern->array); - zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Overloaded object of type %s is not compatible with %s", Z_OBJCE_P(array)->name, intern->std.ce->name); - } - //??? TODO: try to avoid array duplication - if (Z_OBJ_P(array)->properties && GC_REFCOUNT(Z_OBJ_P(array)->properties) > 1) { - if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array)->properties) & IS_ARRAY_IMMUTABLE))) { - GC_REFCOUNT(Z_OBJ_P(array)->properties)--; - } - Z_OBJ_P(array)->properties = zend_array_dup(Z_OBJ_P(array)->properties); + if (handler != std_object_handlers.get_properties) { + zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, + "Overloaded object of type %s is not compatible with %s", + ZSTR_VAL(Z_OBJCE_P(array)->name), ZSTR_VAL(intern->std.ce->name)); + return; } + zval_ptr_dtor(&intern->array); ZVAL_COPY(&intern->array, array); } } @@ -1284,7 +1274,12 @@ SPL_METHOD(Array, exchangeArray) return; } - RETVAL_ARR(zend_array_dup(spl_array_get_hash_table(intern, 0))); + if (intern->nApplyCount > 0) { + zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); + return; + } + + RETVAL_ARR(zend_array_dup(spl_array_get_hash_table(intern))); spl_array_set_array(object, intern, array, 0L, 1); } /* }}} */ @@ -1295,7 +1290,7 @@ SPL_METHOD(Array, getIterator) { zval *object = getThis(); spl_array_object *intern = Z_SPLARRAY_P(object); - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); if (zend_parse_parameters_none() == FAILURE) { return; @@ -1332,7 +1327,7 @@ SPL_METHOD(Array, seek) zend_long opos, position; zval *object = getThis(); spl_array_object *intern = Z_SPLARRAY_P(object); - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); int result; if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &position) == FAILURE) { @@ -1361,7 +1356,7 @@ SPL_METHOD(Array, seek) int static spl_array_object_count_elements_helper(spl_array_object *intern, zend_long *count) /* {{{ */ { - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); HashPosition pos, *pos_ptr; if (!aht) { @@ -1426,7 +1421,7 @@ SPL_METHOD(Array, count) static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fname_len, int use_arg) /* {{{ */ { spl_array_object *intern = Z_SPLARRAY_P(getThis()); - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); zval function_name, params[2], *arg = NULL; uint32_t old_refcount; @@ -1440,9 +1435,9 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam ZVAL_ARR(Z_REFVAL(params[0]), aht); if (!use_arg) { - aht->u.v.nApplyCount++; + intern->nApplyCount++; call_user_function_ex(EG(function_table), NULL, &function_name, return_value, 1, params, 1, NULL); - aht->u.v.nApplyCount--; + intern->nApplyCount--; } else if (use_arg == SPL_ARRAY_METHOD_MAY_USER_ARG) { if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "|z", &arg) == FAILURE) { zend_throw_exception(spl_ce_BadMethodCallException, "Function expects one argument at most", 0); @@ -1451,18 +1446,18 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam if (arg) { ZVAL_COPY_VALUE(¶ms[1], arg); } - aht->u.v.nApplyCount++; + intern->nApplyCount++; call_user_function_ex(EG(function_table), NULL, &function_name, return_value, arg ? 2 : 1, params, 1, NULL); - aht->u.v.nApplyCount--; + intern->nApplyCount--; } else { if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &arg) == FAILURE) { zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0); goto exit; } ZVAL_COPY_VALUE(¶ms[1], arg); - aht->u.v.nApplyCount++; + intern->nApplyCount++; call_user_function_ex(EG(function_table), NULL, &function_name, return_value, 2, params, 1, NULL); - aht->u.v.nApplyCount--; + intern->nApplyCount--; } exit: @@ -1515,7 +1510,7 @@ SPL_METHOD(Array, current) zval *object = getThis(); spl_array_object *intern = Z_SPLARRAY_P(object); zval *entry; - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); if (zend_parse_parameters_none() == FAILURE) { return; @@ -1553,7 +1548,7 @@ SPL_METHOD(Array, key) void spl_array_iterator_key(zval *object, zval *return_value) /* {{{ */ { spl_array_object *intern = Z_SPLARRAY_P(object); - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); if (spl_array_object_verify_pos(intern, aht) == FAILURE) { return; @@ -1569,7 +1564,7 @@ SPL_METHOD(Array, next) { zval *object = getThis(); spl_array_object *intern = Z_SPLARRAY_P(object); - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); if (zend_parse_parameters_none() == FAILURE) { return; @@ -1589,7 +1584,7 @@ SPL_METHOD(Array, valid) { zval *object = getThis(); spl_array_object *intern = Z_SPLARRAY_P(object); - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); if (zend_parse_parameters_none() == FAILURE) { return; @@ -1609,7 +1604,7 @@ SPL_METHOD(Array, hasChildren) { zval *object = getThis(), *entry; spl_array_object *intern = Z_SPLARRAY_P(object); - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); if (zend_parse_parameters_none() == FAILURE) { return; @@ -1633,7 +1628,7 @@ SPL_METHOD(Array, getChildren) { zval *object = getThis(), *entry, flags; spl_array_object *intern = Z_SPLARRAY_P(object); - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); if (zend_parse_parameters_none() == FAILURE) { return; @@ -1669,7 +1664,7 @@ SPL_METHOD(Array, serialize) { zval *object = getThis(); spl_array_object *intern = Z_SPLARRAY_P(object); - HashTable *aht = spl_array_get_hash_table(intern, 0); + HashTable *aht = spl_array_get_hash_table(intern); zval members, flags; php_serialize_data_t var_hash; smart_str buf = {0}; @@ -1728,7 +1723,6 @@ SPL_METHOD(Array, unserialize) const unsigned char *p, *s; php_unserialize_data_t var_hash; zval *members, *zflags; - HashTable *aht; zend_long flags; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &buf, &buf_len) == FAILURE) { @@ -1739,8 +1733,7 @@ SPL_METHOD(Array, unserialize) return; } - aht = spl_array_get_hash_table(intern, 0); - if (aht->u.v.nApplyCount > 0) { + if (intern->nApplyCount > 0) { zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited"); return; } @@ -1778,6 +1771,7 @@ SPL_METHOD(Array, unserialize) intern->ar_flags &= ~SPL_ARRAY_CLONE_MASK; intern->ar_flags |= flags & SPL_ARRAY_CLONE_MASK; zval_ptr_dtor(&intern->array); + ZVAL_UNDEF(&intern->array); if (!php_var_unserialize(&intern->array, &p, s + buf_len, &var_hash)) { goto outexcept; } diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 154a3c08d5..02b0450919 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -117,32 +117,34 @@ void spl_SplObjectStorage_free_storage(zend_object *object) /* {{{ */ } /* }}} */ -static zend_string *spl_object_storage_get_hash(spl_SplObjectStorage *intern, zval *this, zval *obj) { +static int spl_object_storage_get_hash(zend_hash_key *key, spl_SplObjectStorage *intern, zval *this, zval *obj) { if (intern->fptr_get_hash) { zval rv; zend_call_method_with_1_params(this, intern->std.ce, &intern->fptr_get_hash, "getHash", &rv, obj); if (!Z_ISUNDEF(rv)) { if (Z_TYPE(rv) == IS_STRING) { - return Z_STR(rv); + key->key = Z_STR(rv); + return SUCCESS; } else { zend_throw_exception(spl_ce_RuntimeException, "Hash needs to be a string", 0); zval_ptr_dtor(&rv); - return NULL; + return FAILURE; } } else { - return NULL; + return FAILURE; } } else { - zend_string *hash = zend_string_alloc(sizeof(zend_object*), 0); - memcpy(ZSTR_VAL(hash), (void*)&Z_OBJ_P(obj), sizeof(zend_object*)); - ZSTR_VAL(hash)[ZSTR_LEN(hash)] = '\0'; - return hash; + key->key = NULL; + key->h = Z_OBJ_HANDLE_P(obj); + return SUCCESS; } } -static void spl_object_storage_free_hash(spl_SplObjectStorage *intern, zend_string *hash) { - zend_string_release(hash); +static void spl_object_storage_free_hash(spl_SplObjectStorage *intern, zend_hash_key *key) { + if (key->key) { + zend_string_release(key->key); + } } static void spl_object_storage_dtor(zval *element) /* {{{ */ @@ -153,21 +155,24 @@ static void spl_object_storage_dtor(zval *element) /* {{{ */ efree(el); } /* }}} */ -spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, zend_string *hash) /* {{{ */ +static spl_SplObjectStorageElement* spl_object_storage_get(spl_SplObjectStorage *intern, zend_hash_key *key) /* {{{ */ { - return (spl_SplObjectStorageElement*)zend_hash_find_ptr(&intern->storage, hash); + if (key->key) { + return zend_hash_find_ptr(&intern->storage, key->key); + } else { + return zend_hash_index_find_ptr(&intern->storage, key->h); + } } /* }}} */ spl_SplObjectStorageElement *spl_object_storage_attach(spl_SplObjectStorage *intern, zval *this, zval *obj, zval *inf) /* {{{ */ { spl_SplObjectStorageElement *pelement, element; - zend_string *hash = spl_object_storage_get_hash(intern, this, obj); - - if (!hash) { + zend_hash_key key; + if (spl_object_storage_get_hash(&key, intern, this, obj) == FAILURE) { return NULL; } - pelement = spl_object_storage_get(intern, hash); + pelement = spl_object_storage_get(intern, &key); if (pelement) { zval_ptr_dtor(&pelement->inf); @@ -176,7 +181,7 @@ spl_SplObjectStorageElement *spl_object_storage_attach(spl_SplObjectStorage *int } else { ZVAL_NULL(&pelement->inf); } - spl_object_storage_free_hash(intern, hash); + spl_object_storage_free_hash(intern, &key); return pelement; } @@ -186,20 +191,28 @@ spl_SplObjectStorageElement *spl_object_storage_attach(spl_SplObjectStorage *int } else { ZVAL_NULL(&element.inf); } - pelement = zend_hash_update_mem(&intern->storage, hash, &element, sizeof(spl_SplObjectStorageElement)); - spl_object_storage_free_hash(intern, hash); + if (key.key) { + pelement = zend_hash_update_mem(&intern->storage, key.key, &element, sizeof(spl_SplObjectStorageElement)); + } else { + pelement = zend_hash_index_update_mem(&intern->storage, key.h, &element, sizeof(spl_SplObjectStorageElement)); + } + spl_object_storage_free_hash(intern, &key); return pelement; } /* }}} */ -int spl_object_storage_detach(spl_SplObjectStorage *intern, zval *this, zval *obj) /* {{{ */ +static int spl_object_storage_detach(spl_SplObjectStorage *intern, zval *this, zval *obj) /* {{{ */ { int ret = FAILURE; - zend_string *hash = spl_object_storage_get_hash(intern, this, obj); - if (!hash) { + zend_hash_key key; + if (spl_object_storage_get_hash(&key, intern, this, obj) == FAILURE) { return ret; } - ret = zend_hash_del(&intern->storage, hash); - spl_object_storage_free_hash(intern, hash); + if (key.key) { + ret = zend_hash_del(&intern->storage, key.key); + } else { + ret = zend_hash_index_del(&intern->storage, key.h); + } + spl_object_storage_free_hash(intern, &key); return ret; } /* }}}*/ @@ -369,13 +382,17 @@ static zend_object *spl_SplObjectStorage_new(zend_class_entry *class_type) int spl_object_storage_contains(spl_SplObjectStorage *intern, zval *this, zval *obj) /* {{{ */ { int found; - zend_string *hash = spl_object_storage_get_hash(intern, this, obj); - if (!hash) { + zend_hash_key key; + if (spl_object_storage_get_hash(&key, intern, this, obj) == FAILURE) { return 0; } - found = zend_hash_exists(&intern->storage, hash); - spl_object_storage_free_hash(intern, hash); + if (key.key) { + found = zend_hash_exists(&intern->storage, key.key); + } else { + found = zend_hash_index_exists(&intern->storage, key.h); + } + spl_object_storage_free_hash(intern, &key); return found; } /* }}} */ @@ -430,19 +447,18 @@ SPL_METHOD(SplObjectStorage, offsetGet) zval *obj; spl_SplObjectStorageElement *element; spl_SplObjectStorage *intern = Z_SPLOBJSTORAGE_P(getThis()); - zend_string *hash; + zend_hash_key key; if (zend_parse_parameters(ZEND_NUM_ARGS(), "o", &obj) == FAILURE) { return; } - hash = spl_object_storage_get_hash(intern, getThis(), obj); - if (!hash) { + if (spl_object_storage_get_hash(&key, intern, getThis(), obj) == FAILURE) { return; } - element = spl_object_storage_get(intern, hash); - spl_object_storage_free_hash(intern, hash); + element = spl_object_storage_get(intern, &key); + spl_object_storage_free_hash(intern, &key); if (!element) { zend_throw_exception_ex(spl_ce_UnexpectedValueException, 0, "Object not found"); @@ -774,7 +790,7 @@ SPL_METHOD(SplObjectStorage, unserialize) while (count-- > 0) { spl_SplObjectStorageElement *pelement; - zend_string *hash; + zend_hash_key key; if (*p != ';') { goto outexcept; @@ -801,14 +817,13 @@ SPL_METHOD(SplObjectStorage, unserialize) ZVAL_UNDEF(&inf); } - hash = spl_object_storage_get_hash(intern, getThis(), &entry); - if (!hash) { + if (spl_object_storage_get_hash(&key, intern, getThis(), &entry) == FAILURE) { zval_ptr_dtor(&entry); zval_ptr_dtor(&inf); goto outexcept; } - pelement = spl_object_storage_get(intern, hash); - spl_object_storage_free_hash(intern, hash); + pelement = spl_object_storage_get(intern, &key); + spl_object_storage_free_hash(intern, &key); if (pelement) { if (!Z_ISUNDEF(pelement->inf)) { var_push_dtor(&var_hash, &pelement->inf); @@ -821,7 +836,9 @@ SPL_METHOD(SplObjectStorage, unserialize) var_replace(&var_hash, &entry, &element->obj); var_replace(&var_hash, &inf, &element->inf); zval_ptr_dtor(&entry); + ZVAL_UNDEF(&entry); zval_ptr_dtor(&inf); + ZVAL_UNDEF(&inf); } if (*p != ';') { diff --git a/ext/spl/tests/ArrayObject_clone_other_std_props.phpt b/ext/spl/tests/ArrayObject_clone_other_std_props.phpt new file mode 100644 index 0000000000..688954c3d7 --- /dev/null +++ b/ext/spl/tests/ArrayObject_clone_other_std_props.phpt @@ -0,0 +1,23 @@ +--TEST-- +Clone ArrayObject using other with STD_PROP_LIST +--FILE-- +<?php + +$a = new ArrayObject([1, 2, 3], ArrayObject::STD_PROP_LIST); +$b = new ArrayObject($a); +$c = clone $b; +var_dump($c); + +?> +--EXPECT-- +object(ArrayObject)#3 (1) { + ["storage":"ArrayObject":private]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} diff --git a/ext/spl/tests/ArrayObject_dump_during_sort.phpt b/ext/spl/tests/ArrayObject_dump_during_sort.phpt new file mode 100644 index 0000000000..0fb128b655 --- /dev/null +++ b/ext/spl/tests/ArrayObject_dump_during_sort.phpt @@ -0,0 +1,27 @@ +--TEST-- +Dumping an ArrayObject while it is being sorted +--FILE-- +<?php + +$ao = new ArrayObject([1, 2, 3]); +$i = 0; +$ao->uasort(function($a, $b) use ($ao, &$i) { + if ($i++ == 0) { + var_dump($ao); + } + return $a <=> $b; +}); + +?> +--EXPECT-- +object(ArrayObject)#1 (1) { + ["storage":"ArrayObject":private]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} diff --git a/ext/spl/tests/ArrayObject_exchange_array_during_sorting.phpt b/ext/spl/tests/ArrayObject_exchange_array_during_sorting.phpt new file mode 100644 index 0000000000..225d42c1ed --- /dev/null +++ b/ext/spl/tests/ArrayObject_exchange_array_during_sorting.phpt @@ -0,0 +1,29 @@ +--TEST-- +Can't use exchangeArray() while ArrayObject is being sorted +--FILE-- +<?php + +$ao = new ArrayObject([1, 2, 3]); +$i = 0; +$ao->uasort(function($a, $b) use ($ao, &$i) { + if ($i++ == 0) { + $ao->exchangeArray([4, 5, 6]); + var_dump($ao); + } + return $a <=> $b; +}); + +?> +--EXPECTF-- +Warning: Modification of ArrayObject during sorting is prohibited in %s on line %d +object(ArrayObject)#1 (1) { + ["storage":"ArrayObject":private]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} diff --git a/ext/spl/tests/ArrayObject_illegal_offset_leak.phpt b/ext/spl/tests/ArrayObject_illegal_offset_leak.phpt new file mode 100644 index 0000000000..42c649db9f --- /dev/null +++ b/ext/spl/tests/ArrayObject_illegal_offset_leak.phpt @@ -0,0 +1,11 @@ +--TEST-- +Assignments to illegal ArrayObject offsets shouldn't leak +--FILE-- +<?php + +$ao = new ArrayObject([1, 2, 3]); +$ao[[]] = new stdClass; + +?> +--EXPECTF-- +Warning: Illegal offset type in %s on line %d diff --git a/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt b/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt new file mode 100644 index 0000000000..24c247cabd --- /dev/null +++ b/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt @@ -0,0 +1,19 @@ +--TEST-- +Modifications to ArrayObjects should not affect shared properties tables +--FILE-- +<?php + +$obj = (object)['a' => 1, 'b' => 2]; +$ao = new ArrayObject($obj); +$arr = (array) $obj; +$ao['a'] = 42; +var_dump($arr); + +?> +--EXPECT-- +array(2) { + ["a"]=> + int(1) + ["b"]=> + int(2) +} diff --git a/ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt b/ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt new file mode 100644 index 0000000000..8c1121b8d0 --- /dev/null +++ b/ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt @@ -0,0 +1,27 @@ +--TEST-- +Objects with overloaded get_properties are incompatible with ArrayObject +--FILE-- +<?php + +$ao = new ArrayObject([1, 2, 3]); +try { + $ao->exchangeArray(new SplFixedArray); +} catch (Exception $e) { + echo $e->getMessage(), "\n"; +} +var_dump($ao); + +?> +--EXPECT-- +Overloaded object of type SplFixedArray is not compatible with ArrayObject +object(ArrayObject)#1 (1) { + ["storage":"ArrayObject":private]=> + array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) + } +} diff --git a/ext/spl/tests/ArrayObject_std_props_no_recursion.phpt b/ext/spl/tests/ArrayObject_std_props_no_recursion.phpt new file mode 100644 index 0000000000..193e972530 --- /dev/null +++ b/ext/spl/tests/ArrayObject_std_props_no_recursion.phpt @@ -0,0 +1,28 @@ +--TEST-- +Don't recurse into USE_OTHER when checking for STD_PROP_LIST +--FILE-- +<?php + +$a = new ArrayObject([1, 2, 3], ArrayObject::STD_PROP_LIST); +$a->prop = 'a'; +$b = new ArrayObject($a, 0); +$b->prop = 'b'; +var_dump((array) $b); +$c = new ArrayObject($a); +$c->prop = 'c'; +var_dump((array) $c); + +?> +--EXPECT-- +array(3) { + [0]=> + int(1) + [1]=> + int(2) + [2]=> + int(3) +} +array(1) { + ["prop"]=> + string(1) "c" +} diff --git a/ext/spl/tests/bug71617.phpt b/ext/spl/tests/bug71617.phpt new file mode 100644 index 0000000000..412f83f541 --- /dev/null +++ b/ext/spl/tests/bug71617.phpt @@ -0,0 +1,50 @@ +--TEST-- +Bug #71617: private properties lost when unserializing ArrayObject +--FILE-- +<?php + +class Test extends ArrayObject +{ + + private $name = null; + + public function __construct(array $input) + { + parent::__construct($input, ArrayObject::ARRAY_AS_PROPS); + } + + public function setName($name) + { + $this->name = $name; + return $this; + } + + public function getName() + { + return $this->name; + } +} + +$test = new Test(['a' => 'a', 'b' => 'b']); +$test->setName('ok'); + +$ser = serialize($test); +$unSer = unserialize($ser); + +var_dump($unSer->getName()); +var_dump($unSer); + +?> +--EXPECT-- +string(2) "ok" +object(Test)#2 (2) { + ["name":"Test":private]=> + string(2) "ok" + ["storage":"ArrayObject":private]=> + array(2) { + ["a"]=> + string(1) "a" + ["b"]=> + string(1) "b" + } +} diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 6f2656ab51..6416d03e89 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -117,20 +117,13 @@ PHP_METHOD(sqlite3, open) if (strlen(filename) != filename_len) { return; } - if (memcmp(filename, ":memory:", sizeof(":memory:")) != 0) { + if (filename_len != sizeof(":memory:")-1 || + memcmp(filename, ":memory:", sizeof(":memory:")-1) != 0) { if (!(fullpath = expand_filepath(filename, NULL))) { zend_throw_exception(zend_ce_exception, "Unable to expand filepath", 0); return; } -#if PHP_API_VERSION < 20100412 - if (PG(safe_mode) && (!php_checkuid(fullpath, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { - zend_throw_exception_ex(zend_ce_exception, 0, "safe_mode prohibits opening %s", fullpath); - efree(fullpath); - return; - } -#endif - if (php_check_open_basedir(fullpath)) { zend_throw_exception_ex(zend_ce_exception, 0, "open_basedir prohibits opening %s", fullpath); efree(fullpath); @@ -163,11 +156,7 @@ PHP_METHOD(sqlite3, open) db_obj->initialised = 1; -#if PHP_API_VERSION < 20100412 - if (PG(safe_mode) || (PG(open_basedir) && *PG(open_basedir))) { -#else if (PG(open_basedir) && *PG(open_basedir)) { -#endif sqlite3_set_authorizer(db_obj->db, php_sqlite3_authorizer, NULL); } @@ -1980,13 +1969,6 @@ static int php_sqlite3_authorizer(void *autharg, int access_type, const char *ar case SQLITE_ATTACH: { if (memcmp(arg3, ":memory:", sizeof(":memory:")) && *arg3) { - -#if PHP_API_VERSION < 20100412 - if (PG(safe_mode) && (!php_checkuid(arg3, NULL, CHECKUID_CHECK_FILE_AND_DIR))) { - return SQLITE_DENY; - } -#endif - if (php_check_open_basedir(arg3)) { return SQLITE_DENY; } diff --git a/ext/standard/array.c b/ext/standard/array.c index 30ca0508a9..3e9ecdfd46 100644 --- a/ext/standard/array.c +++ b/ext/standard/array.c @@ -46,9 +46,7 @@ #include "php_string.h" #include "php_rand.h" #include "zend_smart_str.h" -#ifdef HAVE_SPL #include "ext/spl/spl_array.h" -#endif /* {{{ defines */ #define EXTR_OVERWRITE 0 @@ -81,8 +79,6 @@ #define INTERSECT_COMP_DATA_USER 1 #define INTERSECT_COMP_KEY_INTERNAL 0 #define INTERSECT_COMP_KEY_USER 1 - -#define DOUBLE_DRIFT_FIX 0.000000000000001 /* }}} */ ZEND_DECLARE_MODULE_GLOBALS(array) @@ -272,7 +268,7 @@ static int php_array_key_compare_string(const void *a, const void *b) /* {{{ */ l2 = s->key->len; } else { s2 = zend_print_long_to_buf(buf2 + sizeof(buf2) - 1, s->h); - l2 = buf2 + sizeof(buf2) - 1 - s1; + l2 = buf2 + sizeof(buf2) - 1 - s2; } return zend_binary_strcmp(s1, l1, s2, l2); } @@ -823,9 +819,7 @@ PHP_FUNCTION(count) RETURN_LONG(cnt); break; case IS_OBJECT: { -#ifdef HAVE_SPL zval retval; -#endif /* first, we check if the handler is defined */ if (Z_OBJ_HT_P(array)->count_elements) { RETVAL_LONG(1); @@ -833,7 +827,6 @@ PHP_FUNCTION(count) return; } } -#ifdef HAVE_SPL /* if not and the object implements Countable we call its count() method */ if (instanceof_function(Z_OBJCE_P(array), spl_ce_Countable)) { zend_call_method_with_0_params(array, NULL, NULL, "count", &retval); @@ -843,7 +836,6 @@ PHP_FUNCTION(count) } return; } -#endif } default: RETURN_LONG(1); @@ -1773,7 +1765,7 @@ PHPAPI int php_prefix_varname(zval *result, zval *prefix, char *var_name, size_t Imports variables into symbol table from an array */ PHP_FUNCTION(extract) { - zval *var_array, *prefix = NULL; + zval *var_array_param, *prefix = NULL; zend_long extract_type = EXTR_OVERWRITE; zval *entry; zend_string *var_name; @@ -1781,14 +1773,15 @@ PHP_FUNCTION(extract) int var_exists, count = 0; int extract_refs = 0; zend_array *symbol_table; + zval var_array; #ifndef FAST_ZPP - if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|lz/", &var_array, &extract_type, &prefix) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|lz/", &var_array_param, &extract_type, &prefix) == FAILURE) { return; } #else ZEND_PARSE_PARAMETERS_START(1, 3) - Z_PARAM_ARRAY(var_array) + Z_PARAM_ARRAY(var_array_param) Z_PARAM_OPTIONAL Z_PARAM_LONG(extract_type) Z_PARAM_ZVAL_EX(prefix, 0, 1) @@ -1797,7 +1790,7 @@ PHP_FUNCTION(extract) extract_refs = (extract_type & EXTR_REFS); if (extract_refs) { - SEPARATE_ZVAL(var_array); + SEPARATE_ZVAL(var_array_param); } extract_type &= 0xff; @@ -1827,7 +1820,11 @@ PHP_FUNCTION(extract) } #endif - ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(var_array), num_key, var_name, entry) { + /* The array might be stored in a local variable that will be overwritten. To avoid losing the + * reference in that case we work on a copy. */ + ZVAL_COPY(&var_array, var_array_param); + + ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(var_array), num_key, var_name, entry) { zval final_name; ZVAL_NULL(&final_name); @@ -1928,6 +1925,7 @@ PHP_FUNCTION(extract) } zval_dtor(&final_name); } ZEND_HASH_FOREACH_END(); + zval_ptr_dtor(&var_array); RETURN_LONG(count); } @@ -1940,6 +1938,7 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu ZVAL_DEREF(entry); if (Z_TYPE_P(entry) == IS_STRING) { if ((value_ptr = zend_hash_find_ind(eg_active_symbol_table, Z_STR_P(entry))) != NULL) { + ZVAL_DEREF(value_ptr); ZVAL_COPY(&data, value_ptr); zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data); } @@ -2061,13 +2060,25 @@ PHP_FUNCTION(array_fill_keys) } /* }}} */ -#define RANGE_CHECK_INIT_ARRAY(start, end) do { \ +#define RANGE_CHECK_DOUBLE_INIT_ARRAY(start, end) do { \ double __calc_size = ((start - end) / step) + 1; \ - if (fabs(__calc_size) >= (double)HT_MAX_SIZE) { \ - php_error_docref(NULL, E_WARNING, "The supplied range exceeds the maximum array size: start=%0.0f end=%0.0f", start > end ? end : start, start > end ? start : end); \ + if (__calc_size >= (double)HT_MAX_SIZE) { \ + php_error_docref(NULL, E_WARNING, "The supplied range exceeds the maximum array size: start=%0.0f end=%0.0f", end, start); \ + RETURN_FALSE; \ + } \ + size = (uint32_t)__calc_size; \ + array_init_size(return_value, size); \ + zend_hash_real_init(Z_ARRVAL_P(return_value), 1); \ + } while (0) + +#define RANGE_CHECK_LONG_INIT_ARRAY(start, end) do { \ + zend_ulong __calc_size = (start - end) / lstep; \ + if (__calc_size >= HT_MAX_SIZE - 1) { \ + php_error_docref(NULL, E_WARNING, "The supplied range exceeds the maximum array size: start=%pd end=%pd", end, start); \ RETURN_FALSE; \ } \ - array_init_size(return_value, (uint32_t)fabs(__calc_size)); \ + size = (uint32_t)(__calc_size + 1); \ + array_init_size(return_value, size); \ zend_hash_real_init(Z_ARRVAL_P(return_value), 1); \ } while (0) @@ -2167,12 +2178,11 @@ PHP_FUNCTION(range) zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); } } else if (Z_TYPE_P(zlow) == IS_DOUBLE || Z_TYPE_P(zhigh) == IS_DOUBLE || is_step_double) { - double low, high, value; - zend_long i; + double low, high; + uint32_t i, size; double_str: low = zval_get_double(zlow); high = zval_get_double(zhigh); - i = 0; if (zend_isinf(high) || zend_isinf(low)) { php_error_docref(NULL, E_WARNING, "Invalid range supplied: start=%0.0f end=%0.0f", low, high); @@ -2186,12 +2196,13 @@ double_str: goto err; } - RANGE_CHECK_INIT_ARRAY(low, high); + RANGE_CHECK_DOUBLE_INIT_ARRAY(low, high); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - for (value = low; value >= (high - DOUBLE_DRIFT_FIX); value = low - (++i * step)) { - Z_DVAL(tmp) = value; - ZEND_HASH_FILL_ADD(&tmp); - } + for (i = 0; i < size; ++i) { + Z_DVAL(tmp) = low - (i * step); + ZEND_HASH_FILL_ADD(&tmp); + } } ZEND_HASH_FILL_END(); } else if (high > low) { /* Positive steps */ if (high - low < step || step <= 0) { @@ -2199,10 +2210,11 @@ double_str: goto err; } - RANGE_CHECK_INIT_ARRAY(high, low); + RANGE_CHECK_DOUBLE_INIT_ARRAY(high, low); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - for (value = low; value <= (high + DOUBLE_DRIFT_FIX); value = low + (++i * step)) { - Z_DVAL(tmp) = value; + for (i = 0; i < size; ++i) { + Z_DVAL(tmp) = low + (i * step); ZEND_HASH_FILL_ADD(&tmp); } } ZEND_HASH_FILL_END(); @@ -2212,43 +2224,53 @@ double_str: zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); } } else { - double low, high; - zend_long lstep; + zend_long low, high; + /* lstep is a ulong so that comparisons to it don't overflow, i.e. low - high < lstep */ + zend_ulong lstep; + uint32_t i, size; long_str: - low = zval_get_double(zlow); - high = zval_get_double(zhigh); - lstep = (zend_long) step; + low = zval_get_long(zlow); + high = zval_get_long(zhigh); + + if (step <= 0) { + err = 1; + goto err; + } + + lstep = step; Z_TYPE_INFO(tmp) = IS_LONG; if (low > high) { /* Negative steps */ - if (low - high < lstep || lstep <= 0) { + if (low - high < lstep) { err = 1; goto err; } - RANGE_CHECK_INIT_ARRAY(low, high); + RANGE_CHECK_LONG_INIT_ARRAY(low, high); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - for (; low >= high; low -= lstep) { - Z_LVAL(tmp) = (zend_long)low; + for (i = 0; i < size; ++i) { + Z_LVAL(tmp) = low - (i * lstep); ZEND_HASH_FILL_ADD(&tmp); } } ZEND_HASH_FILL_END(); } else if (high > low) { /* Positive steps */ - if (high - low < lstep || lstep <= 0) { + if (high - low < lstep) { err = 1; goto err; } - RANGE_CHECK_INIT_ARRAY(high, low); + RANGE_CHECK_LONG_INIT_ARRAY(high, low); + ZEND_HASH_FILL_PACKED(Z_ARRVAL_P(return_value)) { - for (; low <= high; low += lstep) { - Z_LVAL(tmp) = (zend_long)low; + for (i = 0; i < size; ++i) { + Z_LVAL(tmp) = low + (i * lstep); ZEND_HASH_FILL_ADD(&tmp); } } ZEND_HASH_FILL_END(); } else { array_init(return_value); - Z_LVAL(tmp) = (zend_long)low; + Z_LVAL(tmp) = low; zend_hash_next_index_insert_new(Z_ARRVAL_P(return_value), &tmp); } } @@ -2260,7 +2282,8 @@ err: } /* }}} */ -#undef RANGE_CHECK_INIT_ARRAY +#undef RANGE_CHECK_DOUBLE_INIT_ARRAY +#undef RANGE_CHECK_LONG_INIT_ARRAY static void php_array_data_shuffle(zval *array) /* {{{ */ { @@ -3469,6 +3492,10 @@ static inline zval *array_column_fetch_prop(zval *data, zval *name, zval *rv) } } + if (prop) { + ZVAL_DEREF(prop); + } + return prop; } diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c index f03793c13f..f8121c1ebf 100644 --- a/ext/standard/basic_functions.c +++ b/ext/standard/basic_functions.c @@ -3493,8 +3493,8 @@ PHPAPI double php_get_nan(void) /* {{{ */ return HUGE_VAL + -HUGE_VAL; #elif defined(__i386__) || defined(_X86_) || defined(ALPHA) || defined(_ALPHA) || defined(__alpha) double val = 0.0; - ((php_uint32*)&val)[1] = PHP_DOUBLE_QUIET_NAN_HIGH; - ((php_uint32*)&val)[0] = 0; + ((uint32_t*)&val)[1] = PHP_DOUBLE_QUIET_NAN_HIGH; + ((uint32_t*)&val)[0] = 0; return val; #elif HAVE_ATOF_ACCEPTS_NAN return atof("NAN"); @@ -3510,8 +3510,8 @@ PHPAPI double php_get_inf(void) /* {{{ */ return HUGE_VAL; #elif defined(__i386__) || defined(_X86_) || defined(ALPHA) || defined(_ALPHA) || defined(__alpha) double val = 0.0; - ((php_uint32*)&val)[1] = PHP_DOUBLE_INFINITY_HIGH; - ((php_uint32*)&val)[0] = 0; + ((uint32_t*)&val)[1] = PHP_DOUBLE_INFINITY_HIGH; + ((uint32_t*)&val)[0] = 0; return val; #elif HAVE_ATOF_ACCEPTS_INF return atof("INF"); @@ -3659,6 +3659,7 @@ PHP_MINIT_FUNCTION(basic) /* {{{ */ #ifdef PHP_CAN_SUPPORT_PROC_OPEN BASIC_MINIT_SUBMODULE(proc_open) #endif + BASIC_MINIT_SUBMODULE(exec) BASIC_MINIT_SUBMODULE(user_streams) BASIC_MINIT_SUBMODULE(imagetypes) @@ -4839,7 +4840,7 @@ PHP_FUNCTION(forward_static_call) fci.retval = &retval; called_scope = zend_get_called_scope(execute_data); - if (called_scope && + if (called_scope && fci_cache.calling_scope && instanceof_function(called_scope, fci_cache.calling_scope)) { fci_cache.called_scope = called_scope; } @@ -4867,7 +4868,7 @@ PHP_FUNCTION(forward_static_call_array) fci.retval = &retval; called_scope = zend_get_called_scope(execute_data); - if (called_scope && + if (called_scope && fci_cache.calling_scope && instanceof_function(called_scope, fci_cache.calling_scope)) { fci_cache.called_scope = called_scope; } diff --git a/ext/standard/basic_functions.h b/ext/standard/basic_functions.h index 774f85dd1a..e37bca31d6 100644 --- a/ext/standard/basic_functions.h +++ b/ext/standard/basic_functions.h @@ -149,20 +149,12 @@ PHPAPI int _php_error_log(int opt_err, char *message, char *opt, char *headers); PHPAPI int _php_error_log_ex(int opt_err, char *message, size_t message_len, char *opt, char *headers); PHPAPI int php_prefix_varname(zval *result, zval *prefix, char *var_name, size_t var_name_len, zend_bool add_underscore); -#if SIZEOF_INT == 4 -/* Most 32-bit and 64-bit systems have 32-bit ints */ -typedef unsigned int php_uint32; -typedef signed int php_int32; -#elif SIZEOF_LONG == 4 -/* 16-bit systems? */ -typedef unsigned long php_uint32; -typedef signed long php_int32; -#else -#error Need type which holds 32 bits -#endif - #define MT_N (624) +/* Deprecated type aliases -- use the standard types instead */ +typedef uint32_t php_uint32; +typedef int32_t php_int32; + typedef struct _php_basic_globals { HashTable *user_shutdown_function_names; HashTable putenv_ht; @@ -193,8 +185,8 @@ typedef struct _php_basic_globals { php_stream_statbuf ssb, lssb; /* rand.c */ - php_uint32 state[MT_N+1]; /* state vector + 1 extra to not violate ANSI C */ - php_uint32 *next; /* next random value is computed from here */ + uint32_t state[MT_N+1]; /* state vector + 1 extra to not violate ANSI C */ + uint32_t *next; /* next random value is computed from here */ int left; /* can *next++ this many times before reloading */ unsigned int rand_seed; /* Seed for rand(), in ts version */ diff --git a/ext/standard/crc32.c b/ext/standard/crc32.c index 45a2eb0667..e6024dcf11 100644 --- a/ext/standard/crc32.c +++ b/ext/standard/crc32.c @@ -28,8 +28,8 @@ PHP_NAMED_FUNCTION(php_if_crc32) { char *p; size_t nr; - php_uint32 crcinit = 0; - register php_uint32 crc; + uint32_t crcinit = 0; + register uint32_t crc; if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &p, &nr) == FAILURE) { return; diff --git a/ext/standard/exec.c b/ext/standard/exec.c index c4afce3337..a73d0b4e6e 100644 --- a/ext/standard/exec.c +++ b/ext/standard/exec.c @@ -46,10 +46,43 @@ #include <fcntl.h> #endif -#if HAVE_NICE && HAVE_UNISTD_H +#if HAVE_UNISTD_H #include <unistd.h> #endif +#if HAVE_LIMITS_H +#include <limits.h> +#endif + +static int cmd_max_len; + +/* {{{ PHP_MINIT_FUNCTION(exec) */ +PHP_MINIT_FUNCTION(exec) +{ +#ifdef _SC_ARG_MAX + cmd_max_len = sysconf(_SC_ARG_MAX); + if (-1 == cmd_max_len) { +#ifdef _POSIX_ARG_MAX + cmd_max_len = _POSIX_ARG_MAX; +#else + cmd_max_len = 4096; +#endif + } +#elif defined(ARG_MAX) + cmd_max_len = ARG_MAX; +#elif defined(PHP_WIN32) + /* Executed commands will run through cmd.exe. As long as it's the case, + it's just the constant limit.*/ + cmd_max_len = 8192; +#else + /* This is just an arbitrary value for the fallback case. */ + cmd_max_len = 4096; +#endif + + return SUCCESS; +} +/* }}} */ + /* {{{ php_exec * If type==0, only last line of output is returned (exec) * If type==1, all lines will be printed and last lined returned (system) @@ -245,13 +278,19 @@ PHP_FUNCTION(passthru) */ PHPAPI zend_string *php_escape_shell_cmd(char *str) { - register int x, y, l = (int)strlen(str); - size_t estimate = (2 * l) + 1; + register int x, y; + size_t l = strlen(str); + uint64_t estimate = (2 * (uint64_t)l) + 1; zend_string *cmd; #ifndef PHP_WIN32 char *p = NULL; #endif + /* max command line length - two single quotes - \0 byte length */ + if (l > cmd_max_len - 2 - 1) { + php_error_docref(NULL, E_ERROR, "Command exceeds the allowed length of %d bytes", cmd_max_len); + return ZSTR_EMPTY_ALLOC(); + } cmd = zend_string_safe_alloc(2, l, 0, 0); @@ -324,6 +363,12 @@ PHPAPI zend_string *php_escape_shell_cmd(char *str) } ZSTR_VAL(cmd)[y] = '\0'; + if (y - 1 > cmd_max_len) { + php_error_docref(NULL, E_ERROR, "Escaped command exceeds the allowed length of %d bytes", cmd_max_len); + zend_string_release(cmd); + return ZSTR_EMPTY_ALLOC(); + } + if ((estimate - y) > 4096) { /* realloc if the estimate was way overill * Arbitrary cutoff point of 4096 */ @@ -340,10 +385,16 @@ PHPAPI zend_string *php_escape_shell_cmd(char *str) */ PHPAPI zend_string *php_escape_shell_arg(char *str) { - int x, y = 0, l = (int)strlen(str); + int x, y = 0; + size_t l = strlen(str); zend_string *cmd; - size_t estimate = (4 * l) + 3; + uint64_t estimate = (4 * (uint64_t)l) + 3; + /* max command line length - two single quotes - \0 byte length */ + if (l > cmd_max_len - 2 - 1) { + php_error_docref(NULL, E_ERROR, "Argument exceeds the allowed length of %d bytes", cmd_max_len); + return ZSTR_EMPTY_ALLOC(); + } cmd = zend_string_safe_alloc(4, l, 2, 0); /* worst case */ @@ -399,6 +450,12 @@ PHPAPI zend_string *php_escape_shell_arg(char *str) #endif ZSTR_VAL(cmd)[y] = '\0'; + if (y - 1 > cmd_max_len) { + php_error_docref(NULL, E_ERROR, "Escaped argument exceeds the allowed length of %d bytes", cmd_max_len); + zend_string_release(cmd); + return ZSTR_EMPTY_ALLOC(); + } + if ((estimate - y) > 4096) { /* realloc if the estimate was way overill * Arbitrary cutoff point of 4096 */ @@ -421,6 +478,10 @@ PHP_FUNCTION(escapeshellcmd) } if (command_len) { + if (command_len != strlen(command)) { + php_error_docref(NULL, E_ERROR, "Input string contains NULL bytes"); + return; + } RETVAL_STR(php_escape_shell_cmd(command)); } else { RETVAL_EMPTY_STRING(); @@ -440,6 +501,10 @@ PHP_FUNCTION(escapeshellarg) } if (argument) { + if (argument_len != strlen(argument)) { + php_error_docref(NULL, E_ERROR, "Input string contains NULL bytes"); + return; + } RETVAL_STR(php_escape_shell_arg(argument)); } } diff --git a/ext/standard/exec.h b/ext/standard/exec.h index e53abf8145..b1cbf29c13 100644 --- a/ext/standard/exec.h +++ b/ext/standard/exec.h @@ -33,6 +33,7 @@ PHP_FUNCTION(proc_close); PHP_FUNCTION(proc_terminate); PHP_FUNCTION(proc_nice); PHP_MINIT_FUNCTION(proc_open); +PHP_MINIT_FUNCTION(exec); PHPAPI zend_string *php_escape_shell_cmd(char *); PHPAPI zend_string *php_escape_shell_arg(char *); diff --git a/ext/standard/incomplete_class.c b/ext/standard/incomplete_class.c index 887f209299..d327602e75 100644 --- a/ext/standard/incomplete_class.c +++ b/ext/standard/incomplete_class.c @@ -54,7 +54,8 @@ static zval *incomplete_class_get_property(zval *object, zval *member, int type, incomplete_class_message(object, E_NOTICE); if (type == BP_VAR_W || type == BP_VAR_RW) { - return &EG(error_zval); + ZVAL_ERROR(rv); + return rv; } else { return &EG(uninitialized_zval); } diff --git a/ext/standard/iptc.c b/ext/standard/iptc.c index a3547067f6..7e5a8987b4 100644 --- a/ext/standard/iptc.c +++ b/ext/standard/iptc.c @@ -38,6 +38,15 @@ #include <sys/stat.h> +#ifdef PHP_WIN32 +# include "win32/php_stdint.h" +#else +# if HAVE_INTTYPES_H +# include <inttypes.h> +# elif HAVE_STDINT_H +# include <stdint.h> +# endif +#endif /* some defines for the different JPEG block types */ #define M_SOF0 0xC0 /* Start Of Frame N */ @@ -196,6 +205,11 @@ PHP_FUNCTION(iptcembed) RETURN_FALSE; } + if (iptcdata_len >= SIZE_MAX - sizeof(psheader) - 1025) { + php_error_docref(NULL, E_WARNING, "IPTC data too large"); + RETURN_FALSE; + } + if ((fp = VCWD_FOPEN(jpeg_file, "rb")) == 0) { php_error_docref(NULL, E_WARNING, "Unable to open %s", jpeg_file); RETURN_FALSE; @@ -204,7 +218,7 @@ PHP_FUNCTION(iptcembed) if (spool < 2) { zend_fstat(fileno(fp), &sb); - spoolbuf = zend_string_alloc(iptcdata_len + sizeof(psheader) + sb.st_size + 1024, 0); + spoolbuf = zend_string_safe_alloc(1, iptcdata_len + sizeof(psheader) + 1024 + 1, sb.st_size, 0); poi = (unsigned char*)ZSTR_VAL(spoolbuf); memset(poi, 0, iptcdata_len + sizeof(psheader) + sb.st_size + 1024 + 1); } diff --git a/ext/standard/lcg.c b/ext/standard/lcg.c index 9f40aba3e2..74b46eadd2 100644 --- a/ext/standard/lcg.c +++ b/ext/standard/lcg.c @@ -54,8 +54,8 @@ static void lcg_seed(void); PHPAPI double php_combined_lcg(void) /* {{{ */ { - php_int32 q; - php_int32 z; + int32_t q; + int32_t z; if (!LCG(seeded)) { lcg_seed(); diff --git a/ext/standard/math.c b/ext/standard/math.c index 7ea8dc1199..ebfee8ead8 100644 --- a/ext/standard/math.c +++ b/ext/standard/math.c @@ -146,6 +146,7 @@ PHPAPI double _php_math_round(double value, int places, int mode) { return value; } + places = places < INT_MIN+1 ? INT_MIN+1 : places; precision_places = 14 - php_intlog10abs(value); f1 = php_intpow10(abs(places)); @@ -154,8 +155,10 @@ PHPAPI double _php_math_round(double value, int places, int mode) { the requested places BUT is small enough to make sure a non-zero value is returned, pre-round the result to the precision */ if (precision_places > places && precision_places - places < 15) { - f2 = php_intpow10(abs(precision_places)); - if (precision_places >= 0) { + int64_t use_precision = precision_places < INT_MIN+1 ? INT_MIN+1 : precision_places; + + f2 = php_intpow10(abs((int)use_precision)); + if (use_precision >= 0) { tmp_value = value * f2; } else { tmp_value = value / f2; @@ -163,8 +166,11 @@ PHPAPI double _php_math_round(double value, int places, int mode) { /* preround the result (tmp_value will always be something * 1e14, thus never larger than 1e15 here) */ tmp_value = php_round_helper(tmp_value, mode); + + use_precision = places - precision_places; + use_precision = use_precision < INT_MIN+1 ? INT_MIN+1 : use_precision; /* now correctly move the decimal point */ - f2 = php_intpow10(abs(places - precision_places)); + f2 = php_intpow10(abs((int)use_precision)); /* because places < precision_places */ tmp_value = tmp_value / f2; } else { diff --git a/ext/standard/md5.c b/ext/standard/md5.c index 2489b9971a..825df21c69 100644 --- a/ext/standard/md5.c +++ b/ext/standard/md5.c @@ -169,16 +169,16 @@ PHP_NAMED_FUNCTION(php_if_md5_file) */ #if defined(__i386__) || defined(__x86_64__) || defined(__vax__) # define SET(n) \ - (*(php_uint32 *)&ptr[(n) * 4]) + (*(uint32_t *)&ptr[(n) * 4]) # define GET(n) \ SET(n) #else # define SET(n) \ (ctx->block[(n)] = \ - (php_uint32)ptr[(n) * 4] | \ - ((php_uint32)ptr[(n) * 4 + 1] << 8) | \ - ((php_uint32)ptr[(n) * 4 + 2] << 16) | \ - ((php_uint32)ptr[(n) * 4 + 3] << 24)) + (uint32_t)ptr[(n) * 4] | \ + ((uint32_t)ptr[(n) * 4 + 1] << 8) | \ + ((uint32_t)ptr[(n) * 4 + 2] << 16) | \ + ((uint32_t)ptr[(n) * 4 + 3] << 24)) # define GET(n) \ (ctx->block[(n)]) #endif @@ -190,8 +190,8 @@ PHP_NAMED_FUNCTION(php_if_md5_file) static const void *body(PHP_MD5_CTX *ctx, const void *data, size_t size) { const unsigned char *ptr; - php_uint32 a, b, c, d; - php_uint32 saved_a, saved_b, saved_c, saved_d; + uint32_t a, b, c, d; + uint32_t saved_a, saved_b, saved_c, saved_d; ptr = data; @@ -307,8 +307,8 @@ PHPAPI void PHP_MD5Init(PHP_MD5_CTX *ctx) PHPAPI void PHP_MD5Update(PHP_MD5_CTX *ctx, const void *data, size_t size) { - php_uint32 saved_lo; - php_uint32 used, free; + uint32_t saved_lo; + uint32_t used, free; saved_lo = ctx->lo; if ((ctx->lo = (saved_lo + size) & 0x1fffffff) < saved_lo) { @@ -342,7 +342,7 @@ PHPAPI void PHP_MD5Update(PHP_MD5_CTX *ctx, const void *data, size_t size) PHPAPI void PHP_MD5Final(unsigned char *result, PHP_MD5_CTX *ctx) { - php_uint32 used, free; + uint32_t used, free; used = ctx->lo & 0x3f; diff --git a/ext/standard/md5.h b/ext/standard/md5.h index 4210483864..5acd83ecbe 100644 --- a/ext/standard/md5.h +++ b/ext/standard/md5.h @@ -42,10 +42,10 @@ PHP_NAMED_FUNCTION(php_if_md5_file); /* MD5 context. */ typedef struct { - php_uint32 lo, hi; - php_uint32 a, b, c, d; + uint32_t lo, hi; + uint32_t a, b, c, d; unsigned char buffer[64]; - php_uint32 block[16]; + uint32_t block[16]; } PHP_MD5_CTX; PHPAPI void PHP_MD5Init(PHP_MD5_CTX *ctx); diff --git a/ext/standard/pack.c b/ext/standard/pack.c index ab7e9c71dc..a24ee69ad2 100644 --- a/ext/standard/pack.c +++ b/ext/standard/pack.c @@ -986,7 +986,7 @@ PHP_FUNCTION(unpack) /* Reached end of input for '*' repeater */ break; } else { - php_error_docref(NULL, E_WARNING, "Type %c: not enough input, need %d, have %d", type, size, inputlen - inputpos); + php_error_docref(NULL, E_WARNING, "Type %c: not enough input, need %d, have " ZEND_LONG_FMT, type, size, inputlen - inputpos); zval_dtor(return_value); RETURN_FALSE; } diff --git a/ext/standard/php_crypt_r.c b/ext/standard/php_crypt_r.c index a8ca39b08e..8b97d4a496 100644 --- a/ext/standard/php_crypt_r.c +++ b/ext/standard/php_crypt_r.c @@ -323,7 +323,7 @@ char * php_md5_crypt_r(const char *pw, const char *salt, char *out) unsigned char final[16]; unsigned int i, sl, pwl; PHP_MD5_CTX ctx, ctx1; - php_uint32 l; + uint32_t l; int pl; pwl = strlen(pw); diff --git a/ext/standard/php_lcg.h b/ext/standard/php_lcg.h index 60850d6c7c..2c24756012 100644 --- a/ext/standard/php_lcg.h +++ b/ext/standard/php_lcg.h @@ -24,8 +24,8 @@ #include "ext/standard/basic_functions.h" typedef struct { - php_int32 s1; - php_int32 s2; + int32_t s1; + int32_t s2; int seeded; } php_lcg_globals; diff --git a/ext/standard/php_rand.h b/ext/standard/php_rand.h index 44a40a7c3b..39ba00eb56 100644 --- a/ext/standard/php_rand.h +++ b/ext/standard/php_rand.h @@ -55,7 +55,7 @@ PHPAPI void php_srand(zend_long seed); PHPAPI zend_long php_rand(void); -PHPAPI void php_mt_srand(php_uint32 seed); -PHPAPI php_uint32 php_mt_rand(void); +PHPAPI void php_mt_srand(uint32_t seed); +PHPAPI uint32_t php_mt_rand(void); #endif /* PHP_RAND_H */ diff --git a/ext/standard/php_smart_string.h b/ext/standard/php_smart_string.h index a832376064..58c319a5a5 100644 --- a/ext/standard/php_smart_string.h +++ b/ext/standard/php_smart_string.h @@ -93,7 +93,7 @@ smart_string_append_unsigned_ex((dest), (val), 0) #define smart_string_appendc_ex(dest, ch, what) do { \ - register size_t __nl; \ + size_t __nl; \ smart_string_alloc4((dest), 1, (what), __nl); \ (dest)->len = __nl; \ ((unsigned char *) (dest)->c)[(dest)->len - 1] = (ch); \ @@ -109,7 +109,7 @@ } while (0) #define smart_string_appendl_ex(dest, src, nlen, what) do { \ - register size_t __nl; \ + size_t __nl; \ smart_string *__dest = (smart_string *) (dest); \ \ smart_string_alloc4(__dest, (nlen), (what), __nl); \ diff --git a/ext/standard/rand.c b/ext/standard/rand.c index 2dd05e70bb..50729f2418 100644 --- a/ext/standard/rand.c +++ b/ext/standard/rand.c @@ -146,19 +146,19 @@ PHPAPI zend_long php_rand(void) #define loBits(u) ((u) & 0x7FFFFFFFU) /* mask the highest bit of u */ #define mixBits(u, v) (hiBit(u)|loBits(v)) /* move hi bit of u to hi bit of v */ -#define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((php_uint32)(-(php_int32)(loBit(u))) & 0x9908b0dfU)) +#define twist(m,u,v) (m ^ (mixBits(u,v)>>1) ^ ((uint32_t)(-(int32_t)(loBit(u))) & 0x9908b0dfU)) /* {{{ php_mt_initialize */ -static inline void php_mt_initialize(php_uint32 seed, php_uint32 *state) +static inline void php_mt_initialize(uint32_t seed, uint32_t *state) { /* Initialize generator state with seed See Knuth TAOCP Vol 2, 3rd Ed, p.106 for multiplier. In previous versions, most significant bits (MSBs) of the seed affect only MSBs of the state array. Modified 9 Jan 2002 by Makoto Matsumoto. */ - register php_uint32 *s = state; - register php_uint32 *r = state; + register uint32_t *s = state; + register uint32_t *r = state; register int i = 1; *s++ = seed & 0xffffffffU; @@ -176,8 +176,8 @@ static inline void php_mt_reload(void) /* Generate N new values in state Made clearer and faster by Matthew Bellew (matthew.bellew@home.com) */ - register php_uint32 *state = BG(state); - register php_uint32 *p = state; + register uint32_t *state = BG(state); + register uint32_t *p = state; register int i; for (i = N - M; i--; ++p) @@ -192,7 +192,7 @@ static inline void php_mt_reload(void) /* {{{ php_mt_srand */ -PHPAPI void php_mt_srand(php_uint32 seed) +PHPAPI void php_mt_srand(uint32_t seed) { /* Seed the generator with a simple uint32 */ php_mt_initialize(seed, BG(state)); @@ -205,12 +205,12 @@ PHPAPI void php_mt_srand(php_uint32 seed) /* {{{ php_mt_rand */ -PHPAPI php_uint32 php_mt_rand(void) +PHPAPI uint32_t php_mt_rand(void) { /* Pull a 32-bit integer from the generator state Every other access function simply transforms the numbers extracted here */ - register php_uint32 s1; + register uint32_t s1; if (BG(left) == 0) { php_mt_reload(); diff --git a/ext/standard/sha1.c b/ext/standard/sha1.c index ad4f4a5603..c4bed51abc 100644 --- a/ext/standard/sha1.c +++ b/ext/standard/sha1.c @@ -103,9 +103,9 @@ PHP_FUNCTION(sha1_file) /* }}} */ -static void SHA1Transform(php_uint32[5], const unsigned char[64]); -static void SHA1Encode(unsigned char *, php_uint32 *, unsigned int); -static void SHA1Decode(php_uint32 *, const unsigned char *, unsigned int); +static void SHA1Transform(uint32_t[5], const unsigned char[64]); +static void SHA1Encode(unsigned char *, uint32_t *, unsigned int); +static void SHA1Decode(uint32_t *, const unsigned char *, unsigned int); static unsigned char PADDING[64] = { @@ -133,22 +133,22 @@ static unsigned char PADDING[64] = /* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4. */ #define FF(a, b, c, d, e, w) { \ - (e) += F ((b), (c), (d)) + (w) + (php_uint32)(0x5A827999); \ + (e) += F ((b), (c), (d)) + (w) + (uint32_t)(0x5A827999); \ (e) += ROTATE_LEFT ((a), 5); \ (b) = ROTATE_LEFT((b), 30); \ } #define GG(a, b, c, d, e, w) { \ - (e) += G ((b), (c), (d)) + (w) + (php_uint32)(0x6ED9EBA1); \ + (e) += G ((b), (c), (d)) + (w) + (uint32_t)(0x6ED9EBA1); \ (e) += ROTATE_LEFT ((a), 5); \ (b) = ROTATE_LEFT((b), 30); \ } #define HH(a, b, c, d, e, w) { \ - (e) += H ((b), (c), (d)) + (w) + (php_uint32)(0x8F1BBCDC); \ + (e) += H ((b), (c), (d)) + (w) + (uint32_t)(0x8F1BBCDC); \ (e) += ROTATE_LEFT ((a), 5); \ (b) = ROTATE_LEFT((b), 30); \ } #define II(a, b, c, d, e, w) { \ - (e) += I ((b), (c), (d)) + (w) + (php_uint32)(0xCA62C1D6); \ + (e) += I ((b), (c), (d)) + (w) + (uint32_t)(0xCA62C1D6); \ (e) += ROTATE_LEFT ((a), 5); \ (b) = ROTATE_LEFT((b), 30); \ } @@ -184,10 +184,10 @@ PHPAPI void PHP_SHA1Update(PHP_SHA1_CTX * context, const unsigned char *input, index = (unsigned int) ((context->count[0] >> 3) & 0x3F); /* Update number of bits */ - if ((context->count[0] += ((php_uint32) inputLen << 3)) - < ((php_uint32) inputLen << 3)) + if ((context->count[0] += ((uint32_t) inputLen << 3)) + < ((uint32_t) inputLen << 3)) context->count[1]++; - context->count[1] += ((php_uint32) inputLen >> 29); + context->count[1] += ((uint32_t) inputLen >> 29); partLen = 64 - index; @@ -253,11 +253,11 @@ PHPAPI void PHP_SHA1Final(unsigned char digest[20], PHP_SHA1_CTX * context) * SHA1 basic transformation. Transforms state based on block. */ static void SHA1Transform(state, block) -php_uint32 state[5]; +uint32_t state[5]; const unsigned char block[64]; { - php_uint32 a = state[0], b = state[1], c = state[2]; - php_uint32 d = state[3], e = state[4], x[16], tmp; + uint32_t a = state[0], b = state[1], c = state[2]; + uint32_t d = state[3], e = state[4], x[16], tmp; SHA1Decode(x, block, 64); @@ -361,12 +361,12 @@ const unsigned char block[64]; /* }}} */ /* {{{ SHA1Encode - Encodes input (php_uint32) into output (unsigned char). Assumes len is + Encodes input (uint32_t) into output (unsigned char). Assumes len is a multiple of 4. */ static void SHA1Encode(output, input, len) unsigned char *output; -php_uint32 *input; +uint32_t *input; unsigned int len; { unsigned int i, j; @@ -381,19 +381,19 @@ unsigned int len; /* }}} */ /* {{{ SHA1Decode - Decodes input (unsigned char) into output (php_uint32). Assumes len is + Decodes input (unsigned char) into output (uint32_t). Assumes len is a multiple of 4. */ static void SHA1Decode(output, input, len) -php_uint32 *output; +uint32_t *output; const unsigned char *input; unsigned int len; { unsigned int i, j; for (i = 0, j = 0; j < len; i++, j += 4) - output[i] = ((php_uint32) input[j + 3]) | (((php_uint32) input[j + 2]) << 8) | - (((php_uint32) input[j + 1]) << 16) | (((php_uint32) input[j]) << 24); + output[i] = ((uint32_t) input[j + 3]) | (((uint32_t) input[j + 2]) << 8) | + (((uint32_t) input[j + 1]) << 16) | (((uint32_t) input[j]) << 24); } /* }}} */ diff --git a/ext/standard/sha1.h b/ext/standard/sha1.h index d2cc1b70b9..de338fad38 100644 --- a/ext/standard/sha1.h +++ b/ext/standard/sha1.h @@ -25,8 +25,8 @@ /* SHA1 context. */ typedef struct { - php_uint32 state[5]; /* state (ABCD) */ - php_uint32 count[2]; /* number of bits, modulo 2^64 (lsb first) */ + uint32_t state[5]; /* state (ABCD) */ + uint32_t count[2]; /* number of bits, modulo 2^64 (lsb first) */ unsigned char buffer[64]; /* input buffer */ } PHP_SHA1_CTX; diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c index de0f016947..c2f200eedd 100644 --- a/ext/standard/streamsfuncs.c +++ b/ext/standard/streamsfuncs.c @@ -507,6 +507,12 @@ PHP_FUNCTION(stream_get_meta_data) array_init(return_value); + if (!php_stream_populate_meta_data(stream, return_value)) { + add_assoc_bool(return_value, "timed_out", 0); + add_assoc_bool(return_value, "blocked", 1); + add_assoc_bool(return_value, "eof", php_stream_eof(stream)); + } + if (!Z_ISUNDEF(stream->wrapperdata)) { Z_ADDREF_P(&stream->wrapperdata); add_assoc_zval(return_value, "wrapper_data", &stream->wrapperdata); @@ -540,11 +546,6 @@ PHP_FUNCTION(stream_get_meta_data) add_assoc_string(return_value, "uri", stream->orig_path); } - if (!php_stream_populate_meta_data(stream, return_value)) { - add_assoc_bool(return_value, "timed_out", 0); - add_assoc_bool(return_value, "blocked", 1); - add_assoc_bool(return_value, "eof", php_stream_eof(stream)); - } } /* }}} */ diff --git a/ext/standard/string.c b/ext/standard/string.c index 022914625e..82aa97e8cd 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -998,12 +998,12 @@ PHP_FUNCTION(wordwrap) /* Multiple character line break or forced cut */ if (linelength > 0) { chk = (size_t)(ZSTR_LEN(text)/linelength + 1); - newtext = zend_string_alloc(chk * breakchar_len + ZSTR_LEN(text), 0); + newtext = zend_string_safe_alloc(chk, breakchar_len, ZSTR_LEN(text), 0); alloced = ZSTR_LEN(text) + chk * breakchar_len + 1; } else { chk = ZSTR_LEN(text); alloced = ZSTR_LEN(text) * (breakchar_len + 1) + 1; - newtext = zend_string_alloc(ZSTR_LEN(text) * (breakchar_len + 1), 0); + newtext = zend_string_safe_alloc(ZSTR_LEN(text), breakchar_len + 1, 0, 0); } /* now keep track of the actual new text length */ @@ -1245,8 +1245,8 @@ PHPAPI void php_implode(const zend_string *delim, zval *arr, zval *return_value) len += ZSTR_LEN(*strptr); } } ZEND_HASH_FOREACH_END(); - - str = zend_string_alloc(len + (numelems - 1) * ZSTR_LEN(delim), 0); + /* numelems can not be 0, we checked above */ + str = zend_string_safe_alloc(numelems - 1, ZSTR_LEN(delim), len, 0); cptr = ZSTR_VAL(str) + ZSTR_LEN(str); *cptr = 0; @@ -2344,7 +2344,7 @@ PHP_FUNCTION(chunk_split) if ((size_t)chunklen > ZSTR_LEN(str)) { /* to maintain BC, we must return original string + ending */ - result = zend_string_alloc(endlen + ZSTR_LEN(str), 0); + result = zend_string_safe_alloc(ZSTR_LEN(str), 1, endlen, 0); memcpy(ZSTR_VAL(result), ZSTR_VAL(str), ZSTR_LEN(str)); memcpy(ZSTR_VAL(result) + ZSTR_LEN(str), end, endlen); ZSTR_VAL(result)[ZSTR_LEN(result)] = '\0'; @@ -2710,7 +2710,7 @@ PHP_FUNCTION(quotemeta) RETURN_FALSE; } - str = zend_string_alloc(2 * ZSTR_LEN(old), 0); + str = zend_string_safe_alloc(2, ZSTR_LEN(old), 0, 0); for (p = ZSTR_VAL(old), q = ZSTR_VAL(str); p != old_end; p++) { c = *p; @@ -2740,7 +2740,8 @@ PHP_FUNCTION(quotemeta) /* }}} */ /* {{{ proto int ord(string character) - Returns ASCII value of character */ + Returns ASCII value of character + Warning: This function is special-cased by zend_compile.c and so is bypassed for constant string argument */ PHP_FUNCTION(ord) { char *str; @@ -2761,7 +2762,8 @@ PHP_FUNCTION(ord) /* }}} */ /* {{{ proto string chr(int ascii) - Converts ASCII code to a character */ + Converts ASCII code to a character + Warning: This function is special-cased by zend_compile.c and so is bypassed for constant integer argument */ PHP_FUNCTION(chr) { zend_long c; @@ -3231,7 +3233,11 @@ static zend_string *php_str_to_str_ex(zend_string *haystack, /* Needle doesn't occur, shortcircuit the actual replacement. */ goto nothing_todo; } - new_str = zend_string_alloc(count * (str_len - needle_len) + ZSTR_LEN(haystack), 0); + if (str_len > needle_len) { + new_str = zend_string_safe_alloc(count, str_len - needle_len, ZSTR_LEN(haystack), 0); + } else { + new_str = zend_string_alloc(count * (str_len - needle_len) + ZSTR_LEN(haystack), 0); + } e = s = ZSTR_VAL(new_str); end = ZSTR_VAL(haystack) + ZSTR_LEN(haystack); @@ -3308,8 +3314,12 @@ static zend_string *php_str_to_str_i_ex(zend_string *haystack, char *lc_haystack zend_string_release(lc_needle); goto nothing_todo; } - - new_str = zend_string_alloc(count * (str_len - ZSTR_LEN(lc_needle)) + ZSTR_LEN(haystack), 0); + + if (str_len > ZSTR_LEN(lc_needle)) { + new_str = zend_string_safe_alloc(count, str_len - ZSTR_LEN(lc_needle), ZSTR_LEN(haystack), 0); + } else { + new_str = zend_string_alloc(count * (str_len - ZSTR_LEN(lc_needle)) + ZSTR_LEN(haystack), 0); + } e = s = ZSTR_VAL(new_str); end = lc_haystack + ZSTR_LEN(haystack); @@ -3387,7 +3397,11 @@ PHPAPI zend_string *php_str_to_str(char *haystack, size_t length, char *needle, new_str = zend_string_init(haystack, length, 0); return new_str; } else { - new_str = zend_string_alloc(count * (str_len - needle_len) + length, 0); + if (str_len > needle_len) { + new_str = zend_string_safe_alloc(count, str_len - needle_len, length, 0); + } else { + new_str = zend_string_alloc(count * (str_len - needle_len) + length, 0); + } } } @@ -3815,7 +3829,7 @@ PHPAPI zend_string *php_addcslashes(zend_string *str, int should_free, char *wha char *end; char c; size_t newlen; - zend_string *new_str = zend_string_alloc(4 * ZSTR_LEN(str), 0); + zend_string *new_str = zend_string_safe_alloc(4, ZSTR_LEN(str), 0, 0); php_charmask((unsigned char *)what, wlength, flags); @@ -3890,7 +3904,7 @@ PHPAPI zend_string *php_addslashes(zend_string *str, int should_free) do_escape: offset = source - (char *)ZSTR_VAL(str); - new_str = zend_string_alloc(offset + (2 * (ZSTR_LEN(str) - offset)), 0); + new_str = zend_string_safe_alloc(2, ZSTR_LEN(str) - offset, offset, 0); memcpy(ZSTR_VAL(new_str), ZSTR_VAL(str), offset); target = ZSTR_VAL(new_str) + offset; @@ -4412,7 +4426,7 @@ PHP_FUNCTION(nl2br) { size_t repl_len = is_xhtml ? (sizeof("<br />") - 1) : (sizeof("<br>") - 1); - result = zend_string_alloc(repl_cnt * repl_len + ZSTR_LEN(str), 0); + result = zend_string_safe_alloc(repl_cnt, repl_len, ZSTR_LEN(str), 0); target = ZSTR_VAL(result); } @@ -4699,6 +4713,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha size_t pos, i = 0; char *allow_free = NULL; const char *allow_actual; + char is_xml = 0; if (stateptr) state = *stateptr; @@ -4794,10 +4809,10 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha switch (state) { case 1: /* HTML/XML */ lc = '>'; - if (*(p -1) == '-') { + if (is_xml && *(p -1) == '-') { break; } - in_q = state = 0; + in_q = state = is_xml = 0; if (allow) { if (tp - tbuf >= PHP_TAG_BUF_SIZE) { pos = tp - tbuf; @@ -4926,8 +4941,8 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha * state == 2 (PHP). Switch back to HTML. */ - if (state == 2 && p > buf+2 && strncasecmp(p-4, "<?xm", 4) == 0) { - state = 1; + if (state == 2 && p > buf+4 && strncasecmp(p-4, "<?xm", 4) == 0) { + state = 1; is_xml=1; break; } @@ -5596,7 +5611,7 @@ PHP_FUNCTION(money_format) } } - str = zend_string_alloc(format_len + 1024, 0); + str = zend_string_safe_alloc(format_len, 1, 1024, 0); if ((res_len = strfmon(ZSTR_VAL(str), ZSTR_LEN(str), format, value)) < 0) { zend_string_free(str); RETURN_FALSE; diff --git a/ext/standard/tests/array/bug71603.phpt b/ext/standard/tests/array/bug71603.phpt new file mode 100644 index 0000000000..0c25be660c --- /dev/null +++ b/ext/standard/tests/array/bug71603.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #71603 (compact() maintains references in php7) +--FILE-- +<?php +$foo = "okey"; +$foo_reference =& $foo; + +$array = compact('foo_reference'); + +$foo = 'changed!'; + +var_dump($array['foo_reference']); + +--EXPECT-- +string(4) "okey" diff --git a/ext/standard/tests/array/bug71660.phpt b/ext/standard/tests/array/bug71660.phpt new file mode 100644 index 0000000000..c2d7192378 --- /dev/null +++ b/ext/standard/tests/array/bug71660.phpt @@ -0,0 +1,18 @@ +--TEST-- +Bug #71660 (array_column behaves incorrectly after foreach by reference) +--FILE-- +<?php +$arr = array('id' => 12345, 'name' => 'sam'); +foreach ($arr as &$v) { + $v = $v; +} + +$arr = [$arr]; + +var_dump(array_column($arr, 'name', 'id')); +?> +--EXPECT-- +array(1) { + [12345]=> + string(3) "sam" +} diff --git a/ext/standard/tests/array/range_bug71132.phpt b/ext/standard/tests/array/range_bug71132.phpt new file mode 100644 index 0000000000..5e3bcc8f31 --- /dev/null +++ b/ext/standard/tests/array/range_bug71132.phpt @@ -0,0 +1,10 @@ +--TEST-- +Bug #71132 (range function produces 2 segfaults with long integers) +--FILE-- +<?php +var_dump(count(range(PHP_INT_MIN + 513, PHP_INT_MIN))); +var_dump(count(range(PHP_INT_MIN, PHP_INT_MIN + 513))); +?> +--EXPECT-- +int(514) +int(514) diff --git a/ext/standard/tests/array/range_bug71197.phpt b/ext/standard/tests/array/range_bug71197.phpt new file mode 100644 index 0000000000..2031ec7c09 --- /dev/null +++ b/ext/standard/tests/array/range_bug71197.phpt @@ -0,0 +1,8 @@ +--TEST-- +Bug #71197 (range function produces another 2 segfaults with long integers) +--FILE-- +<?php +range(PHP_INT_MIN, PHP_INT_MIN + 513, .01); +range(PHP_INT_MIN + 513, PHP_INT_MIN, .01); +?> +--EXPECT-- diff --git a/ext/standard/tests/class_object/bug71442.phpt b/ext/standard/tests/class_object/bug71442.phpt new file mode 100644 index 0000000000..d6b3d6699b --- /dev/null +++ b/ext/standard/tests/class_object/bug71442.phpt @@ -0,0 +1,37 @@ +--TEST-- +Bug #71442 (forward_static_call crash) +--FILE-- +<?php + +class A +{ + const NAME = 'A'; + public static function test() { + $args = func_get_args(); + echo static::NAME, " ".join(',', $args)." \n"; + } +} + +class B extends A +{ + const NAME = 'B'; + + public static function test() { + echo self::NAME, "\n"; + forward_static_call(array('A', 'test'), 'more', 'args'); + forward_static_call( 'test', 'other', 'args'); + } +} + +B::test('foo'); + +function test() { + $args = func_get_args(); + echo "C ".join(',', $args)." \n"; +} + +?> +--EXPECT-- +B +B more,args +C other,args diff --git a/ext/standard/tests/file/stream_rfc2397_002.phpt b/ext/standard/tests/file/stream_rfc2397_002.phpt index 980863bb5c..1dce5adf6c 100644 --- a/ext/standard/tests/file/stream_rfc2397_002.phpt +++ b/ext/standard/tests/file/stream_rfc2397_002.phpt @@ -34,6 +34,8 @@ foreach($streams as $stream) <?php exit(0); ?> --EXPECTF-- array(7) { + ["base64"]=> + bool(false) ["wrapper_type"]=> string(7) "RFC2397" ["stream_type"]=> @@ -46,8 +48,6 @@ array(7) { bool(true) ["uri"]=> string(8) "data://," - ["base64"]=> - bool(false) } NULL @@ -55,6 +55,8 @@ Warning: fopen(data://): failed to open stream: rfc2397: no comma in URL in %sst NULL NULL array(7) { + ["base64"]=> + bool(true) ["wrapper_type"]=> string(7) "RFC2397" ["stream_type"]=> @@ -67,8 +69,6 @@ array(7) { bool(true) ["uri"]=> string(15) "data://;base64," - ["base64"]=> - bool(true) } NULL @@ -84,6 +84,10 @@ Warning: fopen(data://foo=bar,): failed to open stream: rfc2397: illegal media t NULL NULL array(8) { + ["mediatype"]=> + string(10) "text/plain" + ["base64"]=> + bool(false) ["wrapper_type"]=> string(7) "RFC2397" ["stream_type"]=> @@ -96,10 +100,6 @@ array(8) { bool(true) ["uri"]=> string(18) "data://text/plain," - ["mediatype"]=> - string(10) "text/plain" - ["base64"]=> - bool(false) } NULL @@ -107,6 +107,12 @@ Warning: fopen(data://text/plain;foo,): failed to open stream: rfc2397: illegal NULL NULL array(9) { + ["mediatype"]=> + string(10) "text/plain" + ["foo"]=> + string(3) "bar" + ["base64"]=> + bool(false) ["wrapper_type"]=> string(7) "RFC2397" ["stream_type"]=> @@ -119,12 +125,6 @@ array(9) { bool(true) ["uri"]=> string(26) "data://text/plain;foo=bar," - ["mediatype"]=> - string(10) "text/plain" - ["foo"]=> - string(3) "bar" - ["base64"]=> - bool(false) } string(3) "bar" @@ -132,6 +132,12 @@ Warning: fopen(data://text/plain;foo=bar;bla,): failed to open stream: rfc2397: NULL NULL array(9) { + ["mediatype"]=> + string(10) "text/plain" + ["foo"]=> + string(3) "bar" + ["base64"]=> + bool(true) ["wrapper_type"]=> string(7) "RFC2397" ["stream_type"]=> @@ -144,12 +150,6 @@ array(9) { bool(true) ["uri"]=> string(33) "data://text/plain;foo=bar;base64," - ["mediatype"]=> - string(10) "text/plain" - ["foo"]=> - string(3) "bar" - ["base64"]=> - bool(true) } string(3) "bar" @@ -157,6 +157,14 @@ Warning: fopen(data://text/plain;foo=bar;bar=baz): failed to open stream: rfc239 NULL NULL array(10) { + ["mediatype"]=> + string(10) "text/plain" + ["foo"]=> + string(3) "bar" + ["bar"]=> + string(3) "baz" + ["base64"]=> + bool(false) ["wrapper_type"]=> string(7) "RFC2397" ["stream_type"]=> @@ -169,14 +177,6 @@ array(10) { bool(true) ["uri"]=> string(34) "data://text/plain;foo=bar;bar=baz," - ["mediatype"]=> - string(10) "text/plain" - ["foo"]=> - string(3) "bar" - ["bar"]=> - string(3) "baz" - ["base64"]=> - bool(false) } string(3) "bar" ===DONE=== diff --git a/ext/standard/tests/general_functions/escapeshellarg_bug71039.phpt b/ext/standard/tests/general_functions/escapeshellarg_bug71039.phpt new file mode 100644 index 0000000000..cbb3f6fcc4 --- /dev/null +++ b/ext/standard/tests/general_functions/escapeshellarg_bug71039.phpt @@ -0,0 +1,10 @@ +--TEST-- +Test escapeshellarg() string with \0 bytes +--FILE-- +<?php +escapeshellarg("hello\0world"); + +?> +===DONE=== +--EXPECTF-- +Fatal error: escapeshellarg(): Input string contains NULL bytes in %s on line %d diff --git a/ext/standard/tests/general_functions/escapeshellarg_bug71270.phpt b/ext/standard/tests/general_functions/escapeshellarg_bug71270.phpt new file mode 100644 index 0000000000..c57da3691c --- /dev/null +++ b/ext/standard/tests/general_functions/escapeshellarg_bug71270.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test escapeshellarg() allowed argument length +--FILE-- +<?php +ini_set('memory_limit', -1); +$var_2 = str_repeat('A', 1024*1024*64); +escapeshellarg($var_2); + +?> +===DONE=== +--EXPECTF-- +Fatal error: escapeshellarg(): Argument exceeds the allowed length of %d bytes in %s on line %d diff --git a/ext/standard/tests/general_functions/escapeshellcmd_bug71039.phpt b/ext/standard/tests/general_functions/escapeshellcmd_bug71039.phpt new file mode 100644 index 0000000000..0a4d7eacff --- /dev/null +++ b/ext/standard/tests/general_functions/escapeshellcmd_bug71039.phpt @@ -0,0 +1,10 @@ +--TEST-- +Test escapeshellcmd() string with \0 bytes +--FILE-- +<?php +escapeshellcmd("hello\0world"); + +?> +===DONE=== +--EXPECTF-- +Fatal error: escapeshellcmd(): Input string contains NULL bytes in %s on line %d diff --git a/ext/standard/tests/general_functions/escapeshellcmd_bug71270.phpt b/ext/standard/tests/general_functions/escapeshellcmd_bug71270.phpt new file mode 100644 index 0000000000..4686193d41 --- /dev/null +++ b/ext/standard/tests/general_functions/escapeshellcmd_bug71270.phpt @@ -0,0 +1,12 @@ +--TEST-- +Test escapeshellcmd() allowed argument length +--FILE-- +<?php +ini_set('memory_limit', -1); +$var_2 = str_repeat('A', 1024*1024*64); +escapeshellcmd($var_2); + +?> +===DONE=== +--EXPECTF-- +Fatal error: escapeshellcmd(): Command exceeds the allowed length of %d bytes in %s on line %d diff --git a/ext/standard/tests/general_functions/var_export_bug71314.phpt b/ext/standard/tests/general_functions/var_export_bug71314.phpt new file mode 100644 index 0000000000..aaa8f794c0 --- /dev/null +++ b/ext/standard/tests/general_functions/var_export_bug71314.phpt @@ -0,0 +1,15 @@ +--TEST-- +Bug #71314 (var_export(INF) prints INF.0) +--FILE-- +<?php + +var_export(INF); +echo PHP_EOL; +var_export(-INF); +echo PHP_EOL; +var_export(NAN); +echo PHP_EOL; +--EXPECT-- +INF +-INF +NAN diff --git a/ext/standard/tests/math/mt_rand_value.phpt b/ext/standard/tests/math/mt_rand_value.phpt new file mode 100644 index 0000000000..772305ad63 --- /dev/null +++ b/ext/standard/tests/math/mt_rand_value.phpt @@ -0,0 +1,44 @@ +--TEST-- +Test mt_rand() output +--FILE-- +<?php + +mt_srand(12345678); + +for ($i=0; $i<16; $i++) { + echo mt_rand().PHP_EOL; +} +echo PHP_EOL; + +$x = 0; +for ($i=0; $i<1024; $i++) { + $x ^= mt_rand(); +} +echo $x.PHP_EOL; + +/* + * Note that the output will be different from the original mt19937ar.c, + * because PHP's implementation contains a bug. Thus, this test actually + * checks to make sure that PHP's behaviour is wrong, but consistently so. + */ + +?> +--EXPECTF-- +1614640687 +1711027313 +857485497 +688176834 +1386682158 +412773096 +813703253 +898651287 +2087374214 +1382556330 +1640700129 +1863374167 +1324097651 +1923803667 +676334965 +853386222 + +1571178311 diff --git a/ext/standard/tests/network/socket_get_status_basic.phpt b/ext/standard/tests/network/socket_get_status_basic.phpt index 46215f9838..32a8d9ce6f 100644 --- a/ext/standard/tests/network/socket_get_status_basic.phpt +++ b/ext/standard/tests/network/socket_get_status_basic.phpt @@ -18,6 +18,12 @@ fclose($server); ?> --EXPECTF-- array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["stream_type"]=> string(%d) "tcp_socket%S" ["mode"]=> @@ -26,10 +32,4 @@ array(7) { int(0) ["seekable"]=> bool(false) - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } diff --git a/ext/standard/tests/serialize/bug71311.phpt b/ext/standard/tests/serialize/bug71311.phpt new file mode 100644 index 0000000000..3c70783d37 --- /dev/null +++ b/ext/standard/tests/serialize/bug71311.phpt @@ -0,0 +1,16 @@ +--TEST-- +Bug #71311 Use-after-free vulnerability in SPL(ArrayObject, unserialize) +--FILE-- +<?php +$data = unserialize("C:11:\"ArrayObject\":11:{x:i:0;r:3;XX"); +var_dump($data); +?> +--EXPECTF-- +Fatal error: Uncaught UnexpectedValueException: Error at offset 10 of 11 bytes in %s%ebug71311.php:2 +Stack trace: +#0 [internal function]: ArrayObject->unserialize('x:i:0;r:3;X') +#1 %s%ebug71311.php(2): unserialize('%s') +#2 {main} + thrown in %s%ebug71311.php on line 2 + + diff --git a/ext/standard/tests/serialize/bug71313.phpt b/ext/standard/tests/serialize/bug71313.phpt new file mode 100644 index 0000000000..2ad429227d --- /dev/null +++ b/ext/standard/tests/serialize/bug71313.phpt @@ -0,0 +1,14 @@ +--TEST-- +Bug #71311 Use-after-free vulnerability in SPL(SplObjectStorage, unserialize) +--FILE-- +<?php +$data = unserialize("C:16:\"SplObjectStorage\":113:{x:i:2;O:8:\"stdClass\":0:{},a:2:{s:4:\"prev\";i:2;s:4:\"next\";O:8:\"stdClass\":0:{}};r:7;,R:2;s:4:\"next\";;r:3;};m:a:0:{}}"); +var_dump($data); +?> +--EXPECTF-- +Fatal error: Uncaught UnexpectedValueException: Error at offset 82 of 113 bytes in %s%ebug71313.php:2 +Stack trace: +#0 [internal function]: SplObjectStorage->unserialize('%s') +#1 %s%ebug71313.php(2): unserialize('%s') +#2 {main} + thrown in %s%ebug71313.php on line 2 diff --git a/ext/standard/tests/streams/bug71323.phpt b/ext/standard/tests/streams/bug71323.phpt new file mode 100644 index 0000000000..dfe0bd8afe --- /dev/null +++ b/ext/standard/tests/streams/bug71323.phpt @@ -0,0 +1,31 @@ +--TEST-- +Bug #71323: Output of stream_get_meta_data can be falsified by its input +--FILE-- +<?php +$file = 'data:text/plain;z=y;uri=eviluri;mediatype=wut?;mediatype2=hello,somedata'; +$meta = stream_get_meta_data(fopen($file, "r")); +var_dump($meta); +?> +--EXPECTF-- +array(10) { + ["mediatype"]=> + string(10) "text/plain" + ["z"]=> + string(1) "y" + ["uri"]=> + string(72) "data:text/plain;z=y;uri=eviluri;mediatype=wut?;mediatype2=hello,somedata" + ["mediatype2"]=> + string(5) "hello" + ["base64"]=> + bool(false) + ["wrapper_type"]=> + string(7) "RFC2397" + ["stream_type"]=> + string(7) "RFC2397" + ["mode"]=> + string(1) "r" + ["unread_bytes"]=> + int(0) + ["seekable"]=> + bool(true) +} diff --git a/ext/standard/tests/streams/stream_get_meta_data_dir_basic.phpt b/ext/standard/tests/streams/stream_get_meta_data_dir_basic.phpt index f46c8fd70b..6658d69a4b 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_dir_basic.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_dir_basic.phpt @@ -13,6 +13,12 @@ var_dump(stream_get_meta_data($dirObject->handle)); ?> --EXPECT-- array(8) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -23,14 +29,14 @@ array(8) { int(0) ["seekable"]=> bool(true) +} +array(8) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(8) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -41,10 +47,4 @@ array(8) { int(0) ["seekable"]=> bool(true) - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } diff --git a/ext/standard/tests/streams/stream_get_meta_data_file_basic.phpt b/ext/standard/tests/streams/stream_get_meta_data_file_basic.phpt index 4758c750f9..bad5987990 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_file_basic.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_file_basic.phpt @@ -12,6 +12,12 @@ fclose($fp); ?> --EXPECTF-- array(9) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -24,10 +30,4 @@ array(9) { bool(true) ["uri"]=> string(%i) "%sstream_get_meta_data_file_basic.php" - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } diff --git a/ext/standard/tests/streams/stream_get_meta_data_file_variation1.phpt b/ext/standard/tests/streams/stream_get_meta_data_file_variation1.phpt index 572653e3db..d54eb04410 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_file_variation1.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_file_variation1.phpt @@ -29,6 +29,12 @@ unlink($filename); ?> --EXPECTF-- array(9) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -41,14 +47,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -61,14 +67,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -81,14 +87,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -101,14 +107,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -121,14 +127,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -141,14 +147,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -161,14 +167,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -181,14 +187,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -201,14 +207,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -221,14 +227,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -241,14 +247,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -261,14 +267,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -281,14 +287,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -301,14 +307,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -321,14 +327,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -341,14 +347,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -361,14 +367,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -381,14 +387,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -401,14 +407,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -421,14 +427,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -441,14 +447,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -461,14 +467,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -481,14 +487,14 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -501,10 +507,4 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } diff --git a/ext/standard/tests/streams/stream_get_meta_data_file_variation2.phpt b/ext/standard/tests/streams/stream_get_meta_data_file_variation2.phpt index d186cb7e9b..6b3fde203a 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_file_variation2.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_file_variation2.phpt @@ -43,6 +43,12 @@ unlink($filename); --EXPECTF-- Write some data to the file: array(9) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -55,12 +61,6 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } @@ -68,6 +68,12 @@ Read a line of the file, causing data to be buffered: string(15) "a line of data " array(9) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -80,17 +86,17 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" +} + + +Read 20 bytes from the file: +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} - - -Read 20 bytes from the file: -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -103,17 +109,17 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } Read entire file: array(9) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(true) ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -126,10 +132,4 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s.tmp" - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(true) } diff --git a/ext/standard/tests/streams/stream_get_meta_data_file_variation4.phpt b/ext/standard/tests/streams/stream_get_meta_data_file_variation4.phpt index c51d9bd087..46a5ba5b37 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_file_variation4.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_file_variation4.phpt @@ -28,6 +28,12 @@ unlink($filename); --EXPECTF-- Create a file: array(9) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -40,16 +46,16 @@ array(9) { bool(true) ["uri"]=> string(%i) "File://%sstream_get_meta_data_file_variation4.php.tmp" +} + +Change to file's directory and open with a relative path: +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} - -Change to file's directory and open with a relative path: -array(9) { ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -62,10 +68,4 @@ array(9) { bool(true) ["uri"]=> string(%i) "stream_get_meta_data_file_variation4.php.tmp" - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } diff --git a/ext/standard/tests/streams/stream_get_meta_data_file_variation5.phpt b/ext/standard/tests/streams/stream_get_meta_data_file_variation5.phpt index 386b92f421..22fcee4b6f 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_file_variation5.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_file_variation5.phpt @@ -33,6 +33,12 @@ unlink($filename); --EXPECTF-- Write some data to the file: array(9) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -45,17 +51,17 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s" - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } Read entire file: array(9) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(true) ["wrapper_type"]=> string(9) "plainfile" ["stream_type"]=> @@ -68,10 +74,4 @@ array(9) { bool(true) ["uri"]=> string(%i) "%s" - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(true) } diff --git a/ext/standard/tests/streams/stream_get_meta_data_process_basic.phpt b/ext/standard/tests/streams/stream_get_meta_data_process_basic.phpt index 3f4dfbc43a..b7ab37c7c5 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_process_basic.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_process_basic.phpt @@ -18,6 +18,12 @@ echo "Done"; ?> --EXPECT-- array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["stream_type"]=> string(5) "STDIO" ["mode"]=> @@ -26,11 +32,5 @@ array(7) { int(0) ["seekable"]=> bool(false) - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } Done diff --git a/ext/standard/tests/streams/stream_get_meta_data_socket_basic.phpt b/ext/standard/tests/streams/stream_get_meta_data_socket_basic.phpt index 86c9cd77c8..66658bd5d0 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_socket_basic.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_socket_basic.phpt @@ -10,6 +10,12 @@ fclose($tcp_socket); ?> --EXPECTF-- array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -18,10 +24,4 @@ array(7) { int(0) ["seekable"]=> bool(false) - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } diff --git a/ext/standard/tests/streams/stream_get_meta_data_socket_variation1.phpt b/ext/standard/tests/streams/stream_get_meta_data_socket_variation1.phpt index 88d354b378..1c7f1fd256 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_socket_variation1.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_socket_variation1.phpt @@ -39,6 +39,12 @@ var_dump(stream_get_meta_data($client)); --EXPECTF-- Write some data: array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -47,17 +53,17 @@ array(7) { int(0) ["seekable"]=> bool(false) +} + + +Read a line from the client, causing data to be buffered: +array(7) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} - - -Read a line from the client, causing data to be buffered: -array(7) { ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -66,17 +72,17 @@ array(7) { int(15) ["seekable"]=> bool(false) +} + + +Read 3 bytes of data from the client: +array(7) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} - - -Read 3 bytes of data from the client: -array(7) { ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -85,17 +91,17 @@ array(7) { int(12) ["seekable"]=> bool(false) - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } Close the server side socket and read the remaining data from the client: array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(true) ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -104,10 +110,4 @@ array(7) { int(0) ["seekable"]=> bool(false) - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(true) } diff --git a/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt b/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt index e8e39209c9..cb713c8525 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_socket_variation2.phpt @@ -37,25 +37,12 @@ fclose($server); ?> --EXPECTF-- array(7) { - ["stream_type"]=> - string(%d) "tcp_socke%s" - ["mode"]=> - string(2) "r+" - ["unread_bytes"]=> - int(0) - ["seekable"]=> - bool(false) ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} - - -Set a timeout on the client and attempt a read: -array(7) { ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -64,17 +51,17 @@ array(7) { int(0) ["seekable"]=> bool(false) +} + + +Set a timeout on the client and attempt a read: +array(7) { ["timed_out"]=> bool(true) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} - - -Write some data from the server: -array(7) { ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -83,17 +70,17 @@ array(7) { int(0) ["seekable"]=> bool(false) +} + + +Write some data from the server: +array(7) { ["timed_out"]=> bool(true) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} - - -Read some data from the client: -array(7) { ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -102,10 +89,23 @@ array(7) { int(0) ["seekable"]=> bool(false) +} + + +Read some data from the client: +array(7) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) + ["stream_type"]=> + string(%d) "tcp_socke%s" + ["mode"]=> + string(2) "r+" + ["unread_bytes"]=> + int(0) + ["seekable"]=> + bool(false) } diff --git a/ext/standard/tests/streams/stream_get_meta_data_socket_variation3.phpt b/ext/standard/tests/streams/stream_get_meta_data_socket_variation3.phpt index 5b68eba25d..c7f08cbe12 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_socket_variation3.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_socket_variation3.phpt @@ -32,6 +32,12 @@ fclose($server); ?> --EXPECTF-- array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -40,18 +46,18 @@ array(7) { int(0) ["seekable"]=> bool(false) - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } Set blocking to false: bool(true) array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(false) + ["eof"]=> + bool(false) ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -60,18 +66,18 @@ array(7) { int(0) ["seekable"]=> bool(false) - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(false) - ["eof"]=> - bool(false) } Set blocking to true: bool(true) array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -80,10 +86,4 @@ array(7) { int(0) ["seekable"]=> bool(false) - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } diff --git a/ext/standard/tests/streams/stream_get_meta_data_socket_variation4.phpt b/ext/standard/tests/streams/stream_get_meta_data_socket_variation4.phpt index e3f59d10dc..e37e991f16 100644 --- a/ext/standard/tests/streams/stream_get_meta_data_socket_variation4.phpt +++ b/ext/standard/tests/streams/stream_get_meta_data_socket_variation4.phpt @@ -37,6 +37,12 @@ fclose($client); --EXPECTF-- Write some data: array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -45,17 +51,17 @@ array(7) { int(%i) ["seekable"]=> bool(false) +} + + +Read a line from the client: +array(7) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} - - -Read a line from the client: -array(7) { ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -64,17 +70,17 @@ array(7) { int(%i) ["seekable"]=> bool(false) - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } Close the server side socket and read the remaining data from the client: array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(true) ["stream_type"]=> string(%d) "tcp_socke%s" ["mode"]=> @@ -83,10 +89,4 @@ array(7) { int(%i) ["seekable"]=> bool(false) - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(true) } diff --git a/ext/standard/tests/streams/stream_socket_enable_crypto-win32.phpt b/ext/standard/tests/streams/stream_socket_enable_crypto-win32.phpt new file mode 100644 index 0000000000..c61e93d038 --- /dev/null +++ b/ext/standard/tests/streams/stream_socket_enable_crypto-win32.phpt @@ -0,0 +1,70 @@ +--TEST-- +mixed stream_socket_enable_crypto(resource $stream , bool $enable [, int $crypto_type [, resource $session_stream ]] ) ; +--CREDITS-- +marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao paulo - br +--SKIPIF-- +<?php +if (!extension_loaded('openssl')) { + die('skip ext openssl required'); +} +if (substr(PHP_OS, 0, 3) != 'WIN' ) { + die('skip windows only test'); +} +?> +--FILE-- +<?php +$serverUri = "tcp://127.0.0.1:31854"; +$sock = stream_socket_server($serverUri, $errno, $errstr); + +if (is_resource($sock)) { + var_dump(stream_socket_enable_crypto($sock, false)); + var_dump(stream_socket_enable_crypto($sock, true)); + var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv2_CLIENT)); + var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT)); + var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT)); + var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)); + var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv2_SERVER)); + var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv3_SERVER)); + var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv23_SERVER)); + var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_SERVER)); +} else { + die("Test stream_socket_enable_crypto has failed; Unable to connect: {$errstr} ({$errno})"); +} +?> +--CLEAN-- +<?php +unset($serverUri); +unset($sock); +unset($errno); +unset($errstr); +?> +--EXPECTF-- +bool(false) + +Warning: stream_socket_enable_crypto(): When enabling encryption you must specify the crypto type in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): SSLv2 unavailable in the OpenSSL library against which PHP is linked in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): SSL: A request to send or receive data was disallowed because the socket is not connected and (when sending on a datagram socket using a sendto call) no address was supplied. + in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d +bool(false) + +Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d +bool(false) diff --git a/ext/standard/tests/streams/stream_socket_enable_crypto.phpt b/ext/standard/tests/streams/stream_socket_enable_crypto.phpt index 47d6c62893..e7ee3e5b3b 100644 --- a/ext/standard/tests/streams/stream_socket_enable_crypto.phpt +++ b/ext/standard/tests/streams/stream_socket_enable_crypto.phpt @@ -4,8 +4,12 @@ mixed stream_socket_enable_crypto(resource $stream , bool $enable [, int $crypto marcosptf - <marcosptf@yahoo.com.br> - #phparty7 - @phpsp - novatec/2015 - sao paulo - br --SKIPIF-- <?php -if (phpversion() < "5.3.0") { die('SKIP php version so lower.'); } -if (!extension_loaded('openssl')) { die('ext/openssl required'); } +if (!extension_loaded('openssl')) { + die('skip ext/openssl required'); +} +if(substr(PHP_OS, 0, 3) == 'WIN' ) { + die('skip not for windows'); +} ?> --FILE-- <?php @@ -15,8 +19,8 @@ $sock = stream_socket_server($serverUri, $errno, $errstr); if (is_resource($sock)) { var_dump(stream_socket_enable_crypto($sock, false)); var_dump(stream_socket_enable_crypto($sock, true)); - var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv2_CLIENT)); var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv3_CLIENT)); + var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv2_CLIENT)); var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv23_CLIENT)); var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)); var_dump(stream_socket_enable_crypto($sock, true, STREAM_CRYPTO_METHOD_SSLv2_SERVER)); @@ -40,10 +44,10 @@ bool(false) Warning: stream_socket_enable_crypto(): When enabling encryption you must specify the crypto type in %s on line %d bool(false) -Warning: stream_socket_enable_crypto(): SSLv2 %s in %s on line %d +Warning: stream_socket_enable_crypto(): SSL: Broken pipe in %s on line %d bool(false) -Warning: stream_socket_enable_crypto(): SSL: Broken pipe in %s on line %d +Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d bool(false) Warning: stream_socket_enable_crypto(): SSL/TLS already set-up for this stream in %s on line %d diff --git a/ext/standard/tests/strings/bug53021.phpt b/ext/standard/tests/strings/bug53021.phpt index 4a8fbe4f76..38d904761d 100644 --- a/ext/standard/tests/strings/bug53021.phpt +++ b/ext/standard/tests/strings/bug53021.phpt @@ -10,11 +10,14 @@ echo html_entity_decode(""", ENT_QUOTES, 'UTF-8'), "\n"; echo html_entity_decode(""", ENT_QUOTES, 'UTF-8'), "\n";
echo html_entity_decode(""", ENT_COMPAT, 'UTF-8'), "\n";
echo html_entity_decode(""", ENT_COMPAT, 'UTF-8'), "\n";
+echo html_entity_decode("""), "\n";
+echo html_entity_decode("""), "\n";
echo "\nsingle quotes variations:", "\n";
echo html_entity_decode("'", ENT_NOQUOTES, 'UTF-8'), "\n";
echo html_entity_decode("'", ENT_QUOTES, 'UTF-8'), "\n";
echo html_entity_decode("'", ENT_COMPAT, 'UTF-8'), "\n";
+echo html_entity_decode("'"), "\n";
--EXPECT--
array(1) {
[1]=>
@@ -27,8 +30,11 @@ double quotes variations: "
"
"
+"
+"
single quotes variations:
'
'
'
+'
diff --git a/ext/standard/tests/strings/bug70720.phpt b/ext/standard/tests/strings/bug70720.phpt index edf60080ac..6cdc600c2d 100644 --- a/ext/standard/tests/strings/bug70720.phpt +++ b/ext/standard/tests/strings/bug70720.phpt @@ -5,8 +5,12 @@ Bug #70720 (strip_tags() doesnt handle "xml" correctly) var_dump(strip_tags('<?php $dom->test(); ?> this is a test')); var_dump(strip_tags('<?php $xml->test(); ?> this is a test')); var_dump(strip_tags('<?xml $xml->test(); ?> this is a test')); + +/* "->" case in HTML */ +var_dump(strip_tags("<span class=sf-dump-> this is a test</span>")); ?> --EXPECTF-- string(15) " this is a test" string(15) " this is a test" -string(15) " this is a test"
\ No newline at end of file +string(15) " this is a test" +string(15) " this is a test" diff --git a/ext/standard/tests/strings/html_entity_decode3.phpt b/ext/standard/tests/strings/html_entity_decode3.phpt index fcf2710679..48cff17bda 100644 --- a/ext/standard/tests/strings/html_entity_decode3.phpt +++ b/ext/standard/tests/strings/html_entity_decode3.phpt @@ -14,6 +14,7 @@ $tests = array( "", "", " ", //allowed always + "'", //single quote, depends on flags "", //DEL "€", //C1 "Ÿ", @@ -76,6 +77,17 @@ foreach ($tests as $t) { } } +echo "\n*** Default options ***\n"; + +foreach ($tests as $t) { + $dec = html_entity_decode($t); + if ($t == $dec) { + echo "$t\tNOT DECODED\n"; + } else { + echo "$t\tDECODED\n"; + } +} + echo "\nDone.\n"; --EXPECT-- *** HTML 4.01 *** @@ -89,6 +101,7 @@ echo "\nDone.\n";  NOT DECODED  NOT DECODED   DECODED +' DECODED  NOT DECODED € NOT DECODED Ÿ NOT DECODED @@ -117,6 +130,7 @@ echo "\nDone.\n";  NOT DECODED  NOT DECODED   DECODED +' DECODED  DECODED € DECODED Ÿ DECODED @@ -145,6 +159,7 @@ echo "\nDone.\n";  NOT DECODED  NOT DECODED   DECODED +' DECODED  NOT DECODED € NOT DECODED Ÿ NOT DECODED @@ -173,6 +188,7 @@ echo "\nDone.\n";  NOT DECODED  NOT DECODED   DECODED +' DECODED  DECODED € DECODED Ÿ DECODED @@ -190,4 +206,33 @@ echo "\nDone.\n";  DECODED  DECODED +*** Default options *** +� NOT DECODED + NOT DECODED +	 DECODED +
 DECODED + NOT DECODED + NOT DECODED +
 DECODED + NOT DECODED + NOT DECODED +  DECODED +' NOT DECODED + NOT DECODED +€ NOT DECODED +Ÿ NOT DECODED +  DECODED +퟿ DECODED +� NOT DECODED +� NOT DECODED + DECODED + DECODED + DECODED +﷏ DECODED + DECODED + DECODED +ﷰ DECODED + DECODED + DECODED + Done. diff --git a/ext/standard/var.c b/ext/standard/var.c index 3b03c32ca2..fcee7a9cc6 100644 --- a/ext/standard/var.c +++ b/ext/standard/var.c @@ -108,7 +108,7 @@ again: php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc)); break; case IS_STRING: - php_printf("%sstring(%d) \"", COMMON, Z_STRLEN_P(struc)); + php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc)); PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc)); PUTS("\"\n"); break; @@ -278,7 +278,7 @@ again: php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc)); break; case IS_STRING: - php_printf("%sstring(%d) \"", COMMON, Z_STRLEN_P(struc)); + php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc)); PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc)); php_printf("\" refcount(%u)\n", Z_REFCOUNTED_P(struc) ? Z_REFCOUNT_P(struc) : 1); break; @@ -336,7 +336,7 @@ again: break; case IS_RESOURCE: { const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc)); - php_printf("%sresource(" ZEND_LONG_FMT ") of type (%s) refcount(%u)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc)); + php_printf("%sresource(%d) of type (%s) refcount(%u)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc)); break; } case IS_REFERENCE: @@ -463,8 +463,10 @@ again: /* Without a decimal point, PHP treats a number literal as an int. * This check even works for scientific notation, because the * mantissa always contains a decimal point. + * We need to check for finiteness, because INF, -INF and NAN + * must not have a decimal point added. */ - if (NULL == strchr(tmp_str, '.')) { + if (zend_finite(Z_DVAL_P(struc)) && NULL == strchr(tmp_str, '.')) { smart_str_appendl(buf, ".0", 2); } efree(tmp_str); @@ -1043,7 +1045,8 @@ PHP_FUNCTION(unserialize) } zval_ptr_dtor(return_value); if (!EG(exception)) { - php_error_docref(NULL, E_NOTICE, "Error at offset " ZEND_LONG_FMT " of %d bytes", (zend_long)((char*)p - buf), buf_len); + php_error_docref(NULL, E_NOTICE, "Error at offset " ZEND_LONG_FMT " of %zd bytes", + (zend_long)((char*)p - buf), buf_len); } RETURN_FALSE; } diff --git a/ext/standard/var_unserializer.c b/ext/standard/var_unserializer.c index 20709eee81..12a15c3a69 100644 --- a/ext/standard/var_unserializer.c +++ b/ext/standard/var_unserializer.c @@ -1,4 +1,4 @@ -/* Generated by re2c 0.13.5 */ +/* Generated by re2c 0.13.7.5 */ #line 1 "ext/standard/var_unserializer.re" /* +----------------------------------------------------------------------+ @@ -574,7 +574,7 @@ yy2: yych = *(YYMARKER = ++YYCURSOR); if (yych == ':') goto yy95; yy3: -#line 869 "ext/standard/var_unserializer.re" +#line 873 "ext/standard/var_unserializer.re" { return 0; } #line 580 "ext/standard/var_unserializer.c" yy4: @@ -619,7 +619,7 @@ yy13: goto yy3; yy14: ++YYCURSOR; -#line 863 "ext/standard/var_unserializer.re" +#line 867 "ext/standard/var_unserializer.re" { /* this is the case where we have less data than planned */ php_error_docref(NULL, E_NOTICE, "Unexpected end of serialized data"); @@ -651,11 +651,12 @@ yy20: if (yybm[0+yych] & 128) { goto yy20; } - if (yych != ':') goto yy18; + if (yych <= '/') goto yy18; + if (yych >= ';') goto yy18; yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 718 "ext/standard/var_unserializer.re" +#line 722 "ext/standard/var_unserializer.re" { size_t len, len2, len3, maxlen; zend_long elements; @@ -800,7 +801,7 @@ yy20: return object_common2(UNSERIALIZE_PASSTHRU, elements); } -#line 804 "ext/standard/var_unserializer.c" +#line 805 "ext/standard/var_unserializer.c" yy25: yych = *++YYCURSOR; if (yych <= ',') { @@ -825,14 +826,14 @@ yy27: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 711 "ext/standard/var_unserializer.re" +#line 715 "ext/standard/var_unserializer.re" { if (!var_hash) return 0; return object_common2(UNSERIALIZE_PASSTHRU, object_common1(UNSERIALIZE_PASSTHRU, ZEND_STANDARD_CLASS_DEF_PTR)); } -#line 836 "ext/standard/var_unserializer.c" +#line 837 "ext/standard/var_unserializer.c" yy32: yych = *++YYCURSOR; if (yych == '+') goto yy33; @@ -853,7 +854,7 @@ yy34: yych = *++YYCURSOR; if (yych != '{') goto yy18; ++YYCURSOR; -#line 687 "ext/standard/var_unserializer.re" +#line 691 "ext/standard/var_unserializer.re" { zend_long elements = parse_iv(start + 2); /* use iv() not uiv() in order to check data range */ @@ -877,7 +878,7 @@ yy34: return finish_nested_data(UNSERIALIZE_PASSTHRU); } -#line 881 "ext/standard/var_unserializer.c" +#line 882 "ext/standard/var_unserializer.c" yy39: yych = *++YYCURSOR; if (yych == '+') goto yy40; @@ -898,7 +899,7 @@ yy41: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 659 "ext/standard/var_unserializer.re" +#line 663 "ext/standard/var_unserializer.re" { size_t len, maxlen; zend_string *str; @@ -926,7 +927,7 @@ yy41: ZVAL_STR(rval, str); return 1; } -#line 930 "ext/standard/var_unserializer.c" +#line 931 "ext/standard/var_unserializer.c" yy46: yych = *++YYCURSOR; if (yych == '+') goto yy47; @@ -947,7 +948,7 @@ yy48: yych = *++YYCURSOR; if (yych != '"') goto yy18; ++YYCURSOR; -#line 632 "ext/standard/var_unserializer.re" +#line 636 "ext/standard/var_unserializer.re" { size_t len, maxlen; char *str; @@ -974,7 +975,7 @@ yy48: ZVAL_STRINGL(rval, str, len); return 1; } -#line 978 "ext/standard/var_unserializer.c" +#line 979 "ext/standard/var_unserializer.c" yy53: yych = *++YYCURSOR; if (yych <= '/') { @@ -1062,7 +1063,7 @@ yy61: } yy63: ++YYCURSOR; -#line 623 "ext/standard/var_unserializer.re" +#line 627 "ext/standard/var_unserializer.re" { #if SIZEOF_ZEND_LONG == 4 use_double: @@ -1071,7 +1072,7 @@ use_double: ZVAL_DOUBLE(rval, zend_strtod((const char *)start + 2, NULL)); return 1; } -#line 1075 "ext/standard/var_unserializer.c" +#line 1076 "ext/standard/var_unserializer.c" yy65: yych = *++YYCURSOR; if (yych <= ',') { @@ -1130,7 +1131,7 @@ yy73: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 607 "ext/standard/var_unserializer.re" +#line 611 "ext/standard/var_unserializer.re" { *p = YYCURSOR; @@ -1146,7 +1147,7 @@ yy73: return 1; } -#line 1150 "ext/standard/var_unserializer.c" +#line 1151 "ext/standard/var_unserializer.c" yy76: yych = *++YYCURSOR; if (yych == 'N') goto yy73; @@ -1173,7 +1174,7 @@ yy79: if (yych <= '9') goto yy79; if (yych != ';') goto yy18; ++YYCURSOR; -#line 581 "ext/standard/var_unserializer.re" +#line 585 "ext/standard/var_unserializer.re" { #if SIZEOF_ZEND_LONG == 4 int digits = YYCURSOR - start - 3; @@ -1199,7 +1200,7 @@ yy79: ZVAL_LONG(rval, parse_iv(start + 2)); return 1; } -#line 1203 "ext/standard/var_unserializer.c" +#line 1204 "ext/standard/var_unserializer.c" yy83: yych = *++YYCURSOR; if (yych <= '/') goto yy18; @@ -1207,22 +1208,22 @@ yy83: yych = *++YYCURSOR; if (yych != ';') goto yy18; ++YYCURSOR; -#line 575 "ext/standard/var_unserializer.re" +#line 579 "ext/standard/var_unserializer.re" { *p = YYCURSOR; ZVAL_BOOL(rval, parse_iv(start + 2)); return 1; } -#line 1217 "ext/standard/var_unserializer.c" +#line 1218 "ext/standard/var_unserializer.c" yy87: ++YYCURSOR; -#line 569 "ext/standard/var_unserializer.re" +#line 573 "ext/standard/var_unserializer.re" { *p = YYCURSOR; ZVAL_NULL(rval); return 1; } -#line 1226 "ext/standard/var_unserializer.c" +#line 1227 "ext/standard/var_unserializer.c" yy89: yych = *++YYCURSOR; if (yych <= ',') { @@ -1257,6 +1258,10 @@ yy91: return 0; } + if (rval_ref == rval) { + return 0; + } + if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) { ZVAL_UNDEF(rval); return 1; @@ -1266,7 +1271,7 @@ yy91: return 1; } -#line 1270 "ext/standard/var_unserializer.c" +#line 1275 "ext/standard/var_unserializer.c" yy95: yych = *++YYCURSOR; if (yych <= ',') { @@ -1315,9 +1320,9 @@ yy97: return 1; } -#line 1319 "ext/standard/var_unserializer.c" +#line 1324 "ext/standard/var_unserializer.c" } -#line 871 "ext/standard/var_unserializer.re" +#line 875 "ext/standard/var_unserializer.re" return 0; diff --git a/ext/standard/var_unserializer.re b/ext/standard/var_unserializer.re index 18e3cb381f..e4db9090b9 100644 --- a/ext/standard/var_unserializer.re +++ b/ext/standard/var_unserializer.re @@ -556,6 +556,10 @@ PHPAPI int php_var_unserialize_ex(UNSERIALIZE_PARAMETER) return 0; } + if (rval_ref == rval) { + return 0; + } + if (Z_ISUNDEF_P(rval_ref) || (Z_ISREF_P(rval_ref) && Z_ISUNDEF_P(Z_REFVAL_P(rval_ref)))) { ZVAL_UNDEF(rval); return 1; diff --git a/ext/wddx/tests/bug71335.phpt b/ext/wddx/tests/bug71335.phpt new file mode 100644 index 0000000000..57a7f14f81 --- /dev/null +++ b/ext/wddx/tests/bug71335.phpt @@ -0,0 +1,33 @@ +--TEST-- +Bug #71335 (Type Confusion in WDDX Packet Deserialization) +--SKIPIF-- +<?php +if (!extension_loaded("wddx")) print "skip"; +?> +--FILE-- +<?php +$x = "<?xml version='1.0'?> +<wddxPacket version='1.0'> +<header/> + <data> + <struct> + <var name='php_class_name'> + <string>stdClass</string> + </var> + <var name='php_class_name'> + <string>stdClass</string> + </var> + </struct> + </data> +</wddxPacket>"; + +$d = wddx_deserialize($x); +var_dump($d); +?> +DONE +--EXPECTF-- +object(stdClass)#%d (1) { + ["php_class_name"]=> + string(8) "stdClass" +} +DONE diff --git a/ext/wddx/wddx.c b/ext/wddx/wddx.c index c0971f8974..ca7b711682 100644 --- a/ext/wddx/wddx.c +++ b/ext/wddx/wddx.c @@ -912,7 +912,8 @@ static void php_wddx_pop_element(void *user_data, const XML_Char *name) if (ent1->varname) { if (!strcmp(ent1->varname, PHP_CLASS_NAME_VAR) && - Z_TYPE(ent1->data) == IS_STRING && Z_STRLEN(ent1->data) && ent2->type == ST_STRUCT) { + Z_TYPE(ent1->data) == IS_STRING && Z_STRLEN(ent1->data) && + ent2->type == ST_STRUCT && Z_TYPE(ent2->data) == IS_ARRAY) { zend_bool incomplete_class = 0; zend_str_tolower(Z_STRVAL(ent1->data), Z_STRLEN(ent1->data)); diff --git a/ext/xml/xml.c b/ext/xml/xml.c index 21d5233126..b832732f0d 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -1183,9 +1183,7 @@ PHP_FUNCTION(xml_set_object) } /* please leave this commented - or ask thies@thieso.net before doing it (again) */ -/* #ifdef ZEND_ENGINE_2 - zval_add_ref(&parser->object); -#endif */ + /* zval_add_ref(&parser->object); */ ZVAL_COPY(&parser->object, mythis); diff --git a/ext/xmlrpc/tests/bug71501.phpt b/ext/xmlrpc/tests/bug71501.phpt new file mode 100644 index 0000000000..950d21d6d4 --- /dev/null +++ b/ext/xmlrpc/tests/bug71501.phpt @@ -0,0 +1,23 @@ +--TEST-- +Bug #71501 (xmlrpc_encode_request ignores encoding option) +--SKIPIF-- +<?php +if (!extension_loaded("xmlrpc")) print "skip"; +?> +--FILE-- +<?php +$params = 'Lê Trung Hiếu'; +echo xmlrpc_encode_request('foo', $params, ['encoding' => 'UTF-8', 'escaping' => 'markup']); +?> +--EXPECTF-- +<?xml version="1.0" encoding="UTF-8"?> +<methodCall> +<methodName>foo</methodName> +<params> + <param> + <value> + <string>Lê Trung Hiếu</string> + </value> + </param> +</params> +</methodCall> diff --git a/ext/xmlrpc/xmlrpc-epi-php.c b/ext/xmlrpc/xmlrpc-epi-php.c index dd39047bf0..ea62bdc9a9 100644 --- a/ext/xmlrpc/xmlrpc-epi-php.c +++ b/ext/xmlrpc/xmlrpc-epi-php.c @@ -411,45 +411,46 @@ static void set_output_options(php_output_options* options, zval* output_opts) } } - /* encoding code set */ - if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ENCODING_KEY, ENCODING_KEY_LEN)) != NULL) { - if (Z_TYPE_P(val) == IS_STRING) { - options->xmlrpc_out.xml_elem_opts.encoding = estrdup(Z_STRVAL_P(val)); - } + } + + /* encoding code set */ + if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ENCODING_KEY, ENCODING_KEY_LEN)) != NULL) { + if (Z_TYPE_P(val) == IS_STRING) { + options->xmlrpc_out.xml_elem_opts.encoding = estrdup(Z_STRVAL_P(val)); } + } - /* escaping options */ - if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ESCAPING_KEY, ESCAPING_KEY_LEN)) != NULL) { - /* multiple values allowed. check if array */ - if (Z_TYPE_P(val) == IS_ARRAY) { - zval* iter_val; - - options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_no_escaping; - - ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(val), iter_val) { - if (Z_TYPE_P(iter_val) == IS_STRING && Z_STRVAL_P(iter_val)) { - if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_CDATA)) { - options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_cdata_escaping; - } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_ASCII)) { - options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_ascii_escaping; - } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_PRINT)) { - options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_print_escaping; - } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_MARKUP)) { - options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_markup_escaping; - } + /* escaping options */ + if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ESCAPING_KEY, ESCAPING_KEY_LEN)) != NULL) { + /* multiple values allowed. check if array */ + if (Z_TYPE_P(val) == IS_ARRAY) { + zval* iter_val; + + options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_no_escaping; + + ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(val), iter_val) { + if (Z_TYPE_P(iter_val) == IS_STRING && Z_STRVAL_P(iter_val)) { + if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_CDATA)) { + options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_cdata_escaping; + } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_ASCII)) { + options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_ascii_escaping; + } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_PRINT)) { + options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_print_escaping; + } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_MARKUP)) { + options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_markup_escaping; } - } ZEND_HASH_FOREACH_END(); - /* else, check for single value */ - } else if (Z_TYPE_P(val) == IS_STRING) { - if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_CDATA)) { - options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_cdata_escaping; - } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_ASCII)) { - options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_ascii_escaping; - } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_PRINT)) { - options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_print_escaping; - } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_MARKUP)) { - options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping; } + } ZEND_HASH_FOREACH_END(); + /* else, check for single value */ + } else if (Z_TYPE_P(val) == IS_STRING) { + if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_CDATA)) { + options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_cdata_escaping; + } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_ASCII)) { + options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_ascii_escaping; + } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_PRINT)) { + options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_print_escaping; + } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_MARKUP)) { + options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping; } } } diff --git a/ext/xsl/tests/bug71540.phpt b/ext/xsl/tests/bug71540.phpt new file mode 100644 index 0000000000..a268021765 --- /dev/null +++ b/ext/xsl/tests/bug71540.phpt @@ -0,0 +1,69 @@ +--TEST-- +Bug #71540 (NULL pointer dereference in xsl_ext_function_php()) +--SKIPIF-- +<?php +if (!extension_loaded('xsl')) die("skip Extension XSL is required\n"); +?> +--FILE-- +<?php +$xml = <<<EOB +<allusers> + <user> + <uid>bob</uid> + </user> +</allusers> +EOB; +$xsl = <<<EOB +<?xml version="1.0" encoding="UTF-8"?> +<xsl:stylesheet version="1.0" + xmlns:xsl="http://www.w3.org/1999/XSL/Transform" + xmlns:php="http://php.net/xsl"> +<xsl:output method="html" encoding="utf-8" indent="yes"/> + <xsl:template match="allusers"> + <html><body> + <h2>Users</h2> + <table> + <xsl:for-each select="user"> + <tr><td> + <xsl:value-of + select="php:function('test',uid,test(test))"/> + </td></tr> + </xsl:for-each> + </table> + </body></html> + </xsl:template> +</xsl:stylesheet> +EOB; + +$xmldoc = new DOMDocument(); +$xmldoc->loadXML($xml); +$xsldoc = new DOMDocument(); +$xsldoc->loadXML($xsl); + +$proc = new XSLTProcessor(); +$proc->registerPHPFunctions(); +$proc->importStyleSheet($xsldoc); +echo $proc->transformToXML($xmldoc); +?> +DONE +--EXPECTF-- +Warning: XSLTProcessor::transformToXml(): xmlXPathCompOpEval: function test not found in %sbug71540.php on line %d + +Warning: XSLTProcessor::transformToXml(): Unregistered function in %sbug71540.php on line %d + +Warning: XSLTProcessor::transformToXml(): Stack usage errror in %sbug71540.php on line %d + +Warning: XSLTProcessor::transformToXml(): Stack usage errror in %sbug71540.php on line %d + +Warning: XSLTProcessor::transformToXml(): Handler name must be a string in %sbug71540.php on line %d + +Warning: XSLTProcessor::transformToXml(): xmlXPathCompiledEval: 2 objects left on the stack. in %sbug71540.php on line %d + +Warning: XSLTProcessor::transformToXml(): runtime error: file %s line 13 element value-of in %sbug71540.php on line %d + +Warning: XSLTProcessor::transformToXml(): XPath evaluation returned no result. in %sbug71540.php on line %d +<html xmlns:php="http://php.net/xsl"><body> +<h2>Users</h2> +<table><tr><td></td></tr></table> +</body></html> +DONE
\ No newline at end of file diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c index be46d38de1..600c7cddb0 100644 --- a/ext/xsl/xsltprocessor.c +++ b/ext/xsl/xsltprocessor.c @@ -231,6 +231,10 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t /* Reverse order to pop values off ctxt stack */ for (i = nargs - 2; i >= 0; i--) { obj = valuePop(ctxt); + if (obj == NULL) { + ZVAL_NULL(&args[i]); + continue; + } switch (obj->type) { case XPATH_STRING: ZVAL_STRING(&args[i], (char *)obj->stringval); @@ -300,7 +304,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t obj = valuePop(ctxt); - if (obj->stringval == NULL) { + if (obj == NULL || obj->stringval == NULL) { php_error_docref(NULL, E_WARNING, "Handler name must be a string"); xmlXPathFreeObject(obj); valuePush(ctxt, xmlXPathNewString((const xmlChar *) "")); diff --git a/ext/zip/config.m4 b/ext/zip/config.m4 index 6dbc1e292b..81f47df556 100644 --- a/ext/zip/config.m4 +++ b/ext/zip/config.m4 @@ -122,6 +122,7 @@ if test "$PHP_ZIP" != "no"; then lib/zip_get_archive_comment.c lib/zip_get_archive_flag.c lib/zip_get_compression_implementation.c\ lib/zip_get_encryption_implementation.c lib/zip_get_file_comment.c lib/zip_get_name.c lib/zip_get_num_entries.c \ lib/zip_get_num_files.c lib/zip_memdup.c lib/zip_name_locate.c lib/zip_new.c lib/zip_open.c lib/zip_rename.c lib/zip_replace.c\ + lib/zip_hash.c \ lib/zip_set_archive_comment.c lib/zip_set_archive_flag.c lib/zip_set_default_password.c lib/zip_set_file_comment.c\ lib/zip_set_file_compression.c lib/zip_set_name.c lib/zip_source_buffer.c lib/zip_source_close.c lib/zip_source_crc.c\ lib/zip_source_deflate.c lib/zip_source_error.c lib/zip_source_file.c lib/zip_source_filep.c lib/zip_source_free.c\ diff --git a/ext/zip/config.w32 b/ext/zip/config.w32 index 0aa9f3eaa0..5460b6d6bd 100644 --- a/ext/zip/config.w32 +++ b/ext/zip/config.w32 @@ -21,6 +21,7 @@ if (PHP_ZIP != "no") { zip_get_archive_comment.c zip_get_archive_flag.c zip_get_compression_implementation.c\ zip_get_encryption_implementation.c zip_get_file_comment.c zip_get_name.c zip_get_num_entries.c \ zip_get_num_files.c zip_memdup.c zip_name_locate.c zip_new.c zip_open.c zip_rename.c zip_replace.c\ + zip_hash.c \ zip_set_archive_comment.c zip_set_archive_flag.c zip_set_default_password.c zip_set_file_comment.c\ zip_set_file_compression.c zip_set_name.c zip_source_buffer.c zip_source_close.c zip_source_crc.c\ zip_source_deflate.c zip_source_error.c zip_source_filep.c zip_source_free.c\ diff --git a/ext/zip/lib/zip_add_entry.c b/ext/zip/lib/zip_add_entry.c index 24dbdaf47c..9a9465c5f0 100644 --- a/ext/zip/lib/zip_add_entry.c +++ b/ext/zip/lib/zip_add_entry.c @@ -1,6 +1,6 @@ /* zip_add_entry.c -- create and init struct zip_entry - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -46,8 +46,19 @@ _zip_add_entry(zip_t *za) if (za->nentry+1 >= za->nentry_alloc) { zip_entry_t *rentries; - zip_uint64_t nalloc = za->nentry_alloc + 16; - zip_uint64_t realloc_size = sizeof(struct zip_entry) * (size_t)nalloc; + zip_uint64_t nalloc = za->nentry_alloc; + zip_uint64_t additional_entries = 2 * nalloc; + zip_uint64_t realloc_size; + + if (additional_entries < 16) { + additional_entries = 16; + } + else if (additional_entries > 1024) { + additional_entries = 1024; + } + /* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */ + nalloc += additional_entries; + realloc_size = sizeof(struct zip_entry) * (size_t)nalloc; if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) { zip_error_set(&za->error, ZIP_ER_MEMORY, 0); diff --git a/ext/zip/lib/zip_buffer.c b/ext/zip/lib/zip_buffer.c index 3d79b09f13..43864f9ba9 100644 --- a/ext/zip/lib/zip_buffer.c +++ b/ext/zip/lib/zip_buffer.c @@ -303,6 +303,17 @@ _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset) } +int +_zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) { + zip_uint64_t offset = buffer->offset + length; + + if (offset < buffer->offset) { + buffer->ok = false; + return -1; + } + return _zip_buffer_set_offset(buffer, offset); +} + zip_uint64_t _zip_buffer_size(zip_buffer_t *buffer) { diff --git a/ext/zip/lib/zip_close.c b/ext/zip/lib/zip_close.c index a13e4466b3..b5eca67a46 100644 --- a/ext/zip/lib/zip_close.c +++ b/ext/zip/lib/zip_close.c @@ -40,7 +40,6 @@ #ifdef HAVE_STRINGS_H #include <strings.h> #endif -#include <errno.h> #ifdef HAVE_UNISTD_H #include <unistd.h> #endif diff --git a/ext/zip/lib/zip_delete.c b/ext/zip/lib/zip_delete.c index b3e7abb848..34520b0310 100644 --- a/ext/zip/lib/zip_delete.c +++ b/ext/zip/lib/zip_delete.c @@ -1,6 +1,6 @@ /* zip_delete.c -- delete file from zip archive - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -38,6 +38,8 @@ ZIP_EXTERN int zip_delete(zip_t *za, zip_uint64_t idx) { + const char *name; + if (idx >= za->nentry) { zip_error_set(&za->error, ZIP_ER_INVAL, 0); return -1; @@ -48,6 +50,14 @@ zip_delete(zip_t *za, zip_uint64_t idx) return -1; } + if ((name=_zip_get_name(za, idx, 0, &za->error)) == NULL) { + return -1; + } + + if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) { + return -1; + } + /* allow duplicate file names, because the file will * be removed directly afterwards */ if (_zip_unchange(za, idx, 1) != 0) diff --git a/ext/zip/lib/zip_dirent.c b/ext/zip/lib/zip_dirent.c index e3a78b3146..630b6a49cb 100644 --- a/ext/zip/lib/zip_dirent.c +++ b/ext/zip/lib/zip_dirent.c @@ -1,6 +1,6 @@ /* zip_dirent.c -- read directory entry (local or central), clean dirent - Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -17,7 +17,7 @@ 3. The names of the authors may not be used to endorse or promote products derived from this software without specific prior written permission. - + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -35,7 +35,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <errno.h> #include <sys/types.h> #include <sys/stat.h> @@ -67,7 +66,7 @@ _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error) { zip_cdir_t *cd; zip_uint64_t i; - + if ((cd=(zip_cdir_t *)malloc(sizeof(*cd))) == NULL) { zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; @@ -110,7 +109,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor } offset = (zip_uint64_t)off; - is_zip64 = 0; + is_zip64 = false; for (i=0; i<survivors; i++) { zip_entry_t *entry = za->entry+filelist[i].idx; @@ -135,7 +134,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor zip_error_set(&za->error, ZIP_ER_MEMORY, 0); return -1; } - + if (is_zip64) { _zip_buffer_put(buffer, EOCD64_MAGIC, 4); _zip_buffer_put_64(buffer, EOCD64LEN-12); @@ -152,7 +151,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor _zip_buffer_put_64(buffer, offset+size); _zip_buffer_put_32(buffer, 1); } - + _zip_buffer_put(buffer, EOCD_MAGIC, 4); _zip_buffer_put_32(buffer, 0); _zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors)); @@ -163,7 +162,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor comment = za->comment_changed ? za->comment_changes : za->comment_orig; _zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0)); - + if (!_zip_buffer_ok(buffer)) { zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); _zip_buffer_free(buffer); @@ -199,7 +198,7 @@ _zip_dirent_clone(const zip_dirent_t *sde) memcpy(tde, sde, sizeof(*sde)); else _zip_dirent_init(tde); - + tde->changed = 0; tde->cloned = 1; @@ -289,7 +288,7 @@ _zip_dirent_new(void) Fills the zip directory entry zde. If buffer is non-NULL, data is taken from there; otherwise data is read from fp as needed. - + If local is true, it reads a local header instead of a central directory entry. Returns size of dirent read if successful. On error, error is filled in and -1 is returned. @@ -304,7 +303,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo zip_uint16_t filename_len, comment_len, ef_len; bool from_buffer = (buffer != NULL); - + size = local ? LENTRYSIZE : CDENTRYSIZE; if (buffer) { @@ -337,19 +336,19 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo zde->version_needed = _zip_buffer_get_16(buffer); zde->bitflags = _zip_buffer_get_16(buffer); zde->comp_method = _zip_buffer_get_16(buffer); - + /* convert to time_t */ dostime = _zip_buffer_get_16(buffer); dosdate = _zip_buffer_get_16(buffer); zde->last_mod = _zip_d2u_time(dostime, dosdate); - + zde->crc = _zip_buffer_get_32(buffer); zde->comp_size = _zip_buffer_get_32(buffer); zde->uncomp_size = _zip_buffer_get_32(buffer); - + filename_len = _zip_buffer_get_16(buffer); ef_len = _zip_buffer_get_16(buffer); - + if (local) { comment_len = 0; zde->disk_number = 0; @@ -363,7 +362,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo zde->ext_attrib = _zip_buffer_get_32(buffer); zde->offset = _zip_buffer_get_32(buffer); } - + if (!_zip_buffer_ok(buffer)) { zip_error_set(error, ZIP_ER_INTERNAL, 0); if (!from_buffer) { @@ -386,7 +385,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo } else { _zip_buffer_free(buffer); - + if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) { return -1; } @@ -424,7 +423,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo } return -1; } - if ((zde->extra_fields=_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error)) == NULL) { + if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) { free(ef); if (!from_buffer) { _zip_buffer_free(buffer); @@ -471,7 +470,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo } return -1; } - + if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) { zip_error_set(error, ZIP_ER_MEMORY, 0); if (!from_buffer) { @@ -479,11 +478,14 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo } return -1; } - + if (zde->uncomp_size == ZIP_UINT32_MAX) zde->uncomp_size = _zip_buffer_get_64(ef_buffer); - else if (local) - ef += 8; + else if (local) { + /* From appnote.txt: This entry in the Local header MUST + include BOTH original and compressed file size fields. */ + (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */ + } if (zde->comp_size == ZIP_UINT32_MAX) zde->comp_size = _zip_buffer_get_64(ef_buffer); if (!local) { @@ -492,7 +494,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo if (zde->disk_number == ZIP_UINT16_MAX) zde->disk_number = _zip_buffer_get_32(buffer); } - + if (!_zip_buffer_eof(ef_buffer)) { zip_error_set(error, ZIP_ER_INCONS, 0); _zip_buffer_free(ef_buffer); @@ -503,7 +505,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo } _zip_buffer_free(ef_buffer); } - + if (!_zip_buffer_ok(buffer)) { zip_error_set(error, ZIP_ER_INTERNAL, 0); if (!from_buffer) { @@ -520,7 +522,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo zip_error_set(error, ZIP_ER_SEEK, EFBIG); return -1; } - + zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields); return (zip_int64_t)(size + variable_size); @@ -535,15 +537,15 @@ _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string zip_buffer_t *buffer; const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL); - + if (ef == NULL || ef_len < 5 || ef[0] != 1) { return str; } - + if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) { return str; } - + _zip_buffer_get_8(buffer); ef_crc = _zip_buffer_get_32(buffer); @@ -556,9 +558,9 @@ _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string str = ef_str; } } - + _zip_buffer_free(buffer); - + return str; } @@ -578,7 +580,7 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) _zip_error_set_from_source(error, src); return -1; } - + if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) { return -1; } @@ -586,7 +588,7 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error) for (i=0; i<(local ? 2 : 3); i++) { size += _zip_buffer_get_16(buffer); } - + if (!_zip_buffer_eof(buffer)) { zip_error_set(error, ZIP_ER_INTERNAL, 0); _zip_buffer_free(buffer); @@ -614,16 +616,15 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) zip_uint16_t dostime, dosdate; zip_encoding_type_t com_enc, name_enc; zip_extra_field_t *ef; + zip_extra_field_t *ef64; + zip_uint32_t ef_total_size; bool is_zip64; bool is_really_zip64; zip_uint8_t buf[CDENTRYSIZE]; zip_buffer_t *buffer; - zip_uint32_t ef_total_size; ef = NULL; - is_zip64 = false; - name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN); com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN); @@ -648,20 +649,19 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) ef = ef2; } } - + is_really_zip64 = _zip_dirent_needs_zip64(de, flags); is_zip64 = (flags & (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64) || is_really_zip64; - + if (is_zip64) { zip_uint8_t ef_zip64[EFZIP64SIZE]; zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64)); - zip_extra_field_t *ef64; if (ef_buffer == NULL) { zip_error_set(&za->error, ZIP_ER_MEMORY, 0); _zip_ef_free(ef); return -1; } - + if (flags & ZIP_FL_LOCAL) { if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) { _zip_buffer_put_64(ef_buffer, de->uncomp_size); @@ -681,7 +681,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) } } } - + if (!_zip_buffer_ok(ef_buffer)) { zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); _zip_buffer_free(ef_buffer); @@ -700,9 +700,9 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) _zip_ef_free(ef); return -1; } - + _zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4); - + if ((flags & ZIP_FL_LOCAL) == 0) { _zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby)); } @@ -715,7 +715,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) _zip_buffer_put_16(buffer, dosdate); _zip_buffer_put_32(buffer, de->crc); - + if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) { /* In local headers, if a ZIP64 EF is written, it MUST contain * both compressed and uncompressed sizes (even if one of the @@ -744,7 +744,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) /* TODO: check for overflow */ ef_total_size = (zip_uint32_t)_zip_ef_size(de->extra_fields, flags) + (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH); _zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size); - + if ((flags & ZIP_FL_LOCAL) == 0) { _zip_buffer_put_16(buffer, _zip_string_length(de->comment)); _zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number); @@ -755,7 +755,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) else _zip_buffer_put_32(buffer, ZIP_UINT32_MAX); } - + if (!_zip_buffer_ok(buffer)) { zip_error_set(&za->error, ZIP_ER_INTERNAL, 0); _zip_buffer_free(buffer); @@ -768,7 +768,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags) _zip_ef_free(ef); return -1; } - + _zip_buffer_free(buffer); if (de->filename) { @@ -810,10 +810,10 @@ _zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate) struct tm tm; memset(&tm, 0, sizeof(tm)); - + /* let mktime decide if DST is in effect */ tm.tm_isdst = -1; - + tm.tm_year = ((ddate>>9)&127) + 1980 - 1900; tm.tm_mon = ((ddate>>5)&15) - 1; tm.tm_mday = ddate&31; @@ -834,13 +834,16 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) zip_buffer_t *buffer; zip_extra_field_t *ef; - raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL); + if ((raw=_zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) { + /* error already set */ + return NULL; + } if (len+5 > ZIP_UINT16_MAX) { zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */ return NULL; } - + if ((buffer = _zip_buffer_new(NULL, len+5)) == NULL) { zip_error_set(error, ZIP_ER_MEMORY, 0); return NULL; @@ -855,7 +858,7 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error) _zip_buffer_free(buffer); return NULL; } - + ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH); _zip_buffer_free(buffer); @@ -898,6 +901,10 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate) struct tm *tm; tm = localtime(&intime); + if (tm->tm_year < 80) { + tm->tm_year = 80; + } + *ddate = (zip_uint16_t)(((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday); *dtime = (zip_uint16_t)(((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1)); diff --git a/ext/zip/lib/zip_discard.c b/ext/zip/lib/zip_discard.c index db22370842..1876c84f0c 100644 --- a/ext/zip/lib/zip_discard.c +++ b/ext/zip/lib/zip_discard.c @@ -1,6 +1,6 @@ /* zip_discard.c -- discard and free struct zip - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -58,6 +58,8 @@ zip_discard(zip_t *za) _zip_string_free(za->comment_orig); _zip_string_free(za->comment_changes); + _zip_hash_free(za->names); + if (za->entry) { for (i=0; i<za->nentry; i++) _zip_entry_finalize(za->entry+i); diff --git a/ext/zip/lib/zip_error.c b/ext/zip/lib/zip_error.c index a21a00bc29..43ddf4f9cb 100644 --- a/ext/zip/lib/zip_error.c +++ b/ext/zip/lib/zip_error.c @@ -1,6 +1,6 @@ /* zip_error.c -- zip_error_t helper functions - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -31,7 +31,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <errno.h> #include <stdlib.h> #include "zipint.h" diff --git a/ext/zip/lib/zip_error_strerror.c b/ext/zip/lib/zip_error_strerror.c index 2f124ccd46..29efc8a91c 100644 --- a/ext/zip/lib/zip_error_strerror.c +++ b/ext/zip/lib/zip_error_strerror.c @@ -1,6 +1,6 @@ /* zip_error_sterror.c -- get string representation of struct zip_error - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -32,7 +32,6 @@ */ -#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/ext/zip/lib/zip_error_to_str.c b/ext/zip/lib/zip_error_to_str.c index d4119253f7..22de177842 100644 --- a/ext/zip/lib/zip_error_to_str.c +++ b/ext/zip/lib/zip_error_to_str.c @@ -1,6 +1,6 @@ /* zip_error_to_str.c -- get string representation of zip error code - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -32,7 +32,6 @@ */ -#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> diff --git a/ext/zip/lib/zip_extra_field.c b/ext/zip/lib/zip_extra_field.c index b2566c6887..035047827e 100644 --- a/ext/zip/lib/zip_extra_field.c +++ b/ext/zip/lib/zip_extra_field.c @@ -31,13 +31,11 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#include "zipint.h" - -#include <errno.h> #include <stdlib.h> #include <string.h> +#include "zipint.h" + zip_extra_field_t * _zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error) @@ -207,20 +205,20 @@ _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_fla } -zip_extra_field_t * -_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_error_t *error) +bool +_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_extra_field_t **ef_head_p, zip_error_t *error) { zip_buffer_t *buffer; zip_extra_field_t *ef, *ef2, *ef_head; if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) { zip_error_set(error, ZIP_ER_MEMORY, 0); - return NULL; + return false; } ef_head = ef = NULL; - while (_zip_buffer_ok(buffer) && !_zip_buffer_eof(buffer)) { + while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) { zip_uint16_t fid, flen; zip_uint8_t *ef_data; @@ -229,14 +227,17 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_ ef_data = _zip_buffer_get(buffer, flen); if (ef_data == NULL) { - break; + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_buffer_free(buffer); + _zip_ef_free(ef_head); + return false; } if ((ef2=_zip_ef_new(fid, flen, ef_data, flags)) == NULL) { zip_error_set(error, ZIP_ER_MEMORY, 0); _zip_buffer_free(buffer); _zip_ef_free(ef_head); - return NULL; + return false; } if (ef_head) { @@ -248,15 +249,29 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_ } if (!_zip_buffer_eof(buffer)) { - zip_error_set(error, ZIP_ER_INCONS, 0); - _zip_buffer_free(buffer); - _zip_ef_free(ef_head); - return NULL; + /* Android APK files align stored file data with padding in extra fields; ignore. */ + /* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */ + size_t glen = _zip_buffer_left(buffer); + zip_uint8_t *garbage; + garbage = _zip_buffer_get(buffer, glen); + if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) { + zip_error_set(error, ZIP_ER_INCONS, 0); + _zip_buffer_free(buffer); + _zip_ef_free(ef_head); + return false; + } } _zip_buffer_free(buffer); + + if (ef_head_p) { + *ef_head_p = ef_head; + } + else { + _zip_ef_free(ef_head); + } - return ef_head; + return true; } @@ -400,14 +415,16 @@ _zip_read_local_ef(zip_t *za, zip_uint64_t idx) if (ef_raw == NULL) return -1; - if ((ef=_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &za->error)) == NULL) { + if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) { free(ef_raw); return -1; } free(ef_raw); - - ef = _zip_ef_remove_internal(ef); - e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); + + if (ef) { + ef = _zip_ef_remove_internal(ef); + e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef); + } } e->orig->local_extra_fields_read = 1; diff --git a/ext/zip/lib/zip_fdopen.c b/ext/zip/lib/zip_fdopen.c index c5b55311d2..bbcdf4f6bf 100644 --- a/ext/zip/lib/zip_fdopen.c +++ b/ext/zip/lib/zip_fdopen.c @@ -33,6 +33,9 @@ #include "zipint.h" +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif ZIP_EXTERN zip_t * diff --git a/ext/zip/lib/zip_file_get_offset.c b/ext/zip/lib/zip_file_get_offset.c index 1aaca712d7..0257b042bc 100644 --- a/ext/zip/lib/zip_file_get_offset.c +++ b/ext/zip/lib/zip_file_get_offset.c @@ -1,6 +1,6 @@ /* zip_file_get_offset.c -- get offset of file data in archive. - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -35,7 +35,6 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> -#include <errno.h> #include <sys/types.h> #include <sys/stat.h> diff --git a/ext/zip/lib/zip_filerange_crc.c b/ext/zip/lib/zip_filerange_crc.c index 8e06e8fa8b..f2a27fab34 100644 --- a/ext/zip/lib/zip_filerange_crc.c +++ b/ext/zip/lib/zip_filerange_crc.c @@ -1,6 +1,6 @@ /* zip_filerange_crc.c -- compute CRC32 for a range of a file - Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner + Copyright (C) 2008-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -33,7 +33,6 @@ #include <stdio.h> -#include <errno.h> #include "zipint.h" diff --git a/ext/zip/lib/zip_fopen_index.c b/ext/zip/lib/zip_fopen_index.c index e9a169a2e1..7496f9829f 100644 --- a/ext/zip/lib/zip_fopen_index.c +++ b/ext/zip/lib/zip_fopen_index.c @@ -1,6 +1,6 @@ /* zip_fopen_index.c -- open file in zip archive for reading by index - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -32,7 +32,6 @@ */ -#include <errno.h> #include <stdio.h> #include <stdlib.h> diff --git a/ext/zip/lib/zip_fopen_index_encrypted.c b/ext/zip/lib/zip_fopen_index_encrypted.c index 21cc43333c..92258e85fe 100644 --- a/ext/zip/lib/zip_fopen_index_encrypted.c +++ b/ext/zip/lib/zip_fopen_index_encrypted.c @@ -1,6 +1,6 @@ /* zip_fopen_index_encrypted.c -- open file for reading by index w/ password - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -32,7 +32,6 @@ */ -#include <errno.h> #include <stdio.h> #include <stdlib.h> diff --git a/ext/zip/lib/zip_hash.c b/ext/zip/lib/zip_hash.c new file mode 100644 index 0000000000..23f9708dfd --- /dev/null +++ b/ext/zip/lib/zip_hash.c @@ -0,0 +1,267 @@ +/* + zip_hash.c -- hash table string -> uint64 + Copyright (C) 2015-2016 Dieter Baron and Thomas Klausner + + This file is part of libzip, a library to manipulate ZIP archives. + The authors can be contacted at <libzip@nih.at> + + Redistribution and use in source and binary forms, with or without + modification, are permitted provided that the following conditions + are met: + 1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. + 2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in + the documentation and/or other materials provided with the + distribution. + 3. The names of the authors may not be used to endorse or promote + products derived from this software without specific prior + written permission. + + THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS + OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY + DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE + GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER + IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR + OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN + IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <stdlib.h> +#include <string.h> +#include "zipint.h" + +struct zip_hash_entry { + const zip_uint8_t *name; + zip_int64_t orig_index; + zip_int64_t current_index; + struct zip_hash_entry *next; +}; +typedef struct zip_hash_entry zip_hash_entry_t; + +struct zip_hash { + zip_uint16_t table_size; + zip_hash_entry_t **table; +}; + +zip_hash_t * +_zip_hash_new(zip_uint16_t table_size, zip_error_t *error) +{ + zip_hash_t *hash; + + if (table_size == 0) { + zip_error_set(error, ZIP_ER_INTERNAL, 0); + return NULL; + } + + if ((hash=(zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + hash->table_size = table_size; + if ((hash->table=(zip_hash_entry_t**)calloc(table_size, sizeof(zip_hash_entry_t *))) == NULL) { + free(hash); + zip_error_set(error, ZIP_ER_MEMORY, 0); + return NULL; + } + + return hash; +} + +static void +_free_list(zip_hash_entry_t *entry) +{ + zip_hash_entry_t *next; + do { + next = entry->next; + free(entry); + entry = next; + } while (entry != NULL); +} + +void +_zip_hash_free(zip_hash_t *hash) +{ + zip_uint16_t i; + + if (hash == NULL) { + return; + } + + for (i=0; i<hash->table_size; i++) { + if (hash->table[i] != NULL) { + _free_list(hash->table[i]); + } + } + free(hash->table); + free(hash); +} + +static zip_uint16_t +_hash_string(const zip_uint8_t *name, zip_uint16_t size) +{ +#define HASH_MULTIPLIER 33 + zip_uint16_t value = 5381; + + if (name == NULL) + return 0; + + while (*name != 0) { + value = (zip_uint16_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % size); + name++; + } + + return value; +} + +/* insert into hash, return error on existence or memory issues */ +bool +_zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error) +{ + zip_uint16_t hash_value; + zip_hash_entry_t *entry; + + if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return false; + } + + hash_value = _hash_string(name, hash->table_size); + for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) { + if (strcmp((const char *)name, (const char *)entry->name) == 0) { + if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) { + zip_error_set(error, ZIP_ER_EXISTS, 0); + return false; + } + else { + break; + } + } + } + + if (entry == NULL) { + if ((entry=(zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) { + zip_error_set(error, ZIP_ER_MEMORY, 0); + return false; + } + entry->name = name; + entry->next = hash->table[hash_value]; + hash->table[hash_value] = entry; + entry->orig_index = -1; + } + + if (flags & ZIP_FL_UNCHANGED) { + entry->orig_index = (zip_int64_t)index; + } + entry->current_index = (zip_int64_t)index; + + return true; +} + +/* remove entry from hash, error if not found */ +bool +_zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error) +{ + zip_uint16_t hash_value; + zip_hash_entry_t *entry, *previous; + + if (hash == NULL || name == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return false; + } + + hash_value = _hash_string(name, hash->table_size); + previous = NULL; + entry = hash->table[hash_value]; + while (entry) { + if (strcmp((const char *)name, (const char *)entry->name) == 0) { + if (entry->orig_index == -1) { + if (previous) { + previous->next = entry->next; + } + else { + hash->table[hash_value] = entry->next; + } + free(entry); + } + else { + entry->current_index = -1; + } + return true; + } + previous = entry; + entry = entry->next; + }; + + zip_error_set(error, ZIP_ER_NOENT, 0); + return false; +} + +/* find value for entry in hash, -1 if not found */ +zip_int64_t +_zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error) +{ + zip_uint16_t hash_value; + zip_hash_entry_t *entry; + + if (hash == NULL || name == NULL) { + zip_error_set(error, ZIP_ER_INVAL, 0); + return -1; + } + + hash_value = _hash_string(name, hash->table_size); + for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) { + if (strcmp((const char *)name, (const char *)entry->name) == 0) { + if (flags & ZIP_FL_UNCHANGED) { + if (entry->orig_index != -1) { + return entry->orig_index; + } + } + else { + if (entry->current_index != -1) { + return entry->current_index; + } + } + break; + } + } + + zip_error_set(error, ZIP_ER_NOENT, 0); + return -1; +} + +void +_zip_hash_revert(zip_hash_t *hash) +{ + zip_uint16_t i; + zip_hash_entry_t *entry, *previous; + + for (i = 0; i < hash->table_size; i++) { + previous = NULL; + entry = hash->table[i]; + while (entry) { + if (entry->orig_index == -1) { + zip_hash_entry_t *p; + if (previous) { + previous->next = entry->next; + } + else { + hash->table[i] = entry->next; + } + p = entry; + entry = entry->next; + /* previous does not change */ + free(p); + } + else { + entry->current_index = entry->orig_index; + previous = entry; + entry = entry->next; + } + } + } +} diff --git a/ext/zip/lib/zip_io_util.c b/ext/zip/lib/zip_io_util.c index 4a6bc1ddc1..b16927defb 100644 --- a/ext/zip/lib/zip_io_util.c +++ b/ext/zip/lib/zip_io_util.c @@ -1,6 +1,6 @@ /* zip_io_util.c -- I/O helper functions - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -31,7 +31,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <errno.h> #include <stdlib.h> #include <string.h> diff --git a/ext/zip/lib/zip_name_locate.c b/ext/zip/lib/zip_name_locate.c index 820ea0ca7f..50ca40b1a9 100644 --- a/ext/zip/lib/zip_name_locate.c +++ b/ext/zip/lib/zip_name_locate.c @@ -1,6 +1,6 @@ /* zip_name_locate.c -- get index by name - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -62,27 +62,33 @@ _zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *e return -1; } - cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp; - - for (i=0; i<za->nentry; i++) { - fn = _zip_get_name(za, i, flags, error); - - /* newly added (partially filled) entry or error */ - if (fn == NULL) - continue; - - if (flags & ZIP_FL_NODIR) { - p = strrchr(fn, '/'); - if (p) - fn = p+1; + if (flags & (ZIP_FL_NOCASE|ZIP_FL_NODIR|ZIP_FL_ENC_CP437)) { + /* can't use hash table */ + cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp; + + for (i=0; i<za->nentry; i++) { + fn = _zip_get_name(za, i, flags, error); + + /* newly added (partially filled) entry or error */ + if (fn == NULL) + continue; + + if (flags & ZIP_FL_NODIR) { + p = strrchr(fn, '/'); + if (p) + fn = p+1; + } + + if (cmp(fname, fn) == 0) { + _zip_error_clear(error); + return (zip_int64_t)i; + } } - if (cmp(fname, fn) == 0) { - _zip_error_clear(error); - return (zip_int64_t)i; - } + zip_error_set(error, ZIP_ER_NOENT, 0); + return -1; + } + else { + return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error); } - - zip_error_set(error, ZIP_ER_NOENT, 0); - return -1; } diff --git a/ext/zip/lib/zip_new.c b/ext/zip/lib/zip_new.c index d54a247c29..562dd76a36 100644 --- a/ext/zip/lib/zip_new.c +++ b/ext/zip/lib/zip_new.c @@ -1,6 +1,6 @@ /* zip_new.c -- create and init struct zip - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -52,6 +52,11 @@ _zip_new(zip_error_t *error) return NULL; } + if ((za->names = _zip_hash_new(ZIP_HASH_TABLE_SIZE, error)) == NULL) { + free(za); + return NULL; + } + za->src = NULL; za->open_flags = 0; zip_error_init(&za->error); diff --git a/ext/zip/lib/zip_open.c b/ext/zip/lib/zip_open.c index fb9c566cb1..d6209ee1e7 100644 --- a/ext/zip/lib/zip_open.c +++ b/ext/zip/lib/zip_open.c @@ -33,7 +33,6 @@ #include <sys/stat.h> -#include <errno.h> #include <limits.h> #include <stdio.h> #include <stdlib.h> @@ -184,7 +183,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) zip_t *za; zip_cdir_t *cdir; struct zip_stat st; - zip_uint64_t len; + zip_uint64_t len, idx; zip_stat_init(&st); if (zip_source_stat(src, &st) < 0) { @@ -223,11 +222,31 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error) za->nentry = cdir->nentry; za->nentry_alloc = cdir->nentry_alloc; za->comment_orig = cdir->comment; - - za->ch_flags = za->flags; free(cdir); + for (idx = 0; idx < za->nentry; idx++) { + const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error); + if (name == NULL) { + /* keep src so discard does not get rid of it */ + zip_source_keep(src); + zip_discard(za); + return NULL; + } + + if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) { + if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) { + _zip_error_copy(error, &za->error); + /* keep src so discard does not get rid of it */ + zip_source_keep(src); + zip_discard(za); + return NULL; + } + } + } + + za->ch_flags = za->flags; + return za; } @@ -274,11 +293,6 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err return NULL; } - if (_zip_buffer_get_32(buffer) != 0) { - zip_error_set(error, ZIP_ER_MULTIDISK, 0); - return NULL; - } - if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) { _zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN); cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error); @@ -649,7 +663,8 @@ _zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little } -static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) +static zip_cdir_t * +_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error) { zip_cdir_t *cd; zip_uint64_t i, nentry, size, offset, eocd_offset; @@ -661,7 +676,12 @@ static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, eocd_offset = _zip_buffer_offset(buffer); - _zip_buffer_get(buffer, 8); /* magic and number of disks already verified */ + _zip_buffer_get(buffer, 4); /* magic already verified */ + + if (_zip_buffer_get_32(buffer) != 0) { + zip_error_set(error, ZIP_ER_MULTIDISK, 0); + return NULL; + } /* number of cdir-entries on this disk */ i = _zip_buffer_get_16(buffer); @@ -711,10 +731,14 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse zip_uint64_t eocd_offset; zip_uint64_t size, nentry, i, eocdloc_offset; bool free_buffer; + zip_uint32_t num_disks, num_disks64, eocd_disk, eocd_disk64; eocdloc_offset = _zip_buffer_offset(buffer); - _zip_buffer_get(buffer, 8); /* magic and single disk already verified */ + _zip_buffer_get(buffer, 4); /* magic already verified */ + + num_disks = _zip_buffer_get_16(buffer); + eocd_disk = _zip_buffer_get_16(buffer); eocd_offset = _zip_buffer_get_64(buffer); if (eocd_offset > ZIP_INT64_MAX || eocd_offset + EOCD64LEN < eocd_offset) { @@ -760,8 +784,29 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse return NULL; } - _zip_buffer_get(buffer, 12); /* skip version made by/needed and num disks */ - + _zip_buffer_get(buffer, 4); /* skip version made by/needed */ + + num_disks64 = _zip_buffer_get_32(buffer); + eocd_disk64 = _zip_buffer_get_32(buffer); + + /* if eocd values are 0xffff, we have to use eocd64 values. + otherwise, if the values are not the same, it's inconsistent; + in any case, if the value is not 0, we don't support it */ + if (num_disks == 0xffff) { + num_disks = num_disks64; + } + if (eocd_disk == 0xffff) { + eocd_disk = eocd_disk64; + } + if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) { + zip_error_set(error, ZIP_ER_INCONS, 0); + return NULL; + } + if (num_disks != 0 || eocd_disk != 0) { + zip_error_set(error, ZIP_ER_MULTIDISK, 0); + return NULL; + } + nentry = _zip_buffer_get_64(buffer); i = _zip_buffer_get_64(buffer); diff --git a/ext/zip/lib/zip_set_default_password.c b/ext/zip/lib/zip_set_default_password.c index ac098dc5fc..10b48062fd 100644 --- a/ext/zip/lib/zip_set_default_password.c +++ b/ext/zip/lib/zip_set_default_password.c @@ -44,8 +44,7 @@ zip_set_default_password(zip_t *za, const char *passwd) if (za == NULL) return -1; - if (za->default_password) - free(za->default_password); + free(za->default_password); if (passwd) { if ((za->default_password=strdup(passwd)) == NULL) { diff --git a/ext/zip/lib/zip_set_name.c b/ext/zip/lib/zip_set_name.c index 5a10381753..2a461437e2 100644 --- a/ext/zip/lib/zip_set_name.c +++ b/ext/zip/lib/zip_set_name.c @@ -1,6 +1,6 @@ /* zip_set_name.c -- rename helper function - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -43,8 +43,10 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) { zip_entry_t *e; zip_string_t *str; - int changed; + bool same_as_orig; zip_int64_t i; + const zip_uint8_t *old_name, *new_name; + zip_string_t *old_str; if (idx >= za->nentry) { zip_error_set(&za->error, ZIP_ER_INVAL, 0); @@ -56,7 +58,7 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) return -1; } - if (name && strlen(name) > 0) { + if (name && name[0] != '\0') { /* TODO: check for string too long */ if ((str=_zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL) return -1; @@ -81,34 +83,75 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags) e = za->entry+idx; - if (e->changes) { - _zip_string_free(e->changes->filename); - e->changes->filename = NULL; - e->changes->changed &= ~ZIP_DIRENT_FILENAME; - } - if (e->orig) - changed = !_zip_string_equal(e->orig->filename, str); + same_as_orig = _zip_string_equal(e->orig->filename, str); else - changed = 1; - - if (changed) { - if (e->changes == NULL) { - if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { - zip_error_set(&za->error, ZIP_ER_MEMORY, 0); - _zip_string_free(str); - return -1; - } - } - e->changes->filename = str; - e->changes->changed |= ZIP_DIRENT_FILENAME; + same_as_orig = false; + + if (!same_as_orig && e->changes == NULL) { + if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) { + zip_error_set(&za->error, ZIP_ER_MEMORY, 0); + _zip_string_free(str); + return -1; + } + } + + if ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) { + _zip_string_free(str); + return -1; + } + + if (e->changes) { + old_str = e->changes->filename; + } + else if (e->orig) { + old_str = e->orig->filename; } else { + old_str = NULL; + } + + if (old_str) { + if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) { + _zip_string_free(str); + return -1; + } + } + else { + old_name = NULL; + } + + if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) { + _zip_string_free(str); + return -1; + } + if (old_name) { + _zip_hash_delete(za->names, old_name, NULL); + } + + if (same_as_orig) { + if (e->changes) { + if (e->changes->changed & ZIP_DIRENT_FILENAME) { + _zip_string_free(e->changes->filename); + e->changes->changed &= ~ZIP_DIRENT_FILENAME; + if (e->changes->changed == 0) { + _zip_dirent_free(e->changes); + e->changes = NULL; + } + else { + /* TODO: what if not cloned? can that happen? */ + e->changes->filename = e->orig->filename; + } + } + } _zip_string_free(str); - if (e->changes && e->changes->changed == 0) { - _zip_dirent_free(e->changes); - e->changes = NULL; + } + else { + if (e->changes->changed & ZIP_DIRENT_FILENAME) { + _zip_string_free(e->changes->filename); } + e->changes->changed |= ZIP_DIRENT_FILENAME; + e->changes->filename = str; } return 0; diff --git a/ext/zip/lib/zip_source_buffer.c b/ext/zip/lib/zip_source_buffer.c index aadf6e40b0..f3f8ee0d58 100644 --- a/ext/zip/lib/zip_source_buffer.c +++ b/ext/zip/lib/zip_source_buffer.c @@ -1,6 +1,6 @@ /* zip_source_buffer.c -- create zip data source from buffer - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -31,7 +31,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <errno.h> #include <stdlib.h> #include <string.h> @@ -376,6 +375,7 @@ static zip_int64_t buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *error) { zip_uint64_t n, i, fragment_offset; + zip_uint8_t **fragments; if (buffer->offset + length + buffer->fragment_size - 1 < length) { zip_error_set(error, ZIP_ER_INVAL, 0); @@ -388,7 +388,6 @@ buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip if (needed_fragments > buffer->fragments_capacity) { zip_uint64_t new_capacity = buffer->fragments_capacity; - zip_uint8_t **fragments; while (new_capacity < needed_fragments) { new_capacity *= 2; diff --git a/ext/zip/lib/zip_source_crc.c b/ext/zip/lib/zip_source_crc.c index eed726616a..01f526c647 100644 --- a/ext/zip/lib/zip_source_crc.c +++ b/ext/zip/lib/zip_source_crc.c @@ -1,6 +1,6 @@ /* zip_source_crc.c -- pass-through source that calculates CRC32 and size - Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -39,10 +39,12 @@ #include "zipint.h" struct crc_context { - int eof; - int validate; + int validate; /* whether to check CRC on EOF and return error on mismatch */ + int crc_complete; /* whether CRC was computed for complete file */ zip_error_t error; zip_uint64_t size; + zip_uint64_t position; /* current reading position */ + zip_uint64_t crc_position; /* how far we've computed the CRC */ zip_uint32_t crc; }; @@ -64,12 +66,13 @@ zip_source_crc(zip_t *za, zip_source_t *src, int validate) return NULL; } - ctx->eof = 0; - ctx->validate = validate; zip_error_init(&ctx->error); + ctx->validate = validate; + ctx->crc_complete = 0; + ctx->crc_position = 0; + ctx->crc = (zip_uint32_t)crc32(0, NULL, 0); ctx->size = 0; - ctx->crc = 0; - + return zip_source_layered(za, src, crc_read, ctx); } @@ -84,51 +87,50 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source switch (cmd) { case ZIP_SOURCE_OPEN: - ctx->eof = 0; - ctx->crc = (zip_uint32_t)crc32(0, NULL, 0); - ctx->size = 0; - + ctx->position = 0; return 0; case ZIP_SOURCE_READ: - if (ctx->eof || len == 0) - return 0; - - if ((n=zip_source_read(src, data, len)) < 0) { + if ((n = zip_source_read(src, data, len)) < 0) { _zip_error_set_from_source(&ctx->error, src); return -1; } if (n == 0) { - ctx->eof = 1; - if (ctx->validate) { - struct zip_stat st; + if (ctx->crc_position == ctx->position) { + ctx->crc_complete = 1; + ctx->size = ctx->position; + + if (ctx->validate) { + struct zip_stat st; - if (zip_source_stat(src, &st) < 0) { - _zip_error_set_from_source(&ctx->error, src); - return -1; - } + if (zip_source_stat(src, &st) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } - if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) { - zip_error_set(&ctx->error, ZIP_ER_CRC, 0); - return -1; - } - if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) { - zip_error_set(&ctx->error, ZIP_ER_INCONS, 0); - return -1; + if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) { + zip_error_set(&ctx->error, ZIP_ER_CRC, 0); + return -1; + } + if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) { + zip_error_set(&ctx->error, ZIP_ER_INCONS, 0); + return -1; + } } } } - else { + else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) { zip_uint64_t i, nn; - for (i=0; i < (zip_uint64_t)n; i += nn) { + for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) { nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n-i); ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn); + ctx->crc_position += nn; } - ctx->size += (zip_uint64_t)n; } + ctx->position += (zip_uint64_t)n; return n; case ZIP_SOURCE_CLOSE: @@ -140,7 +142,7 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source st = (zip_stat_t *)data; - if (ctx->eof) { + if (ctx->crc_complete) { /* TODO: Set comp_size, comp_method, encryption_method? After all, this only works for uncompressed data. */ st->size = ctx->size; @@ -161,7 +163,37 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source return 0; case ZIP_SOURCE_SUPPORTS: - return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1); + { + zip_int64_t mask = zip_source_supports(src); + + if (mask < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1); + } + + case ZIP_SOURCE_SEEK: + { + zip_int64_t new_position; + zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error); + + if (args == NULL) { + return -1; + } + if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) { + _zip_error_set_from_source(&ctx->error, src); + return -1; + } + + ctx->position = (zip_uint64_t)new_position; + + return 0; + } + + case ZIP_SOURCE_TELL: + return (zip_int64_t)ctx->position; default: zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0); diff --git a/ext/zip/lib/zip_source_file.c b/ext/zip/lib/zip_source_file.c index 1465e1700e..b3cd7ab29f 100644 --- a/ext/zip/lib/zip_source_file.c +++ b/ext/zip/lib/zip_source_file.c @@ -32,7 +32,6 @@ */ -#include <errno.h> #include <stdio.h> #include "zipint.h" diff --git a/ext/zip/lib/zip_source_filep.c b/ext/zip/lib/zip_source_filep.c index e541305d7f..70255dec41 100644 --- a/ext/zip/lib/zip_source_filep.c +++ b/ext/zip/lib/zip_source_filep.c @@ -31,15 +31,17 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -#include "zipint.h" - #include <sys/stat.h> -#include <errno.h> #include <stdio.h> #include <stdlib.h> #include <string.h> +#include "zipint.h" + +#ifdef HAVE_UNISTD_H +#include <unistd.h> +#endif + #ifdef _WIN32 /* WIN32 needs <fcntl.h> for _O_BINARY */ #include <fcntl.h> @@ -49,11 +51,12 @@ #ifndef S_ISREG #define S_ISREG(m) (((m) & S_IFMT) == S_IFREG) #endif -#ifndef S_IRWXG -#define S_IRWXG (S_IRWXU >> 3) -#endif -#ifndef S_IRWXO -#define S_IRWXO (S_IRWXG >> 3) +#if defined(S_IXUSR) && defined(S_IRWXG) && defined(S_IRWXO) +#define _SAFE_MASK (S_IXUSR | S_IRWXG | S_IRWXO) +#elif defined(_S_IWRITE) +#define _SAFE_MASK (_S_IWRITE) +#else +#error do not know safe values for umask, please report this #endif #ifdef _MSC_VER @@ -183,13 +186,7 @@ create_temp_output(struct read_file *ctx) } sprintf(temp, "%s.XXXXXX", ctx->fname); -#ifdef _WIN32 - /* This might work under VS2015, however there's no good documentation - about it. So let it be for now. */ - mask = 0; -#else - mask = umask(S_IXUSR | S_IRWXG | S_IRWXO); -#endif + mask = umask(_SAFE_MASK); if ((tfd=mkstemp(temp)) == -1) { zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno); umask(mask); diff --git a/ext/zip/lib/zip_source_pkware.c b/ext/zip/lib/zip_source_pkware.c index ce281ac148..125e4e2c2a 100644 --- a/ext/zip/lib/zip_source_pkware.c +++ b/ext/zip/lib/zip_source_pkware.c @@ -1,6 +1,6 @@ /* zip_source_pkware.c -- Traditional PKWARE de/encryption routines - Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -107,7 +107,7 @@ decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in, if (!update_only) { /* decrypt next byte */ tmp = (zip_uint16_t)(ctx->key[2] | 2); - tmp = (zip_uint16_t)((tmp * (tmp ^ 1)) >> 8); + tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8); b ^= (Bytef)tmp; } diff --git a/ext/zip/lib/zip_source_stat.c b/ext/zip/lib/zip_source_stat.c index 34cb05f452..a6b46d06a6 100644 --- a/ext/zip/lib/zip_source_stat.c +++ b/ext/zip/lib/zip_source_stat.c @@ -1,6 +1,6 @@ /* zip_source_stat.c -- get meta information from zip_source - Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner + Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -35,7 +35,7 @@ #include "zipint.h" -int +ZIP_EXTERN int zip_source_stat(zip_source_t *src, zip_stat_t *st) { if (src->source_closed) { diff --git a/ext/zip/lib/zip_source_supports.c b/ext/zip/lib/zip_source_supports.c index 3c100fb71f..75a4a4626d 100644 --- a/ext/zip/lib/zip_source_supports.c +++ b/ext/zip/lib/zip_source_supports.c @@ -1,6 +1,6 @@ /* zip_source_supports.c -- check for supported functions - Copyright (C) 2014 Dieter Baron and Thomas Klausner + Copyright (C) 2014-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -44,7 +44,7 @@ zip_source_supports(zip_source_t *src) } -zip_int64_t +ZIP_EXTERN zip_int64_t zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...) { zip_int64_t bitmap; diff --git a/ext/zip/lib/zip_source_win32a.c b/ext/zip/lib/zip_source_win32a.c index e9786c473e..85493b660e 100644 --- a/ext/zip/lib/zip_source_win32a.c +++ b/ext/zip/lib/zip_source_win32a.c @@ -1,6 +1,6 @@ /* zip_source_win32a.c -- create data source from Windows file (ANSI) -Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner +Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -32,7 +32,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <errno.h> #include <stdio.h> #include "zipint.h" diff --git a/ext/zip/lib/zip_source_win32handle.c b/ext/zip/lib/zip_source_win32handle.c index d195a119db..35e2e67972 100644 --- a/ext/zip/lib/zip_source_win32handle.c +++ b/ext/zip/lib/zip_source_win32handle.c @@ -1,6 +1,6 @@ /* zip_source_win32file.c -- create data source from HANDLE (Win32) -Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner +Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -33,7 +33,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #include <wchar.h> -#include <errno.h> #include <stdlib.h> #include <string.h> @@ -409,6 +408,7 @@ _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd static int _win32_create_temp_file(_zip_source_win32_read_file_t *ctx) { + zip_uint32_t value; /* Windows has GetTempFileName(), but it closes the file after creation, leaving it open to a horrible race condition. So @@ -423,7 +423,6 @@ _win32_create_temp_file(_zip_source_win32_read_file_t *ctx) PSECURITY_ATTRIBUTES psa = NULL; DWORD len; BOOL success; - zip_uint32_t value; /* Read the DACL from the original file, so we can copy it to the temp file. diff --git a/ext/zip/lib/zip_source_win32utf8.c b/ext/zip/lib/zip_source_win32utf8.c index e11214ba05..004c66ac2b 100644 --- a/ext/zip/lib/zip_source_win32utf8.c +++ b/ext/zip/lib/zip_source_win32utf8.c @@ -32,7 +32,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <errno.h> #include <stdio.h> #include "zipint.h" diff --git a/ext/zip/lib/zip_source_win32w.c b/ext/zip/lib/zip_source_win32w.c index 34134561f1..551aba5f37 100644 --- a/ext/zip/lib/zip_source_win32w.c +++ b/ext/zip/lib/zip_source_win32w.c @@ -1,6 +1,6 @@ /* zip_source_win32w.c -- create data source from Windows file (UTF-16) -Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner +Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -32,7 +32,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -#include <errno.h> #include <stdio.h> #include "zipint.h" @@ -100,7 +99,7 @@ _win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32 return INVALID_HANDLE_VALUE; } } - if (swprintf((wchar_t *)*temp, len, L"%s.%08x", (const wchar_t *)ctx->fname, value) != len - 1) { + if (_snwprintf((wchar_t *)*temp, len, L"%s.%08x", (const wchar_t *)ctx->fname, value) != len - 1) { return INVALID_HANDLE_VALUE; } diff --git a/ext/zip/lib/zip_unchange.c b/ext/zip/lib/zip_unchange.c index 6c8a495c78..5ef5462127 100644 --- a/ext/zip/lib/zip_unchange.c +++ b/ext/zip/lib/zip_unchange.c @@ -1,6 +1,6 @@ /* zip_unchange.c -- undo changes to file in zip archive - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -48,6 +48,7 @@ int _zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates) { zip_int64_t i; + const char *orig_name, *changed_name; if (idx >= za->nentry) { zip_error_set(&za->error, ZIP_ER_INVAL, 0); @@ -55,9 +56,32 @@ _zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates) } if (!allow_duplicates && za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME)) { - i = _zip_name_locate(za, _zip_get_name(za, idx, ZIP_FL_UNCHANGED, NULL), 0, NULL); - if (i >= 0 && (zip_uint64_t)i != idx) { - zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + if (za->entry[idx].orig != NULL) { + if ((orig_name=_zip_get_name(za, idx, ZIP_FL_UNCHANGED, &za->error)) == NULL) { + return -1; + } + + i = _zip_name_locate(za, orig_name, 0, NULL); + if (i >= 0 && (zip_uint64_t)i != idx) { + zip_error_set(&za->error, ZIP_ER_EXISTS, 0); + return -1; + } + } + else { + orig_name = NULL; + } + + if ((changed_name=_zip_get_name(za, idx, 0, &za->error)) == NULL) { + return -1; + } + + if (orig_name) { + if (_zip_hash_add(za->names, (const zip_uint8_t *)orig_name, idx, 0, &za->error) == false) { + return -1; + } + } + if (_zip_hash_delete(za->names, (const zip_uint8_t *)changed_name, &za->error) == false) { + _zip_hash_delete(za->names, (const zip_uint8_t *)orig_name, NULL); return -1; } } diff --git a/ext/zip/lib/zip_unchange_all.c b/ext/zip/lib/zip_unchange_all.c index 60076838d4..dc89f7fdaf 100644 --- a/ext/zip/lib/zip_unchange_all.c +++ b/ext/zip/lib/zip_unchange_all.c @@ -1,6 +1,6 @@ /* zip_unchange.c -- undo changes to all files in zip archive - Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -43,6 +43,8 @@ zip_unchange_all(zip_t *za) int ret; zip_uint64_t i; + _zip_hash_revert(za->names); + ret = 0; for (i=0; i<za->nentry; i++) ret |= _zip_unchange(za, i, 1); diff --git a/ext/zip/lib/zipconf.h b/ext/zip/lib/zipconf.h index c8716fb952..8ac2652e1d 100644 --- a/ext/zip/lib/zipconf.h +++ b/ext/zip/lib/zipconf.h @@ -7,10 +7,10 @@ This file was generated automatically by CMake based on ../cmake-zipconf.h.in. */ -#define LIBZIP_VERSION "1.0.1" +#define LIBZIP_VERSION "1.1.2" #define LIBZIP_VERSION_MAJOR 1 -#define LIBZIP_VERSION_MINOR 0 -#define LIBZIP_VERSION_MICRO 1 +#define LIBZIP_VERSION_MINOR 1 +#define LIBZIP_VERSION_MICRO 2 /* #undef HAVE_INTTYPES_H_LIBZIP */ diff --git a/ext/zip/lib/zipint.h b/ext/zip/lib/zipint.h index d13bab42ab..68b18c70a3 100644 --- a/ext/zip/lib/zipint.h +++ b/ext/zip/lib/zipint.h @@ -3,7 +3,7 @@ /* zipint.h -- internal declarations. - Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner + Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner This file is part of libzip, a library to manipulate ZIP archives. The authors can be contacted at <libzip@nih.at> @@ -65,6 +65,22 @@ typedef char bool; #define false 0 #endif +#include <errno.h> + +/* at least MinGW does not provide EOPNOTSUPP, see + * http://sourceforge.net/p/mingw/bugs/263/ + */ +#ifndef EOPNOTSUPP +#define EOPNOTSUPP EINVAL +#endif + +/* at least MinGW does not provide EOVERFLOW, see + * http://sourceforge.net/p/mingw/bugs/242/ + */ +#ifndef EOVERFLOW +#define EOVERFLOW EFBIG +#endif + #ifdef _WIN32 #if defined(HAVE__CLOSE) #define close _close @@ -76,7 +92,7 @@ typedef char bool; #if defined(HAVE__FDOPEN) #define fdopen _fdopen #endif -#if defined(HAVE__FILENO) +#if !defined(HAVE_FILENO) && defined(HAVE__FILENO) #define fileno _fileno #endif /* Windows' open() doesn't understand Unix permissions */ @@ -92,6 +108,9 @@ typedef char bool; #define strdup _strdup #endif #endif +#if !defined(HAVE__SETMODE) && defined(HAVE_SETMODE) +#define _setmode setmode +#endif #endif #ifndef HAVE_FSEEKO @@ -110,6 +129,8 @@ int _zip_mkstemp(char *); #if !defined(HAVE_STRCASECMP) #if defined(HAVE__STRICMP) #define strcasecmp _stricmp +#elif defined(HAVE_STRICMP) +#define strcasecmp stricmp #endif #endif @@ -129,12 +150,10 @@ int _zip_mkstemp(char *); #if defined(HAVE_FTELLO) && defined(HAVE_FSEEKO) #define ZIP_FSEEK_MAX ZIP_OFF_MAX #define ZIP_FSEEK_MIN ZIP_OFF_MIN -#elif SIZEOF_LONG >= 8 -#define ZIP_FSEEK_MAX (long)ZIP_INT64_MAX -#define ZIP_FSEEK_MIN (long)ZIP_INT64_MIN #else -#define ZIP_FSEEK_MAX (long)ZIP_INT32_MAX -#define ZIP_FSEEK_MIN (long)ZIP_INT32_MIN +#include <limits.h> +#define ZIP_FSEEK_MAX LONG_MAX +#define ZIP_FSEEK_MIN LONG_MIN #endif #ifndef SIZE_MAX @@ -255,13 +274,19 @@ enum zip_encoding_type { typedef enum zip_encoding_type zip_encoding_type_t; +#ifndef ZIP_HASH_TABLE_SIZE +#define ZIP_HASH_TABLE_SIZE 8192 +#endif + +struct zip_hash; + typedef struct zip_cdir zip_cdir_t; typedef struct zip_dirent zip_dirent_t; typedef struct zip_entry zip_entry_t; typedef struct zip_extra_field zip_extra_field_t; typedef struct zip_string zip_string_t; typedef struct zip_buffer zip_buffer_t; - +typedef struct zip_hash zip_hash_t; /* zip archive, part of API */ @@ -276,7 +301,7 @@ struct zip { char *default_password; /* password used when no other supplied */ zip_string_t *comment_orig; /* archive comment */ - zip_string_t *comment_changes; /* changed archive comment */ + zip_string_t *comment_changes; /* changed archive comment */ bool comment_changed; /* whether archive comment was changed */ zip_uint64_t nentry; /* number of entries */ @@ -286,6 +311,8 @@ struct zip { unsigned int nopen_source; /* number of open sources using archive */ unsigned int nopen_source_alloc; /* number of sources allocated */ zip_source_t **open_source; /* open sources using archive */ + + zip_hash_t *names; /* hash table for name lookup */ char *tempdir; /* custom temp dir (needed e.g. for OS X sandboxing) */ }; @@ -312,7 +339,7 @@ struct zip_file { struct zip_dirent { zip_uint32_t changed; bool local_extra_fields_read; /* whether we already read in local header extra fields */ - bool cloned; /* whether this instance is cloned, and thus shares non-changed strings */ + bool cloned; /* whether this instance is cloned, and thus shares non-changed strings */ zip_uint16_t version_madeby; /* (c) version of creator */ zip_uint16_t version_needed; /* (cl) version needed to extract */ @@ -415,7 +442,7 @@ struct zip_buffer { struct zip_filelist { zip_uint64_t idx; -// TODO const char *name; +/* TODO const char *name; */ }; typedef struct zip_filelist zip_filelist_t; @@ -453,6 +480,7 @@ int _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i); int _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i); int _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i); int _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i); +int _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length); int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset); zip_uint64_t _zip_buffer_size(zip_buffer_t *buffer); @@ -478,7 +506,7 @@ void _zip_ef_free(zip_extra_field_t *); const zip_uint8_t *_zip_ef_get_by_id(const zip_extra_field_t *, zip_uint16_t *, zip_uint16_t, zip_uint16_t, zip_flags_t, zip_error_t *); zip_extra_field_t *_zip_ef_merge(zip_extra_field_t *, zip_extra_field_t *); zip_extra_field_t *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_flags_t); -zip_extra_field_t *_zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_error_t *); +bool _zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_extra_field_t **, zip_error_t *); zip_extra_field_t *_zip_ef_remove_internal(zip_extra_field_t *); zip_uint16_t _zip_ef_size(const zip_extra_field_t *, zip_flags_t); int _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags); @@ -505,6 +533,13 @@ zip_dirent_t *_zip_get_dirent(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *) enum zip_encoding_type _zip_guess_encoding(zip_string_t *, enum zip_encoding_type); zip_uint8_t *_zip_cp437_to_utf8(const zip_uint8_t * const, zip_uint32_t, zip_uint32_t *, zip_error_t *); +bool _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error); +bool _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *key, zip_error_t *error); +void _zip_hash_free(zip_hash_t *hash); +zip_int64_t _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error); +zip_hash_t *_zip_hash_new(zip_uint16_t hash_size, zip_error_t *error); +void _zip_hash_revert(zip_hash_t *hash); + zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *); int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_error_t *error); diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 803543029d..db201af634 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -16,7 +16,6 @@ +----------------------------------------------------------------------+ */ -/* $Id$ */ #ifdef HAVE_CONFIG_H #include "config.h" @@ -331,7 +330,7 @@ static int php_zip_parse_options(zval *options, zend_long *remove_all_path, char } if (Z_STRLEN_P(option) >= MAXPATHLEN) { - php_error_docref(NULL, E_WARNING, "remove_path string is too long (max: %i, %i given)", + php_error_docref(NULL, E_WARNING, "remove_path string is too long (max: %d, %zd given)", MAXPATHLEN - 1, Z_STRLEN_P(option)); return -1; } @@ -351,7 +350,7 @@ static int php_zip_parse_options(zval *options, zend_long *remove_all_path, char } if (Z_STRLEN_P(option) >= MAXPATHLEN) { - php_error_docref(NULL, E_WARNING, "add_path string too long (max: %i, %i given)", + php_error_docref(NULL, E_WARNING, "add_path string too long (max: %d, %zd given)", MAXPATHLEN - 1, Z_STRLEN_P(option)); return -1; } @@ -2668,7 +2667,7 @@ static ZIPARCHIVE_METHOD(extractTo) for (i = 0; i < filecount; i++) { char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED); - if (!php_zip_extract_file(intern, pathto, file, strlen(file))) { + if (!file || !php_zip_extract_file(intern, pathto, file, strlen(file))) { RETURN_FALSE; } } @@ -3134,7 +3133,6 @@ static PHP_MINFO_FUNCTION(zip) php_info_print_table_start(); php_info_print_table_row(2, "Zip", "enabled"); - php_info_print_table_row(2, "Extension Version","$Id$"); php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION); php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION); diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h index 602b1b1c44..ad65fdeb9d 100644 --- a/ext/zip/php_zip.h +++ b/ext/zip/php_zip.h @@ -16,7 +16,6 @@ +----------------------------------------------------------------------+ */ -/* $Id$ */ #ifndef PHP_ZIP_H #define PHP_ZIP_H @@ -38,24 +37,9 @@ extern zend_module_entry zip_module_entry; #define ZIP_OVERWRITE ZIP_TRUNCATE #endif -#define PHP_ZIP_VERSION "1.13.0" +#define PHP_ZIP_VERSION "1.13.2" -#ifndef Z_SET_REFCOUNT_P -# if PHP_MAJOR_VERSION < 6 && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3) -# define Z_SET_REFCOUNT_P(pz, rc) pz->refcount = rc -# define Z_UNSET_ISREF_P(pz) pz->is_ref = 0 -# endif -#endif - -/* {{{ ZIP_OPENBASEDIR_CHECKPATH(filename) */ -#if PHP_API_VERSION < 20100412 -# define ZIP_OPENBASEDIR_CHECKPATH(filename) \ - (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename) -#else -#define ZIP_OPENBASEDIR_CHECKPATH(filename) \ - php_check_open_basedir(filename) -#endif -/* }}} */ +#define ZIP_OPENBASEDIR_CHECKPATH(filename) php_check_open_basedir(filename) typedef struct _ze_zip_rsrc { struct zip *za; diff --git a/ext/zip/tests/stream_meta_data.phpt b/ext/zip/tests/stream_meta_data.phpt index bd080980ed..63f720ad85 100644 --- a/ext/zip/tests/stream_meta_data.phpt +++ b/ext/zip/tests/stream_meta_data.phpt @@ -35,6 +35,12 @@ fclose($fp); ?> --EXPECTF-- array(8) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["stream_type"]=> string(3) "zip" ["mode"]=> @@ -45,14 +51,14 @@ array(8) { bool(false) ["uri"]=> string(3) "foo" +} +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} -array(9) { ["wrapper_type"]=> string(11) "zip wrapper" ["stream_type"]=> @@ -65,10 +71,4 @@ array(9) { bool(false) ["uri"]=> string(%d) "zip://%stest_with_comment.zip#foo" - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c index 3b200e89d1..a088985198 100644 --- a/ext/zip/zip_stream.c +++ b/ext/zip/zip_stream.c @@ -16,13 +16,11 @@ +----------------------------------------------------------------------+ */ -/* $Id$ */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #include "php.h" #if HAVE_ZIP -#if defined(ZEND_ENGINE_2) || defined(ZEND_ENGINE_3) #include "php_streams.h" #include "ext/standard/file.h" @@ -357,5 +355,4 @@ php_stream_wrapper php_stream_zip_wrapper = { NULL, 0 /* is_url */ }; -#endif /* defined(ZEND_ENGINE_2) || defined(ZEND_ENGINE_3) */ #endif /* HAVE_ZIP */ diff --git a/ext/zlib/tests/zlib_wrapper_meta_data_basic.phpt b/ext/zlib/tests/zlib_wrapper_meta_data_basic.phpt index 2f76b46d96..a9d208eeaa 100644 --- a/ext/zlib/tests/zlib_wrapper_meta_data_basic.phpt +++ b/ext/zlib/tests/zlib_wrapper_meta_data_basic.phpt @@ -25,6 +25,12 @@ gzclose($h); --EXPECTF-- no wrapper array(7) { + ["timed_out"]=> + bool(false) + ["blocked"]=> + bool(true) + ["eof"]=> + bool(false) ["stream_type"]=> string(4) "ZLIB" ["mode"]=> @@ -33,16 +39,16 @@ array(7) { int(0) ["seekable"]=> bool(true) +} + +with wrapper +array(9) { ["timed_out"]=> bool(false) ["blocked"]=> bool(true) ["eof"]=> bool(false) -} - -with wrapper -array(9) { ["wrapper_type"]=> string(4) "ZLIB" ["stream_type"]=> @@ -55,11 +61,5 @@ array(9) { bool(true) ["uri"]=> string(%d) "compress.zlib://%s/004.txt.gz" - ["timed_out"]=> - bool(false) - ["blocked"]=> - bool(true) - ["eof"]=> - bool(false) } ===DONE===
\ No newline at end of file diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index eda939d66e..bfca0f42f7 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -1064,7 +1064,7 @@ PHP_FUNCTION(deflate_init) case Z_DEFAULT_STRATEGY: break; default: - php_error_docref(NULL, E_WARNING, "strategy must be one of ZLIB_FILTERED, ZLIB_HUFFMAN_ONLY, ZLIB_RLE, ZLIB_FIXED or ZLIB_DEFAULT_STRATEGY", strategy); + php_error_docref(NULL, E_WARNING, "strategy must be one of ZLIB_FILTERED, ZLIB_HUFFMAN_ONLY, ZLIB_RLE, ZLIB_FIXED or ZLIB_DEFAULT_STRATEGY"); RETURN_FALSE; } diff --git a/main/fastcgi.c b/main/fastcgi.c index 54ba36b7db..ce33369045 100644 --- a/main/fastcgi.c +++ b/main/fastcgi.c @@ -1277,21 +1277,21 @@ void fcgi_close(fcgi_request *req, int force, int destroy) DisconnectNamedPipe(pipe); } else { if (!force) { - fcgi_header buf; + char buf[8]; shutdown(req->fd, 1); - /* read the last FCGI_STDIN header (it may be omitted) */ - recv(req->fd, (char *)(&buf), sizeof(buf), 0); + /* read any remaining data, it may be omitted */ + while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} } closesocket(req->fd); } #else if (!force) { - fcgi_header buf; + char buf[8]; shutdown(req->fd, 1); - /* read the last FCGI_STDIN header (it may be omitted) */ - recv(req->fd, (char *)(&buf), sizeof(buf), 0); + /* read any remaining data, it may be omitted */ + while (recv(req->fd, buf, sizeof(buf), 0) > 0) {} } close(req->fd); #endif diff --git a/main/fopen_wrappers.h b/main/fopen_wrappers.h index ce13d4a9b2..e9f5159fcd 100644 --- a/main/fopen_wrappers.h +++ b/main/fopen_wrappers.h @@ -34,15 +34,8 @@ PHPAPI int php_check_open_basedir(const char *path); PHPAPI int php_check_open_basedir_ex(const char *path, int warn); PHPAPI int php_check_specific_open_basedir(const char *basedir, const char *path); -/* {{{ OPENBASEDIR_CHECKPATH(filename) to ease merge between 6.x and 5.x */ -#if PHP_API_VERSION < 20100412 -# define OPENBASEDIR_CHECKPATH(filename) \ - (PG(safe_mode) && (!php_checkuid(filename, NULL, CHECKUID_CHECK_FILE_AND_DIR))) || php_check_open_basedir(filename) -#else -#define OPENBASEDIR_CHECKPATH(filename) \ - php_check_open_basedir(filename) -#endif -/* }}} */ +/* OPENBASEDIR_CHECKPATH(filename) to ease merge between 6.x and 5.x */ +#define OPENBASEDIR_CHECKPATH(filename) php_check_open_basedir(filename) PHPAPI int php_check_safe_mode_include_dir(const char *path); diff --git a/main/main.c b/main/main.c index 77a2f64b40..ab879369bc 100644 --- a/main/main.c +++ b/main/main.c @@ -1566,6 +1566,9 @@ int php_request_startup(void) #endif /* HAVE_DTRACE */ #ifdef PHP_WIN32 +# if defined(ZTS) + _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); +# endif PG(com_initialized) = 0; #endif diff --git a/main/output.c b/main/output.c index 2154949810..2a51100960 100644 --- a/main/output.c +++ b/main/output.c @@ -665,7 +665,7 @@ PHPAPI int php_output_handler_alias_register(const char *name, size_t name_len, } /* }}} */ -/* {{{ SUCCESS|FAILURE php_output_handler_hook(php_output_handler_hook_t type, void *arg TSMRLS_DC) +/* {{{ SUCCESS|FAILURE php_output_handler_hook(php_output_handler_hook_t type, void *arg) * Output handler hook for output handler functions to check/modify the current handlers abilities */ PHPAPI int php_output_handler_hook(php_output_handler_hook_t type, void *arg) { @@ -715,7 +715,7 @@ PHPAPI void php_output_handler_dtor(php_output_handler *handler) } /* }}} */ -/* {{{ void php_output_handler_free(php_output_handler **handler TSMRLS_DC) +/* {{{ void php_output_handler_free(php_output_handler **handler) * Destroy and free an output handler */ PHPAPI void php_output_handler_free(php_output_handler **h) { diff --git a/main/php.h b/main/php.h index 14a52a6476..d0ec07c82e 100644 --- a/main/php.h +++ b/main/php.h @@ -297,19 +297,13 @@ static inline ZEND_ATTRIBUTE_DEPRECATED void php_std_error_handling() {} PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int type, const char *format, va_list args) PHP_ATTRIBUTE_FORMAT(printf, 4, 0); -#ifdef ZTS -#define PHP_ATTR_FMT_OFFSET 1 -#else -#define PHP_ATTR_FMT_OFFSET 0 -#endif - /* PHPAPI void php_error(int type, const char *format, ...); */ PHPAPI ZEND_COLD void php_error_docref0(const char *docref, int type, const char *format, ...) - PHP_ATTRIBUTE_FORMAT(printf, PHP_ATTR_FMT_OFFSET + 3, PHP_ATTR_FMT_OFFSET + 4); + PHP_ATTRIBUTE_FORMAT(printf, 3, 4); PHPAPI ZEND_COLD void php_error_docref1(const char *docref, const char *param1, int type, const char *format, ...) - PHP_ATTRIBUTE_FORMAT(printf, PHP_ATTR_FMT_OFFSET + 4, PHP_ATTR_FMT_OFFSET + 5); + PHP_ATTRIBUTE_FORMAT(printf, 4, 5); PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, const char *param2, int type, const char *format, ...) - PHP_ATTRIBUTE_FORMAT(printf, PHP_ATTR_FMT_OFFSET + 5, PHP_ATTR_FMT_OFFSET + 6); + PHP_ATTRIBUTE_FORMAT(printf, 5, 6); #ifdef PHP_WIN32 PHPAPI ZEND_COLD void php_win32_docref2_from_error(DWORD error, const char *param1, const char *param2); #endif @@ -330,7 +324,7 @@ END_EXTERN_C() BEGIN_EXTERN_C() PHPAPI extern int (*php_register_internal_extensions_func)(void); PHPAPI int php_register_internal_extensions(void); -PHPAPI int php_mergesort(void *base, size_t nmemb, register size_t size, int (*cmp)(const void *, const void *)); +PHPAPI int php_mergesort(void *base, size_t nmemb, size_t size, int (*cmp)(const void *, const void *)); PHPAPI void php_register_pre_request_shutdown(void (*func)(void *), void *userdata); PHPAPI void php_com_initialize(void); PHPAPI char *php_get_current_user(void); diff --git a/main/php_streams.h b/main/php_streams.h index e2dda520b6..92abaebf13 100644 --- a/main/php_streams.h +++ b/main/php_streams.h @@ -313,11 +313,7 @@ PHPAPI size_t _php_stream_write(php_stream *stream, const char *buf, size_t coun PHPAPI void _php_stream_fill_read_buffer(php_stream *stream, size_t size); #define php_stream_fill_read_buffer(stream, size) _php_stream_fill_read_buffer((stream), (size)) -#ifdef ZTS -PHPAPI size_t _php_stream_printf(php_stream *stream, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4); -#else PHPAPI size_t _php_stream_printf(php_stream *stream, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); -#endif /* php_stream_printf macro & function require */ #define php_stream_printf _php_stream_printf @@ -579,11 +575,7 @@ PHPAPI const char *php_stream_locate_eol(php_stream *stream, zend_string *buf); php_stream_open_wrapper_ex(Z_STRVAL_P((zstream)), (mode), (options), (opened), (context)) : NULL /* pushes an error message onto the stack for a wrapper instance */ -#ifdef ZTS -PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int options, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 4, 5); -#else PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int options, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4); -#endif #define PHP_STREAM_UNCHANGED 0 /* orig stream was seekable anyway */ #define PHP_STREAM_RELEASED 1 /* newstream should be used; origstream is no longer valid */ diff --git a/main/snprintf.h b/main/snprintf.h index 1fcffb016a..918cb60152 100644 --- a/main/snprintf.h +++ b/main/snprintf.h @@ -86,7 +86,7 @@ PHPAPI int ap_php_vasprintf(char **buf, const char *format, va_list ap); PHPAPI int ap_php_asprintf(char **buf, const char *format, ...); PHPAPI int php_sprintf (char* s, const char* format, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); PHPAPI char * php_gcvt(double value, int ndigit, char dec_point, char exponent, char *buf); -PHPAPI char * php_conv_fp(register char format, register double num, +PHPAPI char * php_conv_fp(char format, double num, boolean_e add_dp, int precision, char dec_point, bool_int * is_negative, char *buf, size_t *len); END_EXTERN_C() @@ -153,11 +153,11 @@ typedef enum { typedef WIDE_INT wide_int; typedef unsigned WIDE_INT u_wide_int; -PHPAPI char * ap_php_conv_10(register wide_int num, register bool_int is_unsigned, - register bool_int * is_negative, char *buf_end, register size_t *len); +PHPAPI char * ap_php_conv_10(wide_int num, bool_int is_unsigned, + bool_int * is_negative, char *buf_end, size_t *len); -PHPAPI char * ap_php_conv_p2(register u_wide_int num, register int nbits, - char format, char *buf_end, register size_t *len); +PHPAPI char * ap_php_conv_p2(u_wide_int num, int nbits, + char format, char *buf_end, size_t *len); /* The maximum precision that's allowed for float conversion. Does not include * decimal separator, exponent, sign, terminator. Currently does not affect diff --git a/main/streams/memory.c b/main/streams/memory.c index e2695ff2d9..56ffe344aa 100644 --- a/main/streams/memory.c +++ b/main/streams/memory.c @@ -22,7 +22,7 @@ #include "php.h" #include "ext/standard/base64.h" -PHPAPI int php_url_decode(char *str, int len); +PHPAPI size_t php_url_decode(char *str, size_t len); /* Memory streams use a dynamic memory buffer to emulate a stream. * You can use php_stream_memory_open to create a readonly stream @@ -697,7 +697,9 @@ static php_stream * php_stream_url_wrap_rfc2397(php_stream_wrapper *wrapper, con plen = sep - path; vlen = (semi ? semi - sep : mlen - plen) - 1 /* '=' */; key = estrndup(path, plen); - add_assoc_stringl_ex(&meta, key, plen, sep + 1, vlen); + if (plen != sizeof("mediatype")-1 || memcmp(key, "mediatype", sizeof("mediatype")-1)) { + add_assoc_stringl_ex(&meta, key, plen, sep + 1, vlen); + } efree(key); plen += vlen + 1; mlen -= plen; @@ -728,7 +730,7 @@ static php_stream * php_stream_url_wrap_rfc2397(php_stream_wrapper *wrapper, con ilen = (int)ZSTR_LEN(base64_comma); } else { comma = estrndup(comma, dlen); - dlen = php_url_decode(comma, (int)dlen); + dlen = php_url_decode(comma, dlen); ilen = (int)dlen; } diff --git a/sapi/apache2handler/sapi_apache2.c b/sapi/apache2handler/sapi_apache2.c index 289b59ae2f..4c69fa6b4d 100644 --- a/sapi/apache2handler/sapi_apache2.c +++ b/sapi/apache2handler/sapi_apache2.c @@ -123,15 +123,15 @@ php_apache_sapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_e } ctx->content_type = estrdup(val); } else if (!strcasecmp(sapi_header->header, "content-length")) { -#ifdef PHP_WIN32 -# ifdef APR_HAS_LARGE_FILES - ap_set_content_length(ctx->r, (apr_off_t) _strtoui64(val, (char **)NULL, 10)); -# else - ap_set_content_length(ctx->r, (apr_off_t) strtol(val, (char **)NULL, 10)); -# endif -#else - ap_set_content_length(ctx->r, (apr_off_t) strtol(val, (char **)NULL, 10)); -#endif + apr_off_t clen = 0; + + if (APR_SUCCESS != apr_strtoff(&clen, val, (char **) NULL, 10)) { + /* We'll fall back to strtol, since that's what we used to + * do anyway. */ + clen = (apr_off_t) strtol(val, (char **) NULL, 10); + } + + ap_set_content_length(ctx->r, clen); } else if (op == SAPI_HEADER_REPLACE) { apr_table_set(ctx->r->headers_out, sapi_header->header, val); } else { diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c index c1cca1e3d2..3058e62815 100644 --- a/sapi/cgi/cgi_main.c +++ b/sapi/cgi/cgi_main.c @@ -35,6 +35,7 @@ #ifdef PHP_WIN32 # include "win32/time.h" # include "win32/signal.h" +# include "win32/winutil.h" # include <process.h> #endif @@ -102,7 +103,6 @@ struct sigaction act, old_term, old_quit, old_int; static void (*php_php_import_environment_variables)(zval *array_ptr); -#ifndef PHP_WIN32 /* these globals used for forking children on unix systems */ /** * Number of child processes that will get created to service requests @@ -115,6 +115,7 @@ static int children = 0; */ static int parent = 1; +#ifndef PHP_WIN32 /* Did parent received exit signals SIG_TERM/SIG_INT/SIG_QUIT */ static int exit_signal = 0; @@ -222,6 +223,14 @@ static php_cgi_globals_struct php_cgi_globals; #define TRANSLATE_SLASHES(path) #endif +#ifdef PHP_WIN32 +#define WIN32_MAX_SPAWN_CHILDREN 64 +HANDLE kid_cgi_ps[WIN32_MAX_SPAWN_CHILDREN]; +int kids; +HANDLE job = NULL; +JOBOBJECT_EXTENDED_LIMIT_INFORMATION job_info = { 0 }; +#endif + #ifndef HAVE_ATTRIBUTE_WEAK static void fcgi_log(int type, const char *format, ...) { va_list ap; @@ -354,9 +363,7 @@ static void sapi_fcgi_flush(void *server_context) fcgi_request *request = (fcgi_request*) server_context; if ( -#ifndef PHP_WIN32 !parent && -#endif request && !fcgi_flush(request, 0)) { php_handle_aborted_connection(); @@ -900,9 +907,7 @@ static int sapi_cgi_deactivate(void) if (SG(sapi_started)) { if (fcgi_is_fastcgi()) { if ( -#ifndef PHP_WIN32 !parent && -#endif !fcgi_finish_request((fcgi_request*)SG(server_context), 0)) { php_handle_aborted_connection(); } @@ -1431,6 +1436,29 @@ void fastcgi_cleanup(int signal) exit(0); } } +#else +BOOL WINAPI fastcgi_cleanup(DWORD sig) +{ + int i = kids; + + while (0 < i--) { + if (NULL == kid_cgi_ps[i]) { + continue; + } + + TerminateProcess(kid_cgi_ps[i], 0); + CloseHandle(kid_cgi_ps[i]); + kid_cgi_ps[i] = NULL; + } + + if (job) { + CloseHandle(job); + } + + parent = 0; + + return TRUE; +} #endif PHP_INI_BEGIN() @@ -1979,8 +2007,7 @@ consult the installation file that came with this distribution, or visit \n\ /* library is already initialized, now init our request */ request = fcgi_init_request(fcgi_fd, NULL, NULL, NULL); -#ifndef PHP_WIN32 - /* Pre-fork, if required */ + /* Pre-fork or spawn, if required */ if (getenv("PHP_FCGI_CHILDREN")) { char * children_str = getenv("PHP_FCGI_CHILDREN"); children = atoi(children_str); @@ -1996,6 +2023,7 @@ consult the installation file that came with this distribution, or visit \n\ fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1); } +#ifndef PHP_WIN32 if (children) { int running = 0; pid_t pid; @@ -2081,6 +2109,103 @@ consult the installation file that came with this distribution, or visit \n\ parent = 0; } +#else + if (children) { + char *cmd_line; + char kid_buf[16]; + char my_name[MAX_PATH] = {0}; + int i; + + ZeroMemory(&kid_cgi_ps, sizeof(kid_cgi_ps)); + kids = children < WIN32_MAX_SPAWN_CHILDREN ? children : WIN32_MAX_SPAWN_CHILDREN; + + SetConsoleCtrlHandler(fastcgi_cleanup, TRUE); + + /* kids will inherit the env, don't let them spawn */ + SetEnvironmentVariable("PHP_FCGI_CHILDREN", NULL); + + GetModuleFileName(NULL, my_name, MAX_PATH); + cmd_line = my_name; + + job = CreateJobObject(NULL, NULL); + if (!job) { + DWORD err = GetLastError(); + char *err_text = php_win32_error_to_msg(err); + + fprintf(stderr, "unable to create job object: [0x%08lx]: %s\n", err, err_text); + + goto parent_out; + } + + job_info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE; + if (!SetInformationJobObject(job, JobObjectExtendedLimitInformation, &job_info, sizeof(job_info))) { + DWORD err = GetLastError(); + char *err_text = php_win32_error_to_msg(err); + + fprintf(stderr, "unable to configure job object: [0x%08lx]: %s\n", err, err_text); + } + + while (parent) { + i = kids; + while (0 < i--) { + DWORD status; + + if (NULL != kid_cgi_ps[i]) { + if(!GetExitCodeProcess(kid_cgi_ps[i], &status) || status != STILL_ACTIVE) { + CloseHandle(kid_cgi_ps[i]); + kid_cgi_ps[i] = NULL; + } + } + } + + i = kids; + while (0 < i--) { + PROCESS_INFORMATION pi; + STARTUPINFO si; + + if (NULL != kid_cgi_ps[i]) { + continue; + } + + ZeroMemory(&si, sizeof(si)); + si.cb = sizeof(si); + ZeroMemory(&pi, sizeof(pi)); + + si.dwFlags = STARTF_USESTDHANDLES; + si.hStdOutput = INVALID_HANDLE_VALUE; + si.hStdInput = (HANDLE)_get_osfhandle(fcgi_fd); + si.hStdError = INVALID_HANDLE_VALUE; + + if (CreateProcess(NULL, cmd_line, NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { + kid_cgi_ps[i] = pi.hProcess; + if (!AssignProcessToJobObject(job, pi.hProcess)) { + DWORD err = GetLastError(); + char *err_text = php_win32_error_to_msg(err); + + fprintf(stderr, "unable to assign child process to job object: [0x%08lx]: %s\n", err, err_text); + } + CloseHandle(pi.hThread); + } else { + DWORD err = GetLastError(); + char *err_text = php_win32_error_to_msg(err); + + kid_cgi_ps[i] = NULL; + + fprintf(stderr, "unable to spawn: [0x%08lx]: %s\n", err, err_text); + } + } + + WaitForMultipleObjects(kids, kid_cgi_ps, FALSE, INFINITE); + } + + snprintf(kid_buf, 16, "%d", children); + /* restore my env */ + SetEnvironmentVariable("PHP_FCGI_CHILDREN", kid_buf); + + goto parent_out; + } else { + parent = 0; + } #endif /* WIN32 */ } @@ -2584,9 +2709,7 @@ out: #endif } -#ifndef PHP_WIN32 parent_out: -#endif SG(server_context) = NULL; php_module_shutdown(); diff --git a/sapi/cli/config.w32 b/sapi/cli/config.w32 index 664394c8a6..c6409b59df 100644 --- a/sapi/cli/config.w32 +++ b/sapi/cli/config.w32 @@ -12,6 +12,11 @@ if (PHP_CLI == "yes") { ADD_FLAG("CFLAGS_CLI", "/D PHP_WIN32_DEBUG_HEAP"); } ADD_FLAG("LDFLAGS_CLI", "/stack:67108864"); + + if (CHECK_LIB("edit_a.lib;edit.lib", "cli", PHP_CLI) && + CHECK_HEADER_ADD_INCLUDE("editline/readline.h", "CFLAGS_CLI")) { + ADD_FLAG("CFLAGS_CLI", "/D HAVE_LIBEDIT"); + } } if (PHP_CLI_WIN32 == "yes") { diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c index a387059e27..907f629c01 100644 --- a/sapi/cli/php_cli.c +++ b/sapi/cli/php_cli.c @@ -517,7 +517,7 @@ static void php_cli_usage(char *argv0) " -a Run interactively\n" #endif " -c <path>|<file> Look for php.ini file in this directory\n" - " -n No php.ini file will be used\n" + " -n No configuration (ini) files will be used\n" " -d foo[=bar] Define INI entry foo with value 'bar'\n" " -e Generate extended information for debugger/profiler\n" " -f <file> Parse and execute <file>.\n" diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c index 4ee85bf538..ac41c44def 100644 --- a/sapi/cli/php_cli_server.c +++ b/sapi/cli/php_cli_server.c @@ -1955,6 +1955,19 @@ static int php_cli_server_begin_send_static(php_cli_server *server, php_cli_serv return php_cli_server_send_error_page(server, client, 400); } +#ifdef PHP_WIN32 + /* The win32 namespace will cut off trailing dots and spaces. Since the + VCWD functionality isn't used here, a sophisticated functionality + would have to be reimplemented to know ahead there are no files + with invalid names there. The simplest is just to forbid invalid + filenames, which is done here. */ + if (client->request.path_translated && + ('.' == client->request.path_translated[client->request.path_translated_len-1] || + ' ' == client->request.path_translated[client->request.path_translated_len-1])) { + return php_cli_server_send_error_page(server, client, 500); + } +#endif + fd = client->request.path_translated ? open(client->request.path_translated, O_RDONLY): -1; if (fd < 0) { return php_cli_server_send_error_page(server, client, 404); diff --git a/sapi/cli/tests/cli_process_title_windows.phpt b/sapi/cli/tests/cli_process_title_windows.phpt index 12eb80756d..4e81b4c634 100644 --- a/sapi/cli/tests/cli_process_title_windows.phpt +++ b/sapi/cli/tests/cli_process_title_windows.phpt @@ -21,7 +21,7 @@ if (shell_exec('PowerShell -Help') === NULL) // cli_set_process_title(). We're only making the API calls to ensure there are // no warnings/errors. -$is_windows8 = false; +$is_windows8_or_above = false; $ps_output = shell_exec("PowerShell -NoProfile \"(Get-Host).UI.RawUI.WindowTitle\""); if ($ps_output === null) { @@ -31,8 +31,8 @@ if ($ps_output === null) $ps_output = trim($ps_output); $end_title_windows8 = ": Windows PowerShell"; -if (($ps_output == "Windows PowerShell") || (strlen($ps_output) > strlen($end_title_windows8) && substr($ps_output,-strlen($end_title_windows8)) === $end_title_windows8)) - $is_windows8 = true; +if (($ps_output == "Windows PowerShell") || (strlen($ps_output) > strlen($end_title_windows8) && substr($ps_output,-strlen($end_title_windows8)) === $end_title_windows8) || PHP_WINDOWS_VERSION_MAJOR >= 10) + $is_windows8_or_above = true; echo "*** Testing setting the process title ***\n"; @@ -42,7 +42,7 @@ $pid = getmypid(); if (cli_set_process_title($original_title) === true) echo "Successfully set title\n"; -if ($is_windows8) +if ($is_windows8_or_above) { $loaded_title = $original_title; } @@ -82,4 +82,4 @@ else *** Testing setting the process title *** Successfully set title Successfully verified title using get-process -Successfully verified title using get
\ No newline at end of file +Successfully verified title using get diff --git a/sapi/fpm/Makefile.frag b/sapi/fpm/Makefile.frag index e39fbcb1e8..b0b4b34658 100644 --- a/sapi/fpm/Makefile.frag +++ b/sapi/fpm/Makefile.frag @@ -19,6 +19,6 @@ install-fpm: $(SAPI_FPM_PATH) @$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man8 @$(INSTALL_DATA) sapi/fpm/php-fpm.8 $(INSTALL_ROOT)$(mandir)/man8/php-fpm$(program_suffix).8 - @echo "Installing PHP FPM status page: $(INSTALL_ROOT)$(datadir)/fpm/" + @echo "Installing PHP FPM status page: $(INSTALL_ROOT)$(datadir)/fpm/" @$(mkinstalldirs) $(INSTALL_ROOT)$(datadir)/fpm @$(INSTALL_DATA) sapi/fpm/status.html $(INSTALL_ROOT)$(datadir)/fpm/status.html diff --git a/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c index b9c7e0b632..940d6c788d 100644 --- a/sapi/fpm/fpm/fpm_main.c +++ b/sapi/fpm/fpm/fpm_main.c @@ -1071,11 +1071,14 @@ static void init_request_info(void) } #define APACHE_PROXY_FCGI_PREFIX "proxy:fcgi://" - /* Fix proxy URLs in SCRIPT_FILENAME generated by Apache mod_proxy_fcgi: +#define APACHE_PROXY_BALANCER_PREFIX "proxy:balancer://" + /* Fix proxy URLs in SCRIPT_FILENAME generated by Apache mod_proxy_fcgi and mod_proxy_balancer: * proxy:fcgi://localhost:9000/some-dir/info.php/test?foo=bar + * proxy:balancer://localhost:9000/some-dir/info.php/test?foo=bar * should be changed to: * /some-dir/info.php/test * See: http://bugs.php.net/bug.php?id=54152 + * http://bugs.php.net/bug.php?id=62172 * https://issues.apache.org/bugzilla/show_bug.cgi?id=50851 */ if (env_script_filename && @@ -1099,6 +1102,27 @@ static void init_request_info(void) } } + if (env_script_filename && + strncasecmp(env_script_filename, APACHE_PROXY_BALANCER_PREFIX, sizeof(APACHE_PROXY_BALANCER_PREFIX) - 1) == 0) { + /* advance to first character of hostname */ + char *p = env_script_filename + (sizeof(APACHE_PROXY_BALANCER_PREFIX) - 1); + while (*p != '\0' && *p != '/') { + p++; /* move past hostname and port */ + } + if (*p != '\0') { + /* Copy path portion in place to avoid memory leak. Note + * that this also affects what script_path_translated points + * to. */ + memmove(env_script_filename, p, strlen(p) + 1); + apache_was_here = 1; + } + /* ignore query string if sent by Apache (RewriteRule) */ + p = strchr(env_script_filename, '?'); + if (p) { + *p =0; + } + } + if (CGIG(fix_pathinfo)) { struct stat st; char *real_path = NULL; diff --git a/sapi/fpm/fpm/fpm_signals.c b/sapi/fpm/fpm/fpm_signals.c index c5d0692f18..a637e69e71 100644 --- a/sapi/fpm/fpm/fpm_signals.c +++ b/sapi/fpm/fpm/fpm_signals.c @@ -241,6 +241,10 @@ int fpm_signals_init_child() /* {{{ */ zlog(ZLOG_SYSERROR, "failed to init child signals: sigaction()"); return -1; } + +#ifdef ZEND_SIGNALS + zend_signal_init(); +#endif return 0; } /* }}} */ diff --git a/sapi/litespeed/Makefile.frag b/sapi/litespeed/Makefile.frag index 767c2e5eb1..125a3b13da 100644 --- a/sapi/litespeed/Makefile.frag +++ b/sapi/litespeed/Makefile.frag @@ -4,6 +4,6 @@ $(SAPI_LITESPEED_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_LITESPEED_OB $(BUILD_LITESPEED) install-litespeed: $(SAPI_LITESPEED_PATH) - @echo "Installing PHP LiteSpeed binary: $(INSTALL_ROOT)$(bindir)/" + @echo "Installing PHP LiteSpeed binary: $(INSTALL_ROOT)$(bindir)/" @$(INSTALL) -m 0755 $(SAPI_LITESPEED_PATH) $(INSTALL_ROOT)$(bindir)/lsphp diff --git a/sapi/phpdbg/config.m4 b/sapi/phpdbg/config.m4 index aa5b0efe3a..9fb4e62984 100644 --- a/sapi/phpdbg/config.m4 +++ b/sapi/phpdbg/config.m4 @@ -11,7 +11,7 @@ PHP_ARG_ENABLE(phpdbg-webhelper, for phpdbg web SAPI support, PHP_ARG_ENABLE(phpdbg-debug, for phpdbg debug build, [ --enable-phpdbg-debug Build phpdbg in debug mode], no, no) -if test "$BUILD_PHPDBG" == "" && test "$PHP_PHPDBG" != "no"; then +if test "$BUILD_PHPDBG" = "" && test "$PHP_PHPDBG" != "no"; then AC_HEADER_TIOCGWINSZ AC_DEFINE(HAVE_PHPDBG, 1, [ ]) diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 54e9a66f5f..9321eed2d3 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -554,11 +554,11 @@ static PHP_FUNCTION(phpdbg_get_executable) if (ce->type == ZEND_USER_CLASS) { if (zend_hash_exists(files, ce->info.user.filename)) { ZEND_HASH_FOREACH_PTR(&ce->function_table, func) { - if (func->type == ZEND_USER_FUNCTION) { + if (func->type == ZEND_USER_FUNCTION && zend_hash_exists(files, func->op_array.filename)) { insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), func->op_array.filename); if (by_function) { - zend_string *fn_name = strpprintf(ZSTR_LEN(name) + ZSTR_LEN(func->op_array.function_name) + 2, "%.*s::%.*s", ZSTR_LEN(name), ZSTR_VAL(name), ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name)); + zend_string *fn_name = strpprintf(ZSTR_LEN(name) + ZSTR_LEN(func->op_array.function_name) + 2, "%.*s::%.*s", (int) ZSTR_LEN(name), ZSTR_VAL(name), (int) ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name)); insert_ht = phpdbg_add_empty_array(insert_ht, fn_name); zend_string_release(fn_name); } @@ -654,7 +654,7 @@ static PHP_FUNCTION(phpdbg_end_oplog) if (last_scope == NULL) { fn_name = zend_string_copy(last_function); } else { - fn_name = strpprintf(ZSTR_LEN(last_function) + ZSTR_LEN(last_scope->name) + 2, "%.*s::%.*s", ZSTR_LEN(last_scope->name), ZSTR_VAL(last_scope->name), ZSTR_LEN(last_function), ZSTR_VAL(last_function)); + fn_name = strpprintf(ZSTR_LEN(last_function) + ZSTR_LEN(last_scope->name) + 2, "%.*s::%.*s", (int) ZSTR_LEN(last_scope->name), ZSTR_VAL(last_scope->name), (int) ZSTR_LEN(last_function), ZSTR_VAL(last_function)); } insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), fn_name); zend_string_release(fn_name); @@ -896,7 +896,7 @@ static inline size_t php_sapi_phpdbg_ub_write(const char *message, size_t length if (PHPDBG_G(socket_fd) != -1 && !(PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE)) { send(PHPDBG_G(socket_fd), message, length, 0); } - return phpdbg_script(P_STDOUT, "%.*s", length, message); + return phpdbg_script(P_STDOUT, "%.*s", (int) length, message); } /* }}} */ /* beginning of struct, see main/streams/plain_wrapper.c line 111 */ @@ -1297,7 +1297,7 @@ int main(int argc, char **argv) /* {{{ */ zend_bool init_file_default; char *oplog_file; size_t oplog_file_len; - zend_ulong flags; + uint64_t flags; char *php_optarg; int php_optind, opt, show_banner = 1; long cleaning = -1; diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c index eac67d4ac7..5436bda5db 100644 --- a/sapi/phpdbg/phpdbg_bp.c +++ b/sapi/phpdbg/phpdbg_bp.c @@ -563,12 +563,14 @@ PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break) /* { } else { zend_execute_data *execute_data = EG(current_execute_data); do { - zend_op_array *op_array = &execute_data->func->op_array; - if (op_array->function_name == NULL && op_array->scope == NULL && new_break->class_len == ZSTR_LEN(op_array->filename) && !memcmp(ZSTR_VAL(op_array->filename), new_break->class_name, new_break->class_len)) { - if (phpdbg_resolve_op_array_break(new_break, op_array) == SUCCESS) { - return SUCCESS; - } else { - return 2; + if (ZEND_USER_CODE(execute_data->func->common.type)) { + zend_op_array *op_array = &execute_data->func->op_array; + if (op_array->function_name == NULL && op_array->scope == NULL && new_break->class_len == ZSTR_LEN(op_array->filename) && !memcmp(ZSTR_VAL(op_array->filename), new_break->class_name, new_break->class_len)) { + if (phpdbg_resolve_op_array_break(new_break, op_array) == SUCCESS) { + return SUCCESS; + } else { + return 2; + } } } } while ((execute_data = execute_data->prev_execute_data) != NULL); diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c index 2d0c693a1e..ab1b554f76 100644 --- a/sapi/phpdbg/phpdbg_frame.c +++ b/sapi/phpdbg/phpdbg_frame.c @@ -218,7 +218,7 @@ void phpdbg_dump_backtrace(size_t num) /* {{{ */ while ((tmp = zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), &position))) { if (file) { /* userland */ phpdbg_out("frame #%d: ", i); - phpdbg_xml("<frame %r id=\"%d\" file=\"%s\" line=\"%d\"", i, Z_STRVAL_P(file), Z_LVAL_P(line)); + phpdbg_xml("<frame %r id=\"%d\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"", i, Z_STRVAL_P(file), Z_LVAL_P(line)); phpdbg_dump_prototype(tmp); phpdbg_out(" at %s:%ld\n", Z_STRVAL_P(file), Z_LVAL_P(line)); i++; diff --git a/sapi/phpdbg/phpdbg_info.c b/sapi/phpdbg/phpdbg_info.c index 76b26ef1e0..5d7608fa76 100644 --- a/sapi/phpdbg/phpdbg_info.c +++ b/sapi/phpdbg/phpdbg_info.c @@ -120,12 +120,18 @@ PHPDBG_INFO(constants) /* {{{ */ phpdbg_out("Address Refs Type Constant\n"); ZEND_HASH_FOREACH_PTR(&consts, data) { -#define VARIABLEINFO(attrs, msg, ...) phpdbg_writeln("constant", "address=\"%p\" refcount=\"%d\" type=\"%s\" name=\"%.*s\" " attrs, "%-18p %-7d %-9s %.*s" msg, &data->value, Z_REFCOUNTED(data->value) ? Z_REFCOUNT(data->value) : 1, zend_zval_type_name(&data->value), ZSTR_LEN(data->name), ZSTR_VAL(data->name), ##__VA_ARGS__) +#define VARIABLEINFO(attrs, msg, ...) \ + phpdbg_writeln("constant", \ + "address=\"%p\" refcount=\"%d\" type=\"%s\" name=\"%.*s\" " attrs, \ + "%-18p %-7d %-9s %.*s" msg, &data->value, \ + Z_REFCOUNTED(data->value) ? Z_REFCOUNT(data->value) : 1, \ + zend_zval_type_name(&data->value), \ + (int) ZSTR_LEN(data->name), ZSTR_VAL(data->name), ##__VA_ARGS__) switch (Z_TYPE(data->value)) { case IS_STRING: phpdbg_try_access { - VARIABLEINFO("length=\"%d\" value=\"%.*s\"", "\nstring (%d) \"%.*s%s\"", Z_STRLEN(data->value), Z_STRLEN(data->value) < 255 ? Z_STRLEN(data->value) : 255, Z_STRVAL(data->value), Z_STRLEN(data->value) > 255 ? "..." : ""); + VARIABLEINFO("length=\"%zd\" value=\"%.*s\"", "\nstring (%zd) \"%.*s%s\"", Z_STRLEN(data->value), Z_STRLEN(data->value) < 255 ? (int) Z_STRLEN(data->value) : 255, Z_STRVAL(data->value), Z_STRLEN(data->value) > 255 ? "..." : ""); } phpdbg_catch_access { VARIABLEINFO("", ""); } phpdbg_end_try_access(); @@ -158,7 +164,7 @@ static int phpdbg_arm_auto_global(zval *ptrzv) { if (auto_global->armed) { if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) { - phpdbg_notice("variableinfo", "unreachable=\"%.*s\"", "Cannot show information about superglobal variable %.*s", ZSTR_LEN(auto_global->name), ZSTR_VAL(auto_global->name)); + phpdbg_notice("variableinfo", "unreachable=\"%.*s\"", "Cannot show information about superglobal variable %.*s", (int) ZSTR_LEN(auto_global->name), ZSTR_VAL(auto_global->name)); } else { auto_global->armed = auto_global->auto_global_callback(auto_global->name); } @@ -224,7 +230,10 @@ static int phpdbg_print_symbols(zend_bool show_globals) { ZEND_HASH_FOREACH_STR_KEY_VAL(&vars, var, data) { phpdbg_try_access { const char *isref = ""; -#define VARIABLEINFO(attrs, msg, ...) phpdbg_writeln("variable", "address=\"%p\" refcount=\"%d\" type=\"%s\" refstatus=\"%s\" name=\"%.*s\" " attrs, "%-18p %-7d %-9s %s$%.*s" msg, data, Z_REFCOUNTED_P(data) ? Z_REFCOUNT_P(data) : 1, zend_zval_type_name(data), isref, ZSTR_LEN(var), ZSTR_VAL(var), ##__VA_ARGS__) +#define VARIABLEINFO(attrs, msg, ...) \ + phpdbg_writeln("variable", \ + "address=\"%p\" refcount=\"%d\" type=\"%s\" refstatus=\"%s\" name=\"%.*s\" " attrs, \ + "%-18p %-7d %-9s %s$%.*s" msg, data, Z_REFCOUNTED_P(data) ? Z_REFCOUNT_P(data) : 1, zend_zval_type_name(data), isref, (int) ZSTR_LEN(var), ZSTR_VAL(var), ##__VA_ARGS__) retry_switch: switch (Z_TYPE_P(data)) { case IS_RESOURCE: @@ -237,14 +246,14 @@ retry_switch: break; case IS_OBJECT: phpdbg_try_access { - VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (%s)\n", Z_OBJCE_P(data)->name); + VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (%s)\n", ZSTR_VAL(Z_OBJCE_P(data)->name)); } phpdbg_catch_access { VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (unknown)\n"); } phpdbg_end_try_access(); break; case IS_STRING: phpdbg_try_access { - VARIABLEINFO("length=\"%d\" value=\"%.*s\"", "\nstring (%d) \"%.*s%s\"", Z_STRLEN_P(data), Z_STRLEN_P(data) < 255 ? Z_STRLEN_P(data) : 255, Z_STRVAL_P(data), Z_STRLEN_P(data) > 255 ? "..." : ""); + VARIABLEINFO("length=\"%zd\" value=\"%.*s\"", "\nstring (%zd) \"%.*s%s\"", Z_STRLEN_P(data), Z_STRLEN_P(data) < 255 ? (int) Z_STRLEN_P(data) : 255, Z_STRVAL_P(data), Z_STRLEN_P(data) > 255 ? "..." : ""); } phpdbg_catch_access { VARIABLEINFO("", ""); } phpdbg_end_try_access(); @@ -369,7 +378,7 @@ static inline void phpdbg_print_class_name(zend_class_entry *ce) /* {{{ */ const char *visibility = ce->type == ZEND_USER_CLASS ? "User" : "Internal"; const char *type = (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : (ce->ce_flags & ZEND_ACC_ABSTRACT) ? "Abstract Class" : "Class"; - phpdbg_writeln("class", "type=\"%s\" flags=\"%s\" name=\"%.*s\" methodcount=\"%d\"", "%s %s %.*s (%d)", visibility, type, ZSTR_LEN(ce->name), ZSTR_VAL(ce->name), zend_hash_num_elements(&ce->function_table)); + phpdbg_writeln("class", "type=\"%s\" flags=\"%s\" name=\"%.*s\" methodcount=\"%d\"", "%s %s %.*s (%d)", visibility, type, (int) ZSTR_LEN(ce->name), ZSTR_VAL(ce->name), zend_hash_num_elements(&ce->function_table)); } /* }}} */ PHPDBG_INFO(classes) /* {{{ */ diff --git a/sapi/phpdbg/phpdbg_opcode.c b/sapi/phpdbg/phpdbg_opcode.c index 70dab12656..ccd7337e5c 100644 --- a/sapi/phpdbg/phpdbg_opcode.c +++ b/sapi/phpdbg/phpdbg_opcode.c @@ -36,7 +36,8 @@ static inline const char *phpdbg_decode_opcode(zend_uchar opcode) /* {{{ */ return "UNKNOWN"; } /* }}} */ -static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, uint32_t type) /* {{{ */ +static inline char *phpdbg_decode_op( + zend_op_array *ops, const znode_op *op, uint32_t type) /* {{{ */ { char *decode = NULL; @@ -49,10 +50,10 @@ static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, uint32_t } break; case IS_VAR: - spprintf(&decode, 0, "@%td", EX_VAR_TO_NUM(op->var) - ops->last_var); + spprintf(&decode, 0, "@%u", EX_VAR_TO_NUM(op->var) - ops->last_var); break; case IS_TMP_VAR: - spprintf(&decode, 0, "~%td", EX_VAR_TO_NUM(op->var) - ops->last_var); + spprintf(&decode, 0, "~%u", EX_VAR_TO_NUM(op->var) - ops->last_var); break; case IS_CONST: { zval *literal = RT_CONSTANT(ops, *op); @@ -62,91 +63,72 @@ static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, uint32_t return decode; } /* }}} */ -char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op) /*{{{ */ +char *phpdbg_decode_input_op( + zend_op_array *ops, const zend_op *opline, znode_op op, zend_uchar op_type, + uint32_t flags) { + char *result = NULL; + if (op_type != IS_UNUSED) { + result = phpdbg_decode_op(ops, &op, op_type); + } else if (ZEND_VM_OP_JMP_ADDR == (flags & ZEND_VM_OP_MASK)) { + spprintf(&result, 0, "J%td", OP_JMP_ADDR(opline, op) - ops->opcodes); + } else if (ZEND_VM_OP_NUM == (flags & ZEND_VM_OP_MASK)) { + spprintf(&result, 0, "%" PRIu32, op.num); + } else if (ZEND_VM_OP_TRY_CATCH == (flags & ZEND_VM_OP_MASK)) { + if (opline->opcode != ZEND_FAST_RET || opline->extended_value) { + spprintf(&result, 0, "try-catch(%" PRIu32 ")", op.num); + } + } else if (ZEND_VM_OP_LIVE_RANGE == (flags & ZEND_VM_OP_MASK)) { + if (opline->extended_value & ZEND_FREE_ON_RETURN) { + spprintf(&result, 0, "live-range(%" PRIu32 ")", op.num); + } + } else if (ZEND_VM_OP_THIS == (flags & ZEND_VM_OP_MASK)) { + result = estrdup("THIS"); + } else if (ZEND_VM_OP_NEXT == (flags & ZEND_VM_OP_MASK)) { + result = estrdup("NEXT"); + } else if (ZEND_VM_OP_CLASS_FETCH == (flags & ZEND_VM_OP_MASK)) { + //zend_dump_class_fetch_type(op.num); + } else if (ZEND_VM_OP_CONSTRUCTOR == (flags & ZEND_VM_OP_MASK)) { + result = estrdup("CONSTRUCTOR"); + } + return result; +} + +char *phpdbg_decode_opline(zend_op_array *ops, zend_op *opline) /*{{{ */ { - const char *opcode_name = phpdbg_decode_opcode(op->opcode); + const char *opcode_name = phpdbg_decode_opcode(opline->opcode); + uint32_t flags = zend_get_opcode_flags(opline->opcode); char *result, *decode[4] = {NULL, NULL, NULL, NULL}; /* EX */ - switch (op->opcode) { + switch (opline->opcode) { case ZEND_FAST_CALL: - if (op->extended_value == ZEND_FAST_CALL_FROM_FINALLY) { + if (opline->extended_value == ZEND_FAST_CALL_FROM_FINALLY) { decode[0] = estrdup("FAST_CALL<FROM_FINALLY>"); } break; case ZEND_FAST_RET: - if (op->extended_value != 0) { + if (opline->extended_value != 0) { spprintf(&decode[0], 0, "FAST_RET<%s>", - op->extended_value == ZEND_FAST_RET_TO_CATCH ? "TO_CATCH" : "TO_FINALLY"); + opline->extended_value == ZEND_FAST_RET_TO_CATCH ? "TO_CATCH" : "TO_FINALLY"); } break; } /* OP1 */ - switch (op->opcode) { - case ZEND_JMP: - case ZEND_FAST_CALL: - spprintf(&decode[1], 0, "J%td", OP_JMP_ADDR(op, op->op1) - ops->opcodes); - break; - - case ZEND_INIT_FCALL: - case ZEND_RECV: - case ZEND_RECV_INIT: - case ZEND_RECV_VARIADIC: - spprintf(&decode[1], 0, "%" PRIu32, op->op1.num); - break; - - default: - decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type); - break; - } + decode[1] = phpdbg_decode_input_op( + ops, opline, opline->op1, opline->op1_type, ZEND_VM_OP1_FLAGS(flags)); /* OP2 */ - switch (op->opcode) { - case ZEND_JMPZNZ: - spprintf(&decode[2], 0, "J%td or J%td", - OP_JMP_ADDR(op, op->op2) - ops->opcodes, - ZEND_OFFSET_TO_OPLINE(op, op->extended_value) - ops->opcodes); - break; - - case ZEND_JMPZ: - case ZEND_JMPNZ: - case ZEND_JMPZ_EX: - case ZEND_JMPNZ_EX: - case ZEND_JMP_SET: - case ZEND_ASSERT_CHECK: - spprintf(&decode[2], 0, "J%td", OP_JMP_ADDR(op, op->op2) - ops->opcodes); - break; - - case ZEND_FAST_CALL: - case ZEND_FAST_RET: - if (op->extended_value != 0) { - spprintf(&decode[2], 0, "%" PRIu32, op->op2.num); - } - break; - - case ZEND_SEND_VAL: - case ZEND_SEND_VAL_EX: - case ZEND_SEND_VAR: - case ZEND_SEND_VAR_NO_REF: - case ZEND_SEND_REF: - case ZEND_SEND_VAR_EX: - case ZEND_SEND_USER: - spprintf(&decode[2], 0, "%" PRIu32, op->op2.num); - break; - - default: - decode[2] = phpdbg_decode_op(ops, &op->op2, op->op2_type); - break; - } + decode[2] = phpdbg_decode_input_op( + ops, opline, opline->op2, opline->op2_type, ZEND_VM_OP2_FLAGS(flags)); /* RESULT */ - switch (op->opcode) { + switch (opline->opcode) { case ZEND_CATCH: - spprintf(&decode[3], 0, "%" PRIu32, op->result.num); + spprintf(&decode[3], 0, "%" PRIu32, opline->result.num); break; default: - decode[3] = phpdbg_decode_op(ops, &op->result, op->result_type); + decode[3] = phpdbg_decode_op(ops, &opline->result, opline->result_type); break; } diff --git a/sapi/phpdbg/phpdbg_out.h b/sapi/phpdbg/phpdbg_out.h index 0a0d7c2410..a6f28da14d 100644 --- a/sapi/phpdbg/phpdbg_out.h +++ b/sapi/phpdbg/phpdbg_out.h @@ -34,20 +34,11 @@ enum { P_LOG }; -#ifdef ZTS -PHPDBG_API int phpdbg_print(int severity, int fd, const char *tag, const char *xmlfmt, const char *strfmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 6, 7); -PHPDBG_API int phpdbg_xml_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4); -PHPDBG_API int phpdbg_log_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4); -PHPDBG_API int phpdbg_out_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4); -PHPDBG_API int phpdbg_rlog_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4); -#else PHPDBG_API int phpdbg_print(int severity, int fd, const char *tag, const char *xmlfmt, const char *strfmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 5, 6); PHPDBG_API int phpdbg_xml_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); PHPDBG_API int phpdbg_log_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); PHPDBG_API int phpdbg_out_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); PHPDBG_API int phpdbg_rlog_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3); -#endif - #define phpdbg_error(tag, xmlfmt, strfmt, ...) phpdbg_print(P_ERROR , PHPDBG_G(io)[PHPDBG_STDOUT].fd, tag, xmlfmt, strfmt, ##__VA_ARGS__) #define phpdbg_notice(tag, xmlfmt, strfmt, ...) phpdbg_print(P_NOTICE , PHPDBG_G(io)[PHPDBG_STDOUT].fd, tag, xmlfmt, strfmt, ##__VA_ARGS__) diff --git a/sapi/phpdbg/phpdbg_print.c b/sapi/phpdbg/phpdbg_print.c index 6b6c706f92..00209cb239 100644 --- a/sapi/phpdbg/phpdbg_print.c +++ b/sapi/phpdbg/phpdbg_print.c @@ -42,7 +42,7 @@ const phpdbg_command_t phpdbg_print_commands[] = { PHPDBG_PRINT(opline) /* {{{ */ { if (PHPDBG_G(in_execution) && EG(current_execute_data)) { - phpdbg_print_opline(EG(current_execute_data), 1); + phpdbg_print_opline(phpdbg_user_execute_data(EG(current_execute_data)), 1); } else { phpdbg_error("inactive", "type=\"execution\"", "Not Executing!"); } @@ -124,7 +124,7 @@ return SUCCESS; PHPDBG_PRINT(stack) /* {{{ */ { if (PHPDBG_G(in_execution) && EG(current_execute_data)) { - zend_op_array *ops = &EG(current_execute_data)->func->op_array; + zend_op_array *ops = &phpdbg_user_execute_data(EG(current_execute_data))->func->op_array; if (ops->function_name) { if (ops->scope) { phpdbg_notice("printinfo", "method=\"%s::%s\" num=\"%d\"", "Stack in %s::%s() (%d ops)", ZSTR_VAL(ops->scope->name), ZSTR_VAL(ops->function_name), ops->last); @@ -278,7 +278,7 @@ void phpdbg_print_opcodes_function(const char *function, size_t len) { return; } - phpdbg_out("function name: %.*s\n", ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name)); + phpdbg_out("function name: %.*s\n", (int) ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name)); phpdbg_print_function_helper(func); } @@ -351,7 +351,7 @@ static void phpdbg_print_opcodes_ce(zend_class_entry *ce) { phpdbg_out("\n"); ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, method_name, method) { - phpdbg_out("\nfunction name: %s\n", method_name); + phpdbg_out("\nfunction name: %s\n", ZSTR_VAL(method_name)); phpdbg_print_function_helper(method); } ZEND_HASH_FOREACH_END(); } diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 97249765f8..edfdba688e 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -518,13 +518,14 @@ PHPDBG_COMMAND(continue) /* {{{ */ } /* }}} */ int phpdbg_skip_line_helper() /* {{{ */ { - const zend_op_array *op_array = &EG(current_execute_data)->func->op_array; + zend_execute_data *ex = phpdbg_user_execute_data(EG(current_execute_data)); + const zend_op_array *op_array = &ex->func->op_array; const zend_op *opline = op_array->opcodes; PHPDBG_G(flags) |= PHPDBG_IN_UNTIL; - PHPDBG_G(seek_ex) = EG(current_execute_data); + PHPDBG_G(seek_ex) = ex; do { - if (opline->lineno != EG(current_execute_data)->opline->lineno + if (opline->lineno != ex->opline->lineno || opline->opcode == ZEND_RETURN || opline->opcode == ZEND_FAST_RET || opline->opcode == ZEND_GENERATOR_RETURN @@ -562,10 +563,11 @@ PHPDBG_COMMAND(next) /* {{{ */ } /* }}} */ static void phpdbg_seek_to_end(void) /* {{{ */ { - const zend_op_array *op_array = &EG(current_execute_data)->func->op_array; + zend_execute_data *ex = phpdbg_user_execute_data(EG(current_execute_data)); + const zend_op_array *op_array = &ex->func->op_array; const zend_op *opline = op_array->opcodes; - PHPDBG_G(seek_ex) = EG(current_execute_data); + PHPDBG_G(seek_ex) = ex; do { switch (opline->opcode) { case ZEND_RETURN: @@ -588,7 +590,7 @@ PHPDBG_COMMAND(finish) /* {{{ */ } phpdbg_seek_to_end(); - if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) EG(current_execute_data)->opline)) { + if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) { zend_hash_clean(&PHPDBG_G(seek)); } else { PHPDBG_G(flags) |= PHPDBG_IN_FINISH; @@ -605,7 +607,7 @@ PHPDBG_COMMAND(leave) /* {{{ */ } phpdbg_seek_to_end(); - if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) EG(current_execute_data)->opline)) { + if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) { zend_hash_clean(&PHPDBG_G(seek)); phpdbg_notice("leave", "type=\"end\"", "Already at the end of the function"); return SUCCESS; @@ -651,7 +653,7 @@ static inline void phpdbg_handle_exception(void) /* {{{ */ phpdbg_error("exception", "name=\"%s\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"", "Uncaught %s in %s on line " ZEND_LONG_FMT, ZSTR_VAL(ex->ce->name), ZSTR_VAL(file), line); zend_string_release(file); - phpdbg_writeln("exceptionmsg", "msg=\"%s\"", ZSTR_VAL(msg)); + phpdbg_writeln("exceptionmsg", "msg=\"%s\"", "%s", ZSTR_VAL(msg)); zend_string_release(msg); if (EG(prev_exception)) { @@ -1518,7 +1520,11 @@ void phpdbg_execute_ex(zend_execute_data *execute_data) /* {{{ */ line = zval_get_long(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("line"), 1, &rv)); msg = zval_get_string(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("message"), 1, &rv)); - phpdbg_error("exception", "name=\"%s\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"", "Uncaught %s in %s on line " ZEND_LONG_FMT ": %.*s", ZSTR_VAL(exception->ce->name), ZSTR_VAL(file), line, ZSTR_LEN(msg) < 80 ? ZSTR_LEN(msg) : 80, ZSTR_VAL(msg)); + phpdbg_error("exception", + "name=\"%s\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"", + "Uncaught %s in %s on line " ZEND_LONG_FMT ": %.*s", + ZSTR_VAL(exception->ce->name), ZSTR_VAL(file), line, + ZSTR_LEN(msg) < 80 ? (int) ZSTR_LEN(msg) : 80, ZSTR_VAL(msg)); zend_string_release(msg); zend_string_release(file); @@ -1627,7 +1633,7 @@ next: execute_data->call->func->type == ZEND_USER_FUNCTION) { zend_execute_ex = execute_ex; } - PHPDBG_G(vmret) = zend_vm_call_opcode_handler(execute_data); + PHPDBG_G(vmret) = zend_vm_call_opcode_handler(execute_data); zend_execute_ex = phpdbg_execute_ex; if (PHPDBG_G(vmret) != 0) { diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c index 696e11e762..a944d256ae 100644 --- a/sapi/phpdbg/phpdbg_utils.c +++ b/sapi/phpdbg/phpdbg_utils.c @@ -484,11 +484,11 @@ PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable key = ZSTR_VAL(strkey); keylen = ZSTR_LEN(strkey); } else { - keylen = spprintf(&key, 0, "%llu", numkey); + keylen = spprintf(&key, 0, ZEND_ULONG_FMT, numkey); } propkey = phpdbg_get_property_key(key); name = emalloc(i + keylen + 2); - namelen = sprintf(name, "%.*s%.*s%s", (int) i, input, keylen - (propkey - key), propkey, input[len - 1] == ']'?"]":""); + namelen = sprintf(name, "%.*s%.*s%s", (int) i, input, (int) (keylen - (propkey - key)), propkey, input[len - 1] == ']'?"]":""); if (!strkey) { efree(key); } @@ -597,7 +597,7 @@ static int phpdbg_xml_array_element_dump(zval *zv, zend_string *key, zend_ulong phpdbg_try_access { if (key) { /* string key */ - phpdbg_xml(" name=\"%.*s\"", ZSTR_LEN(key), ZSTR_VAL(key)); + phpdbg_xml(" name=\"%.*s\"", (int) ZSTR_LEN(key), ZSTR_VAL(key)); } else { /* numeric key */ phpdbg_xml(" name=\"%ld\"", num); } @@ -631,7 +631,7 @@ static int phpdbg_xml_object_property_dump(zval *zv, zend_string *key, zend_ulon phpdbg_xml(" class=\"%s\" protection=\"private\"", class_name); } } else { - phpdbg_xml(" name=\"%.*s\" protection=\"public\"", ZSTR_LEN(key), ZSTR_VAL(key)); + phpdbg_xml(" name=\"%.*s\" protection=\"public\"", (int) ZSTR_LEN(key), ZSTR_VAL(key)); } } else { /* numeric key */ phpdbg_xml(" name=\"%ld\" protection=\"public\"", num); @@ -683,7 +683,7 @@ PHPDBG_API void phpdbg_xml_var_dump(zval *zv) { phpdbg_xml("<float refstatus=\"%s\" value=\"%.*G\" />", COMMON, (int) EG(precision), Z_DVAL_P(zv)); break; case IS_STRING: - phpdbg_xml("<string refstatus=\"%s\" length=\"%d\" value=\"%.*s\" />", COMMON, Z_STRLEN_P(zv), Z_STRLEN_P(zv), Z_STRVAL_P(zv)); + phpdbg_xml("<string refstatus=\"%s\" length=\"%zd\" value=\"%.*s\" />", COMMON, Z_STRLEN_P(zv), (int) Z_STRLEN_P(zv), Z_STRVAL_P(zv)); break; case IS_ARRAY: myht = Z_ARRVAL_P(zv); @@ -705,7 +705,7 @@ PHPDBG_API void phpdbg_xml_var_dump(zval *zv) { } class_name = Z_OBJ_HANDLER_P(zv, get_class_name)(Z_OBJ_P(zv)); - phpdbg_xml("<object refstatus=\"%s\" class=\"%.*s\" id=\"%d\" num=\"%d\">", COMMON, ZSTR_LEN(class_name), ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(zv), myht ? zend_hash_num_elements(myht) : 0); + phpdbg_xml("<object refstatus=\"%s\" class=\"%.*s\" id=\"%d\" num=\"%d\">", COMMON, (int) ZSTR_LEN(class_name), ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(zv), myht ? zend_hash_num_elements(myht) : 0); zend_string_release(class_name); element_dump_func = phpdbg_xml_object_property_dump; @@ -729,7 +729,7 @@ head_done: break; case IS_RESOURCE: { const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(zv)); - phpdbg_xml("<resource refstatus=\"%s\" id=\"%pd\" type=\"%ld\" />", COMMON, Z_RES_P(zv)->handle, type_name ? type_name : "unknown"); + phpdbg_xml("<resource refstatus=\"%s\" id=\"%pd\" type=\"%s\" />", COMMON, Z_RES_P(zv)->handle, type_name ? type_name : "unknown"); break; } default: diff --git a/sapi/phpdbg/phpdbg_utils.h b/sapi/phpdbg/phpdbg_utils.h index 2bd4f35d71..4ba756139b 100644 --- a/sapi/phpdbg/phpdbg_utils.h +++ b/sapi/phpdbg/phpdbg_utils.h @@ -99,6 +99,14 @@ char *phpdbg_short_zval_print(zval *zv, int maxlen); PHPDBG_API zend_bool phpdbg_check_caught_ex(zend_execute_data *ex, zend_object *exception); +static zend_always_inline zend_execute_data *phpdbg_user_execute_data(zend_execute_data *ex) { + while (!ex->func || !ZEND_USER_CODE(ex->func->common.type)) { + ex = ex->prev_execute_data; + ZEND_ASSERT(ex); + } + return ex; +} + #ifdef ZTS #define PHPDBG_OUTPUT_BACKUP_DEFINES() \ zend_output_globals *output_globals_ptr; \ diff --git a/sapi/phpdbg/phpdbg_wait.c b/sapi/phpdbg/phpdbg_wait.c index 180b48c864..c3ae23b7cd 100644 --- a/sapi/phpdbg/phpdbg_wait.c +++ b/sapi/phpdbg/phpdbg_wait.c @@ -231,7 +231,7 @@ void phpdbg_webdata_decompress(char *msg, int len) { } else if (mode > 0) { // not loaded module if (!sapi_module.name || strcmp(sapi_module.name, Z_STRVAL_P(module))) { - phpdbg_notice("wait", "missingmodule=\"%.*s\"", "The module %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/module/%.*s.so", Z_STRLEN_P(module), Z_STRVAL_P(module), Z_STRLEN_P(module), Z_STRVAL_P(module)); + phpdbg_notice("wait", "missingmodule=\"%.*s\"", "The module %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/module/%.*s.so", (int) Z_STRLEN_P(module), Z_STRVAL_P(module), (int) Z_STRLEN_P(module), Z_STRVAL_P(module)); } } } while (module); @@ -292,7 +292,7 @@ void phpdbg_webdata_decompress(char *msg, int len) { ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zvp), name) { if (Z_TYPE_P(name) == IS_STRING) { - phpdbg_notice("wait", "missingextension=\"%.*s\"", "The Zend extension %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/extension.so", Z_STRLEN_P(name), Z_STRVAL_P(name)); + phpdbg_notice("wait", "missingextension=\"%.*s\"", "The Zend extension %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/extension.so", (int) Z_STRLEN_P(name), Z_STRVAL_P(name)); } } ZEND_HASH_FOREACH_END(); } diff --git a/sapi/phpdbg/tests/exceptions_003.phpt b/sapi/phpdbg/tests/exceptions_003.phpt index c83eb7517a..37e7289092 100644 --- a/sapi/phpdbg/tests/exceptions_003.phpt +++ b/sapi/phpdbg/tests/exceptions_003.phpt @@ -25,7 +25,7 @@ prompt> [L7 %s ECHO "ok " 00008: } 00009: } catch (Error $e) { prompt> ok -[L7 %s FAST_RET<TO_CATCH> ~%d 0 %s] +[L7 %s FAST_RET<TO_CATCH> ~%d try-catch(0) %s] [L9 %s CATCH "Error" $e 1 %s] >00005: x(); 00006: } finally { diff --git a/sapi/phpdbg/tests/print_001.phpt b/sapi/phpdbg/tests/print_001.phpt index 1f7a5ac0b9..a4f300572a 100644 --- a/sapi/phpdbg/tests/print_001.phpt +++ b/sapi/phpdbg/tests/print_001.phpt @@ -34,7 +34,7 @@ prompt> [Context %s (11 ops)] L1-19 {main}() %s - %s + 11 ops L4 #0 NOP L14 #1 NOP - L18 #2 NEW "Foo\\Bar" @1 + L18 #2 NEW "Foo\\Bar" J4 @1 L18 #3 DO_FCALL L18 #4 INIT_METHOD_CALL @1 "Foo" L18 #5 SEND_VAL_EX "test" 1 diff --git a/sapi/phpdbg/tests/stepping_001.phpt b/sapi/phpdbg/tests/stepping_001.phpt index 9366550f56..ec9def278f 100644 --- a/sapi/phpdbg/tests/stepping_001.phpt +++ b/sapi/phpdbg/tests/stepping_001.phpt @@ -34,7 +34,7 @@ prompt> [L10 %s ECHO "ok" 00011: } finally { 00012: echo " ... ok"; prompt> ok -[L11 %s FAST_CALL J8 ~%d %s] +[L11 %s FAST_CALL J8 try-catch(0) ~%d %s] >00011: } finally { 00012: echo " ... ok"; 00013: } diff --git a/win32/build/Makefile b/win32/build/Makefile index 19ee82e7b9..06f8ef35d5 100644 --- a/win32/build/Makefile +++ b/win32/build/Makefile @@ -211,9 +211,12 @@ install-sdk: build-devel really-install: @if not exist $(PHP_PREFIX) mkdir $(PHP_PREFIX) + @if not exist $(PHP_PREFIX)\ext mkdir $(PHP_PREFIX)\ext @echo Installing files under $(PHP_PREFIX) @copy $(BUILD_DIR)\*.exe $(PHP_PREFIX) /y >nul - @copy $(BUILD_DIR)\*.dll $(PHP_PREFIX) /y >nul + @copy $(BUILD_DIR)\php_*.dll $(PHP_PREFIX)\ext /y >nul + dir /b $(BUILD_DIR)\php_*.dll > $(BUILD_DIR)\extension_dlls.txt + @xcopy $(BUILD_DIR)\*.dll /exclude:$(BUILD_DIR)\extension_dlls.txt $(PHP_PREFIX) /y >nul @echo Registering event source with syslog (requires admin rights) @echo It's okay for this step to fail: -$(PHP_PREFIX)\php.exe -n -dextension_dir=$(PHP_PREFIX) win32/build/registersyslog.php $(PHP_PREFIX)\$(PHPDLL) diff --git a/win32/build/Makefile.phpize b/win32/build/Makefile.phpize index 1f92f7716c..cd74336039 100644 --- a/win32/build/Makefile.phpize +++ b/win32/build/Makefile.phpize @@ -18,11 +18,13 @@ clean-pecl: clean-all:
@echo Cleaning standard build dirs
+ cd $(BUILD_DIR)
@for %D in (_x $(BUILD_DIRS_SUB)) do @if exist %D @rd /s /q %D
-@del /f /q $(BUILD_DIR)\*.res $(BUILD_DIR)\*.manifest $(BUILD_DIR)\*.lib $(BUILD_DIR)\*.ilk $(BUILD_DIR)\*.pdb $(BUILD_DIR)\*.exp $(PHPDEF) $(BUILD_DIR)\*.rc $(BUILD_DIR)\*.dbg $(BUILD_DIR)\*.bin $(BUILD_DIR)\php*.dll $(BUILD_DIR)\php*.exe > NUL
clean: clean-pecl
@echo Cleaning distribution build dirs
+ cd $(BUILD_DIR)
@for %D in (_x $(BUILD_DIRS_SUB)) do @if exist %D @del /F /Q %D\*.* > NUL
-@del /F /Q $(BUILD_DIR)\*.res $(BUILD_DIR)\*.lib $(BUILD_DIR)\*.ilk $(BUILD_DIR)\*.pdb $(BUILD_DIR)\*.exp $(PHPDEF) $(BUILD_DIR)\php-$(PHP_VERSION_STRING)-Win32.zip $(BUILD_DIR)\pecl-$(PHP_VERSION_STRING)-Win32.zip > NUL
diff --git a/win32/build/config.w32.h.in b/win32/build/config.w32.h.in index d73678b1ec..8ed79b39e4 100644 --- a/win32/build/config.w32.h.in +++ b/win32/build/config.w32.h.in @@ -15,7 +15,7 @@ #define PEAR_INSTALLDIR "@PREFIX@\\pear" #define PHP_BINDIR "@PREFIX@" #define PHP_DATADIR "@PREFIX@" -#define PHP_EXTENSION_DIR "@PREFIX@" +#define PHP_EXTENSION_DIR "@PREFIX@\\ext" #define PHP_INCLUDE_PATH ".;@PREFIX@\\pear" #define PHP_LIBDIR "@PREFIX@" #define PHP_LOCALSTATEDIR "@PREFIX@" diff --git a/win32/build/confutils.js b/win32/build/confutils.js index c2852cfd43..46046e0129 100644 --- a/win32/build/confutils.js +++ b/win32/build/confutils.js @@ -1449,79 +1449,117 @@ function ADD_SOURCES(dir, file_list, target, obj_dir) var sub_build = "$(BUILD_DIR)\\"; - /* if module dir is not a child of the main source dir, - * we need to tweak it; we should have detected such a - * case in condense_path and rewritten the path to - * be relative. - * This probably breaks for non-sibling dirs, but that - * is not a problem as buildconf only checks for pecl - * as either a child or a sibling */ - if (obj_dir == null) { - var build_dir = dir.replace(new RegExp("^..\\\\"), ""); - var mangle_dir = build_dir.replace(new RegExp("[\\\\/.-]", "g"), "_"); - var bd_flags_name = "CFLAGS_BD_" + mangle_dir.toUpperCase(); - } - else { - var build_dir = obj_dir.replace(new RegExp("^..\\\\"), ""); - var mangle_dir = build_dir.replace(new RegExp("[\\\\/.-]", "g"), "_"); - var bd_flags_name = "CFLAGS_BD_" + mangle_dir.toUpperCase(); - } - - var dirs = build_dir.split("\\"); - var i, d = ""; - for (i = 0; i < dirs.length; i++) { - d += dirs[i]; - build_dirs[build_dirs.length] = d; - d += "\\"; - } - sub_build += d; - - - DEFINE(bd_flags_name, "/Fp" + sub_build + " /FR" + sub_build + " "); - if (VS_TOOLSET) { - ADD_FLAG(bd_flags_name, "/Fd" + sub_build); - } + var srcs_by_dir = {}; + /* Parse the file list to create an aggregated structure based on the subdirs passed. */ for (i in file_list) { src = file_list[i]; - obj = src.replace(re, ".obj"); - tv += " " + sub_build + obj; - resp += " " + sub_build.replace('$(BUILD_DIR)', bd) + obj; - - if (!PHP_MP_DISABLED) { - if (i > 0) { - objs_line += " " + sub_build + obj; - srcs_line += " " + dir + "\\" + src; + + var _tmp = src.split("\\"); + + var filename = _tmp.pop(); + + // build the obj out dir and use it as a key + var dirname = _tmp.join("\\"); + + //WARNING("dir: " + dir + " dirname: " + dirname + " filename: " + filename); + + /* if module dir is not a child of the main source dir, + * we need to tweak it; we should have detected such a + * case in condense_path and rewritten the path to + * be relative. + * This probably breaks for non-sibling dirs, but that + * is not a problem as buildconf only checks for pecl + * as either a child or a sibling */ + if (obj_dir == null) { + if (MODE_PHPIZE) { + /* In the phpize mode, the subdirs are always relative to BUID_DIR. + No need to differentiate by extension, only one gets built. */ + var build_dir = (dirname ? dirname : "").replace(new RegExp("^..\\\\"), ""); } else { - objs_line = sub_build + obj; - srcs_line = dir + "\\" + src; + var build_dir = (dirname ? (dir + "\\" + dirname) : dir).replace(new RegExp("^..\\\\"), ""); } - } else { - MFO.WriteLine(sub_build + obj + ": " + dir + "\\" + src); + } + else { + var build_dir = (dirname ? obj_dir + "\\" + dirname : obj_dir).replace(new RegExp("^..\\\\"), ""); + } - if (PHP_ANALYZER == "pvs") { - MFO.WriteLine("\t@\"$(PVS_STUDIO)\" --cl-params $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " --source-file " + dir + "\\" + src - + " --cfg PVS-Studio.conf --errors-off \"V122 V117 V111\" "); - } - MFO.WriteLine("\t@$(CC) $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " /Fo" + sub_build + obj); + obj = sub_build + build_dir + "\\" + filename.replace(re, ".obj"); + + if (i > 0) { + srcs_line += " " + dir + "\\" + src; + objs_line += " " + obj + } else { + srcs_line = dir + "\\" + src; + objs_line = obj; } + + resp += " " + obj.replace('$(BUILD_DIR)', bd); + tv += " " + obj; + + if (!srcs_by_dir.hasOwnProperty(build_dir)) { + srcs_by_dir[build_dir] = []; + } + + /* storing the index from the file_list */ + srcs_by_dir[build_dir].push(i); } - if (!PHP_MP_DISABLED) { - MFO.WriteLine(objs_line + ": " + srcs_line); - MFO.WriteLine("\t$(CC) $(" + flags + ") $(CFLAGS) /Fo" + sub_build + " $(" + bd_flags_name + ") /c " + srcs_line); + /* Create makefile build targets and dependencies. */ + MFO.WriteLine(objs_line + ": " + srcs_line); + + /* Create target subdirs if any and produce the compiler calls, /mp is respected if enabled. */ + for (var k in srcs_by_dir) { + var dirs = k.split("\\"); + var i, d = ""; + for (i = 0; i < dirs.length; i++) { + d += dirs[i]; + build_dirs[build_dirs.length] = d; + d += "\\"; + } + + var mangle_dir = k.replace(new RegExp("[\\\\/.-]", "g"), "_"); + var bd_flags_name = "CFLAGS_BD_" + mangle_dir.toUpperCase(); + + DEFINE(bd_flags_name, "/Fp" + sub_build + d + " /FR" + sub_build + d + " "); + if (VS_TOOLSET) { + ADD_FLAG(bd_flags_name, "/Fd" + sub_build + d); + } + + if (PHP_MP_DISABLED) { + for (var j in srcs_by_dir[k]) { + src = file_list[srcs_by_dir[k][j]]; + if (PHP_ANALYZER == "pvs") { + MFO.WriteLine("\t@\"$(PVS_STUDIO)\" --cl-params $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " --source-file " + dir + "\\" + src + + " --cfg PVS-Studio.conf --errors-off \"V122 V117 V111\" "); + } + + var _tmp = src.split("\\"); + var filename = _tmp.pop(); + obj = filename.replace(re, ".obj"); + + MFO.WriteLine("\t@$(CC) $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " /Fo" + sub_build + d + obj); + } + } else { + /* TODO create a response file at least for the source files to work around the cmd line length limit. */ + var src_line = ""; + for (var j in srcs_by_dir[k]) { + src_line += dir + "\\" + file_list[srcs_by_dir[k][j]] + " "; + } + + MFO.WriteLine("\t$(CC) $(" + flags + ") $(CFLAGS) /Fo" + sub_build + d + " $(" + bd_flags_name + ") /c " + src_line); + } } DEFINE(sym, tv); - /* Generate the response file and define it to the Makefile. This can be - useful when getting the "command line too long" linker errors. */ + /* Generate the object response file and define it to the Makefile. This can be + useful when getting the "command line too long" linker errors. + TODO pack this into a function when response files are used for other kinds of info. */ var obj_lst_fh = null; if (!FSO.FileExists(obj_lst_fn)) { obj_lst_fh = FSO.CreateTextFile(obj_lst_fn); - //STDOUT.WriteLine("Creating " + obj_lst_fn); } else { - //STDOUT.WriteLine("Appending to " + obj_lst_fn); obj_lst_fh = FSO.OpenTextFile(obj_lst_fn, 8); } @@ -2069,7 +2107,8 @@ function generate_makefile() var dll = "php_" + extensions_enabled[i][0] + ".dll"; MF.WriteLine(" @copy $(BUILD_DIR)\\" + lib + " $(BUILD_DIR_DEV)\\lib"); MF.WriteLine(" @if not exist $(PHP_PREFIX) mkdir $(PHP_PREFIX) >nul"); - MF.WriteLine(" @copy $(BUILD_DIR)\\" + dll + " $(PHP_PREFIX)"); + MF.WriteLine(" @if not exist $(PHP_PREFIX)\\ext mkdir $(PHP_PREFIX)\\ext >nul"); + MF.WriteLine(" @copy $(BUILD_DIR)\\" + dll + " $(PHP_PREFIX)\\ext"); } } else { MF.WriteBlankLines(1); @@ -2108,7 +2147,16 @@ function ADD_FLAG(name, flags, target) if (configure_subst.Exists(name)) { var curr_flags = configure_subst.Item(name); - if (curr_flags.indexOf(flags) >= 0) { + /* Prefix with a space, thus making sure the + current flag is not a substring of some + other. It's still not a complete check if + some flags with spaces got added. + + TODO rework to use an array, so direct + match can be done. This will also + help to normalize flags and to not + to insert duplicates. */ + if (curr_flags.indexOf(" " + flags) >= 0) { return; } @@ -2645,6 +2693,15 @@ function toolset_setup_common_cflags() if (VCVERS >= 1900) { ADD_FLAG('CFLAGS', "/guard:cf"); } + if (VCVERS >= 1800) { + if (PHP_PGI != "yes" && PHP_PGO != "yes") { + ADD_FLAG('CFLAGS', "/Zc:inline"); + } + /* We enable /opt:icf only with the debug pack, so /Gw only makes sense there, too. */ + if (PHP_DEBUG_PACK == "yes") { + ADD_FLAG('CFLAGS', "/Gw"); + } + } } } else if (CLANG_TOOLSET) { diff --git a/win32/build/libs_version.txt b/win32/build/libs_version.txt index b98b089796..3d629fcbaa 100644 --- a/win32/build/libs_version.txt +++ b/win32/build/libs_version.txt @@ -1,16 +1,16 @@ bz2-1.0.6 cclient-2007f -freetype-2.6 +freetype-2.6.2 icu-56.1 jpeglib-9a -libcurl-7.43.0 +libcurl-7.46.0 libiconv-1.14 libmcrypt-2.5.8 -libmpir-2.7.0 -libpng-1.6.18 -libpq-9.4.4 +libmpir-2.7.2 +libpng-1.6.20 +libpq-9.4.5 libssh2-1.6.0 libtidy-20090406 libxslt-1.1.28 -libxml-2.9.2 -openssl-1.0.2d +libxml-2.9.3 +openssl-1.0.2f |
