summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--NEWS958
-rw-r--r--UPGRADING755
-rw-r--r--UPGRADING.INTERNALS291
-rw-r--r--Zend/tests/anon/013.phpt15
-rw-r--r--Zend/tests/anon/014.phpt16
-rw-r--r--Zend/tests/bug70918.phpt47
-rw-r--r--Zend/tests/func_get_args.phpt10
-rw-r--r--Zend/tests/jump16.phpt27
-rw-r--r--Zend/tests/jump17.phpt22
-rw-r--r--Zend/tests/return_types/void_allowed.phpt20
-rw-r--r--Zend/tests/return_types/void_disallowed1.phpt12
-rw-r--r--Zend/tests/return_types/void_disallowed2.phpt12
-rw-r--r--Zend/tests/return_types/void_parameter.phpt8
-rw-r--r--Zend/tests/temporary_cleaning_001.phpt2
-rw-r--r--Zend/tests/temporary_cleaning_003.phpt2
-rw-r--r--Zend/tests/temporary_cleaning_004.phpt2
-rw-r--r--Zend/tests/temporary_cleaning_005.phpt2
-rw-r--r--Zend/tests/temporary_cleaning_006.phpt2
-rw-r--r--Zend/tests/temporary_cleaning_008.phpt15
-rw-r--r--Zend/tests/temporary_cleaning_009.phpt27
-rw-r--r--Zend/tests/temporary_cleaning_010.phpt23
-rw-r--r--Zend/tests/temporary_cleaning_011.phpt20
-rw-r--r--Zend/tests/try/try_finally_021.phpt20
-rw-r--r--Zend/tests/try/try_finally_022.phpt41
-rw-r--r--Zend/zend.h2
-rw-r--r--Zend/zend_API.c2
-rw-r--r--Zend/zend_compile.c433
-rw-r--r--Zend/zend_compile.h59
-rw-r--r--Zend/zend_constants.c4
-rw-r--r--Zend/zend_constants.h4
-rw-r--r--Zend/zend_exceptions.c69
-rw-r--r--Zend/zend_execute.c65
-rw-r--r--Zend/zend_extensions.h22
-rw-r--r--Zend/zend_language_scanner.c810
-rw-r--r--Zend/zend_language_scanner.l114
-rw-r--r--Zend/zend_opcode.c60
-rw-r--r--Zend/zend_smart_str.c60
-rw-r--r--Zend/zend_smart_str.h1
-rw-r--r--Zend/zend_types.h5
-rw-r--r--Zend/zend_vm_def.h831
-rw-r--r--Zend/zend_vm_execute.h5294
-rw-r--r--Zend/zend_vm_gen.php154
-rw-r--r--Zend/zend_vm_opcodes.c201
-rw-r--r--Zend/zend_vm_opcodes.h40
-rw-r--r--configure.in4
-rw-r--r--ext/date/tests/date_sun_info_003.phpt42
-rw-r--r--ext/dba/php_dba.h2
-rw-r--r--ext/exif/exif.c2
-rw-r--r--ext/hash/config.m44
-rw-r--r--ext/hash/config.w324
-rw-r--r--ext/hash/hash.c4
-rw-r--r--ext/hash/hash_sha3.c238
-rw-r--r--ext/hash/php_hash.h4
-rw-r--r--ext/hash/php_hash_sha3.h59
-rw-r--r--ext/hash/tests/hash_algos.phpt10
-rw-r--r--ext/hash/tests/hash_copy_001.phpt24
-rw-r--r--ext/hash/tests/sha3.phpt56
-rw-r--r--ext/mcrypt/tests/mcrypt_module_get_algo_block_size.phpt5
-rw-r--r--ext/mcrypt/tests/mcrypt_module_get_algo_key_size.phpt5
-rw-r--r--ext/mysqli/mysqli_api.c6
-rw-r--r--ext/mysqli/mysqli_prop.c8
-rw-r--r--ext/mysqlnd/config.w327
-rw-r--r--ext/mysqlnd/config9.m48
-rw-r--r--ext/mysqlnd/mysqlnd.h108
-rw-r--r--ext/mysqlnd/mysqlnd_alloc.c3
-rw-r--r--ext/mysqlnd/mysqlnd_alloc.h6
-rw-r--r--ext/mysqlnd/mysqlnd_auth.c351
-rw-r--r--ext/mysqlnd/mysqlnd_auth.h126
-rw-r--r--ext/mysqlnd/mysqlnd_block_alloc.c3
-rw-r--r--ext/mysqlnd/mysqlnd_block_alloc.h5
-rw-r--r--ext/mysqlnd/mysqlnd_charset.c5
-rw-r--r--ext/mysqlnd/mysqlnd_charset.h5
-rw-r--r--ext/mysqlnd/mysqlnd_commands.c1470
-rw-r--r--ext/mysqlnd/mysqlnd_commands.h34
-rw-r--r--ext/mysqlnd/mysqlnd_connection.c (renamed from ext/mysqlnd/mysqlnd.c)2084
-rw-r--r--ext/mysqlnd/mysqlnd_connection.h86
-rw-r--r--ext/mysqlnd/mysqlnd_debug.c6
-rw-r--r--ext/mysqlnd/mysqlnd_debug.h17
-rw-r--r--ext/mysqlnd/mysqlnd_driver.c181
-rw-r--r--ext/mysqlnd/mysqlnd_enum_n_def.h42
-rw-r--r--ext/mysqlnd/mysqlnd_ext_plugin.c332
-rw-r--r--ext/mysqlnd/mysqlnd_ext_plugin.h196
-rw-r--r--ext/mysqlnd/mysqlnd_libmysql_compat.h4
-rw-r--r--ext/mysqlnd/mysqlnd_loaddata.c33
-rw-r--r--ext/mysqlnd/mysqlnd_plugin.h40
-rw-r--r--ext/mysqlnd/mysqlnd_priv.h222
-rw-r--r--ext/mysqlnd/mysqlnd_protocol_frame_codec.c506
-rw-r--r--ext/mysqlnd/mysqlnd_protocol_frame_codec.h35
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c767
-rw-r--r--ext/mysqlnd/mysqlnd_ps.h54
-rw-r--r--ext/mysqlnd/mysqlnd_ps_codec.c68
-rw-r--r--ext/mysqlnd/mysqlnd_read_buffer.c95
-rw-r--r--ext/mysqlnd/mysqlnd_read_buffer.h25
-rw-r--r--ext/mysqlnd/mysqlnd_result.c441
-rw-r--r--ext/mysqlnd/mysqlnd_result.h11
-rw-r--r--ext/mysqlnd/mysqlnd_result_meta.c27
-rw-r--r--ext/mysqlnd/mysqlnd_statistics.c48
-rw-r--r--ext/mysqlnd/mysqlnd_statistics.h54
-rw-r--r--ext/mysqlnd/mysqlnd_structs.h674
-rw-r--r--ext/mysqlnd/mysqlnd_vio.c809
-rw-r--r--ext/mysqlnd/mysqlnd_vio.h (renamed from ext/mysqlnd/mysqlnd_net.h)14
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.c966
-rw-r--r--ext/mysqlnd/mysqlnd_wireprotocol.h50
-rw-r--r--ext/mysqlnd/php_mysqlnd.c1
-rw-r--r--ext/opcache/Optimizer/block_pass.c2482
-rw-r--r--ext/opcache/Optimizer/compact_literals.c71
-rw-r--r--ext/opcache/Optimizer/nop_removal.c66
-rw-r--r--ext/opcache/Optimizer/optimize_func_calls.c13
-rw-r--r--ext/opcache/Optimizer/optimize_temp_vars_5.c8
-rw-r--r--ext/opcache/Optimizer/pass1_5.c93
-rw-r--r--ext/opcache/Optimizer/pass2.c17
-rw-r--r--ext/opcache/Optimizer/pass3.c138
-rw-r--r--ext/opcache/Optimizer/zend_cfg.c601
-rw-r--r--ext/opcache/Optimizer/zend_cfg.h111
-rw-r--r--ext/opcache/Optimizer/zend_dump.c292
-rw-r--r--ext/opcache/Optimizer/zend_dump.h36
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.c181
-rw-r--r--ext/opcache/Optimizer/zend_optimizer.h9
-rw-r--r--ext/opcache/Optimizer/zend_optimizer_internal.h67
-rw-r--r--ext/opcache/ZendAccelerator.c80
-rw-r--r--ext/opcache/ZendAccelerator.h49
-rw-r--r--ext/opcache/config.m44
-rw-r--r--ext/opcache/config.w322
-rw-r--r--ext/opcache/zend_accelerator_module.c2
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.c44
-rw-r--r--ext/opcache/zend_file_cache.c40
-rw-r--r--ext/opcache/zend_persist.c38
-rw-r--r--ext/opcache/zend_persist_calc.c20
-rw-r--r--ext/pdo_mysql/php_pdo_mysql_int.h6
-rw-r--r--ext/readline/readline.c2
-rw-r--r--ext/shmop/php_shmop.h2
-rw-r--r--ext/standard/basic_functions.c19
-rw-r--r--ext/standard/ftok.c4
-rw-r--r--ext/standard/random.c4
-rw-r--r--ext/standard/string.c4
-rw-r--r--ext/standard/tests/general_functions/getenv.phpt16
-rw-r--r--ext/standard/tests/url/get_headers_error_001.phpt7
-rw-r--r--ext/standard/tests/url/get_headers_error_003.phpt31
-rw-r--r--ext/standard/url.c10
-rw-r--r--ext/sysvshm/php_sysvshm.h2
-rw-r--r--main/php_ini.c2
-rw-r--r--main/php_streams.h6
-rw-r--r--main/php_version.h8
-rwxr-xr-xrun-tests.php40
-rw-r--r--sapi/fpm/fpm/fpm_events.c3
-rw-r--r--sapi/litespeed/lsapi_main.c5
-rw-r--r--sapi/phpdbg/phpdbg_help.c2
-rw-r--r--sapi/phpdbg/phpdbg_opcode.c2
-rw-r--r--sapi/phpdbg/tests/breakpoints_001.phpt22
-rw-r--r--sapi/phpdbg/tests/breakpoints_002.phpt28
-rw-r--r--sapi/phpdbg/tests/breakpoints_003.phpt14
-rw-r--r--sapi/phpdbg/tests/breakpoints_004.phpt28
-rw-r--r--sapi/phpdbg/tests/exceptions_003.phpt2
-rwxr-xr-xserver-tests.php16
-rw-r--r--win32/build/buildconf.js2
-rw-r--r--win32/build/config.w323
-rw-r--r--win32/build/config.w32.h.in1
-rw-r--r--win32/build/confutils.js4
-rw-r--r--win32/ftok.c52
-rw-r--r--win32/ipc.h29
160 files changed, 15416 insertions, 10499 deletions
diff --git a/NEWS b/NEWS
index c774f0ebe6..c33379064b 100644
--- a/NEWS
+++ b/NEWS
@@ -1,954 +1,18 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-?? ??? 2015, PHP 7.0.1
+?? ??? 2016, PHP 7.1.0
-- Core:
- . Fixed bug #70958 (Invalid opcode while using ::class as trait method
- paramater default value). (Laruence)
- . Fixed bug #70947 (INI parser segfault with INI_SCANNER_TYPED). (Laruence)
- . Fixed bug #70944 (try{ } finally{} can create infinite chains of
- exceptions). (Laruence)
- . Fixed bug #70914 (zend_throw_or_error() format string vulnerability).
- (Taoguang Chen)
- . Fixed bug #70912 (Null ptr dereference instantiating class with invalid
- array property). (Laruence)
- . Fixed bug #70898, #70895 (null ptr deref and segfault with crafted callable).
- (Anatol, Laruence)
- . Fixed bug #70899 (buildconf failure in extensions). (Bob, Reeze)
- . Fixed bug #61751 (SAPI build problem on AIX: Undefined symbol:
- php_register_internal_extensions). (Lior Kaplan)
+Core:
+ . Fixed bug #62210 (Exceptions can leak temporary variables). (Dmitry, Bob)
+ . Added void return type. (Andrea)
-- Mysqlnd:
- . Fixed bug #68077 (LOAD DATA LOCAL INFILE / open_basedir restriction).
- (Laruence)
+Standard
+ . Implemented FR #55716 (Add an option to pass a custom stream context to
+ get_headers()). (Ferenc)
+ . Implemented FR #69359 (Provide a way to fetch the current environment
+ variables). (Ferenc)
-- OCI8:
- . Fixed LOB implementation size_t/zend_long mismatch reported
- by gcov. (Senthil)
- . Fixed memory leak with LOBs. (Senthil)
-
-- Phpdbg:
- . Fixed stderr being written to stdout. (Bob)
-
-- SOAP:
- . Fixed bug #70900 (SoapClient systematic out of memory error). (Dmitry)
- . Fixed bug #70940 (Segfault in soap / type_to_string). (Remi)
-
-- SPL:
- . Fixed bug #70959 (ArrayObject unserialize does not restore protected
- fields). (Laruence)
-
-- Standard:
- . Fixed bug #70960 (ReflectionFunction for array_unique returns wrong number
- of parameters). (Laruence)
- . Fixed bug #70963 (Unserialize shows UNKNOW in result). (Laruence)
- . Fixed count on symbol tables. (Laruence)
- . Fixed bug #70910 (extract() breaks variable references). (Laruence)
-
-- Streams/Socket
- . Add IPV6_V6ONLY constant / make it usable in stream contexts. (Bob)
-
-12 Nov 2015, PHP 7.0.0 RC 7
-
-- Core:
- . Fixed bug #70249 (Segmentation fault while running PHPUnit tests on
- phpBB 3.2-dev). (Laruence)
- . Fixed bug #70873 (Regression on private static properties access).
- (Laruence)
- . Fixed bug #70805 (Segmentation faults whilst running Drupal 8 test suite).
- (Dmitry, Laruence)
- . Fixed bug #70862 (Several functions do not check return code of
- php_stream_copy_to_mem()). (Anatol)
- . Fixed bug #70863 (Incorect logic to increment_function for proxy objects).
- (Anatol)
- . Fixed bug #70842 (Persistent Stream Segmentation Fault). (Caleb Champlin)
- . Fixed bug #70323 (Regression in zend_fetch_debug_backtrace() can cause
- segfaults). (Aharvey, Laruence)
-
-- Mysqlnd:
- . Fixed bug #68344 (MySQLi does not provide way to disable peer certificate
- validation) by introducing MYSQLI_CLIENT_SSL_DONT_VERIFY_SERVER_CERT
- connection flag. (Andrey)
-
-- OCI8:
- . Fixed bug #68298 (OCI int overflow). (Senthil)
-
-- Opcache:
- . Fixed bug #70843 (Segmentation fault on MacOSX with
- opcache.file_cache_only=1). (Laruence)
- . Fixed bug #70656 (require() statement broken after opcache_reset() or a
- few hours of use). (Laruence)
-
-- PDO:
- . Fix bug #70861 (Segmentation fault in pdo_parse_params() during Drupal 8
- test suite). (Anatol)
-
-- Session:
- . Fixed bug #70876 (Segmentation fault when regenerating session id with
- strict mode). (Laruence)
-
-- SOAP:
- . Fixed bug #70875 (Segmentation fault if wsdl has no targetNamespace
- attribute). (Matteo)
-
-- SPL:
- . Fixed bug #70868 (PCRE JIT and pattern reuse segfault). (Laruence)
- . Fixed bug #70853 (SplFixedArray throws exception when using ref variable
- as index). (Laruence)
-
-- Standard:
- . Fixed bug #70808 (array_merge_recursive corrupts memory of unset items).
- (Laruence)
-
-- XSL:
- . Fixed bug #70678 (PHP7 returns true when false is expected). (Felipe)
-
-29 Oct 2015, PHP 7.0.0 RC 6
-
-- Core:
- . Fixed bug #70785 (Infinite loop due to exception during identical
- comparison). (Laruence)
- . Fixed bug #70748 (Segfault in ini_lex () at Zend/zend_ini_scanner.l).
- (Laruence)
- . Fixed bug #70689 (Exception handler does not work as expected). (Laruence)
- . Fixed bug #70430 (Stack buffer overflow in zend_language_parser()). (Nikita)
- . Fixed bug #70782 (null ptr deref and segfault (zend_get_class_fetch_type)).
- (Nikita)
-
-- Opcache:
- . Fixed bug #70724 (Undefined Symbols from opcache.so on Mac OS X 10.10).
- (Laruence)
-
-- PDO_DBlib:
- . Fixed bug #69757 (Segmentation fault on nextRowset).
- (miracle at rpz dot name)
-
-- SPL:
- . Fixed bug #70730 (Incorrect ArrayObject serialization if unset is called
- in serialize()). (Laruence)
-
-- SOAP:
- . Fixed bug #70715 (Segmentation fault inside soap client). (Laruence)
- . Fixed bug #70709 (SOAP Client generates Segfault). (Laruence)
-
-15 Oct 2015, PHP 7.0.0 RC 5
-
-- Core:
- . Fixed bug #70630 (Closure::call/bind() crash with ReflectionFunction->
- getClosure()). (Dmitry, Bob)
- . Fixed bug #70662 (Duplicate array key via undefined index error handler).
- (Nikita)
- . Fixed bug #70681 (Segfault when binding $this of internal instance method
- to null). (Nikita)
- . Fixed bug #70685 (Segfault for getClosure() internal method rebind with
- invalid $this). (Nikita)
-
-- Mcrypt:
- . Fixed bug #70625 (mcrypt_encrypt() won't return data when no IV was
- specified under RC4). (Nikita)
-
-- Opcache:
- . Fixed compatibility with Windows 10 (see also bug #70652). (Anatol)
-
-- Phpdbg:
- . Fixed bug #70614 (incorrect exit code in -rr mode with Exceptions). (Bob)
-
-- Reflection:
- . Fixed bug #70650 (Wrong docblock assignment). (Marcio)
- . Fixed bug #70674 (ReflectionFunction::getClosure() leaks memory when used
- for internal functions). (Dmitry, Bob)
-
-- Standard:
- . Fixed bug #70667 (strtr() causes invalid writes and a crashes). (Dmitry)
- . Fixed bug #70668 (array_keys() doesn't respect references when $strict is
- true). (Bob, Dmitry)
-
-
-01 Oct 2015, PHP 7.0.0 RC 4
-
-- Core:
- . Added zend_internal_function.reserved[] fields. (Dmitry)
- . Fixed bug #70557 (Memleak on return type verifying failed). (Laruence)
- . Fixed bug #70555 (fun_get_arg() on unsetted vars return UNKNOW). (Laruence)
- . Fixed bug #70548 (Redundant information printed in case of uncaught engine
- exception). (Laruence)
- . Fixed bug #70547 (unsetting function variables corrupts backtrace).
- (Laruence)
- . Fixed bug #70528 (assert() with instanceof adds apostrophes around class
- name). (Laruence)
- . Fixed bug #70481 (Memory leak in auto_global_copy_ctor() in ZTS build).
- (Laruence)
-
-- DOM:
- . Fixed bug #70558 ("Couldn't fetch" error in
- DOMDocument::registerNodeClass()). (Laruence)
-
-- FPM:
- . Fixed bug #70538 ("php-fpm -i" crashes). (rainer dot jung at
- kippdata dot de)
- . Fixed bug #70279 (HTTP Authorization Header is sometimes passed to newer
- reqeusts). (Laruence)
-
-- Opcache
- . Attmpt to fix "Unable to reattach to base address" problem. (Matt Ficken)
-
-- OpenSSL
- . Require at least OpenSSL version 0.9.8. (Jakub Zelenka)
- . Fixed bug #68312 (Lookup for openssl.cnf causes a message box). (Anatol)
-
-- Phar:
- . Fixed bug #69720 (Null pointer dereference in phar_get_fp_offset()). (Stas)
- . FIxed bug #70433 (Uninitialized pointer in phar_make_dirstream when zip
- entry filename is "/"). (Stas)
-
-- Phpdbg:
- . Fixed bug #70532 (phpdbg must respect set_exception_handler). (Bob)
- . Fixed bug #70531 (Run and quit mode (-qrr) should not fallback to
- interactive mode). (Bob)
- . Fixed bug #70533 (Help overview (-h) does not rpint anything under Windows).
- (Anatol)
-
-- Session:
- . Fixed bug #70529 (Session read causes "String is not zero-terminated" error).
- (Yasuo)
-
-- SQLite3:
- . Fixed bug #70571 (Memory leak in sqlite3_do_callback). (Adam)
-
--SPL:
- . Fixed bug #70573 (Cloning SplPriorityQueue leads to memory leaks). (Dmitry)
-
-- XMLRPC
- . Fixed bug #70526 (xmlrpc_set_type returns false on success). (Laruence)
-
-- XSL:
- . Fixed bug #70535 (XSLT: free(): invalid pointer). (Laruence)
-
-17 Sep 2015, PHP 7.0.0 RC 3
-
-- Core:
- . Fixed bug #70431 (Memory leak in php_ini.c). (Senthil, Laruence)
- . Fixed bug #70478 (**= does no longer work). (Bob)
-
-- CLI server:
- . Fixed bug #68291 (404 on urls with '+'). (cmb)
-
-- DOM:
- . Fixed bug #70001 (Assigning to DOMNode::textContent does additional entity
- encoding). (cmb)
-
-- Intl:
- . Fixed bug #70453 (IntlChar::foldCase() incorrect arguments and missing
- constants). (cmb)
- . Fixed bug #70454 (IntlChar::forDigit second parameter should be optional).
- (cmb, colinodell)
-
-- Mysqlnd:
- . Fixed bug #70384 (mysqli_real_query():Unknown type 245 sent by the server).
- (Andrey)
- . Fixed bug #70456 (mysqlnd doesn't activate TCP keep-alive when connecting to
- a server). (Sergei Turchanov)
- . Fixed bug #70572 segfault in mysqlnd_connect. (Andrey, Remi)
-
-- Opcache:
- . Fixed bug #70423 (Warning Internal error: wrong size calculation). (Anatol)
-
-- OpenSSL
- . Fixed bug #55259 (openssl extension does not get the DH parameters from
- DH key resource). (Jakub Zelenka)
- . Fixed bug #70395 (Missing ARG_INFO for openssl_seal()). (cmb)
- . Fixed bug #60632 (openssl_seal fails with AES). (Jakub Zelenka)
- . Implemented FR #70438 (Add IV parameter for openssl_seal and openssl_open)
- (Jakub Zelenka)
-
-- Phpdbg:
- . Fixed bug #70449 (PHP won't compile on 10.4 and 10.5 because of missing
- constants). (Bob)
-
-- Session:
- . Fixed bug #70013 (Reference to $_SESSION is lost after a call to
- session_regenerate_id()). (Yasuo)
-
-- Standard:
- . Implemented the RFC `Random Functions Throwing Exceptions in PHP 7`.
- (Sammy Kaye Powers, Anthony)
- . Fixed bug #70487 (pack('x') produces an error). (Nikita)
-
-- Streams:
- . Fixed bug #70361 (HTTP stream wrapper doesn't close keep-alive connections).
- (Niklas Keller)
-
-- XMLReader:
- . Fixed bug #70309 (XmlReader read generates extra output). (Anatol)
-
-- Zip:
- . Fixed bug #70322 (ZipArchive::close() doesn't indicate errors). (cmb)
-
-03 Sep 2015, PHP 7.0.0 RC 2
-
-- Core:
- . Fixed bug #70398 (SIGSEGV, Segmentation fault zend_ast_destroy_ex).
- (Dmitry, Bob, Laruence)
- . Fixed bug #70332 (Wrong behavior while returning reference on object).
- (Laruence, Dmitry)
- . Fixed bug #70300 (Syntactical inconsistency with new group use syntax).
- (marcio dot web2 at gmail dot com)
- . Fixed bug #70321 (Magic getter breaks reference to array property).
- (Laruence)
- . Fixed bug #70187 (Notice: unserialize(): Unexpected end of serialized
- data). (Dmitry)
- . Fixed bug #70145 (From field incorrectly parsed from headers). (Anatol)
- . Fixed bug #70370 (Bundled libtool.m4 doesn't handle FreeBSD 10 when
- building extensions). (Adam)
- . Fixed bug causing exception traces with anon classes to be truncated. (Bob)
- . Fixed bug #70397 (Segmentation fault when using Closure::call and yield).
- (Bob)
-
-- Curl:
- . Fixed bug #70330 (Segmentation Fault with multiple "curl_copy_handle").
- (Laruence)
-
-- EXIF:
- . Fixed bug #70385 (Buffer over-read in exif_read_data with TIFF IFD tag byte
- value of 32 bytes). (Stas)
-
-- GMP:
- . Fixed bug #70284 (Use after free vulnerability in unserialize() with GMP).
- (stas)
-
-- hash:
- . Fixed bug #70312 (HAVAL gives wrong hashes in specific cases). (letsgolee
- at naver dot com)
-
-- Mysqli:
- . Fixed bug #32490 (constructor of mysqli has wrong name). (cmb)
-
-- Pcntl:
- . Fixed bug #70386 (Can't compile on NetBSD because of missing WCONTINUED
- and WIFCONTINUED). (Matteo)
-
-- PCRE:
- . Fixed bug #70232 (Incorrect bump-along behavior with \K and empty string
- match). (cmb)
- . Fixed bug #70345 (Multiple vulnerabilities related to PCRE functions).
- (Anatol Belski)
-
-- PDO:
- . Fixed bug #70389 (PDO constructor changes unrelated variables). (Laruence)
-
-- PDO_OCI:
- . Fixed bug #70308 (PDO::ATTR_PREFETCH is ignored). (Chris Jones)
-
-- SOAP:
- . Fixed bug #70388 (SOAP serialize_function_call() type confusion / RCE).
- (Stas)
-
-- SPL:
- . Fixed bug #70303 (Incorrect constructor reflection for ArrayObject). (cmb)
-
-- Standard:
- . Fixed bug #70342 (changing configuration with ignore_user_abort(true) isn't
- working). (Laruence)
- . Fixed bug #70295 (Segmentation fault with setrawcookie). (Bob)
- . Fixed bug #67131 (setcookie() conditional for empty values not met). (cmb)
- . Fixed bug #70365 (Use-after-free vulnerability in unserialize() with
- SplObjectStorage). (taoguangchen at icloud dot com)
- . Fixed bug #70366 (Use-after-free vulnerability in unserialize() with
- SplDoublyLinkedList). (taoguangchen at icloud dot com)
-
-- Reflection:
- . Fixed bug causing bogus traces for ReflectionGenerator::getTrace(). (Bob)
-
-- XSLT:
- . Fixed bug #69782 (NULL pointer dereference). (Stas)
-
-- ZIP:
- . Fixed bug #70350 (ZipArchive::extractTo allows for directory traversal when
- creating directories). (neal at fb dot com)
-
-20 Aug 2015, PHP 7.0.0 RC 1
-
-- Core:
- . Fixed bug #70299 (Memleak while assigning object offsetGet result).
- (Laruence)
- . Fixed bug #70288 (Apache crash related to ZEND_SEND_REF). (Laruence)
- . Fixed bug #70262 (Accessing array crashes PHP 7.0beta3).
- (Laruence, Dmitry)
- . Fixed bug #70258 (Segfault if do_resize fails to allocated memory).
- (Laruence)
- . Fixed bug #70253 (segfault at _efree () in zend_alloc.c:1389). (Laruence)
- . Fixed bug #70240 (Segfault when doing unset($var());). (Laruence)
- . Fixed bug #70223 (Incrementing value returned by magic getter). (Laruence)
- . Fixed bug #70215 (Segfault when __invoke is static). (Bob)
- . Fixed bug #70207 (Finally is broken with opcache). (Laruence, Dmitry)
- . Fixed bug #70173 (ZVAL_COPY_VALUE_EX broken for 32bit Solaris Sparc).
- (Laruence, cmb)
- . Fixed bug #69487 (SAPI may truncate POST data). (cmb)
- . Fixed bug #70198 (Checking liveness does not work as expected).
- (Shafreeck Sea, Anatol Belski)
- . Fixed bug #70241/#70293 (Skipped assertions affect Generator returns). (Bob)
- . Fixed bug #70239 (Creating a huge array doesn't result in exhausted,
- but segfault). (Laruence, Anatol)
-
-- CLI server:
- . Fixed bug #66606 (Sets HTTP_CONTENT_TYPE but not CONTENT_TYPE).
- (wusuopu, cmb)
- . Fixed bug #70264 (CLI server directory traversal). (cmb)
-
-- Date:
- . Fixed bug #70245 (strtotime does not emit warning when 2nd parameter is
- object or string). (cmb)
- . Fixed bug #70266 (DateInterval::__construct.interval_spec is not supposed to
- be optional). (cmb)
- . Fixed bug #70277 (new DateTimeZone($foo) is ignoring text after null byte).
- (cmb)
-
-- MCrypt:
- . Fixed bug #69833 (mcrypt fd caching not working). (Anatol)
-
-- Opcache:
- . Fixed bug #70237 (Empty while and do-while segmentation fault with opcode
- on CLI enabled). (Dmitry, Laruence)
-
-- PCRE:
- . Fixed bug #70232 (Incorrect bump-along behavior with \K and empty string
- match). (cmb)
-
-- PDO:
- . Fixed bug #70272 (Segfault in pdo_mysql). (Laruence)
- . Fixed bug #70221 (persistent sqlite connection + custom function
- segfaults). (Laruence)
-
-- Phpdbg:
- . Fixed bug #70214 (FASYNC not defined, needs sys/file.h include). (Bob)
-
-- Standard:
- . Fixed bug #70250 (extract() turns array elements to references).
- (Laruence)
- . Fixed bug #70211 (php 7 ZEND_HASH_IF_FULL_DO_RESIZE use after free).
- (Laruence)
- . Fixed bug #70208 (Assert breaking access on objects). (Bob)
-
-06 Aug 2015, PHP 7.0.0 Beta 3
-
-- Core:
- . Fixed "finally" issues. (Nikita, Dmitry)
- . Fixed bug #70098 (Real memory usage doesn't decrease). (Dmitry)
- . Fixed bug #70159 (__CLASS__ is lost in closures). (Julien)
- . Fixed bug #70156 (Segfault in zend_find_alias_name). (Laruence)
- . Fixed bug #70124 (null ptr deref / seg fault in ZEND_HANDLE_EXCEPTION).
- (Laruence)
- . Fixed bug #70117 (Unexpected return type error). (Laruence)
- . Fixed bug #70106 (Inheritance by anonymous class). (Bob)
- . Fixed bug #69674 (SIGSEGV array.c:953). (cmb)
- . Fixed bug #70164 (__COMPILER_HALT_OFFSET__ under namespace is not defined).
- (Bob)
- . Fixed bug #70108 (sometimes empty $_SERVER['QUERY_STRING']). (Anatol)
- . Fixed bug #70179 ($this refcount issue). (Bob)
- . Fixed bug #69896 ('asm' operand has impossible constraints). (Anatol)
- . Fixed bug #70183 (null pointer deref (segfault) in zend_eval_const_expr).
- (Hugh Davenport)
- . Fixed bug #70182 (Segfault in ZEND_ASSIGN_DIV_SPEC_CV_UNUSED_HANDLER).
- (Hugh Davenport)
- . Fixed bug #69793 (Remotely triggerable stack exhaustion via recursive
- method calls). (Stas)
- . Fixed bug #69892 (Different arrays compare indentical due to integer key
- truncation). (Nikita)
- . Fixed bug #70121 (unserialize() could lead to unexpected methods execution
- / NULL pointer deref). (Stas)
-
-- Curl:
- . Fixed bug #70163 (curl_setopt_array() type confusion). (Laruence)
-
-- IMAP:
- . Fixed bug #70158 (Building with static imap fails). (cmb)
- . Fixed bug #69998 (curl multi leaking memory). (Pierrick)
-
-- Opcache:
- . Fixed bug #70111 (Segfault when a function uses both an explicit return
- type and an explicit cast). (Laruence)
-
-- OpenSSL:
- . Fixed bug #70014 (openssl_random_pseudo_bytes() is not cryptographically
- secure). (Stas)
-
-- Phar:
- . Improved fix for bug #69441. (Anatol Belski)
- . Fixed bug #70019 (Files extracted from archive may be placed outside of
- destination directory). (Anatol Belski)
-
-- Phpdbg:
- . Fixed bug #70138 (Segfault when displaying memory leaks). (Bob)
-
-- SOAP:
- . Fixed bug #70081 (SoapClient info leak / null pointer dereference via
- multiple type confusions). (Stas)
-
-- SPL:
- . Fixed bug #70068 (Dangling pointer in the unserialization of ArrayObject
- items). (sean.heelan)
- . Fixed bug #70166 (Use After Free Vulnerability in unserialize() with
- SPLArrayObject). (taoguangchen at icloud dot com)
- . Fixed bug #70168 (Use After Free Vulnerability in unserialize() with
- SplObjectStorage). (taoguangchen at icloud dot com)
- . Fixed bug #70169 (Use After Free Vulnerability in unserialize() with
- SplDoublyLinkedList). (taoguangchen at icloud dot com)
-
-- Standard:
- . Fixed bug #70140 (str_ireplace/php_string_tolower - Arbitrary Code
- Execution). (CVE-2015-6527) (Laruence)
- . Implemented FR #70112 (Allow "dirname" to go up various times). (Remi)
- . Fixed bug #36365 (scandir duplicates file name at every 65535th file). (cmb)
-
-23 Jul 2015, PHP 7.0.0 Beta 2
-
-- Core:
- . Fixed bug #70089 (segfault at ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER ()).
- (Laruence)
- . Fixed bug #70057 (Build failure on 32-bit Mac OS X 10.6.8: recursive
- inlining). (Laruence)
- . Fixed bug #70012 (Exception lost with nested finally block). (Laruence)
- . Fixed bug #69996 (Changing the property of a cloned object affects the
- original). (Dmitry, Laruence)
- . Fixed bug #70083 (Use after free with assign by ref to overloaded objects).
- (Bob)
-
-- Curl:
- . Fixed bug #70065 (curl_getinfo() returns corrupted values). (Anatol)
-
-- GD:
- . Fixed bug #53156 (imagerectangle problem with point ordering). (cmb)
- . Fixed bug #66387 (Stack overflow with imagefilltoborder). (cmb)
- . Fixed bug #70102 (imagecreatefromwebm() shifts colors). (cmb)
- . Fixed bug #66590 (imagewebp() doesn't pad to even length). (cmb)
- . Fixed bug #66882 (imagerotate by -90 degrees truncates image by 1px). (cmb)
- . Fixed bug #70064 (imagescale(..., IMG_BICUBIC) leaks memory). (cmb)
- . Fixed bug #69024 (imagescale segfault with palette based image). (cmb)
- . Fixed bug #53154 (Zero-height rectangle has whiskers). (cmb)
- . Fixed bug #67447 (imagecrop() add a black line when cropping). (cmb)
- . Fixed bug #68714 (copy 'n paste error). (cmb)
- . Fixed bug #66339 (PHP segfaults in imagexbm). (cmb)
- . Fixed bug #70047 (gd_info() doesn't report WebP support). (cmb)
- . Replace libvpx with libwebp for bundled libgd. (cmb, Anatol)
-
-- Opcache:
- . Fixed bug #70058 (Build fails when building for i386). (Laruence)
- . Fixed bug #70022 (Crash with opcache using opcache.file_cache_only=1).
- (Anatol)
-
-- Soap:
- . Fixed bug #70079 (Segmentation fault after more than 100 SoapClient
- calls). (Laruence)
- . Fixed bug #70032 (make_http_soap_request calls
- zend_hash_get_current_key_ex(,,,NULL). (Laruence)
-
-- SPL:
- . Fixed bug #70053 (MutlitpleIterator array-keys incompatible change in
- PHP 7). (Tjerk)
-
-- Standard:
- . Fixed bug #70096 (Repeated iptcembed() adds superfluous FF bytes). (cmb)
- . Fixed bug #70018 (exec does not strip all whitespace). (Laruence)
-
-- Tokenizer:
- . Fixed bug #69430 (token_get_all has new irrecoverable errors). (Nikita)
-
-09 Jul 2015, PHP 7.0.0 Beta 1
-
-- Core:
- . Fixed bug #70006 (cli - function with default arg = STDOUT crash output).
- (Laruence)
- . Fixed bug #69521 (Segfault in gc_collect_cycles()).
- (arjen at react dot com, Laruence)
- . Improved zend_string API (Francois Laupretre)
- . Fixed bug #69955 (Segfault when trying to combine [] and assign-op on
- ArrayAccess object). (Laruence)
- . Fixed bug #69957 (Different ways of handling div/mod/intdiv). (Bob)
- . Fixed bug #69900 (Too long timeout on pipes). (Anatol)
-
-- CLI server:
- . Fixed bug #69655 (php -S changes MKCALENDAR request method to MKCOL). (cmb)
- . Fixed bug #64878 (304 responses return Content-Type header). (cmb)
-
-- COM:
- . Fixed bug #69939 (Casting object to bool returns false). (Kalle)
-
-- JSON:
- . Fixed bug #62010 (json_decode produces invalid byte-sequences).
- (Jakub Zelenka)
-
-- OCI8:
- . Corrected oci8 hash destructors to prevent segfaults, and a few other fixes.
- (Cameron Porter)
-
-- ODBC:
- . Fixed bug #69975 (PHP segfaults when accessing nvarchar(max) defined
- columns). (cmb)
-
-- OpenSSL:
- . Fixed bug #69882 (OpenSSL error "key values mismatch" after
- openssl_pkcs12_read with extra cert). (Tomasz Sawicki)
-
-- PCRE:
- . Fixed bug #53823 (preg_replace: * qualifier on unicode replace garbles the
- string). (cmb)
-
-- Session:
- . Fixed bug #69952 (Data integrity issues accessing superglobals by
- reference). (Bob)
-
-- SPL:
- . Fixed bug #69970 (Use-after-free vulnerability in
- spl_recursive_it_move_forward_ex()). (Laruence)
-
-- Sqlite3:
- . Fixed bug #69972 (Use-after-free vulnerability in
- sqlite3SafetyCheckSickOrOk()). (Laruence)
-
-- Standard:
- . Fixed bug #69983 (get_browser fails with user agent of null).
- (Kalle, cmb, Laruence)
- . Fixed bug #69976 (Unable to parse "all" urls with colon char). (cmb)
- . Fixed bug #69768 (escapeshell*() doesn't cater to !). (cmb)
-
-25 Jun 2015, PHP 7.0.0 Alpha 2
-
-- Core:
- . Fixed bug #69872 (uninitialised value in strtr with array). (Laruence)
- . Fixed bug #69868 (Invalid read of size 1 in zend_compile_short_circuiting).
- (Laruence)
- . Fixed bug #69849 (Broken output of apache_request_headers). (Kalle)
- . Fixed bug #69840 (iconv_substr() doesn't work with UTF-16BE). (Kalle)
- . Fixed bug #69823 (PHP 7.0.0alpha1 segmentation fault when exactly 33
- extensions are loaded). (Laruence)
- . Fixed bug #69805 (null ptr deref and seg fault in zend_resolve_class_name).
- (Laruence)
- . Fixed bug #69802 (Reflection on Closure::__invoke borks type hint class
- name). (Dmitry)
- . Fixed bug #69761 (Serialization of anonymous classes should be prevented).
- (Laruence)
- . Fixed bug #69551 (parse_ini_file() and parse_ini_string() segmentation
- fault). (Christoph M. Becker)
- . Fixed bug #69781 (phpinfo() reports Professional Editions of Windows
- 7/8/8.1/10 as "Business"). (Christian Wenz)
- . Fixed bug #69835 (phpinfo() does not report many Windows SKUs).
- (Christian Wenz)
- . Fixed bug #69889 (Null coalesce operator doesn't work for string offsets).
- (Nikita)
- . Fixed bug #69891 (Unexpected array comparison result). (Nikita)
- . Fixed bug #69892 (Different arrays compare indentical due to integer key
- truncation). (Nikita)
- . Fixed bug #69893 (Strict comparison between integer and empty string keys
- crashes). (Nikita)
-
-- Curl:
- . Fixed bug #69831 (Segmentation fault in curl_getinfo). (im dot denisenko at
- yahoo dot com)
-
-- DOM:
- . Fixed bug #69846 (Segmenation fault (access violation) when iterating over
- DOMNodeList). (Anatol Belski)
-
-- GD:
- . Fixed bug #61221 (imagegammacorrect function loses alpha channel). (cmb)
-
-- JSON:
- . Fixed bug #68546 (json_decode() Fatal error: Cannot access property
- started with '\0'). (Jakub Zelenka)
-
-- mysqlnd:
- . Fixed Bug #69796 (mysqli_stmt::fetch doesn't assign null values to
- bound variables). (Laruence)
-
-- Opcache:
- . Removed opcache.load_comments configuration directive. Now doc comments
- loading costs nothing and always enabled. (Dmitry)
- . Fixed bug #69838 (Wrong size calculation for function table). (Anatol)
-
-- PCRE:
- . Fixed bug #69864 (Segfault in preg_replace_callback). (cmb, ab)
-
-- PDO_pgsql:
- . Fixed bug #69752 (PDOStatement::execute() leaks memory with DML
- Statements when closeCuror() is u). (Philip Hofstetter)
-
-- SPL:
- . Fixed bug #69845 (ArrayObject with ARRAY_AS_PROPS broken). (Dmitry)
-
-- SQLite3:
- . Fixed bug #69897 (segfault when manually constructing SQLite3Result).
- (Kalle)
-
-- Standard:
- . Fixed bug #62922 (Truncating entire string should result in string).
- (Nikita)
-
-11 Jun 2015, PHP 7.0.0 Alpha 1
-
-- Core:
- . Fixed bug #69767 (Default parameter value with wrong type segfaults).
- (cmb, Laruence)
- . Fixed bug #69756 (Fatal error: Nesting level too deep - recursive dependency
- ? with ===). (Dmitry, Laruence)
- . Fixed bug #69758 (Item added to array not being removed by array_pop/shift
- ). (Laruence)
- . Fixed bug #68475 (Add support for $callable() sytnax with 'Class::method').
- (Julien, Aaron Piotrowski)
- . Fixed bug #69485 (Double free on zend_list_dtor). (Laruence)
- . Fixed bug #69427 (Segfault on magic method __call of private method in
- superclass). (Laruence)
- . Improved __call() and __callStatic() magic method handling. Now they are
- called in a stackless way using ZEND_CALL_TRAMPOLINE opcode, without
- additional stack frame. (Laruence, Dmitry)
- . Optimized strings concatenation. (Dmitry, Laruence)
- . Fixed weird operators behavior. Division by zero now emits warning and
- returns +/-INF, modulo by zero and intdid() throws an exception, shifts
- by negative offset throw exceptions. Compile-time evaluation of division
- by zero is disabled. (Dmitry, Andrea, Nikita)
- . Fixed bug #69371 (Hash table collision leads to inaccessible array keys).
- (Laruence)
- . Fixed bug #68933 (Invalid read of size 8 in zend_std_read_property).
- (Laruence, arjen at react dot com)
- . Fixed bug #68252 (segfault in Zend/zend_hash.c in function
- _zend_hash_del_el). (Laruence)
- . Fixed bug #65598 (Closure executed via static autoload incorrectly marked as
- static). (Nikita)
- . Fixed bug #66811 (Cannot access static::class in lambda, writen outside of a
- class). (Nikita)
- . Fixed bug #69568 (call a private function in closure failed). (Nikita)
- . Added PHP_INT_MIN constant. (Andrea)
- . Added Closure::call() method. (Andrea)
- . Fixed bug #67959 (Segfault when calling phpversion('spl')). (Florian)
- . Implemented the RFC `Catchable "Call to a member function bar() on a
- non-object"`. (Timm)
- . Added options parameter for unserialize allowing to specify acceptable
- classes (https://wiki.php.net/rfc/secure_unserialize). (Stas)
- . Fixed bug #63734 (Garbage collector can free zvals that are still
- referenced). (Dmitry)
- . Removed ZEND_ACC_FINAL_CLASS, promoting ZEND_ACC_FINAL as final class
- modifier. (Guilherme Blanco)
- . is_long() & is_integer() is now an alias of is_int(). (Kalle)
- . Implemented FR #55467 (phpinfo: PHP Variables with $ and single quotes). (Kalle)
- . Added ?? operator. (Andrea)
- . Added <=> operator. (Andrea)
- . Added \u{xxxxx} Unicode Codepoint Escape Syntax. (Andrea)
- . Fixed oversight where define() did not support arrays yet const syntax did.
- (Andrea, Dmitry)
- . Use "integer" and "float" instead of "long" and "double" in ZPP, type hint
- and conversion error messages. (Andrea)
- . Implemented FR #55428 (E_RECOVERABLE_ERROR when output buffering in output
- buffering handler). (Kalle)
- . Removed scoped calls of non-static methods from an incompatible $this
- context. (Nikita)
- . Removed support for #-style comments in ini files. (Nikita)
- . Removed support for assigning the result of new by reference. (Nikita)
- . Invalid octal literals in source code now produce compile errors, fixes
- PHPSadness #31. (Andrea)
- . Removed dl() function on fpm-fcgi. (Nikita)
- . Removed support for hexadecimal numeric strings. (Nikita)
- . Removed obsolete extensions and SAPIs. See the full list in UPGRADING. (Anatol)
- . Added NULL byte protection to exec, system and passthru. (Yasuo)
- . Added error_clear_last() function. (Reeze Xia)
- . Fixed bug #68797 (Number 2.2250738585072012e-308 converted incorrectly).
- (Anatol)
- . Improved zend_qsort(using hybrid sorting algo) for better performance,
- and also renamed zend_qsort to zend_sort. (Laruence)
- . Added stable sorting algo zend_insert_sort. (Laruence)
- . Improved zend_memnchr(using sunday algo) for better performance. (Laruence)
- . Implemented the RFC `Scalar Type Decalarations v0.5`. (Anthony)
- . Implemented the RFC `Group Use Declarations`. (Marcio)
- . Implemented the RFC `Continue Output Buffering`. (Mike)
- . Implemented the RFC `Constructor behaviour of internal classes`. (Dan, Dmitry)
- . Implemented the RFC `Fix "foreach" behavior`. (Dmitry)
- . Implemented the RFC `Generator Delegation`. (Bob)
- . Implemented the RFC `Anonymous Class Support`. (Joe, Nikita, Dmitry)
- . Implemented the RFC `Context Sensitive Lexer`. (Marcio Almada)
- . Fixed bug #69511 (Off-by-one buffer overflow in php_sys_readlink).
- (Jan Starke, Anatol)
-
-- CLI server:
- . Refactor MIME type handling to use a hash table instead of linear search.
- (Adam)
- . Update the MIME type list from the one shipped by Apache HTTPD. (Adam)
- . Added support for SEARCH WebDav method. (Mats Lindh)
-
-- Curl:
- . Fixed bug #68937 (Segfault in curl_multi_exec). (Laruence)
- . Removed support for unsafe file uploads. (Nikita)
-
-- Date:
- . Fixed day_of_week function as it could sometimes return negative values
- internally. (Derick)
- . Removed $is_dst parameter from mktime() and gmmktime(). (Nikita)
- . Removed date.timezone warning
- (https://wiki.php.net/rfc/date.timezone_warning_removal). (Bob)
- . Added "v" DateTime format modifier to get the 3-digit version of fraction
- of seconds. (Mariano Iglesias)
- . Implemented FR #69089: Added DateTime::RFC3339_EXTENDED to output in
- RFC3339 Extended format which includes fraction of seconds. (Mariano
- Iglesias)
-
-- DBA:
- . Fixed bug #62490 (dba_delete returns true on missing item (inifile)). (Mike)
- . Fixed bug #68711 (useless comparisons). (bugreports at internot dot info)
-
-- DOM:
- . Made DOMNode::textContent writeable. (Tjerk)
-
-- GD:
- . Made fontFetch's path parser thread-safe. (Sara)
- . Removed T1Lib support. (Kalle)
-
-- Fileinfo:
- . Fixed bug #66242 (libmagic: don't assume char is signed). (ArdB)
-
-- Filter:
- . New FILTER_VALIDATE_DOMAIN and better RFC conformance for FILTER_VALIDATE_URL. (Kevin Dunglas)
-
-- FPM:
- . Fixed bug #68945 (Unknown admin values segfault pools). (Laruence)
- . Fixed bug #65933 (Cannot specify config lines longer than 1024 bytes). (Chris Wright)
- . Implement request #67106 (Split main fpm config). (Elan Ruusamäe, Remi)
-
-- FTP:
- . Fixed bug #69082 (FTPS support on Windows). (Anatol)
-
-- Intl:
- . Removed deprecated aliases datefmt_set_timezone_id() and
- IntlDateFormatter::setTimeZoneID(). (Nikita)
-
-- JSON:
- . Replace non-free JSON parser with a parser from Jsond extension, fixes #63520
- (JSON extension includes a problematic license statement). (Jakub Zelenka)
- . Fixed bug #68938 (json_decode() decodes empty string without error).
- (jeremy at bat-country dot us)
-
-- LDAP:
- . Fixed bug #47222 (Implement LDAP_OPT_DIAGNOSTIC_MESSAGE). (Andreas Heigl)
-
-- LiteSpeed:
- . Updated LiteSpeed SAPI code from V5.5 to V6.6. (George Wang)
-
-- libxml:
- . Fixed handling of big lines in error messages with libxml >= 2.9.0.
- (Christoph M. Becker)
-
-- Mcrypt:
- . Fixed possible read after end of buffer and use after free. (Dmitry)
- . Removed mcrypt_generic_end() alias. (Nikita)
- . Removed mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb(), mcrypt_ofb(). (Nikita)
-
-- Opcache:
- . Fixed bug #69688 (segfault with eval and opcache fast shutdown).
- (Laruence)
- . Added experimental (disabled by default) file based opcode cache.
- (Dmitry, Laruence, Anatol)
- . Fixed bug with try blocks being removed when extended_info opcode
- generation is turned on. (Laruence)
- . Fixed bug #68644 (strlen incorrect : mbstring + func_overload=2 +UTF-8
- + Opcache). (Laruence)
-
-- OpenSSL:
- . Added "alpn_protocols" SSL context option allowing encrypted client/server
- streams to negotiate alternative protocols using the ALPN TLS extension when
- built against OpenSSL 1.0.2 or newer. Negotiated protocol information is
- accessible through stream_get_meta_data() output.
- . Removed "CN_match" and "SNI_server_name" SSL context options. Use automatic
- detection or the "peer_name" option instead. (Nikita)
-
-- pcntl:
- . Fixed bug #60509 (pcntl_signal doesn't decrease ref-count of old handler
- when setting SIG_DFL). (Julien)
- . Request #68505 (Added wifcontinued and wcontinued). (xilon-jul)
- . Added rusage support to pcntl_wait() and pcntl_waitpid(). (Anton Stepanenko,
- Tony)
-
-- PCRE:
- . Removed support for the /e (PREG_REPLACE_EVAL) modifier. (Nikita)
-
-- PDO:
- . Fixed bug #59450 (./configure fails with "Cannot find php_pdo_driver.h").
- (maxime dot besson at smile dot fr)
-
-- PDO_mysql:
- . Fixed bug #68424 (Add new PDO mysql connection attr to control multi
- statements option). (peter dot wolanin at acquia dot com)
-
-- PDO_pgsql:
- . Removed PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT attribute in favor of
- ATTR_EMULATE_PREPARES). (Nikita)
-
-- Reflection:
- . Fixed inheritance chain of Reflector interface. (Tjerk)
- . Added ReflectionGenerator class. (Bob)
- . Added reflection support for return types and type declarations. (Sara,
- Matteo)
-
-- Session:
- . Fixed bug #67694 (Regression in session_regenerate_id()). (Tjerk)
- . Fixed bug #68941 (mod_files.sh is a bash-script). (bugzilla at ii.nl, Yasuo)
-
-- SOAP:
- . Fixed bug #68361 (Segmentation fault on SoapClient::__getTypes). (Laruence)
-
-- SPL:
- . Changed ArrayIterator implementation using zend_hash_iterator_... API.
- Allowed modification of iterated ArrayObject using the same behavior
- as proposed in `Fix "foreach" behavior`. Removed "Array was modified
- outside object and internal position is no longer valid" hack. (Dmitry)
- . Implemented #67886 (SplPriorityQueue/SplHeap doesn't expose extractFlags
- nor curruption state). (Julien)
- . Fixed bug #66405 (RecursiveDirectoryIterator::CURRENT_AS_PATHNAME
- breaks the RecursiveIterator). (Paul Garvin)
-
-- SQLite3:
- . Fixed bug #68260 (SQLite3Result::fetchArray declares wrong
- required_num_args). (Julien)
-
-- Standard:
- . Fixed bug #69723 (Passing parameters by reference and array_column).
- (Laruence)
- . Fixed bug #69523 (Cookie name cannot be empty). (Christoph M. Becker)
- . Fixed bug #69325 (php_copy_file_ex does not pass the argument).
- (imbolk at gmail dot com)
- . Fixed bug #69299 (Regression in array_filter's $flag argument in PHP 7).
- (Laruence)
- . Removed call_user_method() and call_user_method_array() functions. (Kalle)
- . Fixed user session handlers (See rfc:session.user.return-value). (Sara)
- . Added intdiv() function. (Andrea)
- . Improved precision of log() function for base 2 and 10. (Marc Bennewitz)
- . Remove string category support in setlocale(). (Nikita)
- . Remove set_magic_quotes_runtime() and its alias magic_quotes_runtime().
- (Nikita)
- . Fixed bug #65272 (flock() out parameter not set correctly in windows).
- (Daniel Lowrey)
- . Added preg_replace_callback_array function. (Wei Dai)
- . Deprecated salt option to password_hash. (Anthony)
- . Fixed bug #69686 (password_verify reports back error on PHP7 will null
- string). (Anthony)
- . Added Windows support for getrusage(). (Kalle)
- . Removed hardcoded limit on number of pipes in proc_open(). (Tony)
-
-- Streams:
- . Fixed bug #68532 (convert.base64-encode omits padding bytes).
- (blaesius at krumedia dot de)
- . Removed set_socket_blocking() in favor of its alias stream_set_blocking().
- (Nikita)
-
-- XSL:
- . Fixed bug #64776 (The XSLT extension is not thread safe). (Mike)
- . Removed xsl.security_prefs ini option. (Nikita)
-
-- Zlib:
- . Added deflate_init(), deflate_add(), inflate_init(), inflate_add()
- functions allowing incremental/streaming compression/decompression.
- (Daniel Lowrey & Bob Weinand)
-
-- Zip:
- . Added ZipArchive::setCompressionName and ZipArchive::setCompressionIndex
- methods. (Remi, Cedric Delmas)
- . Update bundled libzip to 1.0.1. (Remi, Anatol)
- . Fixed bug #67161 (ZipArchive::getStream() returns NULL for certain file).
- (Christoph M. Becker)
+Hash
+ . Added SHA3 fixed mode algorithms (224, 256, 384, and 512 bit). (Sara)
<<< NOTE: Insert NEWS from last stable release here prior to actual release! >>>
diff --git a/UPGRADING b/UPGRADING
index 9faf7c7ce6..8929404d98 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -1,4 +1,4 @@
-PHP 7.0 UPGRADE NOTES
+PHP 7.1 UPGRADE NOTES
1. Backward Incompatible Changes
2. New Features
@@ -18,795 +18,66 @@
========================================
1. Backward Incompatible Changes
========================================
-
-Language changes
-================
-
-Changes to variable handling
-----------------------------
-
-* Indirect variable, property and method references are now interpreted with
- left-to-right semantics. Some examples:
-
- $$foo['bar']['baz'] // interpreted as ($$foo)['bar']['baz']
- $foo->$bar['baz'] // interpreted as ($foo->$bar)['baz']
- $foo->$bar['baz']() // interpreted as ($foo->$bar)['baz']()
- Foo::$bar['baz']() // interpreted as (Foo::$bar)['baz']()
-
- To restore the previous behavior add explicit curly braces:
-
- ${$foo['bar']['baz']}
- $foo->{$bar['baz']}
- $foo->{$bar['baz']}()
- Foo::{$bar['baz']}()
-
-* The global keyword now only accepts simple variables. Instead of
-
- global $$foo->bar;
-
- it is now required to write the following:
-
- global ${$foo->bar};
-
-* Parentheses around variables or function calls no longer have any influence
- on behavior. For example the following code, where the result of a function
- call is passed to a by-reference function
-
- function getArray() { return [1, 2, 3]; }
-
- $last = array_pop(getArray());
- // Strict Standards: Only variables should be passed by reference
- $last = array_pop((getArray()));
- // Strict Standards: Only variables should be passed by reference
-
- will now throw a strict standards error regardless of whether parentheses
- are used. Previously no notice was generated in the second case.
-
-* Array elements or object properties that are automatically created during
- by-reference assignments will now result in a different order. For example
-
- $array = [];
- $array["a"] =& $array["b"];
- $array["b"] = 1;
- var_dump($array);
-
- now results in the array ["a" => 1, "b" => 1], while previously the result
- was ["b" => 1, "a" => 1];
-
-Relevant RFCs:
-* https://wiki.php.net/rfc/uniform_variable_syntax
-* https://wiki.php.net/rfc/abstract_syntax_tree
-
-Changes to list()
------------------
-
-* list() will no longer assign variables in reverse order. For example
-
- list($array[], $array[], $array[]) = [1, 2, 3];
- var_dump($array);
-
- will now result in $array == [1, 2, 3] rather than [3, 2, 1]. Note that only
- the **order** of the assignments changed, but the assigned values stay the
- same. E.g. a normal usage like
-
- list($a, $b, $c) = [1, 2, 3];
- // $a = 1; $b = 2; $c = 3;
-
- will retain its current behavior.
-
-* Empty list() assignments are no longer allowed. As such all of the following
- are invalid:
-
- list() = $a;
- list(,,) = $a;
- list($x, list(), $y) = $a;
-
-* list() no longer supports unpacking strings (while previously this was only
- supported in some cases). The code
-
- $string = "xy";
- list($x, $y) = $string;
-
- will now result in $x == null and $y == null (without notices) instead of
- $x == "x" and $y == "y". Furthermore list() is now always guaranteed to
- work with objects implementing ArrayAccess, e.g.
-
- list($a, $b) = (object) new ArrayObject([0, 1]);
-
- will now result in $a == 0 and $b == 1. Previously both $a and $b were null.
-
-Relevant RFCs:
-* https://wiki.php.net/rfc/abstract_syntax_tree#changes_to_list
-* https://wiki.php.net/rfc/fix_list_behavior_inconsistency
-
-Changes to foreach
-------------------
-
-* Iteration with foreach() no longer has any effect on the internal array
- pointer, which can be accessed through the current()/next()/etc family of
- functions. For example
-
- $array = [0, 1, 2];
- foreach ($array as &$val) {
- var_dump(current($array));
- }
-
- will now print the value int(0) three times. Previously the output was int(1),
- int(2) and bool(false).
-
-* When iterating arrays by-value, foreach will now always operate on a copy of
- the array, as such changes to the array during iteration will not influence
- iteration behavior. For example
-
- $array = [0, 1, 2];
- $ref =& $array; // Necessary to trigger the old behavior
- foreach ($array as $val) {
- var_dump($val);
- unset($array[1]);
- }
-
- will now print all three elements (0 1 2), while previously the second element
- 1 was skipped (0 2).
-
-* When iterating arrays by-reference, modifications to the array will continue
- to influence the iteration. However PHP will now do a better job of
- maintaining a correct position in a number of cases. E.g. appending to an
- array during by-reference iteration
-
- $array = [0];
- foreach ($array as &$val) {
- var_dump($val);
- $array[1] = 1;
- }
-
- will now iterate over the appended element as well. As such the output of this
- example will now be "int(0) int(1)", while previously it was only "int(0)".
-
-* Iteration of plain (non-Traversable) objects by-value or by-reference will
- behave like by-reference iteration of arrays. This matches the previous
- behavior apart from the more accurate position management mentioned in the
- previous point.
-
-* Iteration of Traversable objects remains unchanged.
-
-Relevant RFC: https://wiki.php.net/rfc/php7_foreach
-
-Changes to parameter handling
------------------------------
-
-* It is no longer possible to define two function parameters with the same name.
- For example, the following method will trigger a compile-time error:
-
- public function foo($a, $b, $unused, $unused) {
- // ...
- }
-
- Code like this should be changed to use distinct parameter names, for example:
-
- public function foo($a, $b, $unused1, $unused2) {
- // ...
- }
-
-* The func_get_arg() and func_get_args() functions will no longer return the
- original value that was passed to a parameter and will instead provide the
- current value (which might have been modified). For example
-
- function foo($x) {
- $x++;
- var_dump(func_get_arg(0));
- }
- foo(1);
-
- will now print "2" instead of "1". This code should be changed to either
- perform modifications only after calling func_get_arg(s)
-
- function foo($x) {
- var_dump(func_get_arg(0));
- $x++;
- }
-
- or avoid modifying the parameters altogether:
-
- function foo($x) {
- $newX = $x + 1;
- var_dump(func_get_arg(0));
- }
-
-* Similarly exception backtraces will no longer display the original value that
- was passed to a function and show the modified value instead. For example
-
- function foo($x) {
- $x = 42;
- throw new Exception;
- }
- foo("string");
-
- will now result in the stack trace
-
- Stack trace:
- #0 file.php(4): foo(42)
- #1 {main}
-
- while previously it was:
-
- Stack trace:
- #0 file.php(4): foo('string')
- #1 {main}
-
- While this should not impact runtime behavior of your code, it is worthwhile
- to be aware of this difference for debugging purposes.
-
- The same limitation also applies to debug_backtrace() and other functions
- inspecting function arguments.
-
-Relevant RFC: https://wiki.php.net/phpng
-
-Changes to integer handling
----------------------------
-
-* Invalid octal literals (containing digits larger than 7) now produce compile
- errors. For example, the following is no longer valid:
-
- $i = 0781; // 8 is not a valid octal digit!
-
- Previously the invalid digits (and any following valid digits) were simply
- ignored. As such $i previously held the value 7, because the last two digits
- were silently discarded.
-
-* Bitwise shifts by negative numbers will now throw an ArithmeticError:
-
- var_dump(1 >> -1);
- // ArithmeticError: Bit shift by negative number
-
-* Left bitwise shifts by a number of bits beyond the bit width of an integer
- will always result in 0:
-
- var_dump(1 << 64); // int(0)
-
- Previously the behavior of this code was dependent on the used CPU
- architecture. For example on x86 (including x86-64) the result was int(1),
- because the shift operand was wrapped.
-
-* Similarly right bitwise shifts by a number of bits beyond the bit width of an
- integer will always result in 0 or -1 (depending on sign):
-
- var_dump(1 >> 64); // int(0)
- var_dump(-1 >> 64); // int(-1)
-
-Relevant RFC: https://wiki.php.net/rfc/integer_semantics
-
-Changes to string handling
---------------------------
-
-* Strings that contain hexadecimal numbers are no longer considered to be
- numeric and don't receive special treatment anymore. Some examples of the
- new behavior:
-
- var_dump("0x123" == "291"); // bool(false) (previously true)
- var_dump(is_numeric("0x123")); // bool(false) (previously true)
- var_dump("0xe" + "0x1"); // int(0) (previously 16)
-
- var_dump(substr("foo", "0x1")); // string(3) "foo" (previously "oo")
- // Notice: A non well formed numeric value encountered
-
- filter_var() can be used to check if a string contains a hexadecimal number
- or convert such a string into an integer:
-
- $str = "0xffff";
- $int = filter_var($str, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX);
- if (false === $int) {
- throw new Exception("Invalid integer!");
- }
- var_dump($int); // int(65535)
-
-* Due to the addition of the Unicode Codepoint Escape Syntax for double-quoted
- strings and heredocs, "\u{" followed by an invalid sequence will now result in
- an error:
-
- $str = "\u{xyz}"; // Fatal error: Invalid UTF-8 codepoint escape sequence
-
- To avoid this the leading backslash should be escaped:
-
- $str = "\\u{xyz}"; // Works fine
-
- However, "\u" without a following { is unaffected. As such the following code
- won't error and will work the same as before:
-
- $str = "\u202e"; // Works fine
-
-Relevant RFCs:
-* https://wiki.php.net/rfc/remove_hex_support_in_numeric_strings
-* https://wiki.php.net/rfc/unicode_escape
-
-Changes to error handling
--------------------------
-
-* There are now two exception classes: Exception and Error. Both classes
- implement a new interface Throwable. Type hints in exception handling code
- may need to be changed to account for this.
-
-* Some fatal errors and recoverable fatal errors now throw an Error instead.
- As Error is a separate class from Exception, these exceptions will not be
- caught by existing try/catch blocks.
-
- For the recoverable fatal errors which have been converted into an exception,
- it is no longer possible to silently ignore the error from an error handler.
- In particular, it is no longer possible to ignore type hint failures.
-
-* Parser errors now generate a ParseError that extends Error. Error
- handling for eval()s on potentially invalid code should be changed to catch
- ParseError in addition to the previous return value / error_get_last()
- based handling.
-
-* Constructors of internal classes will now always throw an exception on
- failure. Previously some constructors returned NULL or an unusable object.
-
-* The error level of some E_STRICT notices has been changed.
-
-Relevant RFCs:
-* https://wiki.php.net/rfc/engine_exceptions_for_php7
-* https://wiki.php.net/rfc/throwable-interface
-* https://wiki.php.net/rfc/internal_constructor_behaviour
-* https://wiki.php.net/rfc/reclassify_e_strict
-
-Other language changes
-----------------------
-
-* Removed support for static calls to non-static methods from an incompatible
- $this context. In this case $this will not be defined, but the call will be
- allowed with a deprecation notice. An example:
-
- class A {
- public function test() { var_dump($this); }
- }
-
- // Note: Does NOT extend A
- class B {
- public function callNonStaticMethodOfA() { A::test(); }
- }
-
- (new B)->callNonStaticMethodOfA();
-
- // Deprecated: Non-static method A::test() should not be called statically
- // Notice: Undefined variable $this
- NULL
-
- Note that this only applies to calls from an incompatible context. If class B
- extended from A the call would be allowed without any notices.
-
-* It is no longer possible to use the following class, interface and trait names
- (case-insensitive):
-
- bool
- int
- float
- string
- null
- false
- true
-
- This applies to class/interface/trait declarations, class_alias() and use
- statements.
-
- Furthermore the following class, interface and trait names are now reserved
- for future use, but do not yet throw an error when used:
-
- resource
- object
- mixed
- numeric
-
-* The yield language construct no longer requires parentheses when used in an
- expression context. It is now a right-associative operator with precedence
- between the "print" and "=>" operators. This can result in different behavior
- in some cases, for example:
-
- echo yield -1;
- // Was previously interpreted as
- echo (yield) - 1;
- // And is now interpreted as
- echo yield (-1);
-
- yield $foo or die;
- // Was previously interpreted as
- yield ($foo or die);
- // And is now interpreted as
- (yield $foo) or die;
-
- Such cases can always be resolved by adding additional parentheses.
-
- . Removed ASP (<%) and script (<script language=php>) tags.
- (RFC: https://wiki.php.net/rfc/remove_alternative_php_tags)
- . Removed support for assigning the result of new by reference.
- . Removed support for scoped calls to non-static methods from an incompatible
- $this context. See details in https://wiki.php.net/rfc/incompat_ctx.
- . Removed support for #-style comments in ini files. Use ;-style comments
- instead.
- . $HTTP_RAW_POST_DATA is no longer available. Use the php://input stream instead.
-
-Standard library changes
-========================
-
- . substr() now returns an empty string instead of FALSE when the truncation happens on boundaries.
- . call_user_method() and call_user_method_array() no longer exists.
- . ob_start() no longer issues an E_ERROR, but instead an E_RECOVERABLE_ERROR in case an
- output buffer is created in an output buffer handler.
- . The internal sorting algorithm has been improved, what may result in
- different sort order of elements that compare as equal.
- . Removed dl() function on fpm-fcgi.
- . setcookie() with an empty cookie name now issues a WARNING and doesn't send an empty set-cookie header line anymore.
-
-Other
-=====
-
-- Curl:
- . Removed support for disabling the CURLOPT_SAFE_UPLOAD option. All curl file
- uploads must use the curl_file / CURLFile APIs.
-
-- Date:
- . Removed $is_dst parameter from mktime() and gmmktime().
-
-- DBA
- . dba_delete() now returns false if the key was not found for the inifile
- handler, too.
-
-- GMP
- . Requires libgmp version 4.2 or newer now.
- . gmp_setbit() and gmp_clrbit() now return FALSE for negative indices, making
- them consistent with other GMP functions.
-
-- Intl:
- . Removed deprecated aliases datefmt_set_timezone_id() and
- IntlDateFormatter::setTimeZoneID(). Use datefmt_set_timezone() and
- IntlDateFormatter::setTimeZone() instead.
-
-- libxml:
- . Added LIBXML_BIGLINES parser option. It's available starting with libxml 2.9.0
- and adds suppport for line numbers >16-bit in the error reporting.
-
-- Mcrypt
- . Removed deprecated mcrypt_generic_end() alias in favor of
- mcrypt_generic_deinit().
- . Removed deprecated mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() and mcrypt_ofb()
- functions in favor of mcrypt_encrypt() and mcrypt_decrypt() with an
- MCRYPT_MODE_* flag.
-
-- Session
- . session_start() accepts all INI settings as array. e.g. ['cache_limiter'=>'private']
- sets session.cache_limiter=private. It also supports 'read_and_close' which closes
- session data immediately after read data.
- . Save handler accepts validate_sid(), update_timestamp() which validates session
- ID existence, updates timestamp of session data. Compatibility of old user defined
- save handler is retained.
- . SessionUpdateTimestampHandlerInterface is added. validateSid(), updateTimestamp()
- is defined in the interface.
- . session.lazy_write(default=On) INI setting enables only write session data when
- session data is updated.
-
-- Opcache
- . Removed opcache.load_comments configuration directive. Now doc comments
- loading costs nothing and always enabled.
-
-- OpenSSL:
- . Removed the "rsa_key_size" SSL context option in favor of automatically
- setting the appropriate size given the negotiated crypto algorithm.
- . Removed "CN_match" and "SNI_server_name" SSL context options. Use automatic
- detection or the "peer_name" option instead.
-
-- PCRE:
- . Removed support for /e (PREG_REPLACE_EVAL) modifier. Use
- preg_replace_callback() instead.
-
-- PDO_pgsql:
- . Removed PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT attribute in favor of
- ATTR_EMULATE_PREPARES.
-
-- Standard:
- . Removed string category support in setlocale(). Use the LC_* constants
- instead.
- . Removed set_magic_quotes_runtime() and its alias magic_quotes_runtime().
-
-- JSON:
- . Rejected RFC 7159 incompatible number formats in json_decode string -
- top level (07, 0xff, .1, -.1) and all levels ([1.], [1.e1])
- . Calling json_decode with 1st argument equal to empty PHP string or value that
- after casting to string is empty string (NULL, FALSE) results in JSON syntax error.
-
-- Stream:
- . Removed set_socket_blocking() in favor of its alias stream_set_blocking().
-
-- XSL:
- . Removed xsl.security_prefs ini option. Use XsltProcessor::setSecurityPrefs()
- instead.
+- Core:
+ . 'void' can no longer be used as the name of a class, interface, or trait.
+ This applies to declarations, class_alias() and use statements.
========================================
2. New Features
========================================
-
- Core
- . Added group use declarations.
- (RFC: https://wiki.php.net/rfc/group_use_declarations)
- . Added null coalesce operator (??).
- (RFC: https://wiki.php.net/rfc/isset_ternary)
- . Support for strings with length >= 2^31 bytes in 64 bit builds.
- . Closure::call() method added (works only with userland classes).
- . Added \u{xxxxxx} Unicode Codepoint Escape Syntax for double-quoted strings
- and heredocs.
- . define() now supports arrays as constant values, fixing an oversight where
- define() did not support arrays yet const syntax did.
- . Added the comparison operator (<=>), aka the spaceship operator.
- (RFC: https://wiki.php.net/rfc/combined-comparison-operator)
- . Added the yield from operator for delegating Generators like coroutines.
- (RFC: https://wiki.php.net/rfc/generator-delegation)
- . Reserved keywords can now be used in various new contexts.
- (RFC: https://wiki.php.net/rfc/context_sensitive_lexer)
- . Added support for scalar type declarations and strict mode using
- declare(strict_types=1) (RFC: https://wiki.php.net/rfc/scalar_type_hints_v5)
- . Added support for cryptographically secure user land RNG
- (RFC: https://wiki.php.net/rfc/easy_userland_csprng)
-
-- Opcache
- . Added second level file based opcode cache. It may be enabled by setting
- opcache.file_cache=<DIR> configuration directive in php.ini. The second
- level cache may improve performance when SHM is full, at server restart or
- SHM reset. In addition, it's possibe to use file cache without SHM at all,
- using opcache.file_cache_only=1 (this may be useful for sharing hosting),
- and disable file cache consistency check, to speedup loading at the cost of
- safety, using opcache.file_cache_consistency_checks=0.
- . Added ability to move PHP code pages (PHP TEXT segment) into HUGE pages.
- It's possible to enable/disable this feature in php.ini through
- opcache.huge_code_pages=0/1. OS should be configured to provide huge pages.
- . Added Windows only opcache.file_cache_fallback=1 ini option, which implies
- the implemented fallback mechanism. When OPcache was not able to reattach
- the shared memory segment to the desired address and opcache.file_cache
- is on, opcache.file_cache_only=1 will be automatically enforced.
-
-- OpenSSL
- . Added "alpn_protocols" SSL context option allowing encrypted client/server
- streams to negotiate alternative protocols using the ALPN TLS extension when
- built against OpenSSL 1.0.2 or newer. Negotiated protocol information is
- accessible through stream_get_meta_data() output.
-
-- Reflection
- . Added a ReflectionGenerator class (yield from Traces, current file/line,
- etc.)
- . Added a ReflectionType class to better support the new return type and
- scalar type declarations features. The new ReflectionParameter::getType()
- and ReflectionFunctionAbstract::getReturnType() methods both return an
- instance of ReflectionType.
-
-- Stream:
- . New Windows only stream context options was added to allow blocking reads
- on pipes. To enable it, pass array("pipe" => array("blocking" => true))
- when creating the stream context. Be aware, that this option can under
- circumstances cause dead locks on the pipe buffer. However it can be useful
- in several CLI use case scenarios.
+ . Added void return type, which requires that a function not return a value.
+ (RFC: https://wiki.php.net/rfc/void_return_type)
========================================
3. Changes in SAPI modules
========================================
-- FPM
- . Fixed bug #65933 (Cannot specify config lines longer than 1024 bytes).
- . Listen = port now listen on all addresses (IPv6 and IPv4-mapped).
-
========================================
4. Deprecated Functionality
========================================
-- Core
- . PHP 4 style constructors, where the constructor name is the same as the
- class name, are now deprecated.
- . Static calls to non-static methods are now deprecated.
-
-- OpenSSL
- . The "capture_session_meta" SSL context option is now deprecated. Meta
- data concerning active crypto on a stream resource is now accessible
- through the return result from stream_get_meta_data().
-
========================================
5. Changed Functions
========================================
-
-- parse_ini_file():
-- parse_ini_string():
- . Added scanner mode INI_SCANNER_TYPED to yield typed .ini values.
-- unserialize():
- . Added second parameter for unserialize function
- (RFC: https://wiki.php.net/rfc/secure_unserialize) allowing to specify
- acceptable classes:
- unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]]);
-
-- proc_open():
- . The maximum number of pipes used by proc_open() was previously limited by
- hardcoded value of 16. This limit is now removed and the number of pipes is
- effectively limited by the amount of memory available to PHP.
- . New Windows only configuration option "blocking_pipes" can be used to
- force blocking reads on child process pipes. This covers several
- edge cases in CLI usage however can lead to dead locks. Also, this
- correlates with the new stream context options for pipes.
-
-- array_column():
- The function now supports an array of objects as well as two-dimensional
- arrays. Only public properties are considered, and objects that make use of
- __get() for dynamic properties must also implement __isset().
-
-- stream_context_create()
- It accepts now a Windows only configuration
- array("pipe" => array("blocking" => <boolean>)) which forces blocking reads
- on pipes. This option should be used carefully because due to the
- platform restrictions dead locks on pipe buffers are possible.
-
-- dirname()
- A new optional argument ($levels) allow to go up various times
- dirname(dirname($foo)) => dirname($foo, 2);
-
-- debug_zval_dump
- It prints now "int" instead of "long", and "float" instead of "double".
+- get_headers() has an extra parameter which allows passing a custom stream
+ context.
+- The first $varname argument for getenv() is no longer mandatory, the
+ current environment variables will be returned as an associative array
+ when omitted.
========================================
6. New Functions
========================================
-- GMP
- . Added gmp_random_seed().
-
-- PCRE:
- . Added preg_replace_callback_array function
- (RFC: https://wiki.php.net/rfc/preg_replace_callback_array)
-
-- Standard
- . Added intdiv() function for integer division.
- . Added error_clear_last() function to reset error state.
-
-- Zip:
- . Added ZipArchive::setCompressionIndex() and ZipArchive::setCompressionName()
- for setting the compression method.
-
-- Zlib:
- . Added deflate_init(), deflate_add(), inflate_init(), inflate_add()
- functions allowing incremental/streaming compression/decompression.
-
========================================
7. New Classes and Interfaces
========================================
-- ReflectionGenerator
-- ReflectionType
-
========================================
8. Removed Extensions and SAPIs
========================================
-- sapi/aolserver
-- sapi/apache
-- sapi/apache_hooks
-- sapi/apache2filter
-- sapi/caudium
-- sapi/continuity
-- sapi/isapi
-- sapi/milter
-- sapi/nsapi
-- sapi/phttpd
-- sapi/pi3web
-- sapi/roxen
-- sapi/thttpd
-- sapi/tux
-- sapi/webjames
-- ext/mssql
-- ext/mysql
-- ext/sybase_ct
-- ext/ereg
-
-For more details see
-
-https://wiki.php.net/rfc/removal_of_dead_sapis_and_exts
-https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7
-
-NOTE: NSAPI was not voted in the RFC, however it was removed afterwards. It turned
-out, that the corresponding SDK isn't available anymore.
-
========================================
9. Other Changes to Extensions
========================================
-- Mhash
- Mhash is not an extension anymore, use function_exists("mhash") to check whether
- it is avaliable.
-
-- GD
- The bundled libgd requires libwebp instead of libvpx for the WebP functionality.
-
-- Openssl
- minimum supported OpenSSL version series was raised to 0.9.8
-
========================================
10. New Global Constants
========================================
-- Core
- . PHP_INT_MIN added.
-
-- PCRE
- . This error constant is added to signal errors due to stack size limitations
- when PCRE JIT support is enabled:
- . PREG_JIT_STACKLIMIT_ERROR
-
-- Zlib
- . These constants are added to control flush behavior with the new
- incremental deflate_add() and inflate_add() functions:
- . ZLIB_NO_FLUSH
- . ZLIB_PARTIAL_FLUSH
- . ZLIB_SYNC_FLUSH
- . ZLIB_FULL_FLUSH
- . ZLIB_BLOCK
- . ZLIB_FINISH
-
-- GD
- . T1Lib support removed, thus lifting the optional dependency on T1Lib, the
- following is therefore not available anymore:
-
- Functions:
- - imagepsbbox()
- - imagepsencodefont()
- - imagepsextendedfont()
- - imagepsfreefont()
- - imagepsloadfont()
- - imagepsslantfont()
- - imagepstext()
-
- Resources:
- - 'gd PS font'
- - 'gd PS encoding'
-
========================================
11. Changes to INI File Handling
========================================
-- Core
- . Removed asp_tags ini directive. Trying to enable it will result in a fatal
- error.
- . Removed always_populate_raw_post_data ini directive.
-
========================================
12. Windows Support
========================================
-- Core
- . Support for native 64 bit integers in 64 bit builds.
- . Support for large files in 64 bit builds.
- . Support for getrusage()
-
-- ftp
- . The ftp extension is always shipped shared
- . For SSL support, the dependency on the openssl extension was abolished. Instead
- it depends alone on the openssl library. If it's present at the compile time,
- ftp_ssl_connect() is enabled automatically.
-
-- imap
- . Static building of ext/imap is disabled
-
-- odbc
- . The odbc extension is always shipped shared
+- Core:
+ . Support for ftok()
========================================
13. Other Changes
========================================
-- Core
- . Instead of being undefined and platform-dependent, NaN and Infinity will
- always be zero when cast to integer.
- . Calling a method on a non-object now raises a catchable error instead of a
- fatal error; see: https://wiki.php.net/rfc/catchable-call-to-member-of-non-object
- . Error messages for zend_parse_parameters, type hints and conversions now
- always say "integer" and "float" instead of "long" and "double".
- . Output buffering now continues to work for an aborted connection if
- ignore_user_abort is set to true.
- . Zend Extensions API was extended with zend_extension.op_array_persist_calc()
- and zend_extensions.op_array_persist() handlers. They allow to store (or
- reset) associated with op_array addition information in Opcache Shared
- Memory.
- . zend_internal_function.reserved[] array was introduced to allow association
- of aditional information with internal functions. In PHP-5 it was possible
- to use zend_function.op_array.reserved[] even for internal functions, but
- now we don't allocate extra space.
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index b263805337..6e30f7cad8 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -1,25 +1,7 @@
-PHP 7.0 INTERNALS UPGRADE NOTES
+PHP 7.1 INTERNALS UPGRADE NOTES
0. Wiki Examples
1. Internal API changes
- e. New data types
- f. zend_parse_parameters() specs
- g. sprintf() formats
- h. HashTable API
- i. New portable macros for large file support
- j. New portable macros for integers
- k. get_class_entry object handler info
- l. get_class_name object handler info
- m. Other portable macros info
- n. ZEND_ENGINE_2 removal
- o. Updated final class modifier
- p. TSRM changes
- q. gc_collect_cycles() is now hookable
- r. PDO uses size_t for lengths
- s. Resource API changes
- t. Optimized strings concatenation.
- u. Streams changes
- v. Sort algorithm changes
2. Build system changes
a. Unix build system changes
@@ -39,219 +21,6 @@ changes. See: https://wiki.php.net/phpng-upgrading
1. Internal API changes
========================
- e. New data types
-
- String
-
- Besides the old way of accepting the strings with 's', the new 'S' ZPP spec
- was introduced. It expects an argument of the type zend_string *. String lengths
- in it are bound to the size_t datatype.
-
- Integer types
-
- Integers do no more depend on the firm 'long' type. Instead a platform
- dependent integer type is used, it is called zend_long. That datatype is
- defined dynamically to guarantee the consistent 64 bit support. The zval
- field representing user land integer it bound to zend_long.
-
- Signed integer is defined as zend_long, unsigned integer as zend_ulong
- inside Zend.
-
- Other datatypes
-
- zend_off_t - portable off_t analogue
- zend_stat_t - portable 'struct stat' analogue
-
- These datatypes are declared to be portable across platforms. Thus, direct
- usage of the functions like fseek, stat, etc. as well as direct usage of
- off_t and struct stat is strongly not recommended. Instead the portable
- macros should be used.
-
- zend_fseek - portable fseek equivalent
- zend_ftell - portable ftell equivalent
- zend_lseek - portable lseek equivalent
- zend_fstat - portable fstat equivalent
- zend_stat - portable stat equivalent
-
- f. zend_parse_parameters() specs
-
- The new spec 'S' introduced, which expects an argument of type zend_string *.
- The 'l' spec expects a parameter of the type zend_long, not long anymore.
- The 's' spec expects parameters of the type char * and size_t, no int anymore.
-
- g. sprintf() formats
-
- New printf modifier 'p' was implemented to platform independently output zend_long,
- zend_ulong and php_size_t datatypes. That modifier can be used with 'd', 'u', 'x' and 'o'
- printf format specs with spprintf, snprintf and the wrapping printf implementations.
- %pu is sufficient for both zend_ulong and php_size_t. the code using %p spec to output
- pointer address might need to be enclosed into #ifdef when it unlickily followed by 'd',
- 'u', 'x' or 'o'.
-
- The only exceptions are the snprintf and zend_sprintf functions yet, because in some cases
- they can use the implemenations available on the system, not the PHP one. With snprintf the
- macros ZEND_LONG_FMT and ZEND_ULONG_FMT should be used.
-
- h. HashTable API
-
- Datatype for array indexes was changed to zend_ulong, for string keys to zend_string *.
-
- i. New portable macros for large file support
-
- Function(s) Alias Comment
- stat, _stat64 zend_stat for use with zend_stat_t
- fstat, _fstat64 zend_fstat for use with zend_stat_t
- lseek, _lseeki64 zend_lseek for use with zend_off_t
- ftell, _ftelli64 zend_ftell for use with zend_off_t
- fseek, _fseeki64 zend_fseek for use with zend_off_t
-
- j. New portable macros for integers
-
- Function(s) Alias Comment
- snprintf with "%ld" or "%lld", _ltoa_s, _i64toa_s ZEND_LTOA for use with zend_long
- atol, atoll, _atoi64 ZEND_ATOL for use with zend_long
- strtol, strtoll, _strtoi64 ZEND_STRTOL for use with zend_long
- strtoul, strtoull, _strtoui64 ZEND_STRTOUL for use with zend_long
- abs, llabs, _abs64 ZEND_ABS for use with zend_long
- - ZEND_LONG_MAX replaces LONG_MAX where appropriate
- - ZEND_LONG_MIN replaces LONG_MIN where appropriate
- - ZEND_ULONG_MAX replaces ULONG_MAX where appropriate
- - SIZEOF_ZEND_LONG reworked SIZEOF_ZEND_LONG representing the size of zend_long datatype
- - ZEND_SIZE_MAX Max value of size_t
- - Z_L casts an integral constant to zend_long
- - Z_UL casts an integral constant to zend_ulong
-
- The macro ZEND_ENABLE_ZVAL_LONG64 reveals whether zval operates on 64 or 32 bit integer.
-
- k. The get_class_entry object handler is no longer available. Instead
- zend_object.ce is always used.
-
- l. The get_class_name object handler is now only used for displaying class
- names in debugging functions like var_dump(). It is no longer used in
- get_class(), get_parent_class() or similar.
-
- The handler is now obligatory, no longer accepts a `parent` argument and
- must return a non-NULL zend_string*, which will be released by the caller.
-
- m. Other portable macros info
-
- ZEND_SECURE_ZERO - zeroes chunk of memory
- ZEND_VALID_SOCKET - validates a php_socket_t variable
-
- ZEND_FASTCALL is defined to use __vectorcall convention on VS2013 and above
- ZEND_NORETURN is defined as __declspec(noreturn) on VS
-
- n. The ZEND_ENGINE_2 macro has been removed. A ZEND_ENGINE_3 macro has been added.
-
- o. Removed ZEND_ACC_FINAL_CLASS in favour of ZEND_ACC_FINAL, turning final class
- modifier now a different class entry flag. Update your extensions.
-
- p. TSRM changes
-
- The TSRM layer undergone significant changes. It is not necessary anymore to
- pass the tsrm_ls pointer explicitly. The TSRMLS_* macros should not be used
- in any new developments.
-
- The recommended way accessing globals in TS builds is by implementing it
- to use a local thread unique pointer to the corresponding data pool. These
- are the new macros that serve to achieve this goal:
-
- - ZEND_TSRMG - based on TSRMG and if static pointer for data pool access is
- implemented, will use it
- - ZEND_TSRMLS_CACHE_EXTERN - to be used in a header shared across multiple
- C/C++ files
- - ZEND_TSRMLS_CACHE_DEFINE - to be used in the main extension C/C++ file
- - ZEND_TSRMLS_CACHE_UPDATE - to be integrated at the top of the globals
- ctor or RINIT function
- - ZEND_ENABLE_STATIC_TSRMLS_CACHE - to be used in the config.[m4|w32] for
- enabling the globals access per thread unique pointer
- - TSRMLS_CACHE - expands to the variable name which links to the thread
- unique data pool
-
- Note that usually it will work without implementing the globals access per
- a thread unique pointer, however it might cause a slowdown. The reason is
- that the access model to the extension/SAPI own globals as well as the
- access to the core globals is determined in the compilation phase depending
- on whether ZEND_ENABLE_STATIC_TSRMLS_CACHE macro is defined.
-
- Due to the current compiler evolution state, the TSRMLS_CACHE pointer
- (when implemented) has to be present and updated in every binary unit which
- is not compiled statically into PHP. So any DLL, DSO, EXE, etc. has to take
- care about defining and updating it's TSRMLS cache. An update should happen
- before any globals was accessed.
-
- Porting an extension or SAPI is usually as easy as removing all the TSRMLS_*
- occurrences and integrating the macros mentioned above. However if tsrm_ls
- is used explicitly, its usage can be considered obsolete in most cases.
- Additionally, if an extension triggers its own threads, TSRMLS_CACHE shouldn't
- be passed to that threads directly.
-
- When working with CTOR/DTOR for the extension globals, only the data passed
- as parameters should be touched. For example, don't use code like
- free(MYEXT_G(vars)); inside globals destructor, as it possibly can destroy
- the data from a wrong thread. Instead use the pointer to the data delivered
- into the destructor. So the previous example could look like
- free(my_struct->vars); given the income was casted to (struct my_struct *).
-
- A new macro was introduced to simplify the declaration to the extension
- globals. A simplified declaration looks as follows
-
- #define MYEXT_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(myext, v)
-
- Another new macro ZEND_MODULE_GLOBALS_BULK(myext) delivers the corresponding
- globals struct as a whole.
-
- Two new storage specifiers was introduced.
-
- ZEND_EXT_TLS - expand to an appropriate thread specific storage specifier in
- the thread safe build, expands to empty in a non thread safe
- build.
- ZEND_TLS - expands to an appropriate thread specific storage specifier
- with static visibility in the thread safe build, expands to
- static specifier in a non thread safe build.
-
- Variables declared with these storage specifiers can not be shared across
- threads. While ZEND_TLS enforces the local scope visibility, ZEND_EXT_TLS
- pertains to the visiblity across several compilation units. In both cases,
- there's no portable way to achieve the visibility across shared objects.
- Thus, these specifiers are not compatible with ZEND_API and PHPAPI specifiers.
-
- q. gc_collect_cycles() is now a function pointer, and can be replaced in the
- same manner as zend_execute_ex() if needed (for example, to include the
- time spent in the garbage collector in a profiler). The default
- implementation has been renamed to zend_gc_collect_cycles(), and is
- exported with ZEND_API.
-
- r. In accordance with general use of size_t as string length, all PDO API
- functions now use size_t for string length.
-
- s. Removed ZEND_REGISTER/FETCH_RESOURCE, use zend_fetch_resource and
- and zend_register_resource instead, zend_fetch_resource accepts a zend_resource *
- as first argument, if you still need to fetch a resource from zval, use
- zend_fetch_resource_ex. More details can be found in Zend/zend_list.c.
-
- t. Optimized strings concatenation.
- ZEND_ADD_STRING/VAR/CHAR are replaced with ZEND_ROPE_INIT, ZEND_ROPE_ADD,
- ZEND_ROPE_END.
- Instead of reallocation and copying string on each ZEND_ADD_STRING/VAR/CAHR,
- collect all the strings and then allocate and construct the resulting string once.
-
- u. Streams changes
- - It is possible to do blocking reads on Windows pipes. It can be done either
- using context stream option PHP_STREAM_OPTION_PIPE_BLOCKING or
- adding STREAM_USE_BLOCKING_PIPE when opening the stream.
-
- v. Sort algorithm changes
- - Improved zend_qsort(using hybrid sorting algo) for better performance,
- and also renamed zend_qsort to zend_sort.
- - Added stable sorting algo zend_insert_sort.
-
- w. Tick functions internal API change
- Tick functions have different declaration now. They expect a single
- parameter while before they were parameterless. When registering the
- tick function a value for this parameter must be passed. This value will be
- provided to the tick function on every execution.
-
========================
2. Build system changes
========================
@@ -260,65 +29,7 @@ changes. See: https://wiki.php.net/phpng-upgrading
b. Windows build system changes
- - Besides Visual Studio, building with Clang or Intel Composer is now
- possible. To enable an alternative toolset, add the option
- --with-toolset=[vs,clang,icc] to the configure line. The default
- toolset is vs. Still clang or icc need the correct environment
- which involves many tools from the vs toolset.
-
- The toolset option is supported by phpize as well.
-
- AWARENESS The only recommended and supported toolset to produce production
- ready binaries is Visual Studio. Still other compilers can be used now for
- testing and analyzing purposes.
-
- - configure.js now produces response files which are passed to the linker
- and library manager. This solves the issues with the long command lines
- which can exceed the OS limit.
-
- - with clang toolset, an option --with-uncritical-warn-choke is available,
- which suppresses the most frequent false positive warnings
-
- - the --with-mp option will by default utilize all the available cores. It's
- enabled by default for release builds and can be disabled with the special
- "disable" keyword.
-
========================
3. Module changes
========================
- Session:
-
- - PS_MOD_UPDATE_TIMESTAMP() session save handler definition is added. New
- save handler should use PS_MOD_UPDATE_TIMESTAMP() definition. Save handler
- must not refer/change PS() variables directly from save handler. Use
- parameters.
- - PS_MOD()/PS_MOD_SID() macro exist only for transition. Beware these
- save handlers are less secure and slower than PS_MOD_UPDATE_TIMESTAMP().
- - PS(invalid_session_id) was removed. It was never worked as it supposed.
- To report invalid session ID, use PS_VALIDATE_SID() handler.
- - PS_VALIDATE_SID() defines session ID validation handler. This handler
- must validate if requested session ID exists in session data storage or not.
- Do not access PS(id) directly, but use this handler and it's parameter.
- - PS_UPDATE_TIMESTAMP() defines timestamp updating handler. This handler
- must update session data timestamp for GC if it is needed. e.g. Memcache
- updates timestamp on read, so it does not need to update timestamp. Return
- SUCCESS simply for this case.
- - PS_CREATE_SID() should check session ID collision. Return NULL for failure.
- - More documentation can be found in ext/session/mod_files.c as comments.
- mod_files.c may be used as reference implementation.
-
- Openssl:
- - several ext/openssl functions require the inclusion of the applink shim
- as documented in the OpenSSL FAQ https://www.openssl.org/support/faq.html#PROG2
- to properly work on Windows. While this primarily affects the OpenSSL
- functionality, the shim needs to be included into the executable file
- which loads the extension DLL, not into the extension DLL itself. Alternatively
- it can be compiled and linked with the main program as a separate object file.
- More information and explanation in the linked OpenSSL FAQ.
-
- Thus, this primarily affects any WAMP or other redistributions bundling the
- official PHP release zipballs or building from sources. The applink shim is
- already integrated with all the PHP executables from the official distribution
- starting with 7.0.0beta1.
-
diff --git a/Zend/tests/anon/013.phpt b/Zend/tests/anon/013.phpt
new file mode 100644
index 0000000000..72ba3d61b7
--- /dev/null
+++ b/Zend/tests/anon/013.phpt
@@ -0,0 +1,15 @@
+--TEST--
+closure binding to anonymous class
+--FILE--
+<?php
+$class = new class {};
+$foo = function() {
+ return $this;
+};
+
+$closure = Closure::bind($foo, $class, $class);
+var_dump($closure());
+?>
+--EXPECTF--
+object(class@anonymous)#1 (0) {
+}
diff --git a/Zend/tests/anon/014.phpt b/Zend/tests/anon/014.phpt
new file mode 100644
index 0000000000..cacac47857
--- /dev/null
+++ b/Zend/tests/anon/014.phpt
@@ -0,0 +1,16 @@
+--TEST--
+anonymous class trait binding
+--FILE--
+<?php
+trait TaskTrait {
+ function run() {
+ return 'Running...';
+ }
+}
+$class = new class() {
+ use TaskTrait;
+};
+var_dump($class->run());
+?>
+--EXPECTF--
+string(10) "Running..."
diff --git a/Zend/tests/bug70918.phpt b/Zend/tests/bug70918.phpt
new file mode 100644
index 0000000000..81e2192d8a
--- /dev/null
+++ b/Zend/tests/bug70918.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #70918 (Segfault using static outside of class scope)
+--FILE--
+<?php
+try {
+ static::x;
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ parent::x;
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ self::x;
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ new static;
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ static::x();
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+
+try {
+ static::$i;
+} catch (Error $e) {
+ var_dump($e->getMessage());
+}
+?>
+--EXPECT--
+string(52) "Cannot access static:: when no class scope is active"
+string(52) "Cannot access parent:: when no class scope is active"
+string(50) "Cannot access self:: when no class scope is active"
+string(52) "Cannot access static:: when no class scope is active"
+string(52) "Cannot access static:: when no class scope is active"
+string(52) "Cannot access static:: when no class scope is active"
diff --git a/Zend/tests/func_get_args.phpt b/Zend/tests/func_get_args.phpt
new file mode 100644
index 0000000000..eea8ae4354
--- /dev/null
+++ b/Zend/tests/func_get_args.phpt
@@ -0,0 +1,10 @@
+--TEST--
+Testing func_get_args()
+--FILE--
+<?php
+
+func_get_args();
+
+?>
+--EXPECTF--
+Warning: func_get_args(): Called from the global scope - no function context in %s on line 3
diff --git a/Zend/tests/jump16.phpt b/Zend/tests/jump16.phpt
new file mode 100644
index 0000000000..cc820c4a6c
--- /dev/null
+++ b/Zend/tests/jump16.phpt
@@ -0,0 +1,27 @@
+--TEST--
+jump 16: goto into try/catch
+--FILE--
+<?php
+goto a;
+try {
+ echo "1";
+a:
+ echo "2";
+ throw new Exception();
+} catch (Exception $e) {
+ echo "3";
+}
+echo "4";
+goto b;
+try {
+ echo "5";
+ throw new Exception();
+} catch (Exception $e) {
+ echo "6";
+b:
+ echo "7";
+}
+echo "8\n";
+?>
+--EXPECT--
+23478
diff --git a/Zend/tests/jump17.phpt b/Zend/tests/jump17.phpt
new file mode 100644
index 0000000000..92d3be511b
--- /dev/null
+++ b/Zend/tests/jump17.phpt
@@ -0,0 +1,22 @@
+--TEST--
+jump 17: goto into try/catch with finally
+--FILE--
+<?php
+goto b;
+try {
+ echo "1";
+a:
+ echo "2";
+ throw new Exception();
+} catch (Exception $e) {
+ echo "3";
+b:
+ echo "4";
+} finally {
+ echo "5";
+c:
+ echo "6";
+}
+echo "7\n";
+--EXPECT--
+4567
diff --git a/Zend/tests/return_types/void_allowed.phpt b/Zend/tests/return_types/void_allowed.phpt
new file mode 100644
index 0000000000..8f07c7392e
--- /dev/null
+++ b/Zend/tests/return_types/void_allowed.phpt
@@ -0,0 +1,20 @@
+--TEST--
+void return type: acceptable cases
+--FILE--
+<?php
+
+function foo(): void {
+ // okay
+}
+
+foo();
+
+function bar(): void {
+ return; // okay
+}
+
+bar();
+
+echo "OK!", PHP_EOL;
+--EXPECT--
+OK!
diff --git a/Zend/tests/return_types/void_disallowed1.phpt b/Zend/tests/return_types/void_disallowed1.phpt
new file mode 100644
index 0000000000..b20f129a58
--- /dev/null
+++ b/Zend/tests/return_types/void_disallowed1.phpt
@@ -0,0 +1,12 @@
+--TEST--
+void return type: unacceptable cases: explicit NULL return
+--FILE--
+<?php
+
+function foo(): void {
+ return NULL; // not permitted in a void function
+}
+
+// Note the lack of function call: function validated at compile-time
+--EXPECTF--
+Fatal error: A void function must not return a value in %s on line %d
diff --git a/Zend/tests/return_types/void_disallowed2.phpt b/Zend/tests/return_types/void_disallowed2.phpt
new file mode 100644
index 0000000000..7bbc3ac24f
--- /dev/null
+++ b/Zend/tests/return_types/void_disallowed2.phpt
@@ -0,0 +1,12 @@
+--TEST--
+void return type: unacceptable cases: explicit return of some other value
+--FILE--
+<?php
+
+function foo(): void {
+ return -1; // not permitted in a void function
+}
+
+// Note the lack of function call: function validated at compile-time
+--EXPECTF--
+Fatal error: A void function must not return a value in %s on line %d
diff --git a/Zend/tests/return_types/void_parameter.phpt b/Zend/tests/return_types/void_parameter.phpt
new file mode 100644
index 0000000000..4c6e918406
--- /dev/null
+++ b/Zend/tests/return_types/void_parameter.phpt
@@ -0,0 +1,8 @@
+--TEST--
+void return type: not valid as a parameter type
+--FILE--
+<?php
+
+function foobar(void $a) {}
+--EXPECTF--
+Fatal error: void cannot be used as a parameter type in %s on line %d
diff --git a/Zend/tests/temporary_cleaning_001.phpt b/Zend/tests/temporary_cleaning_001.phpt
index 40340bc3da..f2ccbb35b8 100644
--- a/Zend/tests/temporary_cleaning_001.phpt
+++ b/Zend/tests/temporary_cleaning_001.phpt
@@ -1,7 +1,5 @@
--TEST--
Temporary leak on exception
---XFAIL--
-See Bug #62210 and attempt to fix it in "tmp_livelibess" branch
--FILE--
<?php
diff --git a/Zend/tests/temporary_cleaning_003.phpt b/Zend/tests/temporary_cleaning_003.phpt
index 0f7d9450eb..acff8c85f0 100644
--- a/Zend/tests/temporary_cleaning_003.phpt
+++ b/Zend/tests/temporary_cleaning_003.phpt
@@ -1,7 +1,5 @@
--TEST--
Fundamental memory leak test on temporaries
---XFAIL--
-See Bug #62210 and attempt to fix it in "tmp_livelibess" branch
--FILE--
<?php
diff --git a/Zend/tests/temporary_cleaning_004.phpt b/Zend/tests/temporary_cleaning_004.phpt
index e2b093654f..b8a02516b0 100644
--- a/Zend/tests/temporary_cleaning_004.phpt
+++ b/Zend/tests/temporary_cleaning_004.phpt
@@ -1,7 +1,5 @@
--TEST--
Temporary leak with switch
---XFAIL--
-See Bug #62210 and attempt to fix it in "tmp_livelibess" branch
--FILE--
<?php
diff --git a/Zend/tests/temporary_cleaning_005.phpt b/Zend/tests/temporary_cleaning_005.phpt
index f671c32543..e8c7febe0b 100644
--- a/Zend/tests/temporary_cleaning_005.phpt
+++ b/Zend/tests/temporary_cleaning_005.phpt
@@ -1,7 +1,5 @@
--TEST--
Temporary leak with foreach
---XFAIL--
-See Bug #62210 and attempt to fix it in "tmp_livelibess" branch
--FILE--
<?php
diff --git a/Zend/tests/temporary_cleaning_006.phpt b/Zend/tests/temporary_cleaning_006.phpt
index 435e7b12dd..a7936d3915 100644
--- a/Zend/tests/temporary_cleaning_006.phpt
+++ b/Zend/tests/temporary_cleaning_006.phpt
@@ -1,7 +1,5 @@
--TEST--
Exception after separation during indirect write to fcall result
---XFAIL--
-See Bug #62210 and attempt to fix it in "tmp_livelibess" branch
--FILE--
<?php
diff --git a/Zend/tests/temporary_cleaning_008.phpt b/Zend/tests/temporary_cleaning_008.phpt
new file mode 100644
index 0000000000..fabd3b4b38
--- /dev/null
+++ b/Zend/tests/temporary_cleaning_008.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Optimization of constant switch expression
+--FILE--
+<?php
+try {
+ switch ("1" . (int)2) {
+ case 12:
+ throw new Exception();
+ }
+} catch (Exception $e) {
+ echo "exception\n";
+}
+?>
+--EXPECT--
+exception
diff --git a/Zend/tests/temporary_cleaning_009.phpt b/Zend/tests/temporary_cleaning_009.phpt
new file mode 100644
index 0000000000..32a84a6ffd
--- /dev/null
+++ b/Zend/tests/temporary_cleaning_009.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Live range & free on return
+--FILE--
+<?php
+class bar {
+ public $foo = 1;
+ public $bar = 1;
+
+ function __destruct() {
+ throw $this->foo;
+ }
+}
+foreach (new bar as &$foo) {
+ try {
+ $foo = new Exception;
+ return; // frees the loop variable
+ } catch (Exception $e) {
+ echo "exception\n";
+ }
+}
+echo "end\n";
+?>
+--EXPECTF--
+Fatal error: Uncaught Exception in %stemporary_cleaning_009.php:12
+Stack trace:
+#0 {main}
+ thrown in %stemporary_cleaning_009.php on line 12
diff --git a/Zend/tests/temporary_cleaning_010.phpt b/Zend/tests/temporary_cleaning_010.phpt
new file mode 100644
index 0000000000..96eab121b8
--- /dev/null
+++ b/Zend/tests/temporary_cleaning_010.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Live range & throw from finally
+--XFAIL--
+See Bug #62210 and attempt to fix it in "tmp_livelibess" branch
+--FILE--
+<?php
+function test() {
+ try {
+ $a = [1, 2, 3];
+ return $a + [];
+ } finally {
+ throw new Exception;
+ }
+}
+
+try {
+ test();
+} catch (Exception $e) {
+ echo "exception\n";
+}
+?>
+--EXPECT--
+exception
diff --git a/Zend/tests/temporary_cleaning_011.phpt b/Zend/tests/temporary_cleaning_011.phpt
new file mode 100644
index 0000000000..e4a6af3ab9
--- /dev/null
+++ b/Zend/tests/temporary_cleaning_011.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Live range & lists
+--FILE--
+<?php
+class A {
+ function __destruct() {
+ throw new Exception();
+ }
+}
+$b = new A();
+$x = 0;
+$c = [[$x,$x]];
+try {
+ list($a, $b) = $c[0];
+} catch (Exception $e) {
+ echo "exception\n";
+}
+?>
+--EXPECT--
+exception
diff --git a/Zend/tests/try/try_finally_021.phpt b/Zend/tests/try/try_finally_021.phpt
new file mode 100644
index 0000000000..ed162f40d0
--- /dev/null
+++ b/Zend/tests/try/try_finally_021.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Live range & return from finally
+--FILE--
+<?php
+$array = [1];
+foreach ([0] as $_) {
+ foreach ($array as $v) {
+ try {
+ echo "ok\n";
+ return;
+ } finally {
+ echo "ok\n";
+ return;
+ }
+ }
+}
+?>
+--EXPECT--
+ok
+ok
diff --git a/Zend/tests/try/try_finally_022.phpt b/Zend/tests/try/try_finally_022.phpt
new file mode 100644
index 0000000000..51f6a26419
--- /dev/null
+++ b/Zend/tests/try/try_finally_022.phpt
@@ -0,0 +1,41 @@
+--TEST--
+Try finally (exception in "return" statement)
+--FILE--
+<?php
+class A {
+ public $x = 1;
+ public $y = 2;
+ function __destruct() {
+ throw new Exception();
+ }
+}
+try{
+ $a = 0;
+ switch ($a) {
+ case 0:
+ }
+ switch ($a) {
+ case 0:
+ }
+ switch ($a) {
+ case 0:
+ }
+ foreach([new stdClass()] as $x) {
+ foreach(new A() as $a) {
+ foreach([new stdClass()] as $y) {
+ try {
+ if (0) { echo "0" . (int)5; }
+ return $a;
+ } catch (Exception $e) {
+ echo "exception1\n";
+ }
+ }
+ }
+ }
+} catch (Exception $e) {
+ echo "exception2\n";
+}
+?>
+--EXPECT--
+exception2
+
diff --git a/Zend/zend.h b/Zend/zend.h
index 2192f5b1b2..bcb1b002d9 100644
--- a/Zend/zend.h
+++ b/Zend/zend.h
@@ -22,7 +22,7 @@
#ifndef ZEND_H
#define ZEND_H
-#define ZEND_VERSION "3.0.0"
+#define ZEND_VERSION "3.1.0-dev"
#define ZEND_ENGINE_3
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 0e6d89fc8a..c3d796f61d 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -183,6 +183,8 @@ ZEND_API char *zend_get_type_by_const(int type) /* {{{ */
return "callable";
case IS_ARRAY:
return "array";
+ case IS_VOID:
+ return "void";
default:
return "unknown";
}
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index b91fddeeb0..9d6ab3f954 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -60,7 +60,7 @@ typedef struct _zend_loop_var {
uint32_t var_num;
union {
uint32_t try_catch_offset;
- uint32_t brk_cont_offset;
+ uint32_t live_range_offset;
} u;
} zend_loop_var;
@@ -86,6 +86,8 @@ ZEND_API zend_compiler_globals compiler_globals;
ZEND_API zend_executor_globals executor_globals;
#endif
+static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2);
+
static void zend_destroy_property_info_internal(zval *zv) /* {{{ */
{
zend_property_info *property_info = Z_PTR_P(zv);
@@ -151,6 +153,7 @@ static const struct reserved_class_name reserved_class_names[] = {
{ZEND_STRL("static")},
{ZEND_STRL("string")},
{ZEND_STRL("true")},
+ {ZEND_STRL("void")},
{NULL, 0}
};
@@ -194,6 +197,7 @@ static const builtin_type_info builtin_types[] = {
{ZEND_STRL("float"), IS_DOUBLE},
{ZEND_STRL("string"), IS_STRING},
{ZEND_STRL("bool"), _IS_BOOL},
+ {ZEND_STRL("void"), IS_VOID},
{NULL, 0, IS_UNDEF}
};
@@ -221,16 +225,22 @@ void zend_oparray_context_begin(zend_oparray_context *prev_context) /* {{{ */
CG(context).opcodes_size = INITIAL_OP_ARRAY_SIZE;
CG(context).vars_size = 0;
CG(context).literals_size = 0;
- CG(context).current_brk_cont = -1;
CG(context).backpatch_count = 0;
CG(context).in_finally = 0;
CG(context).fast_call_var = -1;
+ CG(context).current_brk_cont = -1;
+ CG(context).last_brk_cont = 0;
+ CG(context).brk_cont_array = NULL;
CG(context).labels = NULL;
}
/* }}} */
void zend_oparray_context_end(zend_oparray_context *prev_context) /* {{{ */
{
+ if (CG(context).brk_cont_array) {
+ efree(CG(context).brk_cont_array);
+ CG(context).brk_cont_array = NULL;
+ }
if (CG(context).labels) {
zend_hash_destroy(CG(context).labels);
FREE_HASHTABLE(CG(context).labels);
@@ -570,22 +580,49 @@ void zend_stop_lexing(void)
LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
}
+static uint32_t zend_start_live_range(zend_op_array *op_array, uint32_t start) /* {{{ */
+{
+ zend_live_range *range;
+
+ op_array->last_live_range++;
+ op_array->live_range = erealloc(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
+ range = op_array->live_range + op_array->last_live_range - 1;
+ range->start = start;
+ return op_array->last_live_range - 1;
+}
+/* }}} */
+
+static void zend_end_live_range(zend_op_array *op_array, uint32_t offset, uint32_t end, uint32_t kind, uint32_t var) /* {{{ */
+{
+ zend_live_range *range = op_array->live_range + offset;
+
+ if (range->start == end && offset == op_array->last_live_range - 1) {
+ op_array->last_live_range--;
+ } else {
+ range->end = end;
+ range->var = (var * sizeof(zval)) | kind;
+ }
+}
+/* }}} */
+
static inline void zend_begin_loop(zend_uchar free_opcode, const znode *loop_var) /* {{{ */
{
zend_brk_cont_element *brk_cont_element;
int parent = CG(context).current_brk_cont;
zend_loop_var info = {0};
- CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont;
- brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
+ CG(context).current_brk_cont = CG(context).last_brk_cont;
+ brk_cont_element = get_next_brk_cont_element();
brk_cont_element->parent = parent;
if (loop_var && (loop_var->op_type & (IS_VAR|IS_TMP_VAR))) {
+ uint32_t start = get_next_op_number(CG(active_op_array));
+
info.opcode = free_opcode;
info.var_type = loop_var->op_type;
info.var_num = loop_var->u.op.var;
- info.u.brk_cont_offset = CG(context).current_brk_cont;
- brk_cont_element->start = get_next_op_number(CG(active_op_array));
+ info.u.live_range_offset = zend_start_live_range(CG(active_op_array), start);
+ brk_cont_element->start = start;
} else {
info.opcode = ZEND_NOP;
/* The start field is used to free temporary variables in case of exceptions.
@@ -597,14 +634,22 @@ static inline void zend_begin_loop(zend_uchar free_opcode, const znode *loop_var
}
/* }}} */
-static inline void zend_end_loop(int cont_addr) /* {{{ */
+static inline void zend_end_loop(int cont_addr, const znode *var_node) /* {{{ */
{
+ uint32_t end = get_next_op_number(CG(active_op_array));
zend_brk_cont_element *brk_cont_element
- = &CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont];
+ = &CG(context).brk_cont_array[CG(context).current_brk_cont];
brk_cont_element->cont = cont_addr;
- brk_cont_element->brk = get_next_op_number(CG(active_op_array));
+ brk_cont_element->brk = end;
CG(context).current_brk_cont = brk_cont_element->parent;
+ if (brk_cont_element->start != -1) {
+ zend_loop_var *loop_var = zend_stack_top(&CG(loop_var_stack));
+ zend_end_live_range(CG(active_op_array), loop_var->u.live_range_offset, end,
+ loop_var->opcode == ZEND_FE_FREE ? ZEND_LIVE_LOOP : ZEND_LIVE_TMPVAR,
+ var_node->u.op.var);
+ }
+
zend_stack_del_top(&CG(loop_var_stack));
}
/* }}} */
@@ -612,11 +657,7 @@ static inline void zend_end_loop(int cont_addr) /* {{{ */
void zend_do_free(znode *op1) /* {{{ */
{
if (op1->op_type==IS_TMP_VAR) {
- zend_op *opline = get_next_op(CG(active_op_array));
-
- opline->opcode = ZEND_FREE;
- SET_NODE(opline->op1, op1);
- SET_UNUSED(opline->op2);
+ zend_emit_op(NULL, ZEND_FREE, op1, NULL);
} else if (op1->op_type==IS_VAR) {
zend_op *opline = &CG(active_op_array)->opcodes[CG(active_op_array)->last-1];
@@ -627,14 +668,12 @@ void zend_do_free(znode *op1) /* {{{ */
&& opline->result.var == op1->u.op.var) {
if (opline->opcode == ZEND_FETCH_R ||
opline->opcode == ZEND_FETCH_DIM_R ||
- opline->opcode == ZEND_FETCH_OBJ_R) {
+ opline->opcode == ZEND_FETCH_OBJ_R ||
+ opline->opcode == ZEND_FETCH_STATIC_PROP_R) {
/* It's very rare and useless case. It's better to use
additional FREE opcode and simplify the FETCH handlers
their selves */
- opline = get_next_op(CG(active_op_array));
- opline->opcode = ZEND_FREE;
- SET_NODE(opline->op1, op1);
- SET_UNUSED(opline->op2);
+ zend_emit_op(NULL, ZEND_FREE, op1, NULL);
} else {
opline->result_type |= EXT_TYPE_UNUSED;
}
@@ -643,11 +682,7 @@ void zend_do_free(znode *op1) /* {{{ */
if (opline->opcode == ZEND_FETCH_LIST &&
opline->op1_type == IS_VAR &&
opline->op1.var == op1->u.op.var) {
- opline = get_next_op(CG(active_op_array));
-
- opline->opcode = ZEND_FREE;
- SET_NODE(opline->op1, op1);
- SET_UNUSED(opline->op2);
+ zend_emit_op(NULL, ZEND_FREE, op1, NULL);
return;
}
if (opline->result_type==IS_VAR
@@ -1136,19 +1171,19 @@ static void zend_mark_function_as_generator() /* {{{ */
zend_error_noreturn(E_COMPILE_ERROR,
"The \"yield\" expression can only be used inside a function");
}
+
if (CG(active_op_array)->fn_flags & ZEND_ACC_HAS_RETURN_TYPE) {
const char *msg = "Generators may only declare a return type of Generator, Iterator or Traversable, %s is not permitted";
- if (!CG(active_op_array)->arg_info[-1].class_name) {
- zend_error_noreturn(E_COMPILE_ERROR, msg,
- zend_get_type_by_const(CG(active_op_array)->arg_info[-1].type_hint));
+ zend_arg_info return_info = CG(active_op_array)->arg_info[-1];
+
+ if (!return_info.class_name) {
+ zend_error_noreturn(E_COMPILE_ERROR, msg, zend_get_type_by_const(return_info.type_hint));
}
- if (!(ZSTR_LEN(CG(active_op_array)->arg_info[-1].class_name) == sizeof("Traversable")-1
- && zend_binary_strcasecmp(ZSTR_VAL(CG(active_op_array)->arg_info[-1].class_name), sizeof("Traversable")-1, "Traversable", sizeof("Traversable")-1) == 0) &&
- !(ZSTR_LEN(CG(active_op_array)->arg_info[-1].class_name) == sizeof("Iterator")-1
- && zend_binary_strcasecmp(ZSTR_VAL(CG(active_op_array)->arg_info[-1].class_name), sizeof("Iterator")-1, "Iterator", sizeof("Iterator")-1) == 0) &&
- !(ZSTR_LEN(CG(active_op_array)->arg_info[-1].class_name) == sizeof("Generator")-1
- && zend_binary_strcasecmp(ZSTR_VAL(CG(active_op_array)->arg_info[-1].class_name), sizeof("Generator")-1, "Generator", sizeof("Generator")-1) == 0)) {
- zend_error_noreturn(E_COMPILE_ERROR, msg, ZSTR_VAL(CG(active_op_array)->arg_info[-1].class_name));
+
+ if (!zend_string_equals_literal_ci(return_info.class_name, "Traversable")
+ && !zend_string_equals_literal_ci(return_info.class_name, "Iterator")
+ && !zend_string_equals_literal_ci(return_info.class_name, "Generator")) {
+ zend_error_noreturn(E_COMPILE_ERROR, msg, ZSTR_VAL(return_info.class_name));
}
}
@@ -1807,25 +1842,27 @@ ZEND_API size_t zend_dirname(char *path, size_t len)
static void zend_adjust_for_fetch_type(zend_op *opline, uint32_t type) /* {{{ */
{
+ zend_uchar factor = (opline->opcode == ZEND_FETCH_STATIC_PROP_R) ? 1 : 3;
+
switch (type & BP_VAR_MASK) {
case BP_VAR_R:
return;
case BP_VAR_W:
case BP_VAR_REF:
- opline->opcode += 3;
+ opline->opcode += 1 * factor;
return;
case BP_VAR_RW:
- opline->opcode += 6;
+ opline->opcode += 2 * factor;
return;
case BP_VAR_IS:
- opline->opcode += 9;
+ opline->opcode += 3 * factor;
return;
case BP_VAR_FUNC_ARG:
- opline->opcode += 12;
+ opline->opcode += 4 * factor;
opline->extended_value |= type >> BP_VAR_SHIFT;
return;
case BP_VAR_UNSET:
- opline->opcode += 15;
+ opline->opcode += 5 * factor;
return;
EMPTY_SWITCH_DEFAULT_CASE()
}
@@ -1848,6 +1885,119 @@ static inline void zend_make_tmp_result(znode *result, zend_op *opline) /* {{{ *
}
/* }}} */
+static void zend_find_live_range(zend_op *opline, zend_uchar type, uint32_t var) /* {{{ */
+{
+ zend_op *def = opline;
+
+ while (def != CG(active_op_array)->opcodes) {
+ def--;
+ if (def->result_type == type && def->result.var == var) {
+ if (def->opcode == ZEND_ADD_ARRAY_ELEMENT ||
+ def->opcode == ZEND_ROPE_ADD) {
+ /* not a real definition */
+ continue;
+ } else if (def->opcode == ZEND_JMPZ_EX ||
+ def->opcode == ZEND_JMPNZ_EX ||
+ def->opcode == ZEND_BOOL ||
+ def->opcode == ZEND_BOOL_NOT) {
+ /* result IS_BOOL, it does't have to be destroyed */
+ break;
+ } else if (def->opcode == ZEND_DECLARE_CLASS ||
+ def->opcode == ZEND_DECLARE_INHERITED_CLASS ||
+ def->opcode == ZEND_DECLARE_INHERITED_CLASS_DELAYED ||
+ def->opcode == ZEND_DECLARE_ANON_CLASS ||
+ def->opcode == ZEND_DECLARE_ANON_INHERITED_CLASS) {
+ /* classes don't have to be destroyed */
+ break;
+ } else if (def->opcode == ZEND_FAST_CALL) {
+ /* fast_calls don't have to be destroyed */
+ break;
+ } else if (def->opcode == ZEND_NEW) {
+ /* Objects created via ZEND_NEW are only fully initialized
+ * after the DO_FCALL (constructor call) */
+ def = CG(active_op_array)->opcodes + def->op2.opline_num - 1;
+ if (def + 1 == opline) {
+ break;
+ }
+ }
+ zend_end_live_range(CG(active_op_array),
+ zend_start_live_range(CG(active_op_array),
+ def + 1 - CG(active_op_array)->opcodes),
+ opline - CG(active_op_array)->opcodes,
+ ZEND_LIVE_TMPVAR, def->result.var);
+ break;
+ }
+ }
+}
+/* }}} */
+
+static zend_always_inline int zend_is_def_range(zend_op *opline, zend_uchar type, uint32_t var) /* {{{ */
+{
+ return opline->result_type == type &&
+ opline->result.var == var &&
+ opline->opcode != ZEND_ADD_ARRAY_ELEMENT &&
+ opline->opcode != ZEND_ROPE_ADD;
+}
+/* }}} */
+
+static void zend_check_live_ranges(zend_op *opline) /* {{{ */
+{
+ if ((opline->op1_type & (IS_VAR|IS_TMP_VAR)) &&
+ !zend_is_def_range(opline - 1, opline->op1_type, opline->op1.var)) {
+
+ if (opline->opcode == ZEND_OP_DATA) {
+ if (!zend_is_def_range(opline - 2, opline->op1_type, opline->op1.var)) {
+ zend_find_live_range(opline - 1, opline->op1_type, opline->op1.var);
+ }
+ } else if (opline->opcode == ZEND_INIT_STATIC_METHOD_CALL ||
+ opline->opcode == ZEND_NEW ||
+ opline->opcode == ZEND_FETCH_CLASS_CONSTANT ||
+ opline->opcode == ZEND_ADD_INTERFACE ||
+ opline->opcode == ZEND_ADD_TRAIT ||
+ opline->opcode == ZEND_BIND_TRAITS ||
+ opline->opcode == ZEND_VERIFY_ABSTRACT_CLASS) {
+ /* classes don't have to be destroyed */
+ } else if (opline->opcode == ZEND_FAST_RET) {
+ /* fast_calls don't have to be destroyed */
+ } else if (opline->opcode == ZEND_CASE ||
+ opline->opcode == ZEND_FE_FETCH_R ||
+ opline->opcode == ZEND_FE_FETCH_RW ||
+ opline->opcode == ZEND_FE_FREE ||
+ opline->opcode == ZEND_ROPE_ADD ||
+ opline->opcode == ZEND_ROPE_END ||
+ opline->opcode == ZEND_END_SILENCE ||
+ opline->opcode == ZEND_FETCH_LIST ||
+ opline->opcode == ZEND_VERIFY_RETURN_TYPE) {
+ /* these opcodes are handled separately */
+ } else {
+ zend_find_live_range(opline, opline->op1_type, opline->op1.var);
+ }
+ }
+
+ if ((opline->op2_type & (IS_VAR|IS_TMP_VAR)) &&
+ !zend_is_def_range(opline - 1, opline->op2_type, opline->op2.var)) {
+
+ if (opline->opcode == ZEND_OP_DATA) {
+ if (!zend_is_def_range(opline - 2, opline->op2_type, opline->op2.var)) {
+ zend_find_live_range(opline-1, opline->op2_type, opline->op2.var);
+ }
+ } else if (opline->opcode == ZEND_FETCH_STATIC_PROP_R ||
+ opline->opcode == ZEND_FETCH_STATIC_PROP_W ||
+ opline->opcode == ZEND_FETCH_STATIC_PROP_RW ||
+ opline->opcode == ZEND_FETCH_STATIC_PROP_IS ||
+ opline->opcode == ZEND_FETCH_STATIC_PROP_FUNC_ARG ||
+ opline->opcode == ZEND_FETCH_STATIC_PROP_UNSET ||
+ opline->opcode == ZEND_UNSET_STATIC_PROP ||
+ opline->opcode == ZEND_ISSET_ISEMPTY_STATIC_PROP ||
+ opline->opcode == ZEND_INSTANCEOF) {
+ /* classes don't have to be destroyed */
+ } else {
+ zend_find_live_range(opline, opline->op2_type, opline->op2.var);
+ }
+ }
+}
+/* }}} */
+
static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode *op2) /* {{{ */
{
zend_op *opline = get_next_op(CG(active_op_array));
@@ -1865,6 +2015,8 @@ static zend_op *zend_emit_op(znode *result, zend_uchar opcode, znode *op1, znode
SET_NODE(opline->op2, op2);
}
+ zend_check_live_ranges(opline);
+
if (result) {
zend_make_var_result(result, opline);
}
@@ -1889,6 +2041,8 @@ static zend_op *zend_emit_op_tmp(znode *result, zend_uchar opcode, znode *op1, z
SET_NODE(opline->op2, op2);
}
+ zend_check_live_ranges(opline);
+
if (result) {
zend_make_tmp_result(result, opline);
}
@@ -2003,6 +2157,7 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
for (i = offset; i < count; ++i) {
opline = get_next_op(CG(active_op_array));
memcpy(opline, &oplines[i], sizeof(zend_op));
+ zend_check_live_ranges(opline);
}
CG(delayed_oplines_stack).top = offset;
return opline;
@@ -2011,6 +2166,11 @@ static zend_op *zend_delayed_compile_end(uint32_t offset) /* {{{ */
static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info) /* {{{ */
{
+ /* `return ...;` is illegal in a void function (but `return;` isn't) */
+ if (expr && return_info->type_hint == IS_VOID) {
+ zend_error_noreturn(E_COMPILE_ERROR, "A void function must not return a value");
+ }
+
if (return_info->type_hint != IS_UNDEF) {
zend_op *opline = zend_emit_op(NULL, ZEND_VERIFY_RETURN_TYPE, expr, NULL);
if (expr && expr->op_type == IS_CONST) {
@@ -2027,7 +2187,7 @@ static void zend_emit_return_type_check(znode *expr, zend_arg_info *return_info)
}
/* }}} */
-void zend_emit_final_return(zval *zv) /* {{{ */
+void zend_emit_final_return(int return_one) /* {{{ */
{
znode zn;
zend_op *ret;
@@ -2038,8 +2198,8 @@ void zend_emit_final_return(zval *zv) /* {{{ */
}
zn.op_type = IS_CONST;
- if (zv) {
- ZVAL_COPY_VALUE(&zn.u.constant, zv);
+ if (return_one) {
+ ZVAL_LONG(&zn.u.constant, 1);
} else {
ZVAL_NULL(&zn.u.constant);
}
@@ -2158,6 +2318,61 @@ static zend_op *zend_compile_class_ref(znode *result, zend_ast *name_ast, int th
}
/* }}} */
+static void zend_compile_class_ref_ex(znode *result, zend_ast *name_ast, uint32_t fetch_flags) /* {{{ */
+{
+ uint32_t fetch_type;
+
+ if (name_ast->kind != ZEND_AST_ZVAL) {
+ znode name_node;
+
+ zend_compile_expr(&name_node, name_ast);
+
+ if (name_node.op_type == IS_CONST) {
+ zend_string *name;
+
+ if (Z_TYPE(name_node.u.constant) != IS_STRING) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
+ }
+
+ name = Z_STR(name_node.u.constant);
+ fetch_type = zend_get_class_fetch_type(name);
+
+ if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
+ result->op_type = IS_CONST;
+ ZVAL_STR(&result->u.constant, zend_resolve_class_name(name, ZEND_NAME_FQ));
+ } else {
+ zend_ensure_valid_class_fetch_type(fetch_type);
+ result->op_type = IS_UNUSED;
+ result->u.op.num = fetch_type | fetch_flags;
+ }
+
+ zend_string_release(name);
+ } else {
+ zend_op *opline = zend_emit_op(result, ZEND_FETCH_CLASS, NULL, &name_node);
+ opline->extended_value = ZEND_FETCH_CLASS_DEFAULT | fetch_flags;
+ }
+ return;
+ }
+
+ /* Fully qualified names are always default refs */
+ if (name_ast->attr == ZEND_NAME_FQ) {
+ result->op_type = IS_CONST;
+ ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
+ return;
+ }
+
+ fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
+ if (ZEND_FETCH_CLASS_DEFAULT == fetch_type) {
+ result->op_type = IS_CONST;
+ ZVAL_STR(&result->u.constant, zend_resolve_class_name_ast(name_ast));
+ } else {
+ zend_ensure_valid_class_fetch_type(fetch_type);
+ result->op_type = IS_UNUSED;
+ result->u.op.num = fetch_type | fetch_flags;
+ }
+}
+/* }}} */
+
static int zend_try_compile_cv(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *name_ast = ast->child[0];
@@ -2364,19 +2579,14 @@ zend_op *zend_compile_static_prop_common(znode *result, zend_ast *ast, uint32_t
znode class_node, prop_node;
zend_op *opline;
- if (zend_is_const_default_class_ref(class_ast)) {
- class_node.op_type = IS_CONST;
- ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
- } else {
- zend_compile_class_ref(&class_node, class_ast, 1);
- }
+ zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
zend_compile_expr(&prop_node, prop_ast);
if (delayed) {
- opline = zend_delayed_emit_op(result, ZEND_FETCH_R, &prop_node, NULL);
+ opline = zend_delayed_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
} else {
- opline = zend_emit_op(result, ZEND_FETCH_R, &prop_node, NULL);
+ opline = zend_emit_op(result, ZEND_FETCH_STATIC_PROP_R, &prop_node, NULL);
}
if (opline->op1_type == IS_CONST) {
zend_alloc_polymorphic_cache_slot(opline->op1.constant);
@@ -2747,10 +2957,7 @@ uint32_t zend_compile_args(zend_ast *ast, zend_function *fbc) /* {{{ */
}
}
- opline = get_next_op(CG(active_op_array));
- opline->opcode = opcode;
- SET_NODE(opline->op1, &arg_node);
- SET_UNUSED(opline->op2);
+ opline = zend_emit_op(NULL, opcode, &arg_node, NULL);
opline->op2.opline_num = arg_num;
opline->result.var = (uint32_t)(zend_intptr_t)ZEND_CALL_ARG(NULL, arg_num);
@@ -2853,13 +3060,14 @@ void zend_compile_ns_call(znode *result, znode *name_node, zend_ast *args_ast) /
void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_ast) /* {{{ */
{
- zend_op *opline = get_next_op(CG(active_op_array));
if (name_node->op_type == IS_CONST && Z_TYPE(name_node->u.constant) == IS_STRING) {
const char *colon;
zend_string *str = Z_STR(name_node->u.constant);
if ((colon = zend_memrchr(ZSTR_VAL(str), ':', ZSTR_LEN(str))) != NULL && colon > ZSTR_VAL(str) && *(colon - 1) == ':') {
zend_string *class = zend_string_init(ZSTR_VAL(str), colon - ZSTR_VAL(str) - 1, 0);
zend_string *method = zend_string_init(colon + 1, ZSTR_LEN(str) - (colon - ZSTR_VAL(str)) - 1, 0);
+ zend_op *opline = get_next_op(CG(active_op_array));
+
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
opline->op1_type = IS_CONST;
opline->op1.constant = zend_add_class_name_literal(CG(active_op_array), class);
@@ -2868,6 +3076,8 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a
zend_alloc_cache_slot(opline->op2.constant);
zval_ptr_dtor(&name_node->u.constant);
} else {
+ zend_op *opline = get_next_op(CG(active_op_array));
+
opline->opcode = ZEND_INIT_FCALL_BY_NAME;
SET_UNUSED(opline->op1);
opline->op2_type = IS_CONST;
@@ -2875,9 +3085,7 @@ void zend_compile_dynamic_call(znode *result, znode *name_node, zend_ast *args_a
zend_alloc_cache_slot(opline->op2.constant);
}
} else {
- opline->opcode = ZEND_INIT_DYNAMIC_CALL;
- SET_UNUSED(opline->op1);
- SET_NODE(opline->op2, name_node);
+ zend_emit_op(NULL, ZEND_INIT_DYNAMIC_CALL, NULL, name_node);
}
zend_compile_call_common(result, args_ast, NULL);
@@ -3296,15 +3504,8 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
znode class_node, method_node;
zend_op *opline;
- zend_ulong extended_value = 0;
- if (zend_is_const_default_class_ref(class_ast)) {
- class_node.op_type = IS_CONST;
- ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
- } else {
- opline = zend_compile_class_ref(&class_node, class_ast, 1);
- extended_value = opline->extended_value;
- }
+ zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
zend_compile_expr(&method_node, method_ast);
if (method_node.op_type == IS_CONST) {
@@ -3320,7 +3521,6 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
opline = get_next_op(CG(active_op_array));
opline->opcode = ZEND_INIT_STATIC_METHOD_CALL;
- opline->extended_value = extended_value;
zend_set_class_name_op1(opline, &class_node);
@@ -3336,6 +3536,7 @@ void zend_compile_static_call(znode *result, zend_ast *ast, uint32_t type) /* {{
} else {
SET_NODE(opline->op2, &method_node);
}
+ zend_check_live_ranges(opline);
zend_compile_call_common(result, args_ast, NULL);
}
@@ -3352,10 +3553,7 @@ void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
zend_op *opline;
uint32_t opnum;
- if (zend_is_const_default_class_ref(class_ast)) {
- class_node.op_type = IS_CONST;
- ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
- } else if (class_ast->kind == ZEND_AST_CLASS) {
+ if (class_ast->kind == ZEND_AST_CLASS) {
uint32_t dcl_opnum = get_next_op_number(CG(active_op_array));
zend_compile_class_decl(class_ast);
/* jump over anon class declaration */
@@ -3367,7 +3565,7 @@ void zend_compile_new(znode *result, zend_ast *ast) /* {{{ */
class_node.u.op.var = opline->result.var;
opline->op1.opline_num = get_next_op_number(CG(active_op_array));
} else {
- zend_compile_class_ref(&class_node, class_ast, 1);
+ zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
}
opnum = get_next_op_number(CG(active_op_array));
@@ -3507,7 +3705,7 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */
return;
case ZEND_AST_STATIC_PROP:
opline = zend_compile_static_prop_common(NULL, var_ast, BP_VAR_UNSET, 0);
- opline->opcode = ZEND_UNSET_VAR;
+ opline->opcode = ZEND_UNSET_STATIC_PROP;
return;
EMPTY_SWITCH_DEFAULT_CASE()
}
@@ -3550,7 +3748,7 @@ static int zend_handle_loops_and_finally_ex(zend_long depth) /* {{{ */
opline->op1_type = loop_var->var_type;
opline->op1.var = loop_var->var_num;
SET_UNUSED(opline->op2);
- opline->op2.num = loop_var->u.brk_cont_offset;
+ opline->op2.num = loop_var->u.live_range_offset;
opline->extended_value = ZEND_FREE_ON_RETURN;
depth--;
}
@@ -3695,14 +3893,14 @@ void zend_resolve_goto_label(zend_op_array *op_array, zend_op *opline) /* {{{ */
ZVAL_NULL(label);
current = opline->extended_value;
- for (; current != dest->brk_cont; current = op_array->brk_cont_array[current].parent) {
+ for (; current != dest->brk_cont; current = CG(context).brk_cont_array[current].parent) {
if (current == -1) {
CG(in_compilation) = 1;
CG(active_op_array) = op_array;
CG(zend_lineno) = opline->lineno;
zend_error_noreturn(E_COMPILE_ERROR, "'goto' into loop or switch statement is disallowed");
}
- if (op_array->brk_cont_array[current].start >= 0) {
+ if (CG(context).brk_cont_array[current].start >= 0) {
remove_oplines--;
}
}
@@ -3791,7 +3989,7 @@ void zend_compile_while(zend_ast *ast) /* {{{ */
zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
- zend_end_loop(opnum_cond);
+ zend_end_loop(opnum_cond, NULL);
}
/* }}} */
@@ -3813,7 +4011,7 @@ void zend_compile_do_while(zend_ast *ast) /* {{{ */
zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
- zend_end_loop(opnum_cond);
+ zend_end_loop(opnum_cond, NULL);
}
/* }}} */
@@ -3869,7 +4067,7 @@ void zend_compile_for(zend_ast *ast) /* {{{ */
zend_emit_cond_jump(ZEND_JMPNZ, &result, opnum_start);
- zend_end_loop(opnum_loop);
+ zend_end_loop(opnum_loop, NULL);
}
/* }}} */
@@ -3913,6 +4111,8 @@ void zend_compile_foreach(zend_ast *ast) /* {{{ */
opnum_reset = get_next_op_number(CG(active_op_array));
opline = zend_emit_op(&reset_node, by_ref ? ZEND_FE_RESET_RW : ZEND_FE_RESET_R, &expr_node, NULL);
+ zend_begin_loop(ZEND_FE_FREE, &reset_node);
+
opnum_fetch = get_next_op_number(CG(active_op_array));
opline = zend_emit_op(NULL, by_ref ? ZEND_FE_FETCH_RW : ZEND_FE_FETCH_R, &reset_node, NULL);
@@ -3936,8 +4136,6 @@ void zend_compile_foreach(zend_ast *ast) /* {{{ */
zend_emit_assign_znode(key_ast, &key_node);
}
- zend_begin_loop(ZEND_FE_FREE, &reset_node);
-
zend_compile_stmt(stmt_ast);
zend_emit_jump(opnum_fetch);
@@ -3948,9 +4146,9 @@ void zend_compile_foreach(zend_ast *ast) /* {{{ */
opline = &CG(active_op_array)->opcodes[opnum_fetch];
opline->extended_value = get_next_op_number(CG(active_op_array));
- zend_end_loop(opnum_fetch);
+ zend_end_loop(opnum_fetch, &reset_node);
- zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL);
+ opline = zend_emit_op(NULL, ZEND_FE_FREE, &reset_node, NULL);
}
/* }}} */
@@ -4070,10 +4268,14 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */
zend_update_jump_target_to_next(opnum_default_jmp);
}
- zend_end_loop(get_next_op_number(CG(active_op_array)));
+ 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) {
- zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
+ /* don't use emit_op() to prevent automatic live-range construction */
+ opline = get_next_op(CG(active_op_array));
+ opline->opcode = ZEND_FREE;
+ SET_NODE(opline->op1, &expr_node);
+ SET_UNUSED(opline->op2);
} else if (expr_node.op_type == IS_CONST) {
zval_dtor(&expr_node.u.constant);
}
@@ -4169,7 +4371,9 @@ void zend_compile_try(zend_ast *ast) /* {{{ */
}
opline = &CG(active_op_array)->opcodes[opnum_catch];
- opline->extended_value = get_next_op_number(CG(active_op_array));
+ if (!is_last_catch) {
+ opline->extended_value = get_next_op_number(CG(active_op_array));
+ }
}
for (i = 0; i < catches->children; ++i) {
@@ -4511,6 +4715,10 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
zend_compile_typename(type_ast, arg_info);
+ if (arg_info->type_hint == IS_VOID) {
+ zend_error_noreturn(E_COMPILE_ERROR, "void cannot be used as a parameter type");
+ }
+
if (type_ast->kind == ZEND_AST_TYPE) {
if (arg_info->type_hint == IS_ARRAY) {
if (default_ast && !has_null_default
@@ -4891,7 +5099,7 @@ void zend_compile_func_decl(znode *result, zend_ast *ast) /* {{{ */
CG(zend_lineno) = decl->end_lineno;
zend_do_extended_info();
- zend_emit_final_return(NULL);
+ zend_emit_final_return(0);
pass_two(CG(active_op_array));
zend_oparray_context_end(&orig_oparray_context);
@@ -6301,13 +6509,7 @@ void zend_compile_instanceof(znode *result, zend_ast *ast) /* {{{ */
"instanceof expects an object instance, constant given");
}
- if (zend_is_const_default_class_ref(class_ast)) {
- class_node.op_type = IS_CONST;
- ZVAL_STR(&class_node.u.constant, zend_resolve_class_name_ast(class_ast));
- } else {
- opline = zend_compile_class_ref(&class_node, class_ast, 0);
- opline->extended_value |= ZEND_FETCH_CLASS_NO_AUTOLOAD;
- }
+ zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_NO_AUTOLOAD);
opline = zend_emit_op_tmp(result, ZEND_INSTANCEOF, &obj_node, NULL);
@@ -6379,7 +6581,7 @@ void zend_compile_isset_or_empty(znode *result, zend_ast *ast) /* {{{ */
break;
case ZEND_AST_STATIC_PROP:
opline = zend_compile_static_prop_common(result, var_ast, BP_VAR_IS, 0);
- opline->opcode = ZEND_ISSET_ISEMPTY_VAR;
+ opline->opcode = ZEND_ISSET_ISEMPTY_STATIC_PROP;
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
@@ -6393,10 +6595,9 @@ void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
{
zend_ast *expr_ast = ast->child[0];
znode silence_node;
- uint32_t begin_opline_num, end_opline_num;
- zend_brk_cont_element *brk_cont_element;
+ uint32_t range;
- begin_opline_num = get_next_op_number(CG(active_op_array));
+ range = zend_start_live_range(CG(active_op_array), get_next_op_number(CG(active_op_array)));
zend_emit_op_tmp(&silence_node, ZEND_BEGIN_SILENCE, NULL, NULL);
if (expr_ast->kind == ZEND_AST_VAR) {
@@ -6407,15 +6608,12 @@ void zend_compile_silence(znode *result, zend_ast *ast) /* {{{ */
zend_compile_expr(result, expr_ast);
}
- end_opline_num = get_next_op_number(CG(active_op_array));
- zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);
-
/* Store BEGIN_SILENCE/END_SILENCE pair to restore previous
* EG(error_reporting) value on exception */
- brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
- brk_cont_element->start = begin_opline_num;
- brk_cont_element->cont = brk_cont_element->brk = end_opline_num;
- brk_cont_element->parent = -1;
+ zend_end_live_range(CG(active_op_array), range, get_next_op_number(CG(active_op_array)),
+ ZEND_LIVE_SILENCE, silence_node.u.op.var);
+
+ zend_emit_op(NULL, ZEND_END_SILENCE, &silence_node, NULL);
}
/* }}} */
@@ -6559,7 +6757,6 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
znode class_node, const_node;
zend_op *opline;
- zend_string *resolved_name;
if (zend_try_compile_const_expr_resolve_class_name(&result->u.constant, class_ast, const_ast, 0)) {
if (Z_TYPE(result->u.constant) == IS_NULL) {
@@ -6575,31 +6772,26 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
zend_eval_const_expr(&const_ast);
if (class_ast->kind == ZEND_AST_ZVAL) {
+ zend_string *resolved_name;
+
resolved_name = zend_resolve_class_name_ast(class_ast);
if (const_ast->kind == ZEND_AST_ZVAL && zend_try_ct_eval_class_const(&result->u.constant, resolved_name, zend_ast_get_str(const_ast))) {
result->op_type = IS_CONST;
zend_string_release(resolved_name);
return;
}
+ zend_string_release(resolved_name);
}
if (const_ast->kind == ZEND_AST_ZVAL && zend_string_equals_literal_ci(zend_ast_get_str(const_ast), "class")) {
zend_error_noreturn(E_COMPILE_ERROR,
"Dynamic class names are not allowed in compile-time ::class fetch");
}
- if (zend_is_const_default_class_ref(class_ast)) {
- class_node.op_type = IS_CONST;
- ZVAL_STR(&class_node.u.constant, resolved_name);
- } else {
- if (class_ast->kind == ZEND_AST_ZVAL) {
- zend_string_release(resolved_name);
- }
- zend_compile_class_ref(&class_node, class_ast, 1);
- }
+ zend_compile_class_ref_ex(&class_node, class_ast, ZEND_FETCH_CLASS_EXCEPTION);
zend_compile_expr(&const_node, const_ast);
- opline = zend_emit_op_tmp(result, ZEND_FETCH_CONSTANT, NULL, &const_node);
+ opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_CONSTANT, NULL, &const_node);
zend_set_class_name_op1(opline, &class_node);
@@ -6741,10 +6933,7 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
GET_NODE(result, opline->result);
} else {
uint32_t var;
- zend_brk_cont_element *info = get_next_brk_cont_element(CG(active_op_array));
- info->start = rope_init_lineno;
- info->parent = CG(context).current_brk_cont;
- info->cont = info->brk = opline - CG(active_op_array)->opcodes;
+ uint32_t range = zend_start_live_range(CG(active_op_array), rope_init_lineno);
init_opline->extended_value = j;
opline->opcode = ZEND_ROPE_END;
@@ -6758,6 +6947,10 @@ static void zend_compile_encaps_list(znode *result, zend_ast *ast) /* {{{ */
get_temporary_variable(CG(active_op_array));
i--;
}
+
+ zend_end_live_range(CG(active_op_array), range, opline - CG(active_op_array)->opcodes,
+ ZEND_LIVE_ROPE, var);
+
/* Update all the previous opcodes to use the same variable */
while (opline != init_opline) {
opline--;
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index b777a0ba8c..711fc00009 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -111,18 +111,6 @@ typedef struct _zend_declarables {
zend_long ticks;
} zend_declarables;
-/* Compilation context that is different for each op array. */
-typedef struct _zend_oparray_context {
- uint32_t opcodes_size;
- int vars_size;
- int literals_size;
- int current_brk_cont;
- int backpatch_count;
- int in_finally;
- uint32_t fast_call_var;
- HashTable *labels;
-} zend_oparray_context;
-
/* Compilation context that is different for each file, but shared between op arrays. */
typedef struct _zend_file_context {
zend_declarables declarables;
@@ -185,6 +173,32 @@ typedef struct _zend_try_catch_element {
uint32_t finally_end;
} zend_try_catch_element;
+#define ZEND_LIVE_TMPVAR 0
+#define ZEND_LIVE_LOOP 1
+#define ZEND_LIVE_SILENCE 2
+#define ZEND_LIVE_ROPE 3
+#define ZEND_LIVE_MASK 3
+
+typedef struct _zend_live_range {
+ uint32_t var; /* low bits are used for variable type (ZEND_LIVE_* macros) */
+ uint32_t start;
+ uint32_t end;
+} zend_live_range;
+
+/* Compilation context that is different for each op array. */
+typedef struct _zend_oparray_context {
+ uint32_t opcodes_size;
+ int vars_size;
+ int literals_size;
+ int backpatch_count;
+ int in_finally;
+ uint32_t fast_call_var;
+ int current_brk_cont;
+ int last_brk_cont;
+ zend_brk_cont_element *brk_cont_array;
+ HashTable *labels;
+} zend_oparray_context;
+
/* method flags (types) */
#define ZEND_ACC_STATIC 0x01
#define ZEND_ACC_ABSTRACT 0x02
@@ -354,9 +368,9 @@ struct _zend_op_array {
uint32_t T;
zend_string **vars;
- int last_brk_cont;
+ int last_live_range;
int last_try_catch;
- zend_brk_cont_element *brk_cont_array;
+ zend_live_range *live_range;
zend_try_catch_element *try_catch_array;
/* static variables support */
@@ -514,7 +528,10 @@ struct _zend_execute_data {
#define EX_VAR(n) ZEND_CALL_VAR(execute_data, n)
#define EX_VAR_NUM(n) ZEND_CALL_VAR_NUM(execute_data, n)
-#define EX_VAR_TO_NUM(n) (ZEND_CALL_VAR(NULL, n) - ZEND_CALL_VAR_NUM(NULL, 0))
+#define EX_VAR_TO_NUM(n) ((uint32_t)(ZEND_CALL_VAR(NULL, n) - ZEND_CALL_VAR_NUM(NULL, 0)))
+
+#define ZEND_OPLINE_TO_OFFSET(opline, target) \
+ ((char*)(target) - (char*)(opline))
#define ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline_num) \
((char*)&(op_array)->opcodes[opline_num] - (char*)(opline))
@@ -531,6 +548,10 @@ struct _zend_execute_data {
# define OP_JMP_ADDR(opline, node) \
(node).jmp_addr
+# define ZEND_SET_OP_JMP_ADDR(opline, node, val) do { \
+ (node).jmp_addr = (val); \
+ } while (0)
+
/* convert jump target from compile-time to run-time */
# define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
(node).jmp_addr = (op_array)->opcodes + (node).opline_num; \
@@ -547,6 +568,10 @@ struct _zend_execute_data {
# define OP_JMP_ADDR(opline, node) \
ZEND_OFFSET_TO_OPLINE(opline, (node).jmp_offset)
+# define ZEND_SET_OP_JMP_ADDR(opline, node, val) do { \
+ (node).jmp_offset = ZEND_OPLINE_TO_OFFSET(opline, val); \
+ } while (0)
+
/* convert jump target from compile-time to run-time */
# define ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, node) do { \
(node).jmp_offset = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, (node).opline_num); \
@@ -694,7 +719,7 @@ ZEND_API unary_op_type get_unary_op(int opcode);
ZEND_API binary_op_type get_binary_op(int opcode);
void zend_stop_lexing(void);
-void zend_emit_final_return(zval *zv);
+void zend_emit_final_return(int return_one);
zend_ast *zend_ast_append_str(zend_ast *left, zend_ast *right);
uint32_t zend_add_class_modifier(uint32_t flags, uint32_t new_flag);
uint32_t zend_add_member_modifier(uint32_t flags, uint32_t new_flag);
@@ -755,7 +780,7 @@ zend_op *get_next_op(zend_op_array *op_array);
void init_op(zend_op *op);
int get_next_op_number(zend_op_array *op_array);
ZEND_API int pass_two(zend_op_array *op_array);
-zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array);
+zend_brk_cont_element *get_next_brk_cont_element(void);
ZEND_API zend_bool zend_is_compiling(void);
ZEND_API char *zend_make_compiled_string_description(const char *name);
ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify_handlers);
diff --git a/Zend/zend_constants.c b/Zend/zend_constants.c
index 8d1be740aa..159379d71c 100644
--- a/Zend/zend_constants.c
+++ b/Zend/zend_constants.c
@@ -294,7 +294,7 @@ ZEND_API zval *zend_get_constant(zend_string *name)
return c ? &c->value : NULL;
}
-ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, zend_ulong flags)
+ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope, uint32_t flags)
{
zend_constant *c;
const char *colon;
@@ -427,7 +427,7 @@ ZEND_API zval *zend_get_constant_ex(zend_string *cname, zend_class_entry *scope,
}
}
-zend_constant *zend_quick_get_constant(const zval *key, zend_ulong flags)
+zend_constant *zend_quick_get_constant(const zval *key, uint32_t flags)
{
zend_constant *c;
diff --git a/Zend/zend_constants.h b/Zend/zend_constants.h
index 9ccf53e43a..2f8b7288d7 100644
--- a/Zend/zend_constants.h
+++ b/Zend/zend_constants.h
@@ -67,7 +67,7 @@ void zend_register_standard_constants(void);
void clean_non_persistent_constants(void);
ZEND_API zval *zend_get_constant(zend_string *name);
ZEND_API zval *zend_get_constant_str(const char *name, size_t name_len);
-ZEND_API zval *zend_get_constant_ex(zend_string *name, zend_class_entry *scope, zend_ulong flags);
+ZEND_API zval *zend_get_constant_ex(zend_string *name, zend_class_entry *scope, uint32_t flags);
ZEND_API void zend_register_bool_constant(const char *name, size_t name_len, zend_bool bval, int flags, int module_number);
ZEND_API void zend_register_null_constant(const char *name, size_t name_len, int flags, int module_number);
ZEND_API void zend_register_long_constant(const char *name, size_t name_len, zend_long lval, int flags, int module_number);
@@ -76,7 +76,7 @@ ZEND_API void zend_register_string_constant(const char *name, size_t name_len, c
ZEND_API void zend_register_stringl_constant(const char *name, size_t name_len, char *strval, size_t strlen, int flags, int module_number);
ZEND_API int zend_register_constant(zend_constant *c);
void zend_copy_constants(HashTable *target, HashTable *sourc);
-zend_constant *zend_quick_get_constant(const zval *key, zend_ulong flags);
+zend_constant *zend_quick_get_constant(const zval *key, uint32_t flags);
END_EXTERN_C()
#define ZEND_CONSTANT_DTOR free_zend_constant
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c
index 147fbe8ad9..03db1749ce 100644
--- a/Zend/zend_exceptions.c
+++ b/Zend/zend_exceptions.c
@@ -58,17 +58,19 @@ static int zend_implement_throwable(zend_class_entry *interface, zend_class_entr
}
/* }}} */
-static inline zend_class_entry *i_get_exception_base(zval *object)
+static inline zend_class_entry *i_get_exception_base(zval *object) /* {{{ */
{
return instanceof_function(Z_OBJCE_P(object), zend_ce_exception) ? zend_ce_exception : zend_ce_error;
}
+/* }}} */
-ZEND_API zend_class_entry *zend_get_exception_base(zval *object)
+ZEND_API zend_class_entry *zend_get_exception_base(zval *object) /* {{{ */
{
return i_get_exception_base(object);
}
+/* }}} */
-void zend_exception_set_previous(zend_object *exception, zend_object *add_previous)
+void zend_exception_set_previous(zend_object *exception, zend_object *add_previous) /* {{{ */
{
zval *previous, *ancestor, *ex;
zval pv, zv, rv;
@@ -103,6 +105,7 @@ void zend_exception_set_previous(zend_object *exception, zend_object *add_previo
ex = previous;
} while (Z_OBJ_P(ex) != add_previous);
}
+/* }}} */
void zend_exception_save(void) /* {{{ */
{
@@ -456,63 +459,6 @@ ZEND_METHOD(error_exception, getSeverity)
} \
} while (0)
-/* Windows uses VK_ESCAPE instead of \e */
-#ifndef VK_ESCAPE
-#define VK_ESCAPE '\e'
-#endif
-
-static size_t compute_escaped_string_len(const char *s, size_t l) {
- size_t i, len = l;
- for (i = 0; i < l; ++i) {
- char c = s[i];
- if (c == '\n' || c == '\r' || c == '\t' ||
- c == '\f' || c == '\v' || c == '\\' || c == VK_ESCAPE) {
- len += 1;
- } else if (c < 32 || c > 126) {
- len += 3;
- }
- }
- return len;
-}
-
-static void smart_str_append_escaped(smart_str *str, const char *s, size_t l) {
- char *res;
- size_t i, len = compute_escaped_string_len(s, l);
-
- smart_str_alloc(str, len, 0);
- res = &ZSTR_VAL(str->s)[ZSTR_LEN(str->s)];
- ZSTR_LEN(str->s) += len;
-
- for (i = 0; i < l; ++i) {
- unsigned char c = s[i];
- if (c < 32 || c == '\\' || c > 126) {
- *res++ = '\\';
- switch (c) {
- case '\n': *res++ = 'n'; break;
- case '\r': *res++ = 'r'; break;
- case '\t': *res++ = 't'; break;
- case '\f': *res++ = 'f'; break;
- case '\v': *res++ = 'v'; break;
- case '\\': *res++ = '\\'; break;
- case VK_ESCAPE: *res++ = 'e'; break;
- default:
- *res++ = 'x';
- if ((c >> 4) < 10) {
- *res++ = (c >> 4) + '0';
- } else {
- *res++ = (c >> 4) + 'A' - 10;
- }
- if ((c & 0xf) < 10) {
- *res++ = (c & 0xf) + '0';
- } else {
- *res++ = (c & 0xf) + 'A' - 10;
- }
- }
- } else {
- *res++ = c;
- }
- }
-}
static void _build_trace_args(zval *arg, smart_str *str) /* {{{ */
{
@@ -979,7 +925,7 @@ static void zend_error_va(int type, const char *file, uint lineno, const char *f
}
/* }}} */
-static void zend_error_helper(int type, const char *filename, const uint lineno, const char *format, ...)
+static void zend_error_helper(int type, const char *filename, const uint lineno, const char *format, ...) /* {{{ */
{
va_list va;
@@ -987,6 +933,7 @@ static void zend_error_helper(int type, const char *filename, const uint lineno,
zend_error_cb(type, filename, lineno, format, va);
va_end(va);
}
+/* }}} */
/* This function doesn't return if it uses E_ERROR */
ZEND_API ZEND_COLD void zend_exception_error(zend_object *ex, int severity) /* {{{ */
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index f851833a2d..044b49e760 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -946,6 +946,24 @@ static ZEND_COLD void zend_verify_internal_return_error(const zend_function *zf,
fclass, fsep, fname, need_msg, need_kind, returned_msg, returned_kind);
}
+static ZEND_COLD void zend_verify_void_return_error(const zend_function *zf, const char *returned_msg, const char *returned_kind)
+{
+ const char *fname = ZSTR_VAL(zf->common.function_name);
+ const char *fsep;
+ const char *fclass;
+
+ if (zf->common.scope) {
+ fsep = "::";
+ fclass = ZSTR_VAL(zf->common.scope->name);
+ } else {
+ fsep = "";
+ fclass = "";
+ }
+
+ zend_type_error("%s%s%s() must not return a value, %s%s returned",
+ fclass, fsep, fname, returned_msg, returned_kind);
+}
+
#if ZEND_DEBUG
static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
{
@@ -975,6 +993,8 @@ static int zend_verify_internal_return_type(zend_function *zf, zval *ret)
} else if (ret_info->type_hint == _IS_BOOL &&
EXPECTED(Z_TYPE_P(ret) == IS_FALSE || Z_TYPE_P(ret) == IS_TRUE)) {
/* pass */
+ } else if (ret_info->type_hint == IS_VOID) {
+ zend_verify_void_return_error(zf, zend_zval_type_name(ret), "");
} else {
/* Use strict check to verify return value of internal function */
zend_verify_internal_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
@@ -1035,6 +1055,12 @@ static zend_always_inline void zend_verify_return_type(zend_function *zf, zval *
} else if (ret_info->type_hint == _IS_BOOL &&
EXPECTED(Z_TYPE_P(ret) == IS_FALSE || Z_TYPE_P(ret) == IS_TRUE)) {
/* pass */
+ /* There would be a check here for the IS_VOID type hint, which
+ * would trigger an error because a value had been returned.
+ * However, zend_compile.c already does a compile-time check
+ * that bans `return ...;` within a void function. Thus we can skip
+ * this part of the runtime check for non-internal functions.
+ */
} else if (UNEXPECTED(!zend_verify_scalar_type_hint(ret_info->type_hint, ret, ZEND_RET_USES_STRICT_TYPES()))) {
zend_verify_return_error(zf, "be of the type ", zend_get_type_by_const(ret_info->type_hint), zend_zval_type_name(ret), "");
}
@@ -1048,7 +1074,7 @@ static ZEND_COLD int zend_verify_missing_return_type(zend_function *zf, void **c
char *need_msg;
zend_class_entry *ce;
- if (ret_info->type_hint) {
+ if (ret_info->type_hint && EXPECTED(ret_info->type_hint != IS_VOID)) {
if (ret_info->class_name) {
if (EXPECTED(*cache_slot)) {
ce = (zend_class_entry*)*cache_slot;
@@ -2549,30 +2575,29 @@ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num,
{
int i;
- for (i = 0; i < EX(func)->op_array.last_brk_cont; i++) {
- const zend_brk_cont_element *brk_cont = &EX(func)->op_array.brk_cont_array[i];
- if (brk_cont->start < 0) {
- continue;
- } else if (brk_cont->start > op_num) {
+ for (i = 0; i < EX(func)->op_array.last_live_range; i++) {
+ const zend_live_range *range = &EX(func)->op_array.live_range[i];
+ if (range->start > op_num) {
/* further blocks will not be relevant... */
break;
- } else if (op_num < brk_cont->brk) {
- if (!catch_op_num || catch_op_num >= brk_cont->brk) {
- zend_op *brk_opline = &EX(func)->op_array.opcodes[brk_cont->brk];
-
- if (brk_opline->opcode == ZEND_FREE) {
- zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
- } else if (brk_opline->opcode == ZEND_FE_FREE) {
- zval *var = EX_VAR(brk_opline->op1.var);
+ } else if (op_num < range->end) {
+ if (!catch_op_num || catch_op_num >= range->end) {
+ uint32_t kind = range->var & ZEND_LIVE_MASK;
+ uint32_t var_num = range->var & ~ZEND_LIVE_MASK;
+ zval *var = EX_VAR(var_num);
+
+ if (kind == ZEND_LIVE_TMPVAR) {
+ zval_ptr_dtor_nogc(var);
+ } else if (kind == ZEND_LIVE_LOOP) {
if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
zend_hash_iterator_del(Z_FE_ITER_P(var));
}
zval_ptr_dtor_nogc(var);
- } else if (brk_opline->opcode == ZEND_ROPE_END) {
- zend_string **rope = (zend_string **) EX_VAR(brk_opline->op1.var);
+ } else if (kind == ZEND_LIVE_ROPE) {
+ zend_string **rope = (zend_string **)var;
zend_op *last = EX(func)->op_array.opcodes + op_num;
while ((last->opcode != ZEND_ROPE_ADD && last->opcode != ZEND_ROPE_INIT)
- || last->result.var != brk_opline->op1.var) {
+ || last->result.var != var_num) {
ZEND_ASSERT(last >= EX(func)->op_array.opcodes);
last--;
}
@@ -2584,10 +2609,10 @@ static void cleanup_live_vars(zend_execute_data *execute_data, uint32_t op_num,
zend_string_release(rope[j]);
} while (j--);
}
- } else if (brk_opline->opcode == ZEND_END_SILENCE) {
+ } else if (kind == ZEND_LIVE_SILENCE) {
/* restore previous error_reporting value */
- if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
- EG(error_reporting) = Z_LVAL_P(EX_VAR(brk_opline->op1.var));
+ if (!EG(error_reporting) && Z_LVAL_P(var) != 0) {
+ EG(error_reporting) = Z_LVAL_P(var);
}
}
}
diff --git a/Zend/zend_extensions.h b/Zend/zend_extensions.h
index 36bcf2c004..bdd83e56ad 100644
--- a/Zend/zend_extensions.h
+++ b/Zend/zend_extensions.h
@@ -25,9 +25,27 @@
#include "zend_compile.h"
#include "zend_build.h"
+/*
+The constants below are derived from ext/opcache/ZendAccelerator.h
+
+You can use the following macro to check the extension API version for compatibilities:
+
+#define ZEND_EXTENSION_API_NO_5_0_X 220040412
+#define ZEND_EXTENSION_API_NO_5_1_X 220051025
+#define ZEND_EXTENSION_API_NO_5_2_X 220060519
+#define ZEND_EXTENSION_API_NO_5_3_X 220090626
+#define ZEND_EXTENSION_API_NO_5_4_X 220100525
+#define ZEND_EXTENSION_API_NO_5_5_X 220121212
+#define ZEND_EXTENSION_API_NO_5_6_X 220131226
+#define ZEND_EXTENSION_API_NO_7_0_X 320151012
+
+#if ZEND_EXTENSION_API_NO < ZEND_EXTENSION_API_NO_5_5_X
+ // do something for php versions lower than 5.5.x
+#endif
+*/
+
/* The first number is the engine version and the rest is the date (YYYYMMDD).
- * This way engine 2/3 API no. is always greater than engine 1 API no..
- */
+ * This way engine 2/3 API no. is always greater than engine 1 API no.. */
#define ZEND_EXTENSION_API_NO 320151012
typedef struct _zend_extension_version_info {
diff --git a/Zend/zend_language_scanner.c b/Zend/zend_language_scanner.c
index a73cf88356..62c669c7a2 100644
--- a/Zend/zend_language_scanner.c
+++ b/Zend/zend_language_scanner.c
@@ -570,6 +570,48 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle)
}
END_EXTERN_C()
+static zend_op_array *zend_compile(int type)
+{
+ zend_op_array *op_array = NULL;
+ zend_bool original_in_compilation = CG(in_compilation);
+
+ CG(in_compilation) = 1;
+ CG(ast) = NULL;
+ CG(ast_arena) = zend_arena_create(1024 * 32);
+
+ if (!zendparse()) {
+ zend_file_context original_file_context;
+ zend_oparray_context original_oparray_context;
+ zend_op_array *original_active_op_array = CG(active_op_array);
+
+ op_array = emalloc(sizeof(zend_op_array));
+ init_op_array(op_array, type, INITIAL_OP_ARRAY_SIZE);
+ CG(active_op_array) = op_array;
+
+ if (zend_ast_process) {
+ zend_ast_process(CG(ast));
+ }
+
+ zend_file_context_begin(&original_file_context);
+ zend_oparray_context_begin(&original_oparray_context);
+ zend_compile_top_stmt(CG(ast));
+ zend_emit_final_return(type == ZEND_USER_FUNCTION);
+ op_array->line_start = 1;
+ op_array->line_end = CG(zend_lineno);
+ pass_two(op_array);
+ zend_oparray_context_end(&original_oparray_context);
+ zend_file_context_end(&original_file_context);
+
+ CG(active_op_array) = original_active_op_array;
+ }
+
+ zend_ast_destroy(CG(ast));
+ zend_arena_destroy(CG(ast_arena));
+
+ CG(in_compilation) = original_in_compilation;
+
+ return op_array;
+}
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type)
{
@@ -585,41 +627,7 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type)
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
}
} else {
- zend_bool original_in_compilation = CG(in_compilation);
- CG(in_compilation) = 1;
-
- CG(ast) = NULL;
- CG(ast_arena) = zend_arena_create(1024 * 32);
- if (!zendparse()) {
- zval retval_zv;
- zend_file_context original_file_context;
- zend_oparray_context original_oparray_context;
- zend_op_array *original_active_op_array = CG(active_op_array);
- op_array = emalloc(sizeof(zend_op_array));
- init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
- CG(active_op_array) = op_array;
- ZVAL_LONG(&retval_zv, 1);
-
- if (zend_ast_process) {
- zend_ast_process(CG(ast));
- }
-
- zend_file_context_begin(&original_file_context);
- zend_oparray_context_begin(&original_oparray_context);
- zend_compile_top_stmt(CG(ast));
- zend_emit_final_return(&retval_zv);
- op_array->line_start = 1;
- op_array->line_end = CG(zend_lineno);
- pass_two(op_array);
- zend_oparray_context_end(&original_oparray_context);
- zend_file_context_end(&original_file_context);
-
- CG(active_op_array) = original_active_op_array;
- }
-
- zend_ast_destroy(CG(ast));
- zend_arena_destroy(CG(ast_arena));
- CG(in_compilation) = original_in_compilation;
+ op_array = zend_compile(ZEND_USER_FUNCTION);
}
zend_restore_lexical_state(&original_lex_state);
@@ -734,13 +742,11 @@ ZEND_API size_t zend_get_scanned_file_offset(void)
return offset;
}
-
zend_op_array *compile_string(zval *source_string, char *filename)
{
zend_lex_state original_lex_state;
zend_op_array *op_array = NULL;
zval tmp;
- zend_bool original_in_compilation = CG(in_compilation);
if (Z_STRLEN_P(source_string)==0) {
return NULL;
@@ -750,45 +756,15 @@ zend_op_array *compile_string(zval *source_string, char *filename)
convert_to_string(&tmp);
source_string = &tmp;
- CG(in_compilation) = 1;
zend_save_lexical_state(&original_lex_state);
if (zend_prepare_string_for_scanning(source_string, filename) == SUCCESS) {
- CG(ast) = NULL;
- CG(ast_arena) = zend_arena_create(1024 * 32);
BEGIN(ST_IN_SCRIPTING);
-
- if (!zendparse()) {
- zend_file_context original_file_context;
- zend_oparray_context original_oparray_context;
- zend_op_array *original_active_op_array = CG(active_op_array);
- op_array = emalloc(sizeof(zend_op_array));
- init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE);
- CG(active_op_array) = op_array;
-
- if (zend_ast_process) {
- zend_ast_process(CG(ast));
- }
-
- zend_file_context_begin(&original_file_context);
- zend_oparray_context_begin(&original_oparray_context);
- zend_compile_top_stmt(CG(ast));
- zend_emit_final_return(NULL);
- op_array->line_start = 1;
- op_array->line_end = CG(zend_lineno);
- pass_two(op_array);
- zend_oparray_context_end(&original_oparray_context);
- zend_file_context_end(&original_file_context);
-
- CG(active_op_array) = original_active_op_array;
- }
-
- zend_ast_destroy(CG(ast));
- zend_arena_destroy(CG(ast_arena));
+ op_array = zend_compile(ZEND_EVAL_CODE);
}
zend_restore_lexical_state(&original_lex_state);
zval_dtor(&tmp);
- CG(in_compilation) = original_in_compilation;
+
return op_array;
}
@@ -1117,7 +1093,7 @@ restart:
SCNG(yy_text) = YYCURSOR;
-#line 1121 "Zend/zend_language_scanner.c"
+#line 1097 "Zend/zend_language_scanner.c"
{
YYCTYPE yych;
unsigned int yyaccept = 0;
@@ -1171,7 +1147,7 @@ yyc_INITIAL:
yy3:
YYDEBUG(3, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1812 "Zend/zend_language_scanner.l"
+#line 1788 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
RETURN_TOKEN(END);
@@ -1216,7 +1192,7 @@ inline_char_handler:
HANDLE_NEWLINES(yytext, yyleng);
RETURN_TOKEN(T_INLINE_HTML);
}
-#line 1220 "Zend/zend_language_scanner.c"
+#line 1196 "Zend/zend_language_scanner.c"
yy4:
YYDEBUG(4, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1234,7 +1210,7 @@ yy5:
yy6:
YYDEBUG(6, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1803 "Zend/zend_language_scanner.l"
+#line 1779 "Zend/zend_language_scanner.l"
{
if (CG(short_tags)) {
BEGIN(ST_IN_SCRIPTING);
@@ -1243,18 +1219,18 @@ yy6:
goto inline_char_handler;
}
}
-#line 1247 "Zend/zend_language_scanner.c"
+#line 1223 "Zend/zend_language_scanner.c"
yy7:
YYDEBUG(7, *YYCURSOR);
++YYCURSOR;
YYDEBUG(8, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1790 "Zend/zend_language_scanner.l"
+#line 1766 "Zend/zend_language_scanner.l"
{
BEGIN(ST_IN_SCRIPTING);
RETURN_TOKEN(T_OPEN_TAG_WITH_ECHO);
}
-#line 1258 "Zend/zend_language_scanner.c"
+#line 1234 "Zend/zend_language_scanner.c"
yy9:
YYDEBUG(9, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1285,13 +1261,13 @@ yy13:
yy14:
YYDEBUG(14, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1796 "Zend/zend_language_scanner.l"
+#line 1772 "Zend/zend_language_scanner.l"
{
HANDLE_NEWLINE(yytext[yyleng-1]);
BEGIN(ST_IN_SCRIPTING);
RETURN_TOKEN(T_OPEN_TAG);
}
-#line 1295 "Zend/zend_language_scanner.c"
+#line 1271 "Zend/zend_language_scanner.c"
yy15:
YYDEBUG(15, *YYCURSOR);
++YYCURSOR;
@@ -1361,7 +1337,7 @@ yyc_ST_BACKQUOTE:
yy19:
YYDEBUG(19, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2222 "Zend/zend_language_scanner.l"
+#line 2198 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
RETURN_TOKEN(END);
@@ -1402,7 +1378,7 @@ yy19:
zend_scan_escape_string(zendlval, yytext, yyleng, '`');
RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
-#line 1406 "Zend/zend_language_scanner.c"
+#line 1382 "Zend/zend_language_scanner.c"
yy20:
YYDEBUG(20, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1413,12 +1389,12 @@ yy21:
++YYCURSOR;
YYDEBUG(22, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2166 "Zend/zend_language_scanner.l"
+#line 2142 "Zend/zend_language_scanner.l"
{
BEGIN(ST_IN_SCRIPTING);
RETURN_TOKEN('`');
}
-#line 1422 "Zend/zend_language_scanner.c"
+#line 1398 "Zend/zend_language_scanner.c"
yy23:
YYDEBUG(23, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1428,14 +1404,14 @@ yy24:
++YYCURSOR;
YYDEBUG(25, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2153 "Zend/zend_language_scanner.l"
+#line 2129 "Zend/zend_language_scanner.l"
{
Z_LVAL_P(zendlval) = (zend_long) '{';
yy_push_state(ST_IN_SCRIPTING);
yyless(1);
RETURN_TOKEN(T_CURLY_OPEN);
}
-#line 1439 "Zend/zend_language_scanner.c"
+#line 1415 "Zend/zend_language_scanner.c"
yy26:
YYDEBUG(26, *YYCURSOR);
yyaccept = 0;
@@ -1451,23 +1427,23 @@ yy26:
yy28:
YYDEBUG(28, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1877 "Zend/zend_language_scanner.l"
+#line 1853 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
RETURN_TOKEN(T_VARIABLE);
}
-#line 1460 "Zend/zend_language_scanner.c"
+#line 1436 "Zend/zend_language_scanner.c"
yy29:
YYDEBUG(29, *YYCURSOR);
++YYCURSOR;
YYDEBUG(30, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1595 "Zend/zend_language_scanner.l"
+#line 1571 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME);
RETURN_TOKEN(T_DOLLAR_OPEN_CURLY_BRACES);
}
-#line 1471 "Zend/zend_language_scanner.c"
+#line 1447 "Zend/zend_language_scanner.c"
yy31:
YYDEBUG(31, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1481,14 +1457,14 @@ yy33:
++YYCURSOR;
YYDEBUG(34, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1870 "Zend/zend_language_scanner.l"
+#line 1846 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
RETURN_TOKEN(T_VARIABLE);
}
-#line 1492 "Zend/zend_language_scanner.c"
+#line 1468 "Zend/zend_language_scanner.c"
yy35:
YYDEBUG(35, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1506,14 +1482,14 @@ yy36:
++YYCURSOR;
YYDEBUG(37, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1861 "Zend/zend_language_scanner.l"
+#line 1837 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
RETURN_TOKEN(T_VARIABLE);
}
-#line 1517 "Zend/zend_language_scanner.c"
+#line 1493 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_DOUBLE_QUOTES:
@@ -1581,7 +1557,7 @@ yy40:
yy41:
YYDEBUG(41, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2172 "Zend/zend_language_scanner.l"
+#line 2148 "Zend/zend_language_scanner.l"
{
if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) {
YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1;
@@ -1630,7 +1606,7 @@ double_quotes_scan_done:
zend_scan_escape_string(zendlval, yytext, yyleng, '"');
RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
-#line 1634 "Zend/zend_language_scanner.c"
+#line 1610 "Zend/zend_language_scanner.c"
yy42:
YYDEBUG(42, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1641,12 +1617,12 @@ yy43:
++YYCURSOR;
YYDEBUG(44, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2161 "Zend/zend_language_scanner.l"
+#line 2137 "Zend/zend_language_scanner.l"
{
BEGIN(ST_IN_SCRIPTING);
RETURN_TOKEN('"');
}
-#line 1650 "Zend/zend_language_scanner.c"
+#line 1626 "Zend/zend_language_scanner.c"
yy45:
YYDEBUG(45, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1656,14 +1632,14 @@ yy46:
++YYCURSOR;
YYDEBUG(47, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2153 "Zend/zend_language_scanner.l"
+#line 2129 "Zend/zend_language_scanner.l"
{
Z_LVAL_P(zendlval) = (zend_long) '{';
yy_push_state(ST_IN_SCRIPTING);
yyless(1);
RETURN_TOKEN(T_CURLY_OPEN);
}
-#line 1667 "Zend/zend_language_scanner.c"
+#line 1643 "Zend/zend_language_scanner.c"
yy48:
YYDEBUG(48, *YYCURSOR);
yyaccept = 0;
@@ -1679,23 +1655,23 @@ yy48:
yy50:
YYDEBUG(50, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1877 "Zend/zend_language_scanner.l"
+#line 1853 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
RETURN_TOKEN(T_VARIABLE);
}
-#line 1688 "Zend/zend_language_scanner.c"
+#line 1664 "Zend/zend_language_scanner.c"
yy51:
YYDEBUG(51, *YYCURSOR);
++YYCURSOR;
YYDEBUG(52, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1595 "Zend/zend_language_scanner.l"
+#line 1571 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME);
RETURN_TOKEN(T_DOLLAR_OPEN_CURLY_BRACES);
}
-#line 1699 "Zend/zend_language_scanner.c"
+#line 1675 "Zend/zend_language_scanner.c"
yy53:
YYDEBUG(53, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1709,14 +1685,14 @@ yy55:
++YYCURSOR;
YYDEBUG(56, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1870 "Zend/zend_language_scanner.l"
+#line 1846 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
RETURN_TOKEN(T_VARIABLE);
}
-#line 1720 "Zend/zend_language_scanner.c"
+#line 1696 "Zend/zend_language_scanner.c"
yy57:
YYDEBUG(57, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1734,14 +1710,14 @@ yy58:
++YYCURSOR;
YYDEBUG(59, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1861 "Zend/zend_language_scanner.l"
+#line 1837 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
RETURN_TOKEN(T_VARIABLE);
}
-#line 1745 "Zend/zend_language_scanner.c"
+#line 1721 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_END_HEREDOC:
@@ -1752,7 +1728,7 @@ yyc_ST_END_HEREDOC:
++YYCURSOR;
YYDEBUG(63, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2139 "Zend/zend_language_scanner.l"
+#line 2115 "Zend/zend_language_scanner.l"
{
zend_heredoc_label *heredoc_label = zend_ptr_stack_pop(&SCNG(heredoc_label_stack));
@@ -1765,7 +1741,7 @@ yyc_ST_END_HEREDOC:
BEGIN(ST_IN_SCRIPTING);
RETURN_TOKEN(T_END_HEREDOC);
}
-#line 1769 "Zend/zend_language_scanner.c"
+#line 1745 "Zend/zend_language_scanner.c"
/* *********************************** */
yyc_ST_HEREDOC:
{
@@ -1827,7 +1803,7 @@ yy66:
yy67:
YYDEBUG(67, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2264 "Zend/zend_language_scanner.l"
+#line 2240 "Zend/zend_language_scanner.l"
{
int newline = 0;
@@ -1900,7 +1876,7 @@ heredoc_scan_done:
zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0);
RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
-#line 1904 "Zend/zend_language_scanner.c"
+#line 1880 "Zend/zend_language_scanner.c"
yy68:
YYDEBUG(68, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1915,14 +1891,14 @@ yy70:
++YYCURSOR;
YYDEBUG(71, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2153 "Zend/zend_language_scanner.l"
+#line 2129 "Zend/zend_language_scanner.l"
{
Z_LVAL_P(zendlval) = (zend_long) '{';
yy_push_state(ST_IN_SCRIPTING);
yyless(1);
RETURN_TOKEN(T_CURLY_OPEN);
}
-#line 1926 "Zend/zend_language_scanner.c"
+#line 1902 "Zend/zend_language_scanner.c"
yy72:
YYDEBUG(72, *YYCURSOR);
yyaccept = 0;
@@ -1938,23 +1914,23 @@ yy72:
yy74:
YYDEBUG(74, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1877 "Zend/zend_language_scanner.l"
+#line 1853 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
RETURN_TOKEN(T_VARIABLE);
}
-#line 1947 "Zend/zend_language_scanner.c"
+#line 1923 "Zend/zend_language_scanner.c"
yy75:
YYDEBUG(75, *YYCURSOR);
++YYCURSOR;
YYDEBUG(76, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1595 "Zend/zend_language_scanner.l"
+#line 1571 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME);
RETURN_TOKEN(T_DOLLAR_OPEN_CURLY_BRACES);
}
-#line 1958 "Zend/zend_language_scanner.c"
+#line 1934 "Zend/zend_language_scanner.c"
yy77:
YYDEBUG(77, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1968,14 +1944,14 @@ yy79:
++YYCURSOR;
YYDEBUG(80, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1870 "Zend/zend_language_scanner.l"
+#line 1846 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
RETURN_TOKEN(T_VARIABLE);
}
-#line 1979 "Zend/zend_language_scanner.c"
+#line 1955 "Zend/zend_language_scanner.c"
yy81:
YYDEBUG(81, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1993,14 +1969,14 @@ yy82:
++YYCURSOR;
YYDEBUG(83, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1861 "Zend/zend_language_scanner.l"
+#line 1837 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
RETURN_TOKEN(T_VARIABLE);
}
-#line 2004 "Zend/zend_language_scanner.c"
+#line 1980 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_IN_SCRIPTING:
@@ -2183,12 +2159,12 @@ yy86:
yy87:
YYDEBUG(87, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1900 "Zend/zend_language_scanner.l"
+#line 1876 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, yytext, yyleng);
RETURN_TOKEN(T_STRING);
}
-#line 2192 "Zend/zend_language_scanner.c"
+#line 2168 "Zend/zend_language_scanner.c"
yy88:
YYDEBUG(88, *YYCURSOR);
yych = *++YYCURSOR;
@@ -2420,11 +2396,11 @@ yy101:
yy102:
YYDEBUG(102, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1584 "Zend/zend_language_scanner.l"
+#line 1560 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(yytext[0]);
}
-#line 2428 "Zend/zend_language_scanner.c"
+#line 2404 "Zend/zend_language_scanner.c"
yy103:
YYDEBUG(103, *YYCURSOR);
++YYCURSOR;
@@ -2433,12 +2409,12 @@ yy103:
yy104:
YYDEBUG(104, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1299 "Zend/zend_language_scanner.l"
+#line 1275 "Zend/zend_language_scanner.l"
{
HANDLE_NEWLINES(yytext, yyleng);
RETURN_TOKEN(T_WHITESPACE);
}
-#line 2442 "Zend/zend_language_scanner.c"
+#line 2418 "Zend/zend_language_scanner.c"
yy105:
YYDEBUG(105, *YYCURSOR);
yych = *++YYCURSOR;
@@ -2449,11 +2425,11 @@ yy106:
++YYCURSOR;
YYDEBUG(107, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1324 "Zend/zend_language_scanner.l"
+#line 1300 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_NS_SEPARATOR);
}
-#line 2457 "Zend/zend_language_scanner.c"
+#line 2433 "Zend/zend_language_scanner.c"
yy108:
YYDEBUG(108, *YYCURSOR);
yyaccept = 1;
@@ -2682,18 +2658,18 @@ yy131:
++YYCURSOR;
YYDEBUG(132, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1589 "Zend/zend_language_scanner.l"
+#line 1565 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_IN_SCRIPTING);
RETURN_TOKEN('{');
}
-#line 2691 "Zend/zend_language_scanner.c"
+#line 2667 "Zend/zend_language_scanner.c"
yy133:
YYDEBUG(133, *YYCURSOR);
++YYCURSOR;
YYDEBUG(134, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1601 "Zend/zend_language_scanner.l"
+#line 1577 "Zend/zend_language_scanner.l"
{
RESET_DOC_COMMENT();
if (!zend_stack_is_empty(&SCNG(state_stack))) {
@@ -2701,7 +2677,7 @@ yy133:
}
RETURN_TOKEN('}');
}
-#line 2705 "Zend/zend_language_scanner.c"
+#line 2681 "Zend/zend_language_scanner.c"
yy135:
YYDEBUG(135, *YYCURSOR);
yyaccept = 2;
@@ -2729,7 +2705,7 @@ yy135:
yy136:
YYDEBUG(136, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1654 "Zend/zend_language_scanner.l"
+#line 1630 "Zend/zend_language_scanner.l"
{
char *end;
if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
@@ -2774,7 +2750,7 @@ yy136:
ZEND_ASSERT(!errno);
RETURN_TOKEN(T_LNUMBER);
}
-#line 2778 "Zend/zend_language_scanner.c"
+#line 2754 "Zend/zend_language_scanner.c"
yy137:
YYDEBUG(137, *YYCURSOR);
yyaccept = 2;
@@ -2802,7 +2778,7 @@ yy139:
yy140:
YYDEBUG(140, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1906 "Zend/zend_language_scanner.l"
+#line 1882 "Zend/zend_language_scanner.l"
{
while (YYCURSOR < YYLIMIT) {
switch (*YYCURSOR++) {
@@ -2831,14 +2807,14 @@ yy140:
RETURN_TOKEN(T_COMMENT);
}
-#line 2835 "Zend/zend_language_scanner.c"
+#line 2811 "Zend/zend_language_scanner.c"
yy141:
YYDEBUG(141, *YYCURSOR);
++YYCURSOR;
yy142:
YYDEBUG(142, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1974 "Zend/zend_language_scanner.l"
+#line 1950 "Zend/zend_language_scanner.l"
{
register char *s, *t;
char *end;
@@ -2906,14 +2882,14 @@ yy142:
}
RETURN_TOKEN(T_CONSTANT_ENCAPSED_STRING);
}
-#line 2910 "Zend/zend_language_scanner.c"
+#line 2886 "Zend/zend_language_scanner.c"
yy143:
YYDEBUG(143, *YYCURSOR);
++YYCURSOR;
yy144:
YYDEBUG(144, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2043 "Zend/zend_language_scanner.l"
+#line 2019 "Zend/zend_language_scanner.l"
{
int bprefix = (yytext[0] != '"') ? 1 : 0;
@@ -2954,24 +2930,24 @@ yy144:
BEGIN(ST_DOUBLE_QUOTES);
RETURN_TOKEN('"');
}
-#line 2958 "Zend/zend_language_scanner.c"
+#line 2934 "Zend/zend_language_scanner.c"
yy145:
YYDEBUG(145, *YYCURSOR);
++YYCURSOR;
YYDEBUG(146, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2133 "Zend/zend_language_scanner.l"
+#line 2109 "Zend/zend_language_scanner.l"
{
BEGIN(ST_BACKQUOTE);
RETURN_TOKEN('`');
}
-#line 2969 "Zend/zend_language_scanner.c"
+#line 2945 "Zend/zend_language_scanner.c"
yy147:
YYDEBUG(147, *YYCURSOR);
++YYCURSOR;
YYDEBUG(148, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2395 "Zend/zend_language_scanner.l"
+#line 2371 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
RETURN_TOKEN(END);
@@ -2980,7 +2956,7 @@ yy147:
zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
goto restart;
}
-#line 2984 "Zend/zend_language_scanner.c"
+#line 2960 "Zend/zend_language_scanner.c"
yy149:
YYDEBUG(149, *YYCURSOR);
++YYCURSOR;
@@ -3007,7 +2983,7 @@ yy151:
yy153:
YYDEBUG(153, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1748 "Zend/zend_language_scanner.l"
+#line 1724 "Zend/zend_language_scanner.l"
{
const char *end;
@@ -3016,7 +2992,7 @@ yy153:
ZEND_ASSERT(end == yytext + yyleng);
RETURN_TOKEN(T_DNUMBER);
}
-#line 3020 "Zend/zend_language_scanner.c"
+#line 2996 "Zend/zend_language_scanner.c"
yy154:
YYDEBUG(154, *YYCURSOR);
yyaccept = 2;
@@ -3112,7 +3088,7 @@ yy163:
}
YYDEBUG(165, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1626 "Zend/zend_language_scanner.l"
+#line 1602 "Zend/zend_language_scanner.l"
{
char *bin = yytext + 2; /* Skip "0b" */
int len = yyleng - 2;
@@ -3140,7 +3116,7 @@ yy163:
RETURN_TOKEN(T_DNUMBER);
}
}
-#line 3144 "Zend/zend_language_scanner.c"
+#line 3120 "Zend/zend_language_scanner.c"
yy166:
YYDEBUG(166, *YYCURSOR);
++YYCURSOR;
@@ -3152,7 +3128,7 @@ yy166:
}
YYDEBUG(168, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1699 "Zend/zend_language_scanner.l"
+#line 1675 "Zend/zend_language_scanner.l"
{
char *hex = yytext + 2; /* Skip "0x" */
int len = yyleng - 2;
@@ -3180,7 +3156,7 @@ yy166:
RETURN_TOKEN(T_DNUMBER);
}
}
-#line 3184 "Zend/zend_language_scanner.c"
+#line 3160 "Zend/zend_language_scanner.c"
yy169:
YYDEBUG(169, *YYCURSOR);
++YYCURSOR;
@@ -3205,12 +3181,12 @@ yy169:
yy171:
YYDEBUG(171, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1877 "Zend/zend_language_scanner.l"
+#line 1853 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
RETURN_TOKEN(T_VARIABLE);
}
-#line 3214 "Zend/zend_language_scanner.c"
+#line 3190 "Zend/zend_language_scanner.c"
yy172:
YYDEBUG(172, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3224,11 +3200,11 @@ yy173:
}
YYDEBUG(174, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1572 "Zend/zend_language_scanner.l"
+#line 1548 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_LOGICAL_XOR);
}
-#line 3232 "Zend/zend_language_scanner.c"
+#line 3208 "Zend/zend_language_scanner.c"
yy175:
YYDEBUG(175, *YYCURSOR);
++YYCURSOR;
@@ -3237,71 +3213,71 @@ yy175:
}
YYDEBUG(176, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1564 "Zend/zend_language_scanner.l"
+#line 1540 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_LOGICAL_OR);
}
-#line 3245 "Zend/zend_language_scanner.c"
+#line 3221 "Zend/zend_language_scanner.c"
yy177:
YYDEBUG(177, *YYCURSOR);
++YYCURSOR;
YYDEBUG(178, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1552 "Zend/zend_language_scanner.l"
+#line 1528 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_XOR_EQUAL);
}
-#line 3255 "Zend/zend_language_scanner.c"
+#line 3231 "Zend/zend_language_scanner.c"
yy179:
YYDEBUG(179, *YYCURSOR);
++YYCURSOR;
YYDEBUG(180, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1556 "Zend/zend_language_scanner.l"
+#line 1532 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_BOOLEAN_OR);
}
-#line 3265 "Zend/zend_language_scanner.c"
+#line 3241 "Zend/zend_language_scanner.c"
yy181:
YYDEBUG(181, *YYCURSOR);
++YYCURSOR;
YYDEBUG(182, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1548 "Zend/zend_language_scanner.l"
+#line 1524 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_OR_EQUAL);
}
-#line 3275 "Zend/zend_language_scanner.c"
+#line 3251 "Zend/zend_language_scanner.c"
yy183:
YYDEBUG(183, *YYCURSOR);
++YYCURSOR;
YYDEBUG(184, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1560 "Zend/zend_language_scanner.l"
+#line 1536 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_BOOLEAN_AND);
}
-#line 3285 "Zend/zend_language_scanner.c"
+#line 3261 "Zend/zend_language_scanner.c"
yy185:
YYDEBUG(185, *YYCURSOR);
++YYCURSOR;
YYDEBUG(186, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1544 "Zend/zend_language_scanner.l"
+#line 1520 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_AND_EQUAL);
}
-#line 3295 "Zend/zend_language_scanner.c"
+#line 3271 "Zend/zend_language_scanner.c"
yy187:
YYDEBUG(187, *YYCURSOR);
++YYCURSOR;
YYDEBUG(188, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1532 "Zend/zend_language_scanner.l"
+#line 1508 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_MOD_EQUAL);
}
-#line 3305 "Zend/zend_language_scanner.c"
+#line 3281 "Zend/zend_language_scanner.c"
yy189:
YYDEBUG(189, *YYCURSOR);
yyaccept = 4;
@@ -3310,7 +3286,7 @@ yy189:
yy190:
YYDEBUG(190, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1935 "Zend/zend_language_scanner.l"
+#line 1911 "Zend/zend_language_scanner.l"
{
int doc_com;
@@ -3343,7 +3319,7 @@ yy190:
RETURN_TOKEN(T_COMMENT);
}
-#line 3347 "Zend/zend_language_scanner.c"
+#line 3323 "Zend/zend_language_scanner.c"
yy191:
YYDEBUG(191, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3353,11 +3329,11 @@ yy192:
++YYCURSOR;
YYDEBUG(193, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1524 "Zend/zend_language_scanner.l"
+#line 1500 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_DIV_EQUAL);
}
-#line 3361 "Zend/zend_language_scanner.c"
+#line 3337 "Zend/zend_language_scanner.c"
yy194:
YYDEBUG(194, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3381,62 +3357,62 @@ yy197:
if ((yych = *YYCURSOR) == '=') goto yy201;
YYDEBUG(198, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1516 "Zend/zend_language_scanner.l"
+#line 1492 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_POW);
}
-#line 3389 "Zend/zend_language_scanner.c"
+#line 3365 "Zend/zend_language_scanner.c"
yy199:
YYDEBUG(199, *YYCURSOR);
++YYCURSOR;
YYDEBUG(200, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1512 "Zend/zend_language_scanner.l"
+#line 1488 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_MUL_EQUAL);
}
-#line 3399 "Zend/zend_language_scanner.c"
+#line 3375 "Zend/zend_language_scanner.c"
yy201:
YYDEBUG(201, *YYCURSOR);
++YYCURSOR;
YYDEBUG(202, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1520 "Zend/zend_language_scanner.l"
+#line 1496 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_POW_EQUAL);
}
-#line 3409 "Zend/zend_language_scanner.c"
+#line 3385 "Zend/zend_language_scanner.c"
yy203:
YYDEBUG(203, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) == '=') goto yy207;
YYDEBUG(204, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1580 "Zend/zend_language_scanner.l"
+#line 1556 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_SR);
}
-#line 3420 "Zend/zend_language_scanner.c"
+#line 3396 "Zend/zend_language_scanner.c"
yy205:
YYDEBUG(205, *YYCURSOR);
++YYCURSOR;
YYDEBUG(206, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1500 "Zend/zend_language_scanner.l"
+#line 1476 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_IS_GREATER_OR_EQUAL);
}
-#line 3430 "Zend/zend_language_scanner.c"
+#line 3406 "Zend/zend_language_scanner.c"
yy207:
YYDEBUG(207, *YYCURSOR);
++YYCURSOR;
YYDEBUG(208, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1540 "Zend/zend_language_scanner.l"
+#line 1516 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_SR_EQUAL);
}
-#line 3440 "Zend/zend_language_scanner.c"
+#line 3416 "Zend/zend_language_scanner.c"
yy209:
YYDEBUG(209, *YYCURSOR);
yyaccept = 5;
@@ -3447,53 +3423,53 @@ yy209:
yy210:
YYDEBUG(210, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1576 "Zend/zend_language_scanner.l"
+#line 1552 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_SL);
}
-#line 3455 "Zend/zend_language_scanner.c"
+#line 3431 "Zend/zend_language_scanner.c"
yy211:
YYDEBUG(211, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) == '>') goto yy215;
YYDEBUG(212, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1496 "Zend/zend_language_scanner.l"
+#line 1472 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_IS_SMALLER_OR_EQUAL);
}
-#line 3466 "Zend/zend_language_scanner.c"
+#line 3442 "Zend/zend_language_scanner.c"
yy213:
YYDEBUG(213, *YYCURSOR);
++YYCURSOR;
yy214:
YYDEBUG(214, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1488 "Zend/zend_language_scanner.l"
+#line 1464 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_IS_NOT_EQUAL);
}
-#line 3477 "Zend/zend_language_scanner.c"
+#line 3453 "Zend/zend_language_scanner.c"
yy215:
YYDEBUG(215, *YYCURSOR);
++YYCURSOR;
YYDEBUG(216, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1492 "Zend/zend_language_scanner.l"
+#line 1468 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_SPACESHIP);
}
-#line 3487 "Zend/zend_language_scanner.c"
+#line 3463 "Zend/zend_language_scanner.c"
yy217:
YYDEBUG(217, *YYCURSOR);
++YYCURSOR;
YYDEBUG(218, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1536 "Zend/zend_language_scanner.l"
+#line 1512 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_SL_EQUAL);
}
-#line 3497 "Zend/zend_language_scanner.c"
+#line 3473 "Zend/zend_language_scanner.c"
yy219:
YYDEBUG(219, *YYCURSOR);
++YYCURSOR;
@@ -3598,7 +3574,7 @@ yy228:
yy229:
YYDEBUG(229, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2085 "Zend/zend_language_scanner.l"
+#line 2061 "Zend/zend_language_scanner.l"
{
char *s;
int bprefix = (yytext[0] != '<') ? 1 : 0;
@@ -3645,7 +3621,7 @@ yy229:
RETURN_TOKEN(T_START_HEREDOC);
}
-#line 3649 "Zend/zend_language_scanner.c"
+#line 3625 "Zend/zend_language_scanner.c"
yy230:
YYDEBUG(230, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3685,31 +3661,31 @@ yy233:
++YYCURSOR;
YYDEBUG(235, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1480 "Zend/zend_language_scanner.l"
+#line 1456 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_IS_NOT_IDENTICAL);
}
-#line 3693 "Zend/zend_language_scanner.c"
+#line 3669 "Zend/zend_language_scanner.c"
yy236:
YYDEBUG(236, *YYCURSOR);
++YYCURSOR;
YYDEBUG(237, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1504 "Zend/zend_language_scanner.l"
+#line 1480 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_PLUS_EQUAL);
}
-#line 3703 "Zend/zend_language_scanner.c"
+#line 3679 "Zend/zend_language_scanner.c"
yy238:
YYDEBUG(238, *YYCURSOR);
++YYCURSOR;
YYDEBUG(239, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1468 "Zend/zend_language_scanner.l"
+#line 1444 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_INC);
}
-#line 3713 "Zend/zend_language_scanner.c"
+#line 3689 "Zend/zend_language_scanner.c"
yy240:
YYDEBUG(240, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3728,42 +3704,42 @@ yy242:
}
YYDEBUG(243, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1456 "Zend/zend_language_scanner.l"
+#line 1432 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_LIST);
}
-#line 3736 "Zend/zend_language_scanner.c"
+#line 3712 "Zend/zend_language_scanner.c"
yy244:
YYDEBUG(244, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) == '=') goto yy248;
YYDEBUG(245, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1484 "Zend/zend_language_scanner.l"
+#line 1460 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_IS_EQUAL);
}
-#line 3747 "Zend/zend_language_scanner.c"
+#line 3723 "Zend/zend_language_scanner.c"
yy246:
YYDEBUG(246, *YYCURSOR);
++YYCURSOR;
YYDEBUG(247, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1452 "Zend/zend_language_scanner.l"
+#line 1428 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_DOUBLE_ARROW);
}
-#line 3757 "Zend/zend_language_scanner.c"
+#line 3733 "Zend/zend_language_scanner.c"
yy248:
YYDEBUG(248, *YYCURSOR);
++YYCURSOR;
YYDEBUG(249, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1476 "Zend/zend_language_scanner.l"
+#line 1452 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_IS_IDENTICAL);
}
-#line 3767 "Zend/zend_language_scanner.c"
+#line 3743 "Zend/zend_language_scanner.c"
yy250:
YYDEBUG(250, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3893,11 +3869,11 @@ yy266:
}
YYDEBUG(269, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1785 "Zend/zend_language_scanner.l"
+#line 1761 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_NS_C);
}
-#line 3901 "Zend/zend_language_scanner.c"
+#line 3877 "Zend/zend_language_scanner.c"
yy270:
YYDEBUG(270, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3917,11 +3893,11 @@ yy271:
}
YYDEBUG(274, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1781 "Zend/zend_language_scanner.l"
+#line 1757 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_DIR);
}
-#line 3925 "Zend/zend_language_scanner.c"
+#line 3901 "Zend/zend_language_scanner.c"
yy275:
YYDEBUG(275, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3946,11 +3922,11 @@ yy277:
}
YYDEBUG(280, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1773 "Zend/zend_language_scanner.l"
+#line 1749 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_LINE);
}
-#line 3954 "Zend/zend_language_scanner.c"
+#line 3930 "Zend/zend_language_scanner.c"
yy281:
YYDEBUG(281, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3985,11 +3961,11 @@ yy285:
}
YYDEBUG(288, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1769 "Zend/zend_language_scanner.l"
+#line 1745 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_METHOD_C);
}
-#line 3993 "Zend/zend_language_scanner.c"
+#line 3969 "Zend/zend_language_scanner.c"
yy289:
YYDEBUG(289, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4040,11 +4016,11 @@ yy296:
}
YYDEBUG(299, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1765 "Zend/zend_language_scanner.l"
+#line 1741 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_FUNC_C);
}
-#line 4048 "Zend/zend_language_scanner.c"
+#line 4024 "Zend/zend_language_scanner.c"
yy300:
YYDEBUG(300, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4064,11 +4040,11 @@ yy301:
}
YYDEBUG(304, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1777 "Zend/zend_language_scanner.l"
+#line 1753 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_FILE);
}
-#line 4072 "Zend/zend_language_scanner.c"
+#line 4048 "Zend/zend_language_scanner.c"
yy305:
YYDEBUG(305, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4098,11 +4074,11 @@ yy308:
}
YYDEBUG(311, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1761 "Zend/zend_language_scanner.l"
+#line 1737 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_TRAIT_C);
}
-#line 4106 "Zend/zend_language_scanner.c"
+#line 4082 "Zend/zend_language_scanner.c"
yy312:
YYDEBUG(312, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4132,11 +4108,11 @@ yy315:
}
YYDEBUG(318, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1757 "Zend/zend_language_scanner.l"
+#line 1733 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_CLASS_C);
}
-#line 4140 "Zend/zend_language_scanner.c"
+#line 4116 "Zend/zend_language_scanner.c"
yy319:
YYDEBUG(319, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4198,11 +4174,11 @@ yy330:
}
YYDEBUG(331, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1420 "Zend/zend_language_scanner.l"
+#line 1396 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_HALT_COMPILER);
}
-#line 4206 "Zend/zend_language_scanner.c"
+#line 4182 "Zend/zend_language_scanner.c"
yy332:
YYDEBUG(332, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4222,11 +4198,11 @@ yy334:
}
YYDEBUG(335, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1400 "Zend/zend_language_scanner.l"
+#line 1376 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_USE);
}
-#line 4230 "Zend/zend_language_scanner.c"
+#line 4206 "Zend/zend_language_scanner.c"
yy336:
YYDEBUG(336, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4245,11 +4221,11 @@ yy338:
}
YYDEBUG(339, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1448 "Zend/zend_language_scanner.l"
+#line 1424 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_UNSET);
}
-#line 4253 "Zend/zend_language_scanner.c"
+#line 4229 "Zend/zend_language_scanner.c"
yy340:
YYDEBUG(340, *YYCURSOR);
++YYCURSOR;
@@ -4421,11 +4397,11 @@ yy355:
++YYCURSOR;
YYDEBUG(357, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1348 "Zend/zend_language_scanner.l"
+#line 1324 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_INT_CAST);
}
-#line 4429 "Zend/zend_language_scanner.c"
+#line 4405 "Zend/zend_language_scanner.c"
yy358:
YYDEBUG(358, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4469,11 +4445,11 @@ yy363:
++YYCURSOR;
YYDEBUG(366, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1352 "Zend/zend_language_scanner.l"
+#line 1328 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_DOUBLE_CAST);
}
-#line 4477 "Zend/zend_language_scanner.c"
+#line 4453 "Zend/zend_language_scanner.c"
yy367:
YYDEBUG(367, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4543,11 +4519,11 @@ yy377:
++YYCURSOR;
YYDEBUG(380, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1356 "Zend/zend_language_scanner.l"
+#line 1332 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_STRING_CAST);
}
-#line 4551 "Zend/zend_language_scanner.c"
+#line 4527 "Zend/zend_language_scanner.c"
yy381:
YYDEBUG(381, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4580,11 +4556,11 @@ yy384:
++YYCURSOR;
YYDEBUG(387, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1360 "Zend/zend_language_scanner.l"
+#line 1336 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ARRAY_CAST);
}
-#line 4588 "Zend/zend_language_scanner.c"
+#line 4564 "Zend/zend_language_scanner.c"
yy388:
YYDEBUG(388, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4622,11 +4598,11 @@ yy392:
++YYCURSOR;
YYDEBUG(395, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1364 "Zend/zend_language_scanner.l"
+#line 1340 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_OBJECT_CAST);
}
-#line 4630 "Zend/zend_language_scanner.c"
+#line 4606 "Zend/zend_language_scanner.c"
yy396:
YYDEBUG(396, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4667,11 +4643,11 @@ yy401:
++YYCURSOR;
YYDEBUG(403, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1368 "Zend/zend_language_scanner.l"
+#line 1344 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_BOOL_CAST);
}
-#line 4675 "Zend/zend_language_scanner.c"
+#line 4651 "Zend/zend_language_scanner.c"
yy404:
YYDEBUG(404, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4731,11 +4707,11 @@ yy412:
++YYCURSOR;
YYDEBUG(415, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1372 "Zend/zend_language_scanner.l"
+#line 1348 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_UNSET_CAST);
}
-#line 4739 "Zend/zend_language_scanner.c"
+#line 4715 "Zend/zend_language_scanner.c"
yy416:
YYDEBUG(416, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4749,11 +4725,11 @@ yy417:
}
YYDEBUG(418, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1344 "Zend/zend_language_scanner.l"
+#line 1320 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_VAR);
}
-#line 4757 "Zend/zend_language_scanner.c"
+#line 4733 "Zend/zend_language_scanner.c"
yy419:
YYDEBUG(419, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4773,11 +4749,11 @@ yy421:
}
YYDEBUG(422, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1336 "Zend/zend_language_scanner.l"
+#line 1312 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_NEW);
}
-#line 4781 "Zend/zend_language_scanner.c"
+#line 4757 "Zend/zend_language_scanner.c"
yy423:
YYDEBUG(423, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4816,11 +4792,11 @@ yy429:
}
YYDEBUG(430, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1396 "Zend/zend_language_scanner.l"
+#line 1372 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_NAMESPACE);
}
-#line 4824 "Zend/zend_language_scanner.c"
+#line 4800 "Zend/zend_language_scanner.c"
yy431:
YYDEBUG(431, *YYCURSOR);
++YYCURSOR;
@@ -4829,22 +4805,22 @@ yy431:
yy432:
YYDEBUG(432, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1968 "Zend/zend_language_scanner.l"
+#line 1944 "Zend/zend_language_scanner.l"
{
BEGIN(INITIAL);
RETURN_TOKEN(T_CLOSE_TAG); /* implicit ';' at php-end tag */
}
-#line 4838 "Zend/zend_language_scanner.c"
+#line 4814 "Zend/zend_language_scanner.c"
yy433:
YYDEBUG(433, *YYCURSOR);
++YYCURSOR;
YYDEBUG(434, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1332 "Zend/zend_language_scanner.l"
+#line 1308 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_COALESCE);
}
-#line 4848 "Zend/zend_language_scanner.c"
+#line 4824 "Zend/zend_language_scanner.c"
yy435:
YYDEBUG(435, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4875,11 +4851,11 @@ yy439:
++YYCURSOR;
YYDEBUG(440, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1528 "Zend/zend_language_scanner.l"
+#line 1504 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_CONCAT_EQUAL);
}
-#line 4883 "Zend/zend_language_scanner.c"
+#line 4859 "Zend/zend_language_scanner.c"
yy441:
YYDEBUG(441, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4888,21 +4864,21 @@ yy441:
++YYCURSOR;
YYDEBUG(443, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1328 "Zend/zend_language_scanner.l"
+#line 1304 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ELLIPSIS);
}
-#line 4896 "Zend/zend_language_scanner.c"
+#line 4872 "Zend/zend_language_scanner.c"
yy444:
YYDEBUG(444, *YYCURSOR);
++YYCURSOR;
YYDEBUG(445, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1320 "Zend/zend_language_scanner.l"
+#line 1296 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_PAAMAYIM_NEKUDOTAYIM);
}
-#line 4906 "Zend/zend_language_scanner.c"
+#line 4882 "Zend/zend_language_scanner.c"
yy446:
YYDEBUG(446, *YYCURSOR);
++YYCURSOR;
@@ -4924,32 +4900,32 @@ yy448:
++YYCURSOR;
YYDEBUG(449, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1508 "Zend/zend_language_scanner.l"
+#line 1484 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_MINUS_EQUAL);
}
-#line 4932 "Zend/zend_language_scanner.c"
+#line 4908 "Zend/zend_language_scanner.c"
yy450:
YYDEBUG(450, *YYCURSOR);
++YYCURSOR;
YYDEBUG(451, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1472 "Zend/zend_language_scanner.l"
+#line 1448 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_DEC);
}
-#line 4942 "Zend/zend_language_scanner.c"
+#line 4918 "Zend/zend_language_scanner.c"
yy452:
YYDEBUG(452, *YYCURSOR);
++YYCURSOR;
YYDEBUG(453, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1294 "Zend/zend_language_scanner.l"
+#line 1270 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_PROPERTY);
RETURN_TOKEN(T_OBJECT_OPERATOR);
}
-#line 4953 "Zend/zend_language_scanner.c"
+#line 4929 "Zend/zend_language_scanner.c"
yy454:
YYDEBUG(454, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4994,11 +4970,11 @@ yy459:
}
YYDEBUG(460, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1444 "Zend/zend_language_scanner.l"
+#line 1420 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_PUBLIC);
}
-#line 5002 "Zend/zend_language_scanner.c"
+#line 4978 "Zend/zend_language_scanner.c"
yy461:
YYDEBUG(461, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5053,11 +5029,11 @@ yy468:
}
YYDEBUG(469, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1440 "Zend/zend_language_scanner.l"
+#line 1416 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_PROTECTED);
}
-#line 5061 "Zend/zend_language_scanner.c"
+#line 5037 "Zend/zend_language_scanner.c"
yy470:
YYDEBUG(470, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5087,11 +5063,11 @@ yy474:
}
YYDEBUG(475, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1436 "Zend/zend_language_scanner.l"
+#line 1412 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_PRIVATE);
}
-#line 5095 "Zend/zend_language_scanner.c"
+#line 5071 "Zend/zend_language_scanner.c"
yy476:
YYDEBUG(476, *YYCURSOR);
++YYCURSOR;
@@ -5100,11 +5076,11 @@ yy476:
}
YYDEBUG(477, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1270 "Zend/zend_language_scanner.l"
+#line 1246 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_PRINT);
}
-#line 5108 "Zend/zend_language_scanner.c"
+#line 5084 "Zend/zend_language_scanner.c"
yy478:
YYDEBUG(478, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5129,11 +5105,11 @@ yy481:
}
YYDEBUG(482, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1262 "Zend/zend_language_scanner.l"
+#line 1238 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_GOTO);
}
-#line 5137 "Zend/zend_language_scanner.c"
+#line 5113 "Zend/zend_language_scanner.c"
yy483:
YYDEBUG(483, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5157,11 +5133,11 @@ yy486:
}
YYDEBUG(487, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1408 "Zend/zend_language_scanner.l"
+#line 1384 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_GLOBAL);
}
-#line 5165 "Zend/zend_language_scanner.c"
+#line 5141 "Zend/zend_language_scanner.c"
yy488:
YYDEBUG(488, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5198,11 +5174,11 @@ yy494:
}
YYDEBUG(495, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1254 "Zend/zend_language_scanner.l"
+#line 1230 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_BREAK);
}
-#line 5206 "Zend/zend_language_scanner.c"
+#line 5182 "Zend/zend_language_scanner.c"
yy496:
YYDEBUG(496, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5242,11 +5218,11 @@ yy502:
}
YYDEBUG(503, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1238 "Zend/zend_language_scanner.l"
+#line 1214 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_SWITCH);
}
-#line 5250 "Zend/zend_language_scanner.c"
+#line 5226 "Zend/zend_language_scanner.c"
yy504:
YYDEBUG(504, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5270,11 +5246,11 @@ yy507:
}
YYDEBUG(508, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1424 "Zend/zend_language_scanner.l"
+#line 1400 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_STATIC);
}
-#line 5278 "Zend/zend_language_scanner.c"
+#line 5254 "Zend/zend_language_scanner.c"
yy509:
YYDEBUG(509, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5301,11 +5277,11 @@ yy512:
}
YYDEBUG(513, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1234 "Zend/zend_language_scanner.l"
+#line 1210 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_AS);
}
-#line 5309 "Zend/zend_language_scanner.c"
+#line 5285 "Zend/zend_language_scanner.c"
yy514:
YYDEBUG(514, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5324,11 +5300,11 @@ yy516:
}
YYDEBUG(517, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1460 "Zend/zend_language_scanner.l"
+#line 1436 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ARRAY);
}
-#line 5332 "Zend/zend_language_scanner.c"
+#line 5308 "Zend/zend_language_scanner.c"
yy518:
YYDEBUG(518, *YYCURSOR);
++YYCURSOR;
@@ -5337,11 +5313,11 @@ yy518:
}
YYDEBUG(519, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1568 "Zend/zend_language_scanner.l"
+#line 1544 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_LOGICAL_AND);
}
-#line 5345 "Zend/zend_language_scanner.c"
+#line 5321 "Zend/zend_language_scanner.c"
yy520:
YYDEBUG(520, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5375,11 +5351,11 @@ yy525:
}
YYDEBUG(526, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1428 "Zend/zend_language_scanner.l"
+#line 1404 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ABSTRACT);
}
-#line 5383 "Zend/zend_language_scanner.c"
+#line 5359 "Zend/zend_language_scanner.c"
yy527:
YYDEBUG(527, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5403,11 +5379,11 @@ yy530:
}
YYDEBUG(531, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1194 "Zend/zend_language_scanner.l"
+#line 1170 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_WHILE);
}
-#line 5411 "Zend/zend_language_scanner.c"
+#line 5387 "Zend/zend_language_scanner.c"
yy532:
YYDEBUG(532, *YYCURSOR);
++YYCURSOR;
@@ -5416,11 +5392,11 @@ yy532:
}
YYDEBUG(533, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1178 "Zend/zend_language_scanner.l"
+#line 1154 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_IF);
}
-#line 5424 "Zend/zend_language_scanner.c"
+#line 5400 "Zend/zend_language_scanner.c"
yy534:
YYDEBUG(534, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5472,11 +5448,11 @@ yy539:
}
YYDEBUG(540, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1412 "Zend/zend_language_scanner.l"
+#line 1388 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ISSET);
}
-#line 5480 "Zend/zend_language_scanner.c"
+#line 5456 "Zend/zend_language_scanner.c"
yy541:
YYDEBUG(541, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5530,11 +5506,11 @@ yy547:
yy548:
YYDEBUG(548, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1380 "Zend/zend_language_scanner.l"
+#line 1356 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_INCLUDE);
}
-#line 5538 "Zend/zend_language_scanner.c"
+#line 5514 "Zend/zend_language_scanner.c"
yy549:
YYDEBUG(549, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5563,11 +5539,11 @@ yy553:
}
YYDEBUG(554, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1384 "Zend/zend_language_scanner.l"
+#line 1360 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_INCLUDE_ONCE);
}
-#line 5571 "Zend/zend_language_scanner.c"
+#line 5547 "Zend/zend_language_scanner.c"
yy555:
YYDEBUG(555, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5601,11 +5577,11 @@ yy560:
}
YYDEBUG(561, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1278 "Zend/zend_language_scanner.l"
+#line 1254 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_INTERFACE);
}
-#line 5609 "Zend/zend_language_scanner.c"
+#line 5585 "Zend/zend_language_scanner.c"
yy562:
YYDEBUG(562, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5655,11 +5631,11 @@ yy568:
}
YYDEBUG(569, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1404 "Zend/zend_language_scanner.l"
+#line 1380 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_INSTEADOF);
}
-#line 5663 "Zend/zend_language_scanner.c"
+#line 5639 "Zend/zend_language_scanner.c"
yy570:
YYDEBUG(570, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5688,11 +5664,11 @@ yy574:
}
YYDEBUG(575, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1230 "Zend/zend_language_scanner.l"
+#line 1206 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_INSTANCEOF);
}
-#line 5696 "Zend/zend_language_scanner.c"
+#line 5672 "Zend/zend_language_scanner.c"
yy576:
YYDEBUG(576, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5736,11 +5712,11 @@ yy583:
}
YYDEBUG(584, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1290 "Zend/zend_language_scanner.l"
+#line 1266 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_IMPLEMENTS);
}
-#line 5744 "Zend/zend_language_scanner.c"
+#line 5720 "Zend/zend_language_scanner.c"
yy585:
YYDEBUG(585, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5768,11 +5744,11 @@ yy586:
}
YYDEBUG(588, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1162 "Zend/zend_language_scanner.l"
+#line 1138 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_TRY);
}
-#line 5776 "Zend/zend_language_scanner.c"
+#line 5752 "Zend/zend_language_scanner.c"
yy589:
YYDEBUG(589, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5791,11 +5767,11 @@ yy591:
}
YYDEBUG(592, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1282 "Zend/zend_language_scanner.l"
+#line 1258 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_TRAIT);
}
-#line 5799 "Zend/zend_language_scanner.c"
+#line 5775 "Zend/zend_language_scanner.c"
yy593:
YYDEBUG(593, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5814,11 +5790,11 @@ yy595:
}
YYDEBUG(596, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1174 "Zend/zend_language_scanner.l"
+#line 1150 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_THROW);
}
-#line 5822 "Zend/zend_language_scanner.c"
+#line 5798 "Zend/zend_language_scanner.c"
yy597:
YYDEBUG(597, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5851,11 +5827,11 @@ yy600:
yy601:
YYDEBUG(601, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1158 "Zend/zend_language_scanner.l"
+#line 1134 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_YIELD);
}
-#line 5859 "Zend/zend_language_scanner.c"
+#line 5835 "Zend/zend_language_scanner.c"
yy602:
YYDEBUG(602, *YYCURSOR);
++YYCURSOR;
@@ -5897,11 +5873,11 @@ yy607:
++YYCURSOR;
YYDEBUG(608, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1154 "Zend/zend_language_scanner.l"
+#line 1130 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_YIELD_FROM);
}
-#line 5905 "Zend/zend_language_scanner.c"
+#line 5881 "Zend/zend_language_scanner.c"
yy609:
YYDEBUG(609, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5962,11 +5938,11 @@ yy615:
yy616:
YYDEBUG(616, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1388 "Zend/zend_language_scanner.l"
+#line 1364 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_REQUIRE);
}
-#line 5970 "Zend/zend_language_scanner.c"
+#line 5946 "Zend/zend_language_scanner.c"
yy617:
YYDEBUG(617, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5995,11 +5971,11 @@ yy621:
}
YYDEBUG(622, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1392 "Zend/zend_language_scanner.l"
+#line 1368 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_REQUIRE_ONCE);
}
-#line 6003 "Zend/zend_language_scanner.c"
+#line 5979 "Zend/zend_language_scanner.c"
yy623:
YYDEBUG(623, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6018,11 +5994,11 @@ yy625:
}
YYDEBUG(626, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1150 "Zend/zend_language_scanner.l"
+#line 1126 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_RETURN);
}
-#line 6026 "Zend/zend_language_scanner.c"
+#line 6002 "Zend/zend_language_scanner.c"
yy627:
YYDEBUG(627, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6112,11 +6088,11 @@ yy636:
}
YYDEBUG(637, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1258 "Zend/zend_language_scanner.l"
+#line 1234 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_CONTINUE);
}
-#line 6120 "Zend/zend_language_scanner.c"
+#line 6096 "Zend/zend_language_scanner.c"
yy638:
YYDEBUG(638, *YYCURSOR);
++YYCURSOR;
@@ -6125,11 +6101,11 @@ yy638:
}
YYDEBUG(639, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1146 "Zend/zend_language_scanner.l"
+#line 1122 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_CONST);
}
-#line 6133 "Zend/zend_language_scanner.c"
+#line 6109 "Zend/zend_language_scanner.c"
yy640:
YYDEBUG(640, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6154,11 +6130,11 @@ yy643:
}
YYDEBUG(644, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1340 "Zend/zend_language_scanner.l"
+#line 1316 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_CLONE);
}
-#line 6162 "Zend/zend_language_scanner.c"
+#line 6138 "Zend/zend_language_scanner.c"
yy645:
YYDEBUG(645, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6172,11 +6148,11 @@ yy646:
}
YYDEBUG(647, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1274 "Zend/zend_language_scanner.l"
+#line 1250 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_CLASS);
}
-#line 6180 "Zend/zend_language_scanner.c"
+#line 6156 "Zend/zend_language_scanner.c"
yy648:
YYDEBUG(648, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6222,11 +6198,11 @@ yy655:
}
YYDEBUG(656, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1464 "Zend/zend_language_scanner.l"
+#line 1440 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_CALLABLE);
}
-#line 6230 "Zend/zend_language_scanner.c"
+#line 6206 "Zend/zend_language_scanner.c"
yy657:
YYDEBUG(657, *YYCURSOR);
++YYCURSOR;
@@ -6235,11 +6211,11 @@ yy657:
}
YYDEBUG(658, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1246 "Zend/zend_language_scanner.l"
+#line 1222 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_CASE);
}
-#line 6243 "Zend/zend_language_scanner.c"
+#line 6219 "Zend/zend_language_scanner.c"
yy659:
YYDEBUG(659, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6253,11 +6229,11 @@ yy660:
}
YYDEBUG(661, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1166 "Zend/zend_language_scanner.l"
+#line 1142 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_CATCH);
}
-#line 6261 "Zend/zend_language_scanner.c"
+#line 6237 "Zend/zend_language_scanner.c"
yy662:
YYDEBUG(662, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6308,11 +6284,11 @@ yy670:
}
YYDEBUG(671, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1142 "Zend/zend_language_scanner.l"
+#line 1118 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_FUNCTION);
}
-#line 6316 "Zend/zend_language_scanner.c"
+#line 6292 "Zend/zend_language_scanner.c"
yy672:
YYDEBUG(672, *YYCURSOR);
++YYCURSOR;
@@ -6336,11 +6312,11 @@ yy672:
yy673:
YYDEBUG(673, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1206 "Zend/zend_language_scanner.l"
+#line 1182 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_FOR);
}
-#line 6344 "Zend/zend_language_scanner.c"
+#line 6320 "Zend/zend_language_scanner.c"
yy674:
YYDEBUG(674, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6364,11 +6340,11 @@ yy677:
}
YYDEBUG(678, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1214 "Zend/zend_language_scanner.l"
+#line 1190 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_FOREACH);
}
-#line 6372 "Zend/zend_language_scanner.c"
+#line 6348 "Zend/zend_language_scanner.c"
yy679:
YYDEBUG(679, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6402,11 +6378,11 @@ yy681:
yy682:
YYDEBUG(682, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1432 "Zend/zend_language_scanner.l"
+#line 1408 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_FINAL);
}
-#line 6410 "Zend/zend_language_scanner.c"
+#line 6386 "Zend/zend_language_scanner.c"
yy683:
YYDEBUG(683, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6420,11 +6396,11 @@ yy684:
}
YYDEBUG(685, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1170 "Zend/zend_language_scanner.l"
+#line 1146 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_FINALLY);
}
-#line 6428 "Zend/zend_language_scanner.c"
+#line 6404 "Zend/zend_language_scanner.c"
yy686:
YYDEBUG(686, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6455,11 +6431,11 @@ yy688:
}
YYDEBUG(689, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1202 "Zend/zend_language_scanner.l"
+#line 1178 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_DO);
}
-#line 6463 "Zend/zend_language_scanner.c"
+#line 6439 "Zend/zend_language_scanner.c"
yy690:
YYDEBUG(690, *YYCURSOR);
++YYCURSOR;
@@ -6468,11 +6444,11 @@ yy690:
}
YYDEBUG(691, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1138 "Zend/zend_language_scanner.l"
+#line 1114 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_EXIT);
}
-#line 6476 "Zend/zend_language_scanner.c"
+#line 6452 "Zend/zend_language_scanner.c"
yy692:
YYDEBUG(692, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6507,11 +6483,11 @@ yy697:
}
YYDEBUG(698, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1250 "Zend/zend_language_scanner.l"
+#line 1226 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_DEFAULT);
}
-#line 6515 "Zend/zend_language_scanner.c"
+#line 6491 "Zend/zend_language_scanner.c"
yy699:
YYDEBUG(699, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6535,11 +6511,11 @@ yy702:
}
YYDEBUG(703, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1222 "Zend/zend_language_scanner.l"
+#line 1198 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_DECLARE);
}
-#line 6543 "Zend/zend_language_scanner.c"
+#line 6519 "Zend/zend_language_scanner.c"
yy704:
YYDEBUG(704, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6619,11 +6595,11 @@ yy715:
}
YYDEBUG(716, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1286 "Zend/zend_language_scanner.l"
+#line 1262 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_EXTENDS);
}
-#line 6627 "Zend/zend_language_scanner.c"
+#line 6603 "Zend/zend_language_scanner.c"
yy717:
YYDEBUG(717, *YYCURSOR);
++YYCURSOR;
@@ -6632,11 +6608,11 @@ yy717:
}
YYDEBUG(718, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1134 "Zend/zend_language_scanner.l"
+#line 1110 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_EXIT);
}
-#line 6640 "Zend/zend_language_scanner.c"
+#line 6616 "Zend/zend_language_scanner.c"
yy719:
YYDEBUG(719, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6650,11 +6626,11 @@ yy720:
}
YYDEBUG(721, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1376 "Zend/zend_language_scanner.l"
+#line 1352 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_EVAL);
}
-#line 6658 "Zend/zend_language_scanner.c"
+#line 6634 "Zend/zend_language_scanner.c"
yy722:
YYDEBUG(722, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6724,11 +6700,11 @@ yy731:
}
YYDEBUG(732, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1198 "Zend/zend_language_scanner.l"
+#line 1174 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ENDWHILE);
}
-#line 6732 "Zend/zend_language_scanner.c"
+#line 6708 "Zend/zend_language_scanner.c"
yy733:
YYDEBUG(733, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6757,11 +6733,11 @@ yy737:
}
YYDEBUG(738, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1242 "Zend/zend_language_scanner.l"
+#line 1218 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ENDSWITCH);
}
-#line 6765 "Zend/zend_language_scanner.c"
+#line 6741 "Zend/zend_language_scanner.c"
yy739:
YYDEBUG(739, *YYCURSOR);
++YYCURSOR;
@@ -6770,11 +6746,11 @@ yy739:
}
YYDEBUG(740, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1186 "Zend/zend_language_scanner.l"
+#line 1162 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ENDIF);
}
-#line 6778 "Zend/zend_language_scanner.c"
+#line 6754 "Zend/zend_language_scanner.c"
yy741:
YYDEBUG(741, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6803,11 +6779,11 @@ yy742:
yy743:
YYDEBUG(743, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1210 "Zend/zend_language_scanner.l"
+#line 1186 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ENDFOR);
}
-#line 6811 "Zend/zend_language_scanner.c"
+#line 6787 "Zend/zend_language_scanner.c"
yy744:
YYDEBUG(744, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6831,11 +6807,11 @@ yy747:
}
YYDEBUG(748, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1218 "Zend/zend_language_scanner.l"
+#line 1194 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ENDFOREACH);
}
-#line 6839 "Zend/zend_language_scanner.c"
+#line 6815 "Zend/zend_language_scanner.c"
yy749:
YYDEBUG(749, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6869,11 +6845,11 @@ yy754:
}
YYDEBUG(755, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1226 "Zend/zend_language_scanner.l"
+#line 1202 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ENDDECLARE);
}
-#line 6877 "Zend/zend_language_scanner.c"
+#line 6853 "Zend/zend_language_scanner.c"
yy756:
YYDEBUG(756, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6892,11 +6868,11 @@ yy758:
}
YYDEBUG(759, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1416 "Zend/zend_language_scanner.l"
+#line 1392 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_EMPTY);
}
-#line 6900 "Zend/zend_language_scanner.c"
+#line 6876 "Zend/zend_language_scanner.c"
yy760:
YYDEBUG(760, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6925,11 +6901,11 @@ yy761:
yy762:
YYDEBUG(762, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1190 "Zend/zend_language_scanner.l"
+#line 1166 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ELSE);
}
-#line 6933 "Zend/zend_language_scanner.c"
+#line 6909 "Zend/zend_language_scanner.c"
yy763:
YYDEBUG(763, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6943,11 +6919,11 @@ yy764:
}
YYDEBUG(765, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1182 "Zend/zend_language_scanner.l"
+#line 1158 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ELSEIF);
}
-#line 6951 "Zend/zend_language_scanner.c"
+#line 6927 "Zend/zend_language_scanner.c"
yy766:
YYDEBUG(766, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6961,11 +6937,11 @@ yy767:
}
YYDEBUG(768, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1266 "Zend/zend_language_scanner.l"
+#line 1242 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_ECHO);
}
-#line 6969 "Zend/zend_language_scanner.c"
+#line 6945 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_LOOKING_FOR_PROPERTY:
@@ -7038,12 +7014,12 @@ yy771:
yy772:
YYDEBUG(772, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1299 "Zend/zend_language_scanner.l"
+#line 1275 "Zend/zend_language_scanner.l"
{
HANDLE_NEWLINES(yytext, yyleng);
RETURN_TOKEN(T_WHITESPACE);
}
-#line 7047 "Zend/zend_language_scanner.c"
+#line 7023 "Zend/zend_language_scanner.c"
yy773:
YYDEBUG(773, *YYCURSOR);
++YYCURSOR;
@@ -7051,13 +7027,13 @@ yy773:
yy774:
YYDEBUG(774, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1314 "Zend/zend_language_scanner.l"
+#line 1290 "Zend/zend_language_scanner.l"
{
yyless(0);
yy_pop_state();
goto restart;
}
-#line 7061 "Zend/zend_language_scanner.c"
+#line 7037 "Zend/zend_language_scanner.c"
yy775:
YYDEBUG(775, *YYCURSOR);
++YYCURSOR;
@@ -7066,13 +7042,13 @@ yy775:
yy776:
YYDEBUG(776, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1308 "Zend/zend_language_scanner.l"
+#line 1284 "Zend/zend_language_scanner.l"
{
yy_pop_state();
zend_copy_value(zendlval, yytext, yyleng);
RETURN_TOKEN(T_STRING);
}
-#line 7076 "Zend/zend_language_scanner.c"
+#line 7052 "Zend/zend_language_scanner.c"
yy777:
YYDEBUG(777, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7093,11 +7069,11 @@ yy780:
++YYCURSOR;
YYDEBUG(781, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1304 "Zend/zend_language_scanner.l"
+#line 1280 "Zend/zend_language_scanner.l"
{
RETURN_TOKEN(T_OBJECT_OPERATOR);
}
-#line 7101 "Zend/zend_language_scanner.c"
+#line 7077 "Zend/zend_language_scanner.c"
yy782:
YYDEBUG(782, *YYCURSOR);
++YYCURSOR;
@@ -7182,14 +7158,14 @@ yy786:
yy787:
YYDEBUG(787, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1619 "Zend/zend_language_scanner.l"
+#line 1595 "Zend/zend_language_scanner.l"
{
yyless(0);
yy_pop_state();
yy_push_state(ST_IN_SCRIPTING);
goto restart;
}
-#line 7193 "Zend/zend_language_scanner.c"
+#line 7169 "Zend/zend_language_scanner.c"
yy788:
YYDEBUG(788, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7214,7 +7190,7 @@ yy792:
++YYCURSOR;
YYDEBUG(793, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1610 "Zend/zend_language_scanner.l"
+#line 1586 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
zend_copy_value(zendlval, yytext, yyleng);
@@ -7222,7 +7198,7 @@ yy792:
yy_push_state(ST_IN_SCRIPTING);
RETURN_TOKEN(T_STRING_VARNAME);
}
-#line 7226 "Zend/zend_language_scanner.c"
+#line 7202 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_NOWDOC:
@@ -7233,7 +7209,7 @@ yyc_ST_NOWDOC:
++YYCURSOR;
YYDEBUG(797, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2338 "Zend/zend_language_scanner.l"
+#line 2314 "Zend/zend_language_scanner.l"
{
int newline = 0;
@@ -7289,7 +7265,7 @@ nowdoc_scan_done:
HANDLE_NEWLINES(yytext, yyleng - newline);
RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
-#line 7293 "Zend/zend_language_scanner.c"
+#line 7269 "Zend/zend_language_scanner.c"
/* *********************************** */
yyc_ST_VAR_OFFSET:
{
@@ -7396,7 +7372,7 @@ yy800:
yy801:
YYDEBUG(801, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1727 "Zend/zend_language_scanner.l"
+#line 1703 "Zend/zend_language_scanner.l"
{ /* Offset could be treated as a long */
if (yyleng < MAX_LENGTH_OF_LONG - 1 || (yyleng == MAX_LENGTH_OF_LONG - 1 && strcmp(yytext, long_min_digits) < 0)) {
char *end;
@@ -7412,7 +7388,7 @@ string:
}
RETURN_TOKEN(T_NUM_STRING);
}
-#line 7416 "Zend/zend_language_scanner.c"
+#line 7392 "Zend/zend_language_scanner.c"
yy802:
YYDEBUG(802, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7432,23 +7408,23 @@ yy803:
yy804:
YYDEBUG(804, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1887 "Zend/zend_language_scanner.l"
+#line 1863 "Zend/zend_language_scanner.l"
{
/* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */
RETURN_TOKEN(yytext[0]);
}
-#line 7441 "Zend/zend_language_scanner.c"
+#line 7417 "Zend/zend_language_scanner.c"
yy805:
YYDEBUG(805, *YYCURSOR);
++YYCURSOR;
YYDEBUG(806, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1882 "Zend/zend_language_scanner.l"
+#line 1858 "Zend/zend_language_scanner.l"
{
yy_pop_state();
RETURN_TOKEN(']');
}
-#line 7452 "Zend/zend_language_scanner.c"
+#line 7428 "Zend/zend_language_scanner.c"
yy807:
YYDEBUG(807, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7458,7 +7434,7 @@ yy808:
++YYCURSOR;
YYDEBUG(809, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1892 "Zend/zend_language_scanner.l"
+#line 1868 "Zend/zend_language_scanner.l"
{
/* Invalid rule to return a more explicit parse error with proper line number */
yyless(0);
@@ -7466,7 +7442,7 @@ yy808:
ZVAL_NULL(zendlval);
RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
-#line 7470 "Zend/zend_language_scanner.c"
+#line 7446 "Zend/zend_language_scanner.c"
yy810:
YYDEBUG(810, *YYCURSOR);
++YYCURSOR;
@@ -7475,18 +7451,18 @@ yy810:
yy811:
YYDEBUG(811, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1900 "Zend/zend_language_scanner.l"
+#line 1876 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, yytext, yyleng);
RETURN_TOKEN(T_STRING);
}
-#line 7484 "Zend/zend_language_scanner.c"
+#line 7460 "Zend/zend_language_scanner.c"
yy812:
YYDEBUG(812, *YYCURSOR);
++YYCURSOR;
YYDEBUG(813, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2395 "Zend/zend_language_scanner.l"
+#line 2371 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
RETURN_TOKEN(END);
@@ -7495,7 +7471,7 @@ yy812:
zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
goto restart;
}
-#line 7499 "Zend/zend_language_scanner.c"
+#line 7475 "Zend/zend_language_scanner.c"
yy814:
YYDEBUG(814, *YYCURSOR);
++YYCURSOR;
@@ -7531,12 +7507,12 @@ yy816:
yy818:
YYDEBUG(818, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1877 "Zend/zend_language_scanner.l"
+#line 1853 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
RETURN_TOKEN(T_VARIABLE);
}
-#line 7540 "Zend/zend_language_scanner.c"
+#line 7516 "Zend/zend_language_scanner.c"
yy819:
YYDEBUG(819, *YYCURSOR);
++YYCURSOR;
@@ -7576,12 +7552,12 @@ yy824:
yy826:
YYDEBUG(826, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1743 "Zend/zend_language_scanner.l"
+#line 1719 "Zend/zend_language_scanner.l"
{ /* Offset must be treated as a string */
ZVAL_STRINGL(zendlval, yytext, yyleng);
RETURN_TOKEN(T_NUM_STRING);
}
-#line 7585 "Zend/zend_language_scanner.c"
+#line 7561 "Zend/zend_language_scanner.c"
yy827:
YYDEBUG(827, *YYCURSOR);
++YYCURSOR;
@@ -7604,6 +7580,6 @@ yy829:
goto yy826;
}
}
-#line 2404 "Zend/zend_language_scanner.l"
+#line 2380 "Zend/zend_language_scanner.l"
}
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index 47958b7182..c2a3a45198 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -568,6 +568,48 @@ ZEND_API int open_file_for_scanning(zend_file_handle *file_handle)
}
END_EXTERN_C()
+static zend_op_array *zend_compile(int type)
+{
+ zend_op_array *op_array = NULL;
+ zend_bool original_in_compilation = CG(in_compilation);
+
+ CG(in_compilation) = 1;
+ CG(ast) = NULL;
+ CG(ast_arena) = zend_arena_create(1024 * 32);
+
+ if (!zendparse()) {
+ zend_file_context original_file_context;
+ zend_oparray_context original_oparray_context;
+ zend_op_array *original_active_op_array = CG(active_op_array);
+
+ op_array = emalloc(sizeof(zend_op_array));
+ init_op_array(op_array, type, INITIAL_OP_ARRAY_SIZE);
+ CG(active_op_array) = op_array;
+
+ if (zend_ast_process) {
+ zend_ast_process(CG(ast));
+ }
+
+ zend_file_context_begin(&original_file_context);
+ zend_oparray_context_begin(&original_oparray_context);
+ zend_compile_top_stmt(CG(ast));
+ zend_emit_final_return(type == ZEND_USER_FUNCTION);
+ op_array->line_start = 1;
+ op_array->line_end = CG(zend_lineno);
+ pass_two(op_array);
+ zend_oparray_context_end(&original_oparray_context);
+ zend_file_context_end(&original_file_context);
+
+ CG(active_op_array) = original_active_op_array;
+ }
+
+ zend_ast_destroy(CG(ast));
+ zend_arena_destroy(CG(ast_arena));
+
+ CG(in_compilation) = original_in_compilation;
+
+ return op_array;
+}
ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type)
{
@@ -583,41 +625,7 @@ ZEND_API zend_op_array *compile_file(zend_file_handle *file_handle, int type)
zend_message_dispatcher(ZMSG_FAILED_INCLUDE_FOPEN, file_handle->filename);
}
} else {
- zend_bool original_in_compilation = CG(in_compilation);
- CG(in_compilation) = 1;
-
- CG(ast) = NULL;
- CG(ast_arena) = zend_arena_create(1024 * 32);
- if (!zendparse()) {
- zval retval_zv;
- zend_file_context original_file_context;
- zend_oparray_context original_oparray_context;
- zend_op_array *original_active_op_array = CG(active_op_array);
- op_array = emalloc(sizeof(zend_op_array));
- init_op_array(op_array, ZEND_USER_FUNCTION, INITIAL_OP_ARRAY_SIZE);
- CG(active_op_array) = op_array;
- ZVAL_LONG(&retval_zv, 1);
-
- if (zend_ast_process) {
- zend_ast_process(CG(ast));
- }
-
- zend_file_context_begin(&original_file_context);
- zend_oparray_context_begin(&original_oparray_context);
- zend_compile_top_stmt(CG(ast));
- zend_emit_final_return(&retval_zv);
- op_array->line_start = 1;
- op_array->line_end = CG(zend_lineno);
- pass_two(op_array);
- zend_oparray_context_end(&original_oparray_context);
- zend_file_context_end(&original_file_context);
-
- CG(active_op_array) = original_active_op_array;
- }
-
- zend_ast_destroy(CG(ast));
- zend_arena_destroy(CG(ast_arena));
- CG(in_compilation) = original_in_compilation;
+ op_array = zend_compile(ZEND_USER_FUNCTION);
}
zend_restore_lexical_state(&original_lex_state);
@@ -732,13 +740,11 @@ ZEND_API size_t zend_get_scanned_file_offset(void)
return offset;
}
-
zend_op_array *compile_string(zval *source_string, char *filename)
{
zend_lex_state original_lex_state;
zend_op_array *op_array = NULL;
zval tmp;
- zend_bool original_in_compilation = CG(in_compilation);
if (Z_STRLEN_P(source_string)==0) {
return NULL;
@@ -748,45 +754,15 @@ zend_op_array *compile_string(zval *source_string, char *filename)
convert_to_string(&tmp);
source_string = &tmp;
- CG(in_compilation) = 1;
zend_save_lexical_state(&original_lex_state);
if (zend_prepare_string_for_scanning(source_string, filename) == SUCCESS) {
- CG(ast) = NULL;
- CG(ast_arena) = zend_arena_create(1024 * 32);
BEGIN(ST_IN_SCRIPTING);
-
- if (!zendparse()) {
- zend_file_context original_file_context;
- zend_oparray_context original_oparray_context;
- zend_op_array *original_active_op_array = CG(active_op_array);
- op_array = emalloc(sizeof(zend_op_array));
- init_op_array(op_array, ZEND_EVAL_CODE, INITIAL_OP_ARRAY_SIZE);
- CG(active_op_array) = op_array;
-
- if (zend_ast_process) {
- zend_ast_process(CG(ast));
- }
-
- zend_file_context_begin(&original_file_context);
- zend_oparray_context_begin(&original_oparray_context);
- zend_compile_top_stmt(CG(ast));
- zend_emit_final_return(NULL);
- op_array->line_start = 1;
- op_array->line_end = CG(zend_lineno);
- pass_two(op_array);
- zend_oparray_context_end(&original_oparray_context);
- zend_file_context_end(&original_file_context);
-
- CG(active_op_array) = original_active_op_array;
- }
-
- zend_ast_destroy(CG(ast));
- zend_arena_destroy(CG(ast_arena));
+ op_array = zend_compile(ZEND_EVAL_CODE);
}
zend_restore_lexical_state(&original_lex_state);
zval_dtor(&tmp);
- CG(in_compilation) = original_in_compilation;
+
return op_array;
}
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index 8abfd7a56c..86fe4020a7 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -78,9 +78,9 @@ void init_op_array(zend_op_array *op_array, zend_uchar type, int initial_ops_siz
op_array->scope = NULL;
op_array->prototype = NULL;
- op_array->brk_cont_array = NULL;
+ op_array->live_range = NULL;
op_array->try_catch_array = NULL;
- op_array->last_brk_cont = 0;
+ op_array->last_live_range = 0;
op_array->static_variables = NULL;
op_array->last_try_catch = 0;
@@ -387,8 +387,8 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
if (op_array->doc_comment) {
zend_string_release(op_array->doc_comment);
}
- if (op_array->brk_cont_array) {
- efree(op_array->brk_cont_array);
+ if (op_array->live_range) {
+ efree(op_array->live_range);
}
if (op_array->try_catch_array) {
efree(op_array->try_catch_array);
@@ -451,11 +451,11 @@ int get_next_op_number(zend_op_array *op_array)
return op_array->last;
}
-zend_brk_cont_element *get_next_brk_cont_element(zend_op_array *op_array)
+zend_brk_cont_element *get_next_brk_cont_element(void)
{
- op_array->last_brk_cont++;
- op_array->brk_cont_array = erealloc(op_array->brk_cont_array, sizeof(zend_brk_cont_element)*op_array->last_brk_cont);
- return &op_array->brk_cont_array[op_array->last_brk_cont-1];
+ CG(context).last_brk_cont++;
+ CG(context).brk_cont_array = erealloc(CG(context).brk_cont_array, sizeof(zend_brk_cont_element) * CG(context).last_brk_cont);
+ return &CG(context).brk_cont_array[CG(context).last_brk_cont-1];
}
static void zend_update_extended_info(zend_op_array *op_array)
@@ -516,48 +516,52 @@ static void zend_check_finally_breakout(zend_op_array *op_array, uint32_t op_num
static void zend_resolve_fast_call(zend_op_array *op_array, uint32_t op_num)
{
int i;
- uint32_t finally_op_num = 0;
+ uint32_t finally_num = (uint32_t)-1;
for (i = 0; i < op_array->last_try_catch; i++) {
if (op_num >= op_array->try_catch_array[i].finally_op
&& op_num < op_array->try_catch_array[i].finally_end) {
- finally_op_num = op_array->try_catch_array[i].finally_op;
+ finally_num = i;
}
}
- if (finally_op_num) {
+ if (finally_num != (uint32_t)-1) {
/* Must be ZEND_FAST_CALL */
- ZEND_ASSERT(op_array->opcodes[finally_op_num - 2].opcode == ZEND_FAST_CALL);
+ ZEND_ASSERT(op_array->opcodes[op_array->try_catch_array[finally_num].finally_op - 2].opcode == ZEND_FAST_CALL);
op_array->opcodes[op_num].extended_value = ZEND_FAST_CALL_FROM_FINALLY;
- op_array->opcodes[op_num].op2.opline_num = finally_op_num - 2;
+ op_array->opcodes[op_num].op2.num = finally_num;
}
}
static void zend_resolve_finally_ret(zend_op_array *op_array, uint32_t op_num)
{
int i;
- uint32_t catch_op_num = 0, finally_op_num = 0;
+ uint32_t finally_num = (uint32_t)-1;
+ uint32_t catch_num = (uint32_t)-1;
for (i = 0; i < op_array->last_try_catch; i++) {
if (op_array->try_catch_array[i].try_op > op_num) {
break;
}
if (op_num < op_array->try_catch_array[i].finally_op) {
- finally_op_num = op_array->try_catch_array[i].finally_op;
+ finally_num = i;
}
if (op_num < op_array->try_catch_array[i].catch_op) {
- catch_op_num = op_array->try_catch_array[i].catch_op;
+ catch_num = i;
}
}
- if (finally_op_num && (!catch_op_num || catch_op_num >= finally_op_num)) {
+ if (finally_num != (uint32_t)-1 &&
+ (catch_num == (uint32_t)-1 ||
+ op_array->try_catch_array[catch_num].catch_op >=
+ op_array->try_catch_array[finally_num].finally_op)) {
/* in case of unhandled exception return to upward finally block */
op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_FINALLY;
- op_array->opcodes[op_num].op2.opline_num = finally_op_num;
- } else if (catch_op_num) {
+ op_array->opcodes[op_num].op2.num = finally_num;
+ } else if (catch_num != (uint32_t)-1) {
/* in case of unhandled exception return to upward catch block */
op_array->opcodes[op_num].extended_value = ZEND_FAST_RET_TO_CATCH;
- op_array->opcodes[op_num].op2.opline_num = catch_op_num;
+ op_array->opcodes[op_num].op2.num = catch_num;
}
}
@@ -566,7 +570,7 @@ static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const ze
int array_offset = opline->op1.num;
zend_brk_cont_element *jmp_to;
do {
- jmp_to = &op_array->brk_cont_array[array_offset];
+ jmp_to = &CG(context).brk_cont_array[array_offset];
if (nest_levels > 1) {
array_offset = jmp_to->parent;
}
@@ -646,6 +650,10 @@ ZEND_API int pass_two(zend_op_array *op_array)
case ZEND_DECLARE_ANON_CLASS:
ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
break;
+ case ZEND_CATCH:
+ /* absolute index to relative offset */
+ opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
+ break;
case ZEND_JMPZNZ:
/* absolute index to relative offset */
opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
@@ -699,6 +707,16 @@ ZEND_API int pass_two(zend_op_array *op_array)
opline++;
}
+ if (op_array->live_range) {
+ uint32_t i;
+
+ for (i = 0; i < op_array->last_live_range; i++) {
+ op_array->live_range[i].var =
+ (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + (op_array->live_range[i].var / sizeof(zval))) |
+ (op_array->live_range[i].var & ZEND_LIVE_MASK);
+ }
+ }
+
op_array->fn_flags |= ZEND_ACC_DONE_PASS_TWO;
return 0;
}
diff --git a/Zend/zend_smart_str.c b/Zend/zend_smart_str.c
index 1d90c83060..40a206abcb 100644
--- a/Zend/zend_smart_str.c
+++ b/Zend/zend_smart_str.c
@@ -17,7 +17,7 @@
*/
#include <zend.h>
-#include "zend_smart_str_public.h"
+#include "zend_smart_str.h"
#define SMART_STR_OVERHEAD (ZEND_MM_OVERHEAD + _ZSTR_HEADER_SIZE)
@@ -59,3 +59,61 @@ ZEND_API void ZEND_FASTCALL smart_str_realloc(smart_str *str, size_t len)
str->s = (zend_string *) realloc(str->s, _ZSTR_HEADER_SIZE + str->a + 1);
}
}
+
+/* Windows uses VK_ESCAPE instead of \e */
+#ifndef VK_ESCAPE
+#define VK_ESCAPE '\e'
+#endif
+
+static size_t zend_compute_escaped_string_len(const char *s, size_t l) {
+ size_t i, len = l;
+ for (i = 0; i < l; ++i) {
+ char c = s[i];
+ if (c == '\n' || c == '\r' || c == '\t' ||
+ c == '\f' || c == '\v' || c == '\\' || c == VK_ESCAPE) {
+ len += 1;
+ } else if (c < 32 || c > 126) {
+ len += 3;
+ }
+ }
+ return len;
+}
+
+ZEND_API void ZEND_FASTCALL smart_str_append_escaped(smart_str *str, const char *s, size_t l) {
+ char *res;
+ size_t i, len = zend_compute_escaped_string_len(s, l);
+
+ smart_str_alloc(str, len, 0);
+ res = &ZSTR_VAL(str->s)[ZSTR_LEN(str->s)];
+ ZSTR_LEN(str->s) += len;
+
+ for (i = 0; i < l; ++i) {
+ unsigned char c = s[i];
+ if (c < 32 || c == '\\' || c > 126) {
+ *res++ = '\\';
+ switch (c) {
+ case '\n': *res++ = 'n'; break;
+ case '\r': *res++ = 'r'; break;
+ case '\t': *res++ = 't'; break;
+ case '\f': *res++ = 'f'; break;
+ case '\v': *res++ = 'v'; break;
+ case '\\': *res++ = '\\'; break;
+ case VK_ESCAPE: *res++ = 'e'; break;
+ default:
+ *res++ = 'x';
+ if ((c >> 4) < 10) {
+ *res++ = (c >> 4) + '0';
+ } else {
+ *res++ = (c >> 4) + 'A' - 10;
+ }
+ if ((c & 0xf) < 10) {
+ *res++ = (c & 0xf) + '0';
+ } else {
+ *res++ = (c & 0xf) + 'A' - 10;
+ }
+ }
+ } else {
+ *res++ = c;
+ }
+ }
+}
diff --git a/Zend/zend_smart_str.h b/Zend/zend_smart_str.h
index 39478511a8..5279b1ddb5 100644
--- a/Zend/zend_smart_str.h
+++ b/Zend/zend_smart_str.h
@@ -45,6 +45,7 @@ BEGIN_EXTERN_C()
ZEND_API void ZEND_FASTCALL smart_str_erealloc(smart_str *str, size_t len);
ZEND_API void ZEND_FASTCALL smart_str_realloc(smart_str *str, size_t len);
+ZEND_API void ZEND_FASTCALL smart_str_append_escaped(smart_str *str, const char *s, size_t l);
END_EXTERN_C()
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index eda7f9e0a2..805ea6d8c7 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -274,7 +274,7 @@ typedef struct _HashTableIterator {
struct _zend_object {
zend_refcounted_h gc;
- uint32_t handle;
+ uint32_t handle; // TODO: may be removed ???
zend_class_entry *ce;
const zend_object_handlers *handlers;
HashTable *properties;
@@ -283,7 +283,7 @@ struct _zend_object {
struct _zend_resource {
zend_refcounted_h gc;
- int handle;
+ int handle; // TODO: may be removed ???
int type;
void *ptr;
};
@@ -318,6 +318,7 @@ struct _zend_ast_ref {
/* fake types */
#define _IS_BOOL 13
#define IS_CALLABLE 14
+#define IS_VOID 18
/* internal types */
#define IS_INDIRECT 15
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 8fae72b2f6..a6537800fd 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -872,7 +872,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|CV, CONST|TMPVAR|CV, binary_
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(23, ZEND_ASSIGN_ADD, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(23, ZEND_ASSIGN_ADD, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -892,7 +892,7 @@ ZEND_VM_HANDLER(23, ZEND_ASSIGN_ADD, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HANDLER(24, ZEND_ASSIGN_SUB, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(24, ZEND_ASSIGN_SUB, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -912,7 +912,7 @@ ZEND_VM_HANDLER(24, ZEND_ASSIGN_SUB, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HANDLER(25, ZEND_ASSIGN_MUL, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(25, ZEND_ASSIGN_MUL, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -932,7 +932,7 @@ ZEND_VM_HANDLER(25, ZEND_ASSIGN_MUL, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HANDLER(26, ZEND_ASSIGN_DIV, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(26, ZEND_ASSIGN_DIV, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -952,7 +952,7 @@ ZEND_VM_HANDLER(26, ZEND_ASSIGN_DIV, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HANDLER(27, ZEND_ASSIGN_MOD, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(27, ZEND_ASSIGN_MOD, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -972,7 +972,7 @@ ZEND_VM_HANDLER(27, ZEND_ASSIGN_MOD, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HANDLER(28, ZEND_ASSIGN_SL, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(28, ZEND_ASSIGN_SL, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -992,7 +992,7 @@ ZEND_VM_HANDLER(28, ZEND_ASSIGN_SL, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HANDLER(29, ZEND_ASSIGN_SR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(29, ZEND_ASSIGN_SR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -1012,7 +1012,7 @@ ZEND_VM_HANDLER(29, ZEND_ASSIGN_SR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HANDLER(30, ZEND_ASSIGN_CONCAT, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(30, ZEND_ASSIGN_CONCAT, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -1032,7 +1032,7 @@ ZEND_VM_HANDLER(30, ZEND_ASSIGN_CONCAT, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HANDLER(31, ZEND_ASSIGN_BW_OR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(31, ZEND_ASSIGN_BW_OR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -1052,7 +1052,7 @@ ZEND_VM_HANDLER(31, ZEND_ASSIGN_BW_OR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HANDLER(32, ZEND_ASSIGN_BW_AND, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(32, ZEND_ASSIGN_BW_AND, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -1072,7 +1072,7 @@ ZEND_VM_HANDLER(32, ZEND_ASSIGN_BW_AND, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HANDLER(33, ZEND_ASSIGN_BW_XOR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(33, ZEND_ASSIGN_BW_XOR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -1092,7 +1092,7 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_BW_XOR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HANDLER(167, ZEND_ASSIGN_POW, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(167, ZEND_ASSIGN_POW, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, DIM_OBJ)
{
#if !defined(ZEND_VM_SPEC) || (OP2_TYPE != IS_UNUSED)
USE_OPLINE
@@ -1470,7 +1470,7 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMPVAR|CV, ANY)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|VAR, int type)
+ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED, int type)
{
USE_OPLINE
zend_free_op free_op1;
@@ -1494,61 +1494,30 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
name = zval_get_string(varname);
}
- if (OP2_TYPE != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (OP2_TYPE == IS_CONST) {
- if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- FREE_OP1();
- HANDLE_EXCEPTION();
- }
-
- ZEND_VM_C_GOTO(fetch_var_return);
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (OP1_TYPE != IS_CONST) {
- zend_string_release(name);
- }
- FREE_OP1();
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (OP1_TYPE == IS_CONST &&
- (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- FREE_OP1();
- HANDLE_EXCEPTION();
- }
-
- ZEND_VM_C_GOTO(fetch_var_return);
- }
- }
- retval = zend_std_get_static_property(ce, name, 0);
- if (UNEXPECTED(EG(exception))) {
- FREE_OP1();
- HANDLE_EXCEPTION();
- }
- if (OP1_TYPE == IS_CONST && retval) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ retval = zend_hash_find(target_symbol_table, name);
+ if (retval == NULL) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
+ retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
+ break;
+ case BP_VAR_W:
+ retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
}
-
- FREE_OP1();
- } else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- retval = zend_hash_find(target_symbol_table, name);
- if (retval == NULL) {
+ /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
+ } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
+ retval = Z_INDIRECT_P(retval);
+ if (Z_TYPE_P(retval) == IS_UNDEF) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
@@ -1559,52 +1528,30 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
- break;
+ /* break missing intentionally */
case BP_VAR_W:
- retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
+ ZVAL_NULL(retval);
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
- /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
- retval = Z_INDIRECT_P(retval);
- if (Z_TYPE_P(retval) == IS_UNDEF) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_W:
- ZVAL_NULL(retval);
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- }
}
- 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();
- }
+ }
+
+ 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) {
- FREE_OP1();
}
+ } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
+ FREE_OP1();
}
if (OP1_TYPE != IS_CONST) {
zend_string_release(name);
}
-ZEND_VM_C_LABEL(fetch_var_return):
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
@@ -1617,22 +1564,22 @@ ZEND_VM_C_LABEL(fetch_var_return):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+ZEND_VM_HANDLER(80, ZEND_FETCH_R, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
{
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_R);
}
-ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+ZEND_VM_HANDLER(83, ZEND_FETCH_W, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
{
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_W);
}
-ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+ZEND_VM_HANDLER(86, ZEND_FETCH_RW, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
{
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_RW);
}
-ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
{
USE_OPLINE
@@ -1643,16 +1590,150 @@ ZEND_VM_HANDLER(92, ZEND_FETCH_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
}
}
-ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+ZEND_VM_HANDLER(95, ZEND_FETCH_UNSET, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
{
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_UNSET);
}
-ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+ZEND_VM_HANDLER(89, ZEND_FETCH_IS, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
{
ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_var_address_helper, type, BP_VAR_IS);
}
+ZEND_VM_HELPER_EX(zend_fetch_static_prop_helper, CONST|TMPVAR|CV, UNUSED|CONST|VAR, int type)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval *retval;
+ zend_string *name;
+ zend_class_entry *ce;
+
+ SAVE_OPLINE();
+ varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
+
+ if (OP1_TYPE == IS_CONST) {
+ name = Z_STR_P(varname);
+ } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
+ name = Z_STR_P(varname);
+ zend_string_addref(name);
+ } else {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(varname, BP_VAR_R);
+ }
+ name = zval_get_string(varname);
+ }
+
+ if (OP2_TYPE == IS_CONST) {
+ if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ FREE_OP1();
+ HANDLE_EXCEPTION();
+ }
+
+ ZEND_VM_C_GOTO(fetch_static_prop_return);
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (OP1_TYPE != IS_CONST) {
+ zend_string_release(name);
+ }
+ FREE_OP1();
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (OP2_TYPE == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
+ }
+ if (OP1_TYPE == IS_CONST &&
+ (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ FREE_OP1();
+ HANDLE_EXCEPTION();
+ }
+
+ ZEND_VM_C_GOTO(fetch_static_prop_return);
+ }
+ }
+ retval = zend_std_get_static_property(ce, name, 0);
+ if (UNEXPECTED(EG(exception))) {
+ FREE_OP1();
+ HANDLE_EXCEPTION();
+ }
+ if (OP1_TYPE == IS_CONST && retval) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ }
+
+ FREE_OP1();
+
+ if (OP1_TYPE != IS_CONST) {
+ zend_string_release(name);
+ }
+
+ZEND_VM_C_LABEL(fetch_static_prop_return):
+ ZEND_ASSERT(retval != NULL);
+ if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ } else {
+ ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
+ }
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+ZEND_VM_HANDLER(173, ZEND_FETCH_STATIC_PROP_R, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+{
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_R);
+}
+
+ZEND_VM_HANDLER(174, ZEND_FETCH_STATIC_PROP_W, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+{
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_W);
+}
+
+ZEND_VM_HANDLER(175, ZEND_FETCH_STATIC_PROP_RW, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+{
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_RW);
+}
+
+ZEND_VM_HANDLER(177, ZEND_FETCH_STATIC_PROP_FUNC_ARG, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+{
+ USE_OPLINE
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_W);
+ } else {
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_R);
+ }
+}
+
+ZEND_VM_HANDLER(178, ZEND_FETCH_STATIC_PROP_UNSET, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+{
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_UNSET);
+}
+
+ZEND_VM_HANDLER(176, ZEND_FETCH_STATIC_PROP_IS, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+{
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_fetch_static_prop_helper, type, BP_VAR_IS);
+}
+
ZEND_VM_HANDLER(81, ZEND_FETCH_DIM_R, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
@@ -2437,7 +2518,7 @@ ZEND_VM_HELPER(zend_leave_helper, ANY, ANY)
}
}
-ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
+ZEND_VM_HANDLER(42, ZEND_JMP, JMP_ADDR, ANY)
{
USE_OPLINE
@@ -2445,7 +2526,7 @@ ZEND_VM_HANDLER(42, ZEND_JMP, ANY, ANY)
ZEND_VM_CONTINUE();
}
-ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, ANY)
+ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -2480,7 +2561,7 @@ ZEND_VM_HANDLER(43, ZEND_JMPZ, CONST|TMPVAR|CV, ANY)
ZEND_VM_JMP(opline);
}
-ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, ANY)
+ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -2514,7 +2595,7 @@ ZEND_VM_HANDLER(44, ZEND_JMPNZ, CONST|TMPVAR|CV, ANY)
ZEND_VM_JMP(opline);
}
-ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, ANY)
+ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, JMP_ADDR, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -2551,7 +2632,7 @@ ZEND_VM_HANDLER(45, ZEND_JMPZNZ, CONST|TMPVAR|CV, ANY)
ZEND_VM_JMP(opline);
}
-ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, ANY)
+ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -2594,7 +2675,7 @@ ZEND_VM_HANDLER(46, ZEND_JMPZ_EX, CONST|TMPVAR|CV, ANY)
ZEND_VM_JMP(opline);
}
-ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, ANY)
+ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -2634,7 +2715,7 @@ ZEND_VM_HANDLER(47, ZEND_JMPNZ_EX, CONST|TMPVAR|CV, ANY)
ZEND_VM_JMP(opline);
}
-ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, ANY)
+ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, LIVE_RANGE)
{
USE_OPLINE
@@ -2643,7 +2724,7 @@ ZEND_VM_HANDLER(70, ZEND_FREE, TMPVAR, ANY)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(127, ZEND_FE_FREE, TMPVAR, ANY)
+ZEND_VM_HANDLER(127, ZEND_FE_FREE, TMPVAR, LIVE_RANGE)
{
zval *var;
USE_OPLINE
@@ -2724,7 +2805,7 @@ ZEND_VM_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMPVAR|CV, NUM)
{
USE_OPLINE
zend_free_op free_op2;
@@ -2757,7 +2838,7 @@ ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMPVAR|CV)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMPVAR|CV, NUM)
{
USE_OPLINE
zend_free_op free_op2;
@@ -2790,7 +2871,7 @@ ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMPVAR|CV)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV, NUM)
{
USE_OPLINE
zend_free_op free_op2;
@@ -2843,7 +2924,7 @@ ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMPVAR|UNUSED|CV, CLASS_FETCH)
{
USE_OPLINE
@@ -2886,7 +2967,7 @@ ZEND_VM_C_LABEL(try_class_name):
}
}
-ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV, NUM)
{
USE_OPLINE
zval *function_name;
@@ -3007,7 +3088,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, UNUSED|CONST|VAR, CONST|TMPVAR|UNUSED|CV, NUM)
{
USE_OPLINE
zval *function_name;
@@ -3032,6 +3113,12 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (OP1_TYPE == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -3125,10 +3212,10 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
}
}
- if (OP1_TYPE != IS_CONST) {
+ if (OP1_TYPE == IS_UNUSED) {
/* previous opcode is ZEND_FETCH_CLASS */
- if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
- ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
ce = EX(called_scope);
}
}
@@ -3141,7 +3228,7 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST)
+ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST, NUM)
{
USE_OPLINE
zend_function *fbc;
@@ -3168,7 +3255,7 @@ ZEND_VM_HANDLER(59, ZEND_INIT_FCALL_BY_NAME, ANY, CONST)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(128, ZEND_INIT_DYNAMIC_CALL, ANY, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(128, ZEND_INIT_DYNAMIC_CALL, ANY, CONST|TMPVAR|CV, NUM)
{
USE_OPLINE
zend_function *fbc;
@@ -3381,7 +3468,7 @@ ZEND_VM_C_LABEL(try_function_name):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV, NUM)
{
USE_OPLINE
zend_free_op free_op2;
@@ -3440,7 +3527,7 @@ ZEND_VM_HANDLER(118, ZEND_INIT_USER_CALL, CONST, CONST|TMPVAR|CV)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
+ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST, NUM)
{
USE_OPLINE
zval *func_name;
@@ -3473,7 +3560,7 @@ ZEND_VM_HANDLER(69, ZEND_INIT_NS_FCALL_BY_NAME, ANY, CONST)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST)
+ZEND_VM_HANDLER(61, ZEND_INIT_FCALL, ANY, CONST, NUM)
{
USE_OPLINE
zend_free_op free_op2;
@@ -3920,8 +4007,6 @@ ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED)
if (UNEXPECTED(EG(exception) != NULL)) {
if (OP1_TYPE == IS_CONST) {
zval_ptr_dtor_nogc(retval_ptr);
- } else {
- FREE_OP1();
}
}
#endif
@@ -4126,7 +4211,7 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY)
HANDLE_EXCEPTION();
}
-ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
+ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV, JMP_ADDR)
{
USE_OPLINE
zend_class_entry *ce, *catch_ce;
@@ -4136,8 +4221,8 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
/* Check whether an exception has been thrown, if not, jump over code */
zend_exception_restore();
if (EG(exception) == NULL) {
- ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
- ZEND_VM_CONTINUE(); /* CHECK_ME */
+ ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
+ ZEND_VM_CONTINUE();
}
catch_ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
if (UNEXPECTED(catch_ce == NULL)) {
@@ -4159,8 +4244,8 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
zend_throw_exception_internal(NULL);
HANDLE_EXCEPTION();
}
- ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
- ZEND_VM_CONTINUE(); /* CHECK_ME */
+ ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
+ ZEND_VM_CONTINUE();
}
}
@@ -4176,7 +4261,7 @@ ZEND_VM_HANDLER(107, ZEND_CATCH, CONST, CV)
}
}
-ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
+ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, NUM)
{
USE_OPLINE
zval *value, *arg;
@@ -4193,7 +4278,7 @@ ZEND_VM_HANDLER(65, ZEND_SEND_VAL, CONST|TMP, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, ANY)
+ZEND_VM_HANDLER(116, ZEND_SEND_VAL_EX, CONST|TMP, NUM)
{
USE_OPLINE
zval *value, *arg;
@@ -4224,7 +4309,7 @@ ZEND_VM_C_LABEL(send_val_by_ref):
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(117, ZEND_SEND_VAR, VAR|CV, ANY)
+ZEND_VM_HANDLER(117, ZEND_SEND_VAR, VAR|CV, NUM)
{
USE_OPLINE
zval *varptr, *arg;
@@ -4263,7 +4348,7 @@ ZEND_VM_HANDLER(117, ZEND_SEND_VAR, VAR|CV, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR, ANY)
+ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR, NUM)
{
USE_OPLINE
zend_free_op free_op1;
@@ -4300,7 +4385,7 @@ ZEND_VM_HANDLER(106, ZEND_SEND_VAR_NO_REF, VAR, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
+ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, NUM)
{
USE_OPLINE
zend_free_op free_op1;
@@ -4335,7 +4420,7 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, ANY)
+ZEND_VM_HANDLER(66, ZEND_SEND_VAR_EX, VAR|CV, NUM)
{
USE_OPLINE
zval *varptr, *arg;
@@ -4646,7 +4731,7 @@ ZEND_VM_C_LABEL(send_array):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY)
+ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, NUM)
{
USE_OPLINE
zval *arg, *param;
@@ -4701,7 +4786,7 @@ ZEND_VM_HANDLER(120, ZEND_SEND_USER, VAR|CV, ANY)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
+ZEND_VM_HANDLER(63, ZEND_RECV, NUM, ANY)
{
USE_OPLINE
uint32_t arg_num = opline->op1.num;
@@ -4722,7 +4807,7 @@ ZEND_VM_HANDLER(63, ZEND_RECV, ANY, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
+ZEND_VM_HANDLER(64, ZEND_RECV_INIT, NUM, CONST)
{
USE_OPLINE
uint32_t arg_num;
@@ -4761,7 +4846,7 @@ ZEND_VM_HANDLER(64, ZEND_RECV_INIT, ANY, CONST)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, ANY, ANY)
+ZEND_VM_HANDLER(164, ZEND_RECV_VARIADIC, NUM, ANY)
{
USE_OPLINE
uint32_t arg_num = opline->op1.num;
@@ -4892,7 +4977,7 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
+ZEND_VM_HANDLER(68, ZEND_NEW, UNUSED|CONST|VAR, JMP_ADDR, NUM)
{
USE_OPLINE
zval object_zval;
@@ -4909,6 +4994,12 @@ ZEND_VM_HANDLER(68, ZEND_NEW, CONST|VAR, ANY)
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (OP1_TYPE == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -5025,114 +5116,130 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
+ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, UNUSED, CONST, CONST_FETCH)
{
USE_OPLINE
+ zend_constant *c;
SAVE_OPLINE();
- if (OP1_TYPE == IS_UNUSED) {
- zend_constant *c;
-
- if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
- c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- } else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
- if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
- char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
- if (!actual) {
- ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(EX_CONSTANT(opline->op2)));
- } else {
- actual++;
- ZVAL_STRINGL(EX_VAR(opline->result.var),
- actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
- }
- /* non-qualified constant - allow text substitution */
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
- Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+
+ if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
+ c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ } else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
+ if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
+ char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
+ if (!actual) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(EX_CONSTANT(opline->op2)));
} else {
- zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- HANDLE_EXCEPTION();
+ actual++;
+ ZVAL_STRINGL(EX_VAR(opline->result.var),
+ actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
}
+ /* non-qualified constant - allow text substitution */
+ zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
+ Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} else {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
+ zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ HANDLE_EXCEPTION();
}
+ } else {
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
+ }
+
#ifdef ZTS
- if (c->flags & CONST_PERSISTENT) {
- ZVAL_DUP(EX_VAR(opline->result.var), &c->value);
- } else {
- ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
- }
-#else
+ if (c->flags & CONST_PERSISTENT) {
+ ZVAL_DUP(EX_VAR(opline->result.var), &c->value);
+ } else {
ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
+ }
+#else
+ ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
#endif
- } else {
- /* class constant */
- zend_class_entry *ce;
- zval *value;
- do {
- if (OP1_TYPE == IS_CONST) {
- if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- ZVAL_DEREF(value);
+ ZEND_VM_NEXT_OPCODE();
+}
+
+ZEND_VM_HANDLER(181, ZEND_FETCH_CLASS_CONSTANT, VAR|CONST|UNUSED, CONST)
+{
+ zend_class_entry *ce;
+ zval *value;
+ USE_OPLINE
+
+ SAVE_OPLINE();
+
+ do {
+ if (OP1_TYPE == IS_CONST) {
+ if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ ZVAL_DEREF(value);
#ifdef ZTS
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
#endif
- break;
- } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
- } else {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
- }
- HANDLE_EXCEPTION();
+ break;
+ } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ } else {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ HANDLE_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ }
+ } else {
+ if (OP1_TYPE == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
- if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
- ZVAL_DEREF(value);
- break;
- }
}
-
- if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
ZVAL_DEREF(value);
- if (Z_CONSTANT_P(value)) {
- EG(scope) = ce;
- zval_update_constant_ex(value, 1, NULL);
- EG(scope) = EX(func)->op_array.scope;
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
- }
- }
- if (OP1_TYPE == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
- } else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ break;
+ }
+ }
+
+ if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ ZVAL_DEREF(value);
+ if (Z_CONSTANT_P(value)) {
+ EG(scope) = ce;
+ zval_update_constant_ex(value, 1, NULL);
+ EG(scope) = EX(func)->op_array.scope;
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
}
+ }
+ if (OP1_TYPE == IS_CONST) {
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
} else {
- zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- HANDLE_EXCEPTION();
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
}
- } while (0);
-#ifdef ZTS
- if (ce->type == ZEND_INTERNAL_CLASS) {
- ZVAL_DUP(EX_VAR(opline->result.var), value);
} else {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ HANDLE_EXCEPTION();
}
-#else
+ } while (0);
+
+#ifdef ZTS
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ ZVAL_DUP(EX_VAR(opline->result.var), value);
+ } else {
ZVAL_COPY(EX_VAR(opline->result.var), value);
-#endif
}
+#else
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+#endif
+
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSED|CV, NUM)
{
USE_OPLINE
zend_free_op free_op1;
@@ -5231,7 +5338,7 @@ ZEND_VM_C_LABEL(num_index):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
+ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV, ARRAY_INIT)
{
zval *array;
uint32_t size;
@@ -5262,7 +5369,7 @@ ZEND_VM_HANDLER(71, ZEND_INIT_ARRAY, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|UNUSE
}
}
-ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY, TYPE)
{
USE_OPLINE
zend_free_op free_op1;
@@ -5364,7 +5471,7 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY)
+ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY, EVAL)
{
USE_OPLINE
zend_op_array *new_op_array=NULL;
@@ -5493,7 +5600,7 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH)
{
USE_OPLINE
zval tmp, *varname;
@@ -5502,7 +5609,6 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
SAVE_OPLINE();
if (OP1_TYPE == IS_CV &&
- OP2_TYPE == IS_UNUSED &&
(opline->extended_value & ZEND_QUICK_SET)) {
zval *var = EX_VAR(opline->op1.var);
@@ -5539,33 +5645,62 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
varname = &tmp;
}
- if (OP2_TYPE != IS_UNUSED) {
- zend_class_entry *ce;
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
- if (OP2_TYPE == IS_CONST) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+ FREE_OP1();
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+ZEND_VM_HANDLER(179, ZEND_UNSET_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ zend_class_entry *ce;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+
+ varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
+
+ ZVAL_UNDEF(&tmp);
+ if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
+ varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R);
+ }
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
+
+ if (OP2_TYPE == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- }
- if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
- FREE_OP1();
- HANDLE_EXCEPTION();
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+ FREE_OP1();
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (OP2_TYPE == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
- zend_std_unset_static_property(ce, Z_STR_P(varname));
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ zend_std_unset_static_property(ce, Z_STR_P(varname));
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
@@ -5717,7 +5852,7 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -5822,7 +5957,7 @@ ZEND_VM_HANDLER(77, ZEND_FE_RESET_R, CONST|TMP|VAR|CV, ANY)
}
}
-ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -5986,7 +6121,7 @@ ZEND_VM_HANDLER(125, ZEND_FE_RESET_RW, CONST|TMP|VAR|CV, ANY)
}
}
-ZEND_VM_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY)
+ZEND_VM_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY, JMP_ADDR)
{
USE_OPLINE
zval *array;
@@ -6104,13 +6239,11 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY)
* In case that ever happens we need an additional flag. */
iter->funcs->move_forward(iter);
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
if (UNEXPECTED(iter->funcs->valid(iter) == FAILURE)) {
/* reached end of iteration */
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
ZEND_VM_C_GOTO(fe_fetch_r_exit);
@@ -6118,7 +6251,6 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY)
}
value = iter->funcs->get_current_data(iter);
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
if (!value) {
@@ -6129,7 +6261,6 @@ ZEND_VM_HANDLER(78, ZEND_FE_FETCH_R, VAR, ANY)
if (iter->funcs->get_current_key) {
iter->funcs->get_current_key(iter, EX_VAR(opline->result.var));
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
} else {
@@ -6163,7 +6294,7 @@ ZEND_VM_C_LABEL(fe_fetch_r_exit):
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY)
+ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY, JMP_ADDR)
{
USE_OPLINE
zval *array;
@@ -6296,13 +6427,11 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY)
* In case that ever happens we need an additional flag. */
iter->funcs->move_forward(iter);
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
if (UNEXPECTED(iter->funcs->valid(iter) == FAILURE)) {
/* reached end of iteration */
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
ZEND_VM_C_GOTO(fe_fetch_w_exit);
@@ -6310,7 +6439,6 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY)
}
value = iter->funcs->get_current_data(iter);
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
if (!value) {
@@ -6321,7 +6449,6 @@ ZEND_VM_HANDLER(126, ZEND_FE_FETCH_RW, VAR, ANY)
if (iter->funcs->get_current_key) {
iter->funcs->get_current_key(iter, EX_VAR(opline->result.var));
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
} else {
@@ -6364,14 +6491,13 @@ ZEND_VM_C_LABEL(fe_fetch_w_exit):
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
+ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED, VAR_FETCH|ISSET)
{
USE_OPLINE
zval *value;
int result;
if (OP1_TYPE == IS_CV &&
- OP2_TYPE == IS_UNUSED &&
(opline->extended_value & ZEND_QUICK_SET)) {
value = EX_VAR(opline->op1.var);
if (opline->extended_value & ZEND_ISSET) {
@@ -6392,6 +6518,7 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
} else {
zend_free_op free_op1;
zval tmp, *varname;
+ HashTable *target_symbol_table;
SAVE_OPLINE();
varname = GET_OP1_ZVAL_PTR(BP_VAR_IS);
@@ -6401,56 +6528,14 @@ ZEND_VM_HANDLER(114, ZEND_ISSET_ISEMPTY_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
varname = &tmp;
}
- if (OP2_TYPE != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (OP2_TYPE == IS_CONST) {
- if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
-
- ZEND_VM_C_GOTO(is_var_return);
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (OP1_TYPE == IS_CONST &&
- (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
-
- ZEND_VM_C_GOTO(is_var_return);
- }
- }
-
- value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
-
- if (OP1_TYPE == IS_CONST && value) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
- }
- } else {
- HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
- }
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
}
FREE_OP1();
-ZEND_VM_C_LABEL(is_var_return):
if (opline->extended_value & ZEND_ISSET) {
result = value && Z_TYPE_P(value) > IS_NULL &&
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
@@ -6464,7 +6549,87 @@ ZEND_VM_C_LABEL(is_var_return):
}
}
-ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(180, ZEND_ISSET_ISEMPTY_STATIC_PROP, CONST|TMPVAR|CV, UNUSED|CONST|VAR, ISSET)
+{
+ USE_OPLINE
+ zval *value;
+ int result;
+ zend_free_op free_op1;
+ zval tmp, *varname;
+ zend_class_entry *ce;
+
+ SAVE_OPLINE();
+ varname = GET_OP1_ZVAL_PTR(BP_VAR_IS);
+ ZVAL_UNDEF(&tmp);
+ if (OP1_TYPE != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
+
+ if (OP2_TYPE == IS_CONST) {
+ if (OP1_TYPE == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
+
+ ZEND_VM_C_GOTO(is_static_prop_return);
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (OP2_TYPE == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
+ }
+ if (OP1_TYPE == IS_CONST &&
+ (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
+
+ ZEND_VM_C_GOTO(is_static_prop_return);
+ }
+ }
+
+ value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
+
+ if (OP1_TYPE == IS_CONST && value) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ }
+
+ if (OP1_TYPE != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+ FREE_OP1();
+
+ZEND_VM_C_LABEL(is_static_prop_return):
+ if (opline->extended_value & ZEND_ISSET) {
+ result = value && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = !value || !i_zend_is_true(value);
+ }
+
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV, ISSET)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -6601,7 +6766,7 @@ ZEND_VM_C_LABEL(isset_dim_obj_exit):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV)
+ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV, ISSET)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -6720,7 +6885,7 @@ ZEND_VM_HANDLER(58, ZEND_END_SILENCE, TMP, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -6759,7 +6924,7 @@ ZEND_VM_HANDLER(152, ZEND_JMP_SET, CONST|TMP|VAR|CV, ANY)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(169, ZEND_COALESCE, CONST|TMP|VAR|CV, JMP_ADDR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -6878,7 +7043,7 @@ ZEND_VM_HANDLER(139, ZEND_DECLARE_CLASS, ANY, ANY)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, ANY, ANY)
+ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, ANY, ANY, VAR)
{
USE_OPLINE
@@ -6887,7 +7052,7 @@ ZEND_VM_HANDLER(140, ZEND_DECLARE_INHERITED_CLASS, ANY, ANY)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, ANY, ANY)
+ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, ANY, ANY, VAR)
{
USE_OPLINE
zval *zce, *orig_zce;
@@ -6901,7 +7066,7 @@ ZEND_VM_HANDLER(145, ZEND_DECLARE_INHERITED_CLASS_DELAYED, ANY, ANY)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(171, ZEND_DECLARE_ANON_CLASS, ANY, ANY)
+ZEND_VM_HANDLER(171, ZEND_DECLARE_ANON_CLASS, JMP_ADDR, ANY)
{
zend_class_entry *ce;
USE_OPLINE
@@ -6922,7 +7087,7 @@ ZEND_VM_HANDLER(171, ZEND_DECLARE_ANON_CLASS, ANY, ANY)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(172, ZEND_DECLARE_ANON_INHERITED_CLASS, ANY, ANY)
+ZEND_VM_HANDLER(172, ZEND_DECLARE_ANON_INHERITED_CLASS, JMP_ADDR, ANY, VAR)
{
zend_class_entry *ce;
USE_OPLINE
@@ -6950,7 +7115,7 @@ ZEND_VM_HANDLER(141, ZEND_DECLARE_FUNCTION, ANY, ANY)
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY)
+ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY, NUM)
{
USE_OPLINE
@@ -6965,7 +7130,7 @@ ZEND_VM_HANDLER(105, ZEND_TICKS, ANY, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, CONST|VAR)
+ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, UNUSED|CONST|VAR)
{
USE_OPLINE
zend_free_op free_op1;
@@ -6990,6 +7155,12 @@ ZEND_VM_C_LABEL(try_instanceof):
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
+ } else if (OP2_TYPE == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
@@ -7100,7 +7271,7 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
* are logically thrown at the end of the foreach loop, so adjust the
* op_num.
*/
- op_num = EX(func)->op_array.brk_cont_array[exc_opline->op2.num].brk;
+ op_num = EX(func)->op_array.live_range[exc_opline->op2.num].end;
}
}
@@ -7526,7 +7697,7 @@ ZEND_VM_HANDLER(159, ZEND_DISCARD_EXCEPTION, ANY, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
+ZEND_VM_HANDLER(162, ZEND_FAST_CALL, JMP_ADDR, TRY_CATCH, FAST_CALL)
{
USE_OPLINE
zval *fast_call = EX_VAR(opline->result.var);
@@ -7542,7 +7713,7 @@ ZEND_VM_HANDLER(162, ZEND_FAST_CALL, ANY, ANY)
ZEND_VM_CONTINUE();
}
-ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
+ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, TRY_CATCH, FAST_RET)
{
USE_OPLINE
zval *fast_call = EX_VAR(opline->op1.var);
@@ -7551,7 +7722,7 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno;
ZEND_VM_SET_OPCODE(fast_ret + 1);
if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) {
- fast_call->u2.lineno = fast_ret->op2.opline_num;
+ fast_call->u2.lineno = EX(func)->op_array.try_catch_array[fast_ret->op2.num].finally_op - 2;
}
ZEND_VM_CONTINUE();
} else {
@@ -7559,15 +7730,19 @@ ZEND_VM_HANDLER(163, ZEND_FAST_RET, ANY, ANY)
USE_OPLINE
if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
- cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num);
- ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
+ uint32_t finally_op = EX(func)->op_array.try_catch_array[opline->op2.num].finally_op;
+
+ cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, finally_op);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op]);
ZEND_VM_CONTINUE();
} else {
EG(exception) = Z_OBJ_P(fast_call);
Z_OBJ_P(fast_call) = NULL;
if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
- cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num);
- ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
+ uint32_t catch_op = EX(func)->op_array.try_catch_array[opline->op2.num].catch_op;
+
+ cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, catch_op);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op]);
ZEND_VM_CONTINUE();
} else {
cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, 0);
@@ -7717,7 +7892,7 @@ ZEND_VM_C_LABEL(try_strlen):
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-ZEND_VM_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMP|VAR|CV, ANY)
+ZEND_VM_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMP|VAR|CV, ANY, TYPE)
{
USE_OPLINE
zval *value;
@@ -7773,7 +7948,7 @@ ZEND_VM_HANDLER(122, ZEND_DEFINED, CONST, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, ANY)
+ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, JMP_ADDR)
{
USE_OPLINE
@@ -7790,7 +7965,7 @@ ZEND_VM_HANDLER(151, ZEND_ASSERT_CHECK, ANY, ANY)
}
}
-ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, ANY, ANY)
+ZEND_VM_HANDLER(157, ZEND_FETCH_CLASS_NAME, ANY, ANY, CLASS_FETCH)
{
uint32_t fetch_type;
USE_OPLINE
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 5f02d4357e..975143a50a 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -1490,7 +1490,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
* are logically thrown at the end of the foreach loop, so adjust the
* op_num.
*/
- op_num = EX(func)->op_array.brk_cont_array[exc_opline->op2.num].brk;
+ op_num = EX(func)->op_array.live_range[exc_opline->op2.num].end;
}
}
@@ -1633,7 +1633,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPC
const zend_op *fast_ret = EX(func)->op_array.opcodes + fast_call->u2.lineno;
ZEND_VM_SET_OPCODE(fast_ret + 1);
if (fast_ret->extended_value & ZEND_FAST_CALL_FROM_FINALLY) {
- fast_call->u2.lineno = fast_ret->op2.opline_num;
+ fast_call->u2.lineno = EX(func)->op_array.try_catch_array[fast_ret->op2.num].finally_op - 2;
}
ZEND_VM_CONTINUE();
} else {
@@ -1641,15 +1641,19 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_RET_SPEC_HANDLER(ZEND_OPC
USE_OPLINE
if (opline->extended_value == ZEND_FAST_RET_TO_FINALLY) {
- cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num);
- ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
+ uint32_t finally_op = EX(func)->op_array.try_catch_array[opline->op2.num].finally_op;
+
+ cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, finally_op);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[finally_op]);
ZEND_VM_CONTINUE();
} else {
EG(exception) = Z_OBJ_P(fast_call);
Z_OBJ_P(fast_call) = NULL;
if (opline->extended_value == ZEND_FAST_RET_TO_CATCH) {
- cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, opline->op2.opline_num);
- ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->op2.opline_num]);
+ uint32_t catch_op = EX(func)->op_array.try_catch_array[opline->op2.num].catch_op;
+
+ cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, catch_op);
+ ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[catch_op]);
ZEND_VM_CONTINUE();
} else {
cleanup_live_vars(execute_data, opline - EX(func)->op_array.opcodes, 0);
@@ -3357,6 +3361,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_CONST_HANDLER(ZEND_OP
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -4929,14 +4939,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CONST_HAND
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_CONST(int type ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_CONST_CONST(int type ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zval *varname;
zval *retval;
zend_string *name;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
SAVE_OPLINE();
varname = EX_CONSTANT(opline->op1);
@@ -4953,116 +4963,66 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
name = zval_get_string(varname);
}
- if (IS_CONST != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_CONST == IS_CONST) {
- if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
-
- HANDLE_EXCEPTION();
- }
+ if (IS_CONST == IS_CONST) {
+ if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- goto fetch_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (IS_CONST != IS_CONST) {
- zend_string_release(name);
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CONST == IS_CONST &&
- (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- HANDLE_EXCEPTION();
+ goto fetch_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CONST != IS_CONST) {
+ zend_string_release(name);
}
- goto fetch_var_return;
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
- retval = zend_std_get_static_property(ce, name, 0);
- if (UNEXPECTED(EG(exception))) {
-
- HANDLE_EXCEPTION();
- }
- if (IS_CONST == IS_CONST && retval) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
- }
-
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- retval = zend_hash_find(target_symbol_table, name);
- if (retval == NULL) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- case BP_VAR_W:
- retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
- retval = Z_INDIRECT_P(retval);
- if (Z_TYPE_P(retval) == IS_UNDEF) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_W:
- ZVAL_NULL(retval);
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
+ if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
- 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)) {
+ if (IS_CONST == IS_CONST &&
+ (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- HANDLE_EXCEPTION();
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+
+ HANDLE_EXCEPTION();
}
- } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
+ goto fetch_static_prop_return;
}
}
+ retval = zend_std_get_static_property(ce, name, 0);
+ if (UNEXPECTED(EG(exception))) {
+
+ HANDLE_EXCEPTION();
+ }
+ if (IS_CONST == IS_CONST && retval) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ }
if (IS_CONST != IS_CONST) {
zend_string_release(name);
}
-fetch_var_return:
+fetch_static_prop_return:
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
@@ -5075,40 +5035,40 @@ fetch_var_return:
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_CONST(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
} else {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_CONST(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_CONST(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_CONST(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -5622,6 +5582,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -5715,10 +5681,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
}
}
- if (IS_CONST != IS_CONST) {
+ if (IS_CONST == IS_UNUSED) {
/* previous opcode is ZEND_FETCH_CLASS */
- if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
- ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
ce = EX(called_scope);
}
}
@@ -5855,110 +5821,82 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CONST_HANDLER(
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
+ zend_class_entry *ce;
+ zval *value;
USE_OPLINE
SAVE_OPLINE();
- if (IS_CONST == IS_UNUSED) {
- zend_constant *c;
-
- if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
- c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- } else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
- if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
- char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
- if (!actual) {
- ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(EX_CONSTANT(opline->op2)));
- } else {
- actual++;
- ZVAL_STRINGL(EX_VAR(opline->result.var),
- actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
- }
- /* non-qualified constant - allow text substitution */
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
- Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- } else {
- zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- HANDLE_EXCEPTION();
- }
- } else {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
- }
-#ifdef ZTS
- if (c->flags & CONST_PERSISTENT) {
- ZVAL_DUP(EX_VAR(opline->result.var), &c->value);
- } else {
- ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
- }
-#else
- ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
-#endif
- } else {
- /* class constant */
- zend_class_entry *ce;
- zval *value;
- do {
- if (IS_CONST == IS_CONST) {
- if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- ZVAL_DEREF(value);
+ do {
+ if (IS_CONST == IS_CONST) {
+ if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ ZVAL_DEREF(value);
#ifdef ZTS
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
#endif
- break;
- } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
- } else {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
- }
- HANDLE_EXCEPTION();
+ break;
+ } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ } else {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ HANDLE_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ }
+ } else {
+ if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
- if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
- ZVAL_DEREF(value);
- break;
- }
}
-
- if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
ZVAL_DEREF(value);
- if (Z_CONSTANT_P(value)) {
- EG(scope) = ce;
- zval_update_constant_ex(value, 1, NULL);
- EG(scope) = EX(func)->op_array.scope;
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
- }
- }
- if (IS_CONST == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
- } else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ break;
+ }
+ }
+
+ if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ ZVAL_DEREF(value);
+ if (Z_CONSTANT_P(value)) {
+ EG(scope) = ce;
+ zval_update_constant_ex(value, 1, NULL);
+ EG(scope) = EX(func)->op_array.scope;
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
}
+ }
+ if (IS_CONST == IS_CONST) {
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
} else {
- zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- HANDLE_EXCEPTION();
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
}
- } while (0);
-#ifdef ZTS
- if (ce->type == ZEND_INTERNAL_CLASS) {
- ZVAL_DUP(EX_VAR(opline->result.var), value);
} else {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ HANDLE_EXCEPTION();
}
-#else
+ } while (0);
+
+#ifdef ZTS
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ ZVAL_DUP(EX_VAR(opline->result.var), value);
+ } else {
ZVAL_COPY(EX_VAR(opline->result.var), value);
-#endif
}
+#else
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+#endif
+
ZEND_VM_NEXT_OPCODE();
}
@@ -6092,40 +6030,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CONST_CONST_HA
}
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval tmp, *varname;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
SAVE_OPLINE();
- if (IS_CONST == IS_CV &&
- IS_CONST == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- zval *var = EX_VAR(opline->op1.var);
-
- if (Z_REFCOUNTED_P(var)) {
- zend_refcounted *garbage = Z_COUNTED_P(var);
-
- if (!--GC_REFCOUNT(garbage)) {
- ZVAL_UNDEF(var);
- zval_dtor_func_for_ptr(garbage);
- } else {
- zval *z = var;
- ZVAL_DEREF(z);
- if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) {
- ZVAL_UNDEF(var);
- gc_possible_root(Z_COUNTED_P(z));
- } else {
- ZVAL_UNDEF(var);
- }
- }
- } else {
- ZVAL_UNDEF(var);
- }
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
varname = EX_CONSTANT(opline->op1);
@@ -6138,33 +6050,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HAN
varname = &tmp;
}
- if (IS_CONST != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_CONST == IS_CONST) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (IS_CONST == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- }
- if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
-
- HANDLE_EXCEPTION();
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
- zend_std_unset_static_property(ce, Z_STR_P(varname));
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ zend_std_unset_static_property(ce, Z_STR_P(varname));
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
@@ -6173,103 +6084,83 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HAN
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *value;
int result;
- if (IS_CONST == IS_CV &&
- IS_CONST == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- value = EX_VAR(opline->op1.var);
- if (opline->extended_value & ZEND_ISSET) {
- result =
- Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- SAVE_OPLINE();
- result = !i_zend_is_true(value);
- if (UNEXPECTED(EG(exception))) {
- HANDLE_EXCEPTION();
- }
- }
- ZEND_VM_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_SET_NEXT_OPCODE(opline + 1);
- ZEND_VM_CONTINUE();
- } else {
-
- zval tmp, *varname;
-
- SAVE_OPLINE();
- varname = EX_CONSTANT(opline->op1);
- ZVAL_UNDEF(&tmp);
- if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
- ZVAL_STR(&tmp, zval_get_string(varname));
- varname = &tmp;
- }
-
- if (IS_CONST != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_CONST == IS_CONST) {
- if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
+ zval tmp, *varname;
+ zend_class_entry *ce;
- goto is_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CONST == IS_CONST &&
- (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+ SAVE_OPLINE();
+ varname = EX_CONSTANT(opline->op1);
+ ZVAL_UNDEF(&tmp);
+ if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
+ if (IS_CONST == IS_CONST) {
+ if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- goto is_var_return;
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
}
- value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
-
- if (IS_CONST == IS_CONST && value) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ goto is_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
} else {
- HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ if (IS_CONST == IS_CONST &&
+ (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
-is_var_return:
- if (opline->extended_value & ZEND_ISSET) {
- result = value && Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- result = !value || !i_zend_is_true(value);
+ goto is_static_prop_return;
}
+ }
- ZEND_VM_SMART_BRANCH(result, 1);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
+
+ if (IS_CONST == IS_CONST && value) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ }
+
+ if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
}
+
+is_static_prop_return:
+ if (opline->extended_value & ZEND_ISSET) {
+ result = value && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = !value || !i_zend_is_true(value);
+ }
+
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CONST_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -6845,14 +6736,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_VA
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CONST_VAR(int type ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_CONST_VAR(int type ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zval *varname;
zval *retval;
zend_string *name;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
SAVE_OPLINE();
varname = EX_CONSTANT(opline->op1);
@@ -6869,116 +6760,66 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
name = zval_get_string(varname);
}
- if (IS_VAR != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_VAR == IS_CONST) {
- if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
-
- HANDLE_EXCEPTION();
- }
+ if (IS_VAR == IS_CONST) {
+ if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- goto fetch_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (IS_CONST != IS_CONST) {
- zend_string_release(name);
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CONST == IS_CONST &&
- (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
-
- HANDLE_EXCEPTION();
+ goto fetch_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CONST != IS_CONST) {
+ zend_string_release(name);
}
- goto fetch_var_return;
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
- retval = zend_std_get_static_property(ce, name, 0);
- if (UNEXPECTED(EG(exception))) {
-
- HANDLE_EXCEPTION();
- }
- if (IS_CONST == IS_CONST && retval) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
- }
-
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- retval = zend_hash_find(target_symbol_table, name);
- if (retval == NULL) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- case BP_VAR_W:
- retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
- retval = Z_INDIRECT_P(retval);
- if (Z_TYPE_P(retval) == IS_UNDEF) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_W:
- ZVAL_NULL(retval);
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
+ if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
- 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)) {
+ if (IS_CONST == IS_CONST &&
+ (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- HANDLE_EXCEPTION();
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+
+ HANDLE_EXCEPTION();
}
- } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
+ goto fetch_static_prop_return;
}
}
+ retval = zend_std_get_static_property(ce, name, 0);
+ if (UNEXPECTED(EG(exception))) {
+
+ HANDLE_EXCEPTION();
+ }
+ if (IS_CONST == IS_CONST && retval) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ }
if (IS_CONST != IS_CONST) {
zend_string_release(name);
}
-fetch_var_return:
+fetch_static_prop_return:
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
@@ -6991,76 +6832,50 @@ fetch_var_return:
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_VAR(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
} else {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_VAR(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_VAR(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_VAR(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval tmp, *varname;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
SAVE_OPLINE();
- if (IS_CONST == IS_CV &&
- IS_VAR == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- zval *var = EX_VAR(opline->op1.var);
-
- if (Z_REFCOUNTED_P(var)) {
- zend_refcounted *garbage = Z_COUNTED_P(var);
-
- if (!--GC_REFCOUNT(garbage)) {
- ZVAL_UNDEF(var);
- zval_dtor_func_for_ptr(garbage);
- } else {
- zval *z = var;
- ZVAL_DEREF(z);
- if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) {
- ZVAL_UNDEF(var);
- gc_possible_root(Z_COUNTED_P(z));
- } else {
- ZVAL_UNDEF(var);
- }
- }
- } else {
- ZVAL_UNDEF(var);
- }
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
varname = EX_CONSTANT(opline->op1);
@@ -7073,33 +6888,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDL
varname = &tmp;
}
- if (IS_VAR != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_VAR == IS_CONST) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (IS_VAR == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- }
- if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
-
- HANDLE_EXCEPTION();
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
- zend_std_unset_static_property(ce, Z_STR_P(varname));
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ zend_std_unset_static_property(ce, Z_STR_P(varname));
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
@@ -7108,103 +6922,83 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDL
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *value;
int result;
- if (IS_CONST == IS_CV &&
- IS_VAR == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- value = EX_VAR(opline->op1.var);
- if (opline->extended_value & ZEND_ISSET) {
- result =
- Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- SAVE_OPLINE();
- result = !i_zend_is_true(value);
- if (UNEXPECTED(EG(exception))) {
- HANDLE_EXCEPTION();
- }
- }
- ZEND_VM_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_SET_NEXT_OPCODE(opline + 1);
- ZEND_VM_CONTINUE();
- } else {
-
- zval tmp, *varname;
-
- SAVE_OPLINE();
- varname = EX_CONSTANT(opline->op1);
- ZVAL_UNDEF(&tmp);
- if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
- ZVAL_STR(&tmp, zval_get_string(varname));
- varname = &tmp;
- }
-
- if (IS_VAR != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_VAR == IS_CONST) {
- if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
+ zval tmp, *varname;
+ zend_class_entry *ce;
- goto is_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CONST == IS_CONST &&
- (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+ SAVE_OPLINE();
+ varname = EX_CONSTANT(opline->op1);
+ ZVAL_UNDEF(&tmp);
+ if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
+ if (IS_VAR == IS_CONST) {
+ if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- goto is_var_return;
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
}
- value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
-
- if (IS_CONST == IS_CONST && value) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ goto is_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
} else {
- HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ if (IS_CONST == IS_CONST &&
+ (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
-is_var_return:
- if (opline->extended_value & ZEND_ISSET) {
- result = value && Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- result = !value || !i_zend_is_true(value);
+ goto is_static_prop_return;
}
+ }
- ZEND_VM_SMART_BRANCH(result, 1);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
+
+ if (IS_CONST == IS_CONST && value) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ }
+
+ if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+
+is_static_prop_return:
+ if (opline->extended_value & ZEND_ISSET) {
+ result = value && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = !value || !i_zend_is_true(value);
}
+
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -7372,60 +7166,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
name = zval_get_string(varname);
}
- if (IS_UNUSED != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_UNUSED == IS_CONST) {
- if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
-
- HANDLE_EXCEPTION();
- }
-
- goto fetch_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (IS_CONST != IS_CONST) {
- zend_string_release(name);
- }
-
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CONST == IS_CONST &&
- (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
-
- HANDLE_EXCEPTION();
- }
-
- goto fetch_var_return;
- }
- }
- retval = zend_std_get_static_property(ce, name, 0);
- if (UNEXPECTED(EG(exception))) {
-
- HANDLE_EXCEPTION();
- }
- if (IS_CONST == IS_CONST && retval) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ retval = zend_hash_find(target_symbol_table, name);
+ if (retval == NULL) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
+ retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
+ break;
+ case BP_VAR_W:
+ retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
}
-
- } else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- retval = zend_hash_find(target_symbol_table, name);
- if (retval == NULL) {
+ /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
+ } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
+ retval = Z_INDIRECT_P(retval);
+ if (Z_TYPE_P(retval) == IS_UNDEF) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
@@ -7436,52 +7200,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
- break;
+ /* break missing intentionally */
case BP_VAR_W:
- retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
+ ZVAL_NULL(retval);
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
- /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
- retval = Z_INDIRECT_P(retval);
- if (Z_TYPE_P(retval) == IS_UNDEF) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_W:
- ZVAL_NULL(retval);
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- }
}
- 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_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 (IS_CONST != IS_CONST) {
zend_string_release(name);
}
-fetch_var_return:
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
@@ -7530,6 +7272,138 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CONST_UNUSED_HAN
ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CONST_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_CONST_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC)
+{
+ USE_OPLINE
+
+ zval *varname;
+ zval *retval;
+ zend_string *name;
+ zend_class_entry *ce;
+
+ SAVE_OPLINE();
+ varname = EX_CONSTANT(opline->op1);
+
+ if (IS_CONST == IS_CONST) {
+ name = Z_STR_P(varname);
+ } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
+ name = Z_STR_P(varname);
+ zend_string_addref(name);
+ } else {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(varname, BP_VAR_R);
+ }
+ name = zval_get_string(varname);
+ }
+
+ if (IS_UNUSED == IS_CONST) {
+ if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+
+ HANDLE_EXCEPTION();
+ }
+
+ goto fetch_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CONST != IS_CONST) {
+ zend_string_release(name);
+ }
+
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
+ }
+ if (IS_CONST == IS_CONST &&
+ (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+
+ HANDLE_EXCEPTION();
+ }
+
+ goto fetch_static_prop_return;
+ }
+ }
+ retval = zend_std_get_static_property(ce, name, 0);
+ if (UNEXPECTED(EG(exception))) {
+
+ HANDLE_EXCEPTION();
+ }
+ if (IS_CONST == IS_CONST && retval) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ }
+
+ if (IS_CONST != IS_CONST) {
+ zend_string_release(name);
+ }
+
+fetch_static_prop_return:
+ ZEND_ASSERT(retval != NULL);
+ if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ } else {
+ ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
+ }
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_UNUSED(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ } else {
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ }
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_UNUSED(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CONST_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -7597,6 +7471,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -7690,10 +7570,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
}
}
- if (IS_CONST != IS_CONST) {
+ if (IS_CONST == IS_UNUSED) {
/* previous opcode is ZEND_FETCH_CLASS */
- if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
- ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
ce = EX(called_scope);
}
}
@@ -7754,8 +7634,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_
if (UNEXPECTED(EG(exception) != NULL)) {
if (IS_CONST == IS_CONST) {
zval_ptr_dtor_nogc(retval_ptr);
- } else {
-
}
}
#endif
@@ -7902,7 +7780,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HA
SAVE_OPLINE();
if (IS_CONST == IS_CV &&
- IS_UNUSED == IS_UNUSED &&
(opline->extended_value & ZEND_QUICK_SET)) {
zval *var = EX_VAR(opline->op1.var);
@@ -7939,33 +7816,62 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HA
varname = &tmp;
}
- if (IS_UNUSED != IS_UNUSED) {
- zend_class_entry *ce;
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
- if (IS_UNUSED == IS_CONST) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- }
- if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
+ if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
- HANDLE_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ zend_class_entry *ce;
+
+
+ SAVE_OPLINE();
+
+ varname = EX_CONSTANT(opline->op1);
+
+ ZVAL_UNDEF(&tmp);
+ if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
+ varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R);
+ }
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
+
+ if (IS_UNUSED == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
- zend_std_unset_static_property(ce, Z_STR_P(varname));
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ zend_std_unset_static_property(ce, Z_STR_P(varname));
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
@@ -7981,7 +7887,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_U
int result;
if (IS_CONST == IS_CV &&
- IS_UNUSED == IS_UNUSED &&
(opline->extended_value & ZEND_QUICK_SET)) {
value = EX_VAR(opline->op1.var);
if (opline->extended_value & ZEND_ISSET) {
@@ -8002,6 +7907,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_U
} else {
zval tmp, *varname;
+ HashTable *target_symbol_table;
SAVE_OPLINE();
varname = EX_CONSTANT(opline->op1);
@@ -8011,55 +7917,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_U
varname = &tmp;
}
- if (IS_UNUSED != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_UNUSED == IS_CONST) {
- if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
-
- goto is_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CONST == IS_CONST &&
- (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
-
- goto is_var_return;
- }
- }
-
- value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
-
- if (IS_CONST == IS_CONST && value) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
- }
- } else {
- HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
- }
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
}
-is_var_return:
if (opline->extended_value & ZEND_ISSET) {
result = value && Z_TYPE_P(value) > IS_NULL &&
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
@@ -8073,6 +7937,85 @@ is_var_return:
}
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *value;
+ int result;
+
+ zval tmp, *varname;
+ zend_class_entry *ce;
+
+ SAVE_OPLINE();
+ varname = EX_CONSTANT(opline->op1);
+ ZVAL_UNDEF(&tmp);
+ if (IS_CONST != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
+
+ if (IS_UNUSED == IS_CONST) {
+ if (IS_CONST == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
+
+ goto is_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
+ }
+ if (IS_CONST == IS_CONST &&
+ (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
+
+ goto is_static_prop_return;
+ }
+ }
+
+ value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
+
+ if (IS_CONST == IS_CONST && value) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ }
+
+ if (IS_CONST != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+
+is_static_prop_return:
+ if (opline->extended_value & ZEND_ISSET) {
+ result = value && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = !value || !i_zend_is_true(value);
+ }
+
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DECLARE_LAMBDA_FUNCTION_SPEC_CONST_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -9340,6 +9283,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -9433,10 +9382,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
}
}
- if (IS_CONST != IS_CONST) {
+ if (IS_CONST == IS_UNUSED) {
/* previous opcode is ZEND_FETCH_CLASS */
- if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
- ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
ce = EX(called_scope);
}
}
@@ -9517,8 +9466,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZE
/* Check whether an exception has been thrown, if not, jump over code */
zend_exception_restore();
if (EG(exception) == NULL) {
- ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
- ZEND_VM_CONTINUE(); /* CHECK_ME */
+ ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
+ ZEND_VM_CONTINUE();
}
catch_ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
if (UNEXPECTED(catch_ce == NULL)) {
@@ -9540,8 +9489,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CATCH_SPEC_CONST_CV_HANDLER(ZE
zend_throw_exception_internal(NULL);
HANDLE_EXCEPTION();
}
- ZEND_VM_SET_OPCODE(&EX(func)->op_array.opcodes[opline->extended_value]);
- ZEND_VM_CONTINUE(); /* CHECK_ME */
+ ZEND_VM_SET_RELATIVE_OPCODE(opline, opline->extended_value);
+ ZEND_VM_CONTINUE();
}
}
@@ -11148,6 +11097,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -11241,10 +11196,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
}
}
- if (IS_CONST != IS_CONST) {
+ if (IS_CONST == IS_UNUSED) {
/* previous opcode is ZEND_FETCH_CLASS */
- if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
- ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
ce = EX(called_scope);
}
}
@@ -13546,8 +13501,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN
if (UNEXPECTED(EG(exception) != NULL)) {
if (IS_TMP_VAR == IS_CONST) {
zval_ptr_dtor_nogc(retval_ptr);
- } else {
- zval_ptr_dtor_nogc(free_op1);
}
}
#endif
@@ -15347,6 +15300,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_VAR_HANDLER(ZEND_OPCO
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -15871,13 +15830,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZE
* In case that ever happens we need an additional flag. */
iter->funcs->move_forward(iter);
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
if (UNEXPECTED(iter->funcs->valid(iter) == FAILURE)) {
/* reached end of iteration */
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
goto fe_fetch_r_exit;
@@ -15885,7 +15842,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZE
}
value = iter->funcs->get_current_data(iter);
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
if (!value) {
@@ -15896,7 +15852,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_R_SPEC_VAR_HANDLER(ZE
if (iter->funcs->get_current_key) {
iter->funcs->get_current_key(iter, EX_VAR(opline->result.var));
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
} else {
@@ -16063,13 +16018,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z
* In case that ever happens we need an additional flag. */
iter->funcs->move_forward(iter);
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
if (UNEXPECTED(iter->funcs->valid(iter) == FAILURE)) {
/* reached end of iteration */
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
goto fe_fetch_w_exit;
@@ -16077,7 +16030,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z
}
value = iter->funcs->get_current_data(iter);
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
if (!value) {
@@ -16088,7 +16040,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FE_FETCH_RW_SPEC_VAR_HANDLER(Z
if (iter->funcs->get_current_key) {
iter->funcs->get_current_key(iter, EX_VAR(opline->result.var));
if (UNEXPECTED(EG(exception) != NULL)) {
- zval_ptr_dtor(array);
HANDLE_EXCEPTION();
}
} else {
@@ -17477,6 +17428,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -17570,10 +17527,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
}
}
- if (IS_VAR != IS_CONST) {
+ if (IS_VAR == IS_UNUSED) {
/* previous opcode is ZEND_FETCH_CLASS */
- if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
- ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
ce = EX(called_scope);
}
}
@@ -17586,110 +17543,82 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
+ zend_class_entry *ce;
+ zval *value;
USE_OPLINE
SAVE_OPLINE();
- if (IS_VAR == IS_UNUSED) {
- zend_constant *c;
-
- if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
- c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- } else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
- if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
- char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
- if (!actual) {
- ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(EX_CONSTANT(opline->op2)));
- } else {
- actual++;
- ZVAL_STRINGL(EX_VAR(opline->result.var),
- actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
- }
- /* non-qualified constant - allow text substitution */
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
- Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- } else {
- zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- HANDLE_EXCEPTION();
- }
- } else {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
- }
-#ifdef ZTS
- if (c->flags & CONST_PERSISTENT) {
- ZVAL_DUP(EX_VAR(opline->result.var), &c->value);
- } else {
- ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
- }
-#else
- ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
-#endif
- } else {
- /* class constant */
- zend_class_entry *ce;
- zval *value;
- do {
- if (IS_VAR == IS_CONST) {
- if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- ZVAL_DEREF(value);
+ do {
+ if (IS_VAR == IS_CONST) {
+ if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ ZVAL_DEREF(value);
#ifdef ZTS
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
#endif
- break;
- } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
- } else {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
- }
- HANDLE_EXCEPTION();
+ break;
+ } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ } else {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ HANDLE_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ }
+ } else {
+ if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
- if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
- ZVAL_DEREF(value);
- break;
- }
}
-
- if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
ZVAL_DEREF(value);
- if (Z_CONSTANT_P(value)) {
- EG(scope) = ce;
- zval_update_constant_ex(value, 1, NULL);
- EG(scope) = EX(func)->op_array.scope;
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
- }
- }
- if (IS_VAR == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
- } else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ break;
+ }
+ }
+
+ if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ ZVAL_DEREF(value);
+ if (Z_CONSTANT_P(value)) {
+ EG(scope) = ce;
+ zval_update_constant_ex(value, 1, NULL);
+ EG(scope) = EX(func)->op_array.scope;
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
}
+ }
+ if (IS_VAR == IS_CONST) {
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
} else {
- zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- HANDLE_EXCEPTION();
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
}
- } while (0);
-#ifdef ZTS
- if (ce->type == ZEND_INTERNAL_CLASS) {
- ZVAL_DUP(EX_VAR(opline->result.var), value);
} else {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ HANDLE_EXCEPTION();
}
-#else
+ } while (0);
+
+#ifdef ZTS
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ ZVAL_DUP(EX_VAR(opline->result.var), value);
+ } else {
ZVAL_COPY(EX_VAR(opline->result.var), value);
-#endif
}
+#else
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+#endif
+
ZEND_VM_NEXT_OPCODE();
}
@@ -19105,6 +19034,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -19198,10 +19133,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
}
}
- if (IS_VAR != IS_CONST) {
+ if (IS_VAR == IS_UNUSED) {
/* previous opcode is ZEND_FETCH_CLASS */
- if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
- ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
ce = EX(called_scope);
}
}
@@ -19262,8 +19197,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN
if (UNEXPECTED(EG(exception) != NULL)) {
if (IS_VAR == IS_CONST) {
zval_ptr_dtor_nogc(retval_ptr);
- } else {
- zval_ptr_dtor_nogc(free_op1);
}
}
#endif
@@ -20726,6 +20659,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -20819,10 +20758,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
}
}
- if (IS_VAR != IS_CONST) {
+ if (IS_VAR == IS_UNUSED) {
/* previous opcode is ZEND_FETCH_CLASS */
- if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
- ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
ce = EX(called_scope);
}
}
@@ -22296,6 +22235,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
+ } else if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
}
@@ -22389,10 +22334,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
}
}
- if (IS_VAR != IS_CONST) {
+ if (IS_VAR == IS_UNUSED) {
/* previous opcode is ZEND_FETCH_CLASS */
- if (((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
- ((opline-1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
ce = EX(called_scope);
}
}
@@ -22678,6 +22623,64 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_NEW_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval object_zval;
+ zend_function *constructor;
+ zend_class_entry *ce;
+
+ SAVE_OPLINE();
+ if (IS_UNUSED == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ }
+ } else if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op1.var));
+ }
+ if (UNEXPECTED(object_init_ex(&object_zval, ce) != SUCCESS)) {
+ HANDLE_EXCEPTION();
+ }
+ constructor = Z_OBJ_HT(object_zval)->get_constructor(Z_OBJ(object_zval));
+
+ 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),
+ constructor,
+ opline->extended_value,
+ ce,
+ Z_OBJ(object_zval));
+ call->prev_execute_data = EX(call);
+ EX(call) = call;
+
+ if (EXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_COPY(EX_VAR(opline->result.var), &object_zval);
+ }
+
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -23779,110 +23782,266 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
+ zval *function_name;
+ zend_class_entry *ce;
+ zend_object *object;
+ zend_function *fbc;
+ zend_execute_data *call;
SAVE_OPLINE();
- if (IS_UNUSED == IS_UNUSED) {
- zend_constant *c;
-
- if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
- c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- } else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
- if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
- char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
- if (!actual) {
- ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(EX_CONSTANT(opline->op2)));
- } else {
- actual++;
- ZVAL_STRINGL(EX_VAR(opline->result.var),
- actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
+
+ if (IS_UNUSED == IS_CONST) {
+ /* no function found. try a static method in class */
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
}
- /* non-qualified constant - allow text substitution */
- zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
- Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- } else {
- zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
HANDLE_EXCEPTION();
}
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ }
+ } else if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op1.var));
+ }
+
+ if (IS_UNUSED == IS_CONST &&
+ IS_CONST == IS_CONST &&
+ EXPECTED((fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ /* nothing to do */
+ } else if (IS_UNUSED != IS_CONST &&
+ IS_CONST == IS_CONST &&
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
+ /* do nothing */
+ } else if (IS_CONST != IS_UNUSED) {
+
+
+ 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();
+ }
+ }
+ zend_throw_error(NULL, "Function name must be a string");
+
+ HANDLE_EXCEPTION();
+ }
+ }
+
+ if (ce->get_static_method) {
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name));
} else {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CONST == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
}
-#ifdef ZTS
- if (c->flags & CONST_PERSISTENT) {
- ZVAL_DUP(EX_VAR(opline->result.var), &c->value);
+ if (UNEXPECTED(fbc == NULL)) {
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(ce->name), Z_STRVAL_P(function_name));
+ }
+
+ HANDLE_EXCEPTION();
+ }
+ if (IS_CONST == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
+ if (IS_UNUSED == IS_CONST) {
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
+ } else {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
+ }
+ }
+ if (IS_CONST != IS_CONST) {
+
+ }
+ } else {
+ if (UNEXPECTED(ce->constructor == NULL)) {
+ zend_throw_error(NULL, "Cannot call constructor");
+ HANDLE_EXCEPTION();
+ }
+ if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+ zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name));
+ HANDLE_EXCEPTION();
+ }
+ fbc = ce->constructor;
+ }
+
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
+ object = Z_OBJ(EX(This));
+ }
+ if (!object) {
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ /* Allowed for PHP 4 compatibility. */
+ zend_error(
+ E_DEPRECATED,
+ "Non-static method %s::%s() should not be called statically",
+ ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ /* An internal function assumes $this is present and won't check that.
+ * So PHP would crash by allowing the call. */
+ zend_throw_error(
+ zend_ce_error,
+ "Non-static method %s::%s() cannot be called statically",
+ ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
+ HANDLE_EXCEPTION();
+ }
+ }
+ }
+
+ if (IS_UNUSED == IS_UNUSED) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ ce = EX(called_scope);
+ }
+ }
+
+ call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+ fbc, opline->extended_value, ce, object);
+ call->prev_execute_data = EX(call);
+ EX(call) = call;
+
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_constant *c;
+
+ SAVE_OPLINE();
+
+ if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
+ c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ } else if ((c = zend_quick_get_constant(EX_CONSTANT(opline->op2) + 1, opline->extended_value)) == NULL) {
+ if ((opline->extended_value & IS_CONSTANT_UNQUALIFIED) != 0) {
+ char *actual = (char *)zend_memrchr(Z_STRVAL_P(EX_CONSTANT(opline->op2)), '\\', Z_STRLEN_P(EX_CONSTANT(opline->op2)));
+ if (!actual) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), Z_STR_P(EX_CONSTANT(opline->op2)));
+ } else {
+ actual++;
+ ZVAL_STRINGL(EX_VAR(opline->result.var),
+ actual, Z_STRLEN_P(EX_CONSTANT(opline->op2)) - (actual - Z_STRVAL_P(EX_CONSTANT(opline->op2))));
+ }
+ /* non-qualified constant - allow text substitution */
+ zend_error(E_NOTICE, "Use of undefined constant %s - assumed '%s'",
+ Z_STRVAL_P(EX_VAR(opline->result.var)), Z_STRVAL_P(EX_VAR(opline->result.var)));
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
} else {
- ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
+ zend_throw_error(NULL, "Undefined constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ HANDLE_EXCEPTION();
}
-#else
+ } else {
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
+ }
+
+#ifdef ZTS
+ if (c->flags & CONST_PERSISTENT) {
+ ZVAL_DUP(EX_VAR(opline->result.var), &c->value);
+ } else {
ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
+ }
+#else
+ ZVAL_COPY(EX_VAR(opline->result.var), &c->value);
#endif
- } else {
- /* class constant */
- zend_class_entry *ce;
- zval *value;
- do {
- if (IS_UNUSED == IS_CONST) {
- if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- ZVAL_DEREF(value);
+ ZEND_VM_NEXT_OPCODE();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_CONSTANT_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ zend_class_entry *ce;
+ zval *value;
+ USE_OPLINE
+
+ SAVE_OPLINE();
+
+ do {
+ if (IS_UNUSED == IS_CONST) {
+ if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2))))) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ ZVAL_DEREF(value);
#ifdef ZTS
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
#endif
- break;
- } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
- } else {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
- }
- HANDLE_EXCEPTION();
+ break;
+ } else if (EXPECTED(CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1))))) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ } else {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ HANDLE_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ }
+ } else {
+ if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
} else {
ce = Z_CE_P(EX_VAR(opline->op1.var));
- if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
- ZVAL_DEREF(value);
- break;
- }
}
-
- if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ if ((value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce)) != NULL) {
ZVAL_DEREF(value);
- if (Z_CONSTANT_P(value)) {
- EG(scope) = ce;
- zval_update_constant_ex(value, 1, NULL);
- EG(scope) = EX(func)->op_array.scope;
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
- }
- }
- if (IS_UNUSED == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
- } else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ break;
+ }
+ }
+
+ if (EXPECTED((value = zend_hash_find(&ce->constants_table, Z_STR_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ ZVAL_DEREF(value);
+ if (Z_CONSTANT_P(value)) {
+ EG(scope) = ce;
+ zval_update_constant_ex(value, 1, NULL);
+ EG(scope) = EX(func)->op_array.scope;
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
}
+ }
+ if (IS_UNUSED == IS_CONST) {
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
} else {
- zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- HANDLE_EXCEPTION();
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
}
- } while (0);
-#ifdef ZTS
- if (ce->type == ZEND_INTERNAL_CLASS) {
- ZVAL_DUP(EX_VAR(opline->result.var), value);
} else {
- ZVAL_COPY(EX_VAR(opline->result.var), value);
+ zend_throw_error(NULL, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ HANDLE_EXCEPTION();
}
-#else
+ } while (0);
+
+#ifdef ZTS
+ if (ce->type == ZEND_INTERNAL_CLASS) {
+ ZVAL_DUP(EX_VAR(opline->result.var), value);
+ } else {
ZVAL_COPY(EX_VAR(opline->result.var), value);
-#endif
}
+#else
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+#endif
+
ZEND_VM_NEXT_OPCODE();
}
@@ -24974,6 +25133,146 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_POW_SPEC_UNUSED_UNUSED_
#endif
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *function_name;
+ zend_class_entry *ce;
+ zend_object *object;
+ zend_function *fbc;
+ zend_execute_data *call;
+
+ SAVE_OPLINE();
+
+ if (IS_UNUSED == IS_CONST) {
+ /* no function found. try a static method in class */
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
+ HANDLE_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ }
+ } else if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op1.var));
+ }
+
+ if (IS_UNUSED == IS_CONST &&
+ IS_UNUSED == IS_CONST &&
+ EXPECTED((fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ /* nothing to do */
+ } else if (IS_UNUSED != IS_CONST &&
+ IS_UNUSED == IS_CONST &&
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
+ /* do nothing */
+ } else if (IS_UNUSED != IS_UNUSED) {
+
+
+ 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();
+ }
+ }
+ zend_throw_error(NULL, "Function name must be a string");
+
+ HANDLE_EXCEPTION();
+ }
+ }
+
+ if (ce->get_static_method) {
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name));
+ } else {
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_UNUSED == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
+ }
+ if (UNEXPECTED(fbc == NULL)) {
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(ce->name), Z_STRVAL_P(function_name));
+ }
+
+ HANDLE_EXCEPTION();
+ }
+ if (IS_UNUSED == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
+ if (IS_UNUSED == IS_CONST) {
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
+ } else {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
+ }
+ }
+ if (IS_UNUSED != IS_CONST) {
+
+ }
+ } else {
+ if (UNEXPECTED(ce->constructor == NULL)) {
+ zend_throw_error(NULL, "Cannot call constructor");
+ HANDLE_EXCEPTION();
+ }
+ if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+ zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name));
+ HANDLE_EXCEPTION();
+ }
+ fbc = ce->constructor;
+ }
+
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
+ object = Z_OBJ(EX(This));
+ }
+ if (!object) {
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ /* Allowed for PHP 4 compatibility. */
+ zend_error(
+ E_DEPRECATED,
+ "Non-static method %s::%s() should not be called statically",
+ ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ /* An internal function assumes $this is present and won't check that.
+ * So PHP would crash by allowing the call. */
+ zend_throw_error(
+ zend_ce_error,
+ "Non-static method %s::%s() cannot be called statically",
+ ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
+ HANDLE_EXCEPTION();
+ }
+ }
+ }
+
+ if (IS_UNUSED == IS_UNUSED) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ ce = EX(called_scope);
+ }
+ }
+
+ call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+ fbc, opline->extended_value, ce, object);
+ call->prev_execute_data = EX(call);
+ EX(call) = call;
+
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -25022,8 +25321,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED
if (UNEXPECTED(EG(exception) != NULL)) {
if (IS_UNUSED == IS_CONST) {
zval_ptr_dtor_nogc(retval_ptr);
- } else {
-
}
}
#endif
@@ -26194,6 +26491,146 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *function_name;
+ zend_class_entry *ce;
+ zend_object *object;
+ zend_function *fbc;
+ zend_execute_data *call;
+
+ SAVE_OPLINE();
+
+ if (IS_UNUSED == IS_CONST) {
+ /* no function found. try a static method in class */
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
+ HANDLE_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ }
+ } else if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op1.var));
+ }
+
+ if (IS_UNUSED == IS_CONST &&
+ IS_CV == IS_CONST &&
+ EXPECTED((fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ /* nothing to do */
+ } else if (IS_UNUSED != IS_CONST &&
+ IS_CV == IS_CONST &&
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
+ /* do nothing */
+ } else if (IS_CV != IS_UNUSED) {
+
+
+ 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();
+ }
+ }
+ zend_throw_error(NULL, "Function name must be a string");
+
+ HANDLE_EXCEPTION();
+ }
+ }
+
+ if (ce->get_static_method) {
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name));
+ } else {
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), ((IS_CV == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
+ }
+ if (UNEXPECTED(fbc == NULL)) {
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(ce->name), Z_STRVAL_P(function_name));
+ }
+
+ HANDLE_EXCEPTION();
+ }
+ if (IS_CV == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
+ if (IS_UNUSED == IS_CONST) {
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
+ } else {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
+ }
+ }
+ if (IS_CV != IS_CONST) {
+
+ }
+ } else {
+ if (UNEXPECTED(ce->constructor == NULL)) {
+ zend_throw_error(NULL, "Cannot call constructor");
+ HANDLE_EXCEPTION();
+ }
+ if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+ zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name));
+ HANDLE_EXCEPTION();
+ }
+ fbc = ce->constructor;
+ }
+
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
+ object = Z_OBJ(EX(This));
+ }
+ if (!object) {
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ /* Allowed for PHP 4 compatibility. */
+ zend_error(
+ E_DEPRECATED,
+ "Non-static method %s::%s() should not be called statically",
+ ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ /* An internal function assumes $this is present and won't check that.
+ * So PHP would crash by allowing the call. */
+ zend_throw_error(
+ zend_ce_error,
+ "Non-static method %s::%s() cannot be called statically",
+ ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
+ HANDLE_EXCEPTION();
+ }
+ }
+ }
+
+ if (IS_UNUSED == IS_UNUSED) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ ce = EX(called_scope);
+ }
+ }
+
+ call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+ fbc, opline->extended_value, ce, object);
+ call->prev_execute_data = EX(call);
+ EX(call) = call;
+
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
@@ -27687,6 +28124,146 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *function_name;
+ zend_class_entry *ce;
+ zend_object *object;
+ zend_function *fbc;
+ zend_execute_data *call;
+
+ SAVE_OPLINE();
+
+ if (IS_UNUSED == IS_CONST) {
+ /* no function found. try a static method in class */
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op1)), EX_CONSTANT(opline->op1) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
+ HANDLE_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
+ }
+ } else if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op1.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op1.var));
+ }
+
+ if (IS_UNUSED == IS_CONST &&
+ (IS_TMP_VAR|IS_VAR) == IS_CONST &&
+ EXPECTED((fbc = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) != NULL)) {
+ /* nothing to do */
+ } else if (IS_UNUSED != IS_CONST &&
+ (IS_TMP_VAR|IS_VAR) == IS_CONST &&
+ (fbc = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce))) {
+ /* do nothing */
+ } else if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
+ zend_free_op free_op2;
+
+ 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();
+ }
+ }
+ zend_throw_error(NULL, "Function name must be a string");
+ zval_ptr_dtor_nogc(free_op2);
+ HANDLE_EXCEPTION();
+ }
+ }
+
+ if (ce->get_static_method) {
+ fbc = ce->get_static_method(ce, Z_STR_P(function_name));
+ } else {
+ fbc = zend_std_get_static_method(ce, Z_STR_P(function_name), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? (EX_CONSTANT(opline->op2) + 1) : NULL));
+ }
+ if (UNEXPECTED(fbc == NULL)) {
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Call to undefined method %s::%s()", ZSTR_VAL(ce->name), Z_STRVAL_P(function_name));
+ }
+ zval_ptr_dtor_nogc(free_op2);
+ HANDLE_EXCEPTION();
+ }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
+ EXPECTED(fbc->type <= ZEND_USER_FUNCTION) &&
+ EXPECTED(!(fbc->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE|ZEND_ACC_NEVER_CACHE)))) {
+ if (IS_UNUSED == IS_CONST) {
+ CACHE_PTR(Z_CACHE_SLOT_P(function_name), fbc);
+ } else {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(function_name), ce, fbc);
+ }
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ zval_ptr_dtor_nogc(free_op2);
+ }
+ } else {
+ if (UNEXPECTED(ce->constructor == NULL)) {
+ zend_throw_error(NULL, "Cannot call constructor");
+ HANDLE_EXCEPTION();
+ }
+ if (Z_OBJ(EX(This)) && Z_OBJ(EX(This))->ce != ce->constructor->common.scope && (ce->constructor->common.fn_flags & ZEND_ACC_PRIVATE)) {
+ zend_throw_error(NULL, "Cannot call private %s::__construct()", ZSTR_VAL(ce->name));
+ HANDLE_EXCEPTION();
+ }
+ fbc = ce->constructor;
+ }
+
+ object = NULL;
+ if (!(fbc->common.fn_flags & ZEND_ACC_STATIC)) {
+ if (Z_OBJ(EX(This)) && instanceof_function(Z_OBJCE(EX(This)), ce)) {
+ object = Z_OBJ(EX(This));
+ }
+ if (!object) {
+ if (fbc->common.fn_flags & ZEND_ACC_ALLOW_STATIC) {
+ /* Allowed for PHP 4 compatibility. */
+ zend_error(
+ E_DEPRECATED,
+ "Non-static method %s::%s() should not be called statically",
+ ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ /* An internal function assumes $this is present and won't check that.
+ * So PHP would crash by allowing the call. */
+ zend_throw_error(
+ zend_ce_error,
+ "Non-static method %s::%s() cannot be called statically",
+ ZSTR_VAL(fbc->common.scope->name), ZSTR_VAL(fbc->common.function_name));
+ HANDLE_EXCEPTION();
+ }
+ }
+ }
+
+ if (IS_UNUSED == IS_UNUSED) {
+ /* previous opcode is ZEND_FETCH_CLASS */
+ if ((opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_PARENT ||
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ ce = EX(called_scope);
+ }
+ }
+
+ call = zend_vm_stack_push_call_frame(ZEND_CALL_NESTED_FUNCTION,
+ fbc, opline->extended_value, ce, object);
+ call->prev_execute_data = EX(call);
+ EX(call) = call;
+
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
zval *array;
@@ -30946,14 +31523,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CONST_HAN
ZEND_VM_TAIL_CALL(zend_post_incdec_property_helper_SPEC_CV_CONST(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_CONST(int type ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_CV_CONST(int type ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zval *varname;
zval *retval;
zend_string *name;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
SAVE_OPLINE();
varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
@@ -30970,116 +31547,66 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
name = zval_get_string(varname);
}
- if (IS_CONST != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_CONST == IS_CONST) {
- if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
-
- HANDLE_EXCEPTION();
- }
+ if (IS_CONST == IS_CONST) {
+ if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- goto fetch_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (IS_CV != IS_CONST) {
- zend_string_release(name);
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CV == IS_CONST &&
- (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- HANDLE_EXCEPTION();
+ goto fetch_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CV != IS_CONST) {
+ zend_string_release(name);
}
- goto fetch_var_return;
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
- retval = zend_std_get_static_property(ce, name, 0);
- if (UNEXPECTED(EG(exception))) {
-
- HANDLE_EXCEPTION();
- }
- if (IS_CV == IS_CONST && retval) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
- }
-
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- retval = zend_hash_find(target_symbol_table, name);
- if (retval == NULL) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- case BP_VAR_W:
- retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
- retval = Z_INDIRECT_P(retval);
- if (Z_TYPE_P(retval) == IS_UNDEF) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_W:
- ZVAL_NULL(retval);
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
+ if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
- 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)) {
+ if (IS_CV == IS_CONST &&
+ (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- HANDLE_EXCEPTION();
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+
+ HANDLE_EXCEPTION();
}
- } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
+ goto fetch_static_prop_return;
}
}
+ retval = zend_std_get_static_property(ce, name, 0);
+ if (UNEXPECTED(EG(exception))) {
+
+ HANDLE_EXCEPTION();
+ }
+ if (IS_CV == IS_CONST && retval) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ }
if (IS_CV != IS_CONST) {
zend_string_release(name);
}
-fetch_var_return:
+fetch_static_prop_return:
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
@@ -31092,40 +31619,40 @@ fetch_var_return:
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_CONST(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
} else {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_CONST(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_CONST(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_CONST(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -32133,40 +32660,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_ARRAY_SPEC_CV_CONST_HANDL
}
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval tmp, *varname;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
SAVE_OPLINE();
- if (IS_CV == IS_CV &&
- IS_CONST == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- zval *var = EX_VAR(opline->op1.var);
-
- if (Z_REFCOUNTED_P(var)) {
- zend_refcounted *garbage = Z_COUNTED_P(var);
-
- if (!--GC_REFCOUNT(garbage)) {
- ZVAL_UNDEF(var);
- zval_dtor_func_for_ptr(garbage);
- } else {
- zval *z = var;
- ZVAL_DEREF(z);
- if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) {
- ZVAL_UNDEF(var);
- gc_possible_root(Z_COUNTED_P(z));
- } else {
- ZVAL_UNDEF(var);
- }
- }
- } else {
- ZVAL_UNDEF(var);
- }
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
@@ -32179,33 +32680,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLE
varname = &tmp;
}
- if (IS_CONST != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_CONST == IS_CONST) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (IS_CONST == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- }
- if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
-
- HANDLE_EXCEPTION();
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
- zend_std_unset_static_property(ce, Z_STR_P(varname));
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ zend_std_unset_static_property(ce, Z_STR_P(varname));
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
@@ -32355,103 +32855,83 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLE
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *value;
int result;
- if (IS_CV == IS_CV &&
- IS_CONST == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- value = EX_VAR(opline->op1.var);
- if (opline->extended_value & ZEND_ISSET) {
- result =
- Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- SAVE_OPLINE();
- result = !i_zend_is_true(value);
- if (UNEXPECTED(EG(exception))) {
- HANDLE_EXCEPTION();
- }
- }
- ZEND_VM_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_SET_NEXT_OPCODE(opline + 1);
- ZEND_VM_CONTINUE();
- } else {
-
- zval tmp, *varname;
-
- SAVE_OPLINE();
- varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
- ZVAL_UNDEF(&tmp);
- if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
- ZVAL_STR(&tmp, zval_get_string(varname));
- varname = &tmp;
- }
-
- if (IS_CONST != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_CONST == IS_CONST) {
- if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
+ zval tmp, *varname;
+ zend_class_entry *ce;
- goto is_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CV == IS_CONST &&
- (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
+ ZVAL_UNDEF(&tmp);
+ if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
+ if (IS_CONST == IS_CONST) {
+ if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- goto is_var_return;
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
}
- value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
-
- if (IS_CV == IS_CONST && value) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ goto is_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
} else {
- HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ if (IS_CV == IS_CONST &&
+ (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
-is_var_return:
- if (opline->extended_value & ZEND_ISSET) {
- result = value && Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- result = !value || !i_zend_is_true(value);
+ goto is_static_prop_return;
}
+ }
- ZEND_VM_SMART_BRANCH(result, 1);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
+
+ if (IS_CV == IS_CONST && value) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
}
+
+ if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+
+is_static_prop_return:
+ if (opline->extended_value & ZEND_ISSET) {
+ result = value && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = !value || !i_zend_is_true(value);
+ }
+
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -32662,6 +33142,12 @@ try_instanceof:
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
+ } else if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
@@ -33154,14 +33640,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_H
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_CV_VAR(int type ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_CV_VAR(int type ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zval *varname;
zval *retval;
zend_string *name;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
SAVE_OPLINE();
varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
@@ -33178,116 +33664,66 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
name = zval_get_string(varname);
}
- if (IS_VAR != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_VAR == IS_CONST) {
- if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ if (IS_VAR == IS_CONST) {
+ if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- HANDLE_EXCEPTION();
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- goto fetch_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (IS_CV != IS_CONST) {
- zend_string_release(name);
- }
-
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CV == IS_CONST &&
- (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- HANDLE_EXCEPTION();
+ goto fetch_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CV != IS_CONST) {
+ zend_string_release(name);
}
- goto fetch_var_return;
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
- retval = zend_std_get_static_property(ce, name, 0);
- if (UNEXPECTED(EG(exception))) {
-
- HANDLE_EXCEPTION();
- }
- if (IS_CV == IS_CONST && retval) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
- }
-
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- retval = zend_hash_find(target_symbol_table, name);
- if (retval == NULL) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- case BP_VAR_W:
- retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
- retval = Z_INDIRECT_P(retval);
- if (Z_TYPE_P(retval) == IS_UNDEF) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_W:
- ZVAL_NULL(retval);
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
+ if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
- 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)) {
+ if (IS_CV == IS_CONST &&
+ (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- HANDLE_EXCEPTION();
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+
+ HANDLE_EXCEPTION();
}
- } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
+ goto fetch_static_prop_return;
}
}
+ retval = zend_std_get_static_property(ce, name, 0);
+ if (UNEXPECTED(EG(exception))) {
+
+ HANDLE_EXCEPTION();
+ }
+ if (IS_CV == IS_CONST && retval) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ }
if (IS_CV != IS_CONST) {
zend_string_release(name);
}
-fetch_var_return:
+fetch_static_prop_return:
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
@@ -33300,40 +33736,40 @@ fetch_var_return:
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
} else {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_VAR(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_VAR(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ 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)
@@ -33423,40 +33859,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval tmp, *varname;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
SAVE_OPLINE();
- if (IS_CV == IS_CV &&
- IS_VAR == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- zval *var = EX_VAR(opline->op1.var);
-
- if (Z_REFCOUNTED_P(var)) {
- zend_refcounted *garbage = Z_COUNTED_P(var);
-
- if (!--GC_REFCOUNT(garbage)) {
- ZVAL_UNDEF(var);
- zval_dtor_func_for_ptr(garbage);
- } else {
- zval *z = var;
- ZVAL_DEREF(z);
- if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) {
- ZVAL_UNDEF(var);
- gc_possible_root(Z_COUNTED_P(z));
- } else {
- ZVAL_UNDEF(var);
- }
- }
- } else {
- ZVAL_UNDEF(var);
- }
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
@@ -33469,33 +33879,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(
varname = &tmp;
}
- if (IS_VAR != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_VAR == IS_CONST) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (IS_VAR == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- }
- if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
-
- HANDLE_EXCEPTION();
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
- zend_std_unset_static_property(ce, Z_STR_P(varname));
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ zend_std_unset_static_property(ce, Z_STR_P(varname));
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
@@ -33504,103 +33913,83 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *value;
int result;
- if (IS_CV == IS_CV &&
- IS_VAR == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- value = EX_VAR(opline->op1.var);
- if (opline->extended_value & ZEND_ISSET) {
- result =
- Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- SAVE_OPLINE();
- result = !i_zend_is_true(value);
- if (UNEXPECTED(EG(exception))) {
- HANDLE_EXCEPTION();
- }
- }
- ZEND_VM_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_SET_NEXT_OPCODE(opline + 1);
- ZEND_VM_CONTINUE();
- } else {
-
- zval tmp, *varname;
-
- SAVE_OPLINE();
- varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
- ZVAL_UNDEF(&tmp);
- if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
- ZVAL_STR(&tmp, zval_get_string(varname));
- varname = &tmp;
- }
-
- if (IS_VAR != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_VAR == IS_CONST) {
- if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
+ zval tmp, *varname;
+ zend_class_entry *ce;
- goto is_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CV == IS_CONST &&
- (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
+ ZVAL_UNDEF(&tmp);
+ if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
+ if (IS_VAR == IS_CONST) {
+ if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- goto is_var_return;
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
}
- value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
-
- if (IS_CV == IS_CONST && value) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ goto is_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
} else {
- HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ if (IS_CV == IS_CONST &&
+ (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
-is_var_return:
- if (opline->extended_value & ZEND_ISSET) {
- result = value && Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- result = !value || !i_zend_is_true(value);
+ goto is_static_prop_return;
}
+ }
- ZEND_VM_SMART_BRANCH(result, 1);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
+
+ if (IS_CV == IS_CONST && value) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ }
+
+ if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
}
+
+is_static_prop_return:
+ if (opline->extended_value & ZEND_ISSET) {
+ result = value && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = !value || !i_zend_is_true(value);
+ }
+
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -33628,6 +34017,12 @@ try_instanceof:
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
+ } else if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
@@ -34122,60 +34517,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
name = zval_get_string(varname);
}
- if (IS_UNUSED != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_UNUSED == IS_CONST) {
- if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
-
- HANDLE_EXCEPTION();
- }
-
- goto fetch_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (IS_CV != IS_CONST) {
- zend_string_release(name);
- }
-
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CV == IS_CONST &&
- (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
-
- HANDLE_EXCEPTION();
- }
-
- goto fetch_var_return;
- }
- }
- retval = zend_std_get_static_property(ce, name, 0);
- if (UNEXPECTED(EG(exception))) {
-
- HANDLE_EXCEPTION();
- }
- if (IS_CV == IS_CONST && retval) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ retval = zend_hash_find(target_symbol_table, name);
+ if (retval == NULL) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
+ retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
+ break;
+ case BP_VAR_W:
+ retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
}
-
- } else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- retval = zend_hash_find(target_symbol_table, name);
- if (retval == NULL) {
+ /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
+ } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
+ retval = Z_INDIRECT_P(retval);
+ if (Z_TYPE_P(retval) == IS_UNDEF) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
@@ -34186,52 +34551,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
- break;
+ /* break missing intentionally */
case BP_VAR_W:
- retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
+ ZVAL_NULL(retval);
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
- /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
- retval = Z_INDIRECT_P(retval);
- if (Z_TYPE_P(retval) == IS_UNDEF) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_W:
- ZVAL_NULL(retval);
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- }
}
- 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_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 (IS_CV != IS_CONST) {
zend_string_release(name);
}
-fetch_var_return:
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
@@ -34280,6 +34623,138 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_CV_UNUSED_HANDLE
ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_CV_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_CV_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC)
+{
+ USE_OPLINE
+
+ zval *varname;
+ zval *retval;
+ zend_string *name;
+ zend_class_entry *ce;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
+
+ if (IS_CV == IS_CONST) {
+ name = Z_STR_P(varname);
+ } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
+ name = Z_STR_P(varname);
+ zend_string_addref(name);
+ } else {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(varname, BP_VAR_R);
+ }
+ name = zval_get_string(varname);
+ }
+
+ if (IS_UNUSED == IS_CONST) {
+ if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+
+ HANDLE_EXCEPTION();
+ }
+
+ goto fetch_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (IS_CV != IS_CONST) {
+ zend_string_release(name);
+ }
+
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
+ }
+ if (IS_CV == IS_CONST &&
+ (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+
+ HANDLE_EXCEPTION();
+ }
+
+ goto fetch_static_prop_return;
+ }
+ }
+ retval = zend_std_get_static_property(ce, name, 0);
+ if (UNEXPECTED(EG(exception))) {
+
+ HANDLE_EXCEPTION();
+ }
+ if (IS_CV == IS_CONST && retval) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ }
+
+ if (IS_CV != IS_CONST) {
+ zend_string_release(name);
+ }
+
+fetch_static_prop_return:
+ ZEND_ASSERT(retval != NULL);
+ if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ } else {
+ ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
+ }
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_UNUSED(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ } else {
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ }
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_UNUSED(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_CV_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -34520,8 +34995,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU
if (UNEXPECTED(EG(exception) != NULL)) {
if (IS_CV == IS_CONST) {
zval_ptr_dtor_nogc(retval_ptr);
- } else {
-
}
}
#endif
@@ -34668,7 +35141,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDL
SAVE_OPLINE();
if (IS_CV == IS_CV &&
- IS_UNUSED == IS_UNUSED &&
(opline->extended_value & ZEND_QUICK_SET)) {
zval *var = EX_VAR(opline->op1.var);
@@ -34705,33 +35177,62 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDL
varname = &tmp;
}
- if (IS_UNUSED != IS_UNUSED) {
- zend_class_entry *ce;
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
- if (IS_UNUSED == IS_CONST) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- }
- if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
+ if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
- HANDLE_EXCEPTION();
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ zend_class_entry *ce;
+
+
+ SAVE_OPLINE();
+
+ varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
+
+ ZVAL_UNDEF(&tmp);
+ if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
+ varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R);
+ }
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
+
+ if (IS_UNUSED == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
- zend_std_unset_static_property(ce, Z_STR_P(varname));
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ zend_std_unset_static_property(ce, Z_STR_P(varname));
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
@@ -34747,7 +35248,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUS
int result;
if (IS_CV == IS_CV &&
- IS_UNUSED == IS_UNUSED &&
(opline->extended_value & ZEND_QUICK_SET)) {
value = EX_VAR(opline->op1.var);
if (opline->extended_value & ZEND_ISSET) {
@@ -34768,6 +35268,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUS
} else {
zval tmp, *varname;
+ HashTable *target_symbol_table;
SAVE_OPLINE();
varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
@@ -34777,55 +35278,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_UNUS
varname = &tmp;
}
- if (IS_UNUSED != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_UNUSED == IS_CONST) {
- if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
-
- goto is_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if (IS_CV == IS_CONST &&
- (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
-
- goto is_var_return;
- }
- }
-
- value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
-
- if (IS_CV == IS_CONST && value) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
- }
- } else {
- HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
- }
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
}
-is_var_return:
if (opline->extended_value & ZEND_ISSET) {
result = value && Z_TYPE_P(value) > IS_NULL &&
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
@@ -34839,6 +35298,135 @@ is_var_return:
}
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *value;
+ int result;
+
+ zval tmp, *varname;
+ zend_class_entry *ce;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_cv_BP_VAR_IS(execute_data, opline->op1.var);
+ ZVAL_UNDEF(&tmp);
+ if (IS_CV != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
+
+ if (IS_UNUSED == IS_CONST) {
+ if (IS_CV == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
+
+ goto is_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
+ }
+ if (IS_CV == IS_CONST &&
+ (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
+
+ goto is_static_prop_return;
+ }
+ }
+
+ value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
+
+ if (IS_CV == IS_CONST && value) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ }
+
+ if (IS_CV != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+
+is_static_prop_return:
+ if (opline->extended_value & ZEND_ISSET) {
+ result = value && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = !value || !i_zend_is_true(value);
+ }
+
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ zval *expr;
+ zend_bool result;
+
+ SAVE_OPLINE();
+ expr = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
+
+try_instanceof:
+ if (Z_TYPE_P(expr) == IS_OBJECT) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
+ if (UNEXPECTED(ce == NULL)) {
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
+ }
+ result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
+ expr = Z_REFVAL_P(expr);
+ goto try_instanceof;
+ } else {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(expr, BP_VAR_R);
+ }
+ result = 0;
+ }
+
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -41290,14 +41878,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HAN
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(int type ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_TMPVAR_CONST(int type ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op1;
zval *varname;
zval *retval;
zend_string *name;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
SAVE_OPLINE();
varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -41314,117 +41902,68 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
name = zval_get_string(varname);
}
- if (IS_CONST != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_CONST == IS_CONST) {
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
- }
+ if (IS_CONST == IS_CONST) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- goto fetch_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- zend_string_release(name);
- }
- zval_ptr_dtor_nogc(free_op1);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
- (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
+ goto fetch_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ zend_string_release(name);
}
-
- goto fetch_var_return;
+ zval_ptr_dtor_nogc(free_op1);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
- retval = zend_std_get_static_property(ce, name, 0);
- if (UNEXPECTED(EG(exception))) {
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
- }
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && retval) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
- }
-
- zval_ptr_dtor_nogc(free_op1);
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- retval = zend_hash_find(target_symbol_table, name);
- if (retval == NULL) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- case BP_VAR_W:
- retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
- retval = Z_INDIRECT_P(retval);
- if (Z_TYPE_P(retval) == IS_UNDEF) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_W:
- ZVAL_NULL(retval);
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
+ if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
- 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();
- }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
+ (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
}
- } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
- zval_ptr_dtor_nogc(free_op1);
+
+ goto fetch_static_prop_return;
}
}
+ retval = zend_std_get_static_property(ce, name, 0);
+ if (UNEXPECTED(EG(exception))) {
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
+ }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && retval) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ }
+
+ zval_ptr_dtor_nogc(free_op1);
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
zend_string_release(name);
}
-fetch_var_return:
+fetch_static_prop_return:
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
@@ -41437,40 +41976,40 @@ fetch_var_return:
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_CONST(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_CONST(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
} else {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_CONST(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_CONST(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_CONST(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_CONST(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -41870,40 +42409,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval tmp, *varname;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
zend_free_op free_op1;
SAVE_OPLINE();
- if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
- IS_CONST == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- zval *var = EX_VAR(opline->op1.var);
-
- if (Z_REFCOUNTED_P(var)) {
- zend_refcounted *garbage = Z_COUNTED_P(var);
-
- if (!--GC_REFCOUNT(garbage)) {
- ZVAL_UNDEF(var);
- zval_dtor_func_for_ptr(garbage);
- } else {
- zval *z = var;
- ZVAL_DEREF(z);
- if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) {
- ZVAL_UNDEF(var);
- gc_possible_root(Z_COUNTED_P(z));
- } else {
- ZVAL_UNDEF(var);
- }
- }
- } else {
- ZVAL_UNDEF(var);
- }
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -41916,33 +42429,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HA
varname = &tmp;
}
- if (IS_CONST != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_CONST == IS_CONST) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (IS_CONST == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- }
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
- zend_std_unset_static_property(ce, Z_STR_P(varname));
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ zend_std_unset_static_property(ce, Z_STR_P(varname));
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
@@ -41951,104 +42463,84 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HA
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *value;
int result;
+ zend_free_op free_op1;
+ zval tmp, *varname;
+ zend_class_entry *ce;
- if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
- IS_CONST == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- value = EX_VAR(opline->op1.var);
- if (opline->extended_value & ZEND_ISSET) {
- result =
- Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- SAVE_OPLINE();
- result = !i_zend_is_true(value);
- if (UNEXPECTED(EG(exception))) {
- HANDLE_EXCEPTION();
- }
- }
- ZEND_VM_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_SET_NEXT_OPCODE(opline + 1);
- ZEND_VM_CONTINUE();
- } else {
- zend_free_op free_op1;
- zval tmp, *varname;
-
- SAVE_OPLINE();
- varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
- ZVAL_UNDEF(&tmp);
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
- ZVAL_STR(&tmp, zval_get_string(varname));
- varname = &tmp;
- }
-
- if (IS_CONST != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_CONST == IS_CONST) {
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
-
- goto is_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
- (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ ZVAL_UNDEF(&tmp);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
+ if (IS_CONST == IS_CONST) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- goto is_var_return;
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
}
- value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
-
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && value) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ goto is_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
} else {
- HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
+ (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
- zval_ptr_dtor_nogc(free_op1);
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
-is_var_return:
- if (opline->extended_value & ZEND_ISSET) {
- result = value && Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- result = !value || !i_zend_is_true(value);
+ goto is_static_prop_return;
}
+ }
- ZEND_VM_SMART_BRANCH(result, 1);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
+
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && value) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ }
+
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
}
+ zval_ptr_dtor_nogc(free_op1);
+
+is_static_prop_return:
+ if (opline->extended_value & ZEND_ISSET) {
+ result = value && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = !value || !i_zend_is_true(value);
+ }
+
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMPVAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -42259,6 +42751,12 @@ try_instanceof:
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
+ } else if (IS_CONST == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
@@ -42278,14 +42776,14 @@ try_instanceof:
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(int type ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_TMPVAR_VAR(int type ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op1;
zval *varname;
zval *retval;
zend_string *name;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
SAVE_OPLINE();
varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -42302,117 +42800,68 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
name = zval_get_string(varname);
}
- if (IS_VAR != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_VAR == IS_CONST) {
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
- }
+ if (IS_VAR == IS_CONST) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- goto fetch_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- zend_string_release(name);
- }
- zval_ptr_dtor_nogc(free_op1);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
- (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
+ goto fetch_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ zend_string_release(name);
}
-
- goto fetch_var_return;
+ zval_ptr_dtor_nogc(free_op1);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
- retval = zend_std_get_static_property(ce, name, 0);
- if (UNEXPECTED(EG(exception))) {
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
- }
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && retval) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
- }
-
- zval_ptr_dtor_nogc(free_op1);
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- retval = zend_hash_find(target_symbol_table, name);
- if (retval == NULL) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- case BP_VAR_W:
- retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
- retval = Z_INDIRECT_P(retval);
- if (Z_TYPE_P(retval) == IS_UNDEF) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_W:
- ZVAL_NULL(retval);
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
+ if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
- 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();
- }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
+ (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
}
- } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
- zval_ptr_dtor_nogc(free_op1);
+
+ goto fetch_static_prop_return;
}
}
+ retval = zend_std_get_static_property(ce, name, 0);
+ if (UNEXPECTED(EG(exception))) {
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
+ }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && retval) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ }
+
+ zval_ptr_dtor_nogc(free_op1);
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
zend_string_release(name);
}
-fetch_var_return:
+fetch_static_prop_return:
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
@@ -42425,76 +42874,50 @@ fetch_var_return:
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_R_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_W_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_RW_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_VAR(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_VAR(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
} else {
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_VAR(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_UNSET_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_VAR(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_VAR(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_VAR(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval tmp, *varname;
- HashTable *target_symbol_table;
+ zend_class_entry *ce;
zend_free_op free_op1;
SAVE_OPLINE();
- if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
- IS_VAR == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- zval *var = EX_VAR(opline->op1.var);
-
- if (Z_REFCOUNTED_P(var)) {
- zend_refcounted *garbage = Z_COUNTED_P(var);
-
- if (!--GC_REFCOUNT(garbage)) {
- ZVAL_UNDEF(var);
- zval_dtor_func_for_ptr(garbage);
- } else {
- zval *z = var;
- ZVAL_DEREF(z);
- if (Z_COLLECTABLE_P(z) && UNEXPECTED(!Z_GC_INFO_P(z))) {
- ZVAL_UNDEF(var);
- gc_possible_root(Z_COUNTED_P(z));
- } else {
- ZVAL_UNDEF(var);
- }
- }
- } else {
- ZVAL_UNDEF(var);
- }
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -42507,33 +42930,32 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HAND
varname = &tmp;
}
- if (IS_VAR != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_VAR == IS_CONST) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (IS_VAR == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- }
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
- zend_std_unset_static_property(ce, Z_STR_P(varname));
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ zend_std_unset_static_property(ce, Z_STR_P(varname));
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
@@ -42542,104 +42964,84 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HAND
ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
zval *value;
int result;
+ zend_free_op free_op1;
+ zval tmp, *varname;
+ zend_class_entry *ce;
- if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
- IS_VAR == IS_UNUSED &&
- (opline->extended_value & ZEND_QUICK_SET)) {
- value = EX_VAR(opline->op1.var);
- if (opline->extended_value & ZEND_ISSET) {
- result =
- Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- SAVE_OPLINE();
- result = !i_zend_is_true(value);
- if (UNEXPECTED(EG(exception))) {
- HANDLE_EXCEPTION();
- }
- }
- ZEND_VM_SMART_BRANCH(result, 0);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_SET_NEXT_OPCODE(opline + 1);
- ZEND_VM_CONTINUE();
- } else {
- zend_free_op free_op1;
- zval tmp, *varname;
-
- SAVE_OPLINE();
- varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
- ZVAL_UNDEF(&tmp);
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
- ZVAL_STR(&tmp, zval_get_string(varname));
- varname = &tmp;
- }
-
- if (IS_VAR != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_VAR == IS_CONST) {
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
-
- goto is_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
- (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ ZVAL_UNDEF(&tmp);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
+ if (IS_VAR == IS_CONST) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
- goto is_var_return;
- }
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
}
- value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
-
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && value) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ goto is_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
} else {
- HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
+ (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
- zval_ptr_dtor_nogc(free_op1);
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
-is_var_return:
- if (opline->extended_value & ZEND_ISSET) {
- result = value && Z_TYPE_P(value) > IS_NULL &&
- (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
- } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
- result = !value || !i_zend_is_true(value);
+ goto is_static_prop_return;
}
+ }
- ZEND_VM_SMART_BRANCH(result, 1);
- ZVAL_BOOL(EX_VAR(opline->result.var), result);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
+
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && value) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ }
+
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
}
+ zval_ptr_dtor_nogc(free_op1);
+
+is_static_prop_return:
+ if (opline->extended_value & ZEND_ISSET) {
+ result = value && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = !value || !i_zend_is_true(value);
+ }
+
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -42667,6 +43069,12 @@ try_instanceof:
}
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
}
+ } else if (IS_VAR == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
} else {
ce = Z_CE_P(EX_VAR(opline->op2.var));
}
@@ -42710,61 +43118,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
name = zval_get_string(varname);
}
- if (IS_UNUSED != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_UNUSED == IS_CONST) {
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
- }
-
- goto fetch_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- zend_string_release(name);
- }
- zval_ptr_dtor_nogc(free_op1);
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
- (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
- }
-
- goto fetch_var_return;
- }
- }
- retval = zend_std_get_static_property(ce, name, 0);
- if (UNEXPECTED(EG(exception))) {
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
- }
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && retval) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ retval = zend_hash_find(target_symbol_table, name);
+ if (retval == NULL) {
+ switch (type) {
+ case BP_VAR_R:
+ case BP_VAR_UNSET:
+ zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
+ /* break missing intentionally */
+ case BP_VAR_IS:
+ retval = &EG(uninitialized_zval);
+ break;
+ case BP_VAR_RW:
+ zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
+ retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
+ break;
+ case BP_VAR_W:
+ retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
+ break;
+ EMPTY_SWITCH_DEFAULT_CASE()
}
-
- zval_ptr_dtor_nogc(free_op1);
- } else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- retval = zend_hash_find(target_symbol_table, name);
- if (retval == NULL) {
+ /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
+ } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
+ retval = Z_INDIRECT_P(retval);
+ if (Z_TYPE_P(retval) == IS_UNDEF) {
switch (type) {
case BP_VAR_R:
case BP_VAR_UNSET:
@@ -42775,52 +43152,30 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
break;
case BP_VAR_RW:
zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- retval = zend_hash_update(target_symbol_table, name, &EG(uninitialized_zval));
- break;
+ /* break missing intentionally */
case BP_VAR_W:
- retval = zend_hash_add_new(target_symbol_table, name, &EG(uninitialized_zval));
+ ZVAL_NULL(retval);
break;
EMPTY_SWITCH_DEFAULT_CASE()
}
- /* GLOBAL or $$name variable may be an INDIRECT pointer to CV */
- } else if (Z_TYPE_P(retval) == IS_INDIRECT) {
- retval = Z_INDIRECT_P(retval);
- if (Z_TYPE_P(retval) == IS_UNDEF) {
- switch (type) {
- case BP_VAR_R:
- case BP_VAR_UNSET:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_IS:
- retval = &EG(uninitialized_zval);
- break;
- case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined variable: %s", ZSTR_VAL(name));
- /* break missing intentionally */
- case BP_VAR_W:
- ZVAL_NULL(retval);
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
- }
}
- 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();
- }
+ }
+
+ 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) {
- zval_ptr_dtor_nogc(free_op1);
}
+ } else if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) != ZEND_FETCH_GLOBAL_LOCK) {
+ zval_ptr_dtor_nogc(free_op1);
}
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
zend_string_release(name);
}
-fetch_var_return:
ZEND_ASSERT(retval != NULL);
if (type == BP_VAR_R || type == BP_VAR_IS) {
if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
@@ -42869,6 +43224,140 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HA
ZEND_VM_TAIL_CALL(zend_fetch_var_address_helper_SPEC_TMPVAR_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_static_prop_helper_SPEC_TMPVAR_UNUSED(int type ZEND_OPCODE_HANDLER_ARGS_DC)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *varname;
+ zval *retval;
+ zend_string *name;
+ zend_class_entry *ce;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+ name = Z_STR_P(varname);
+ } else if (EXPECTED(Z_TYPE_P(varname) == IS_STRING)) {
+ name = Z_STR_P(varname);
+ zend_string_addref(name);
+ } else {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(varname, BP_VAR_R);
+ }
+ name = zval_get_string(varname);
+ }
+
+ if (IS_UNUSED == IS_CONST) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ retval = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
+ }
+
+ goto fetch_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ zend_string_release(name);
+ }
+ zval_ptr_dtor_nogc(free_op1);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
+ }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
+ (retval = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ zend_throw_error(NULL, "Access to undeclared static property: %s::$%s", ZSTR_VAL(ce->name), ZSTR_VAL(name));
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
+ }
+
+ goto fetch_static_prop_return;
+ }
+ }
+ retval = zend_std_get_static_property(ce, name, 0);
+ if (UNEXPECTED(EG(exception))) {
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
+ }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && retval) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, retval);
+ }
+
+ zval_ptr_dtor_nogc(free_op1);
+
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ zend_string_release(name);
+ }
+
+fetch_static_prop_return:
+ ZEND_ASSERT(retval != NULL);
+ if (type == BP_VAR_R || type == BP_VAR_IS) {
+ if (/*type == BP_VAR_R &&*/ Z_ISREF_P(retval) && Z_REFCOUNT_P(retval) == 1) {
+ ZVAL_UNREF(retval);
+ }
+ ZVAL_COPY(EX_VAR(opline->result.var), retval);
+ } else {
+ ZVAL_INDIRECT(EX_VAR(opline->result.var), retval);
+ }
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_R_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_W_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_RW_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_UNUSED(BP_VAR_RW ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+
+ if (zend_is_by_ref_func_arg_fetch(opline, EX(call))) {
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_UNUSED(BP_VAR_W ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ } else {
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_UNUSED(BP_VAR_R ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+ }
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_UNSET_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_UNUSED(BP_VAR_UNSET ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_STATIC_PROP_IS_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ ZEND_VM_TAIL_CALL(zend_fetch_static_prop_helper_SPEC_TMPVAR_UNUSED(BP_VAR_IS ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC));
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -42878,7 +43367,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H
SAVE_OPLINE();
if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
- IS_UNUSED == IS_UNUSED &&
(opline->extended_value & ZEND_QUICK_SET)) {
zval *var = EX_VAR(opline->op1.var);
@@ -42915,33 +43403,62 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H
varname = &tmp;
}
- if (IS_UNUSED != IS_UNUSED) {
- zend_class_entry *ce;
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
- if (IS_UNUSED == IS_CONST) {
- ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+ zval_ptr_dtor_nogc(free_op1);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_STATIC_PROP_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval tmp, *varname;
+ zend_class_entry *ce;
+ zend_free_op free_op1;
+
+ SAVE_OPLINE();
+
+ varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+
+ ZVAL_UNDEF(&tmp);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(varname) == IS_UNDEF)) {
+ varname = GET_OP1_UNDEF_CV(varname, BP_VAR_R);
+ }
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
+
+ if (IS_UNUSED == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
if (UNEXPECTED(ce == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- if (EXPECTED(!EG(exception))) {
- zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
- }
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
- zend_string_release(Z_STR(tmp));
- }
- zval_ptr_dtor_nogc(free_op1);
- HANDLE_EXCEPTION();
+ if (EXPECTED(!EG(exception))) {
+ zend_throw_error(NULL, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+ zval_ptr_dtor_nogc(free_op1);
+ HANDLE_EXCEPTION();
}
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
}
- zend_std_unset_static_property(ce, Z_STR_P(varname));
} else {
- target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- zend_hash_del_ind(target_symbol_table, Z_STR_P(varname));
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
}
+ zend_std_unset_static_property(ce, Z_STR_P(varname));
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
@@ -42957,7 +43474,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_
int result;
if ((IS_TMP_VAR|IS_VAR) == IS_CV &&
- IS_UNUSED == IS_UNUSED &&
(opline->extended_value & ZEND_QUICK_SET)) {
value = EX_VAR(opline->op1.var);
if (opline->extended_value & ZEND_ISSET) {
@@ -42978,6 +43494,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_
} else {
zend_free_op free_op1;
zval tmp, *varname;
+ HashTable *target_symbol_table;
SAVE_OPLINE();
varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -42987,56 +43504,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_
varname = &tmp;
}
- if (IS_UNUSED != IS_UNUSED) {
- zend_class_entry *ce;
-
- if (IS_UNUSED == IS_CONST) {
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
-
- goto is_var_return;
- } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
- ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
- if (UNEXPECTED(ce == NULL)) {
- ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
- }
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
- }
- } else {
- ce = Z_CE_P(EX_VAR(opline->op2.var));
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
- (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
-
- /* check if static properties were destoyed */
- if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
- value = NULL;
- }
-
- goto is_var_return;
- }
- }
-
- value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
-
- if ((IS_TMP_VAR|IS_VAR) == IS_CONST && value) {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
- }
- } else {
- HashTable *target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
- value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
- }
+ target_symbol_table = zend_get_target_symbol_table(execute_data, opline->extended_value & ZEND_FETCH_TYPE_MASK);
+ value = zend_hash_find_ind(target_symbol_table, Z_STR_P(varname));
if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
zend_string_release(Z_STR(tmp));
}
zval_ptr_dtor_nogc(free_op1);
-is_var_return:
if (opline->extended_value & ZEND_ISSET) {
result = value && Z_TYPE_P(value) > IS_NULL &&
(!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
@@ -43050,6 +43525,136 @@ is_var_return:
}
}
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_STATIC_PROP_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zval *value;
+ int result;
+ zend_free_op free_op1;
+ zval tmp, *varname;
+ zend_class_entry *ce;
+
+ SAVE_OPLINE();
+ varname = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ ZVAL_UNDEF(&tmp);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE_P(varname) != IS_STRING) {
+ ZVAL_STR(&tmp, zval_get_string(varname));
+ varname = &tmp;
+ }
+
+ if (IS_UNUSED == IS_CONST) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && EXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)))) != NULL)) {
+ value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)) + sizeof(void*));
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
+
+ goto is_static_prop_return;
+ } else if (UNEXPECTED((ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_DEFAULT | ZEND_FETCH_CLASS_EXCEPTION);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else {
+ if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
+ }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST &&
+ (value = CACHED_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce)) != NULL) {
+
+ /* check if static properties were destoyed */
+ if (UNEXPECTED(CE_STATIC_MEMBERS(ce) == NULL)) {
+ value = NULL;
+ }
+
+ goto is_static_prop_return;
+ }
+ }
+
+ value = zend_std_get_static_property(ce, Z_STR_P(varname), 1);
+
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST && value) {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce, value);
+ }
+
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && Z_TYPE(tmp) != IS_UNDEF) {
+ zend_string_release(Z_STR(tmp));
+ }
+ zval_ptr_dtor_nogc(free_op1);
+
+is_static_prop_return:
+ if (opline->extended_value & ZEND_ISSET) {
+ result = value && Z_TYPE_P(value) > IS_NULL &&
+ (!Z_ISREF_P(value) || Z_TYPE_P(Z_REFVAL_P(value)) != IS_NULL);
+ } else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
+ result = !value || !i_zend_is_true(value);
+ }
+
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
+{
+ USE_OPLINE
+ zend_free_op free_op1;
+ zval *expr;
+ zend_bool result;
+
+ SAVE_OPLINE();
+ expr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+
+try_instanceof:
+ if (Z_TYPE_P(expr) == IS_OBJECT) {
+ zend_class_entry *ce;
+
+ if (IS_UNUSED == IS_CONST) {
+ ce = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
+ if (UNEXPECTED(ce == NULL)) {
+ ce = zend_fetch_class_by_name(Z_STR_P(EX_CONSTANT(opline->op2)), EX_CONSTANT(opline->op2) + 1, ZEND_FETCH_CLASS_NO_AUTOLOAD);
+ if (UNEXPECTED(ce == NULL)) {
+ ZVAL_FALSE(EX_VAR(opline->result.var));
+ zval_ptr_dtor_nogc(free_op1);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce);
+ }
+ } else if (IS_UNUSED == IS_UNUSED) {
+ ce = zend_fetch_class(NULL, opline->op2.num);
+ if (UNEXPECTED(ce == NULL)) {
+ ZEND_ASSERT(EG(exception));
+ HANDLE_EXCEPTION();
+ }
+ } else {
+ ce = Z_CE_P(EX_VAR(opline->op2.var));
+ }
+ result = ce && instanceof_function(Z_OBJCE_P(expr), ce);
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(expr) == IS_REFERENCE) {
+ expr = Z_REFVAL_P(expr);
+ goto try_instanceof;
+ } else {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(expr, BP_VAR_R);
+ }
+ result = 0;
+ }
+ zval_ptr_dtor_nogc(free_op1);
+ ZEND_VM_SMART_BRANCH(result, 1);
+ ZVAL_BOOL(EX_VAR(opline->result.var), result);
+ ZEND_VM_NEXT_OPCODE_CHECK_EXCEPTION();
+}
+
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_SPEC_TMPVAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
USE_OPLINE
@@ -47054,11 +47659,11 @@ void zend_init_opcodes_handlers(void)
ZEND_NEW_SPEC_VAR_HANDLER,
ZEND_NEW_SPEC_VAR_HANDLER,
ZEND_NEW_SPEC_VAR_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_NULL_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,
@@ -47189,19 +47794,19 @@ void zend_init_opcodes_handlers(void)
ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER,
ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER,
ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLER,
- ZEND_UNSET_VAR_SPEC_CONST_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47209,9 +47814,9 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47339,19 +47944,19 @@ void zend_init_opcodes_handlers(void)
ZEND_EXIT_SPEC_CV_HANDLER,
ZEND_EXIT_SPEC_CV_HANDLER,
ZEND_EXIT_SPEC_CV_HANDLER,
- ZEND_FETCH_R_SPEC_CONST_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_R_SPEC_CONST_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_R_SPEC_CONST_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_R_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_R_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_R_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_R_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_R_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47359,9 +47964,9 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_R_SPEC_CV_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_R_SPEC_CV_VAR_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,
@@ -47414,19 +48019,19 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER,
- ZEND_FETCH_W_SPEC_CONST_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_W_SPEC_CONST_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_W_SPEC_CONST_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_W_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_W_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_W_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_W_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_W_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47434,9 +48039,9 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_W_SPEC_CV_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_W_SPEC_CV_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_W_SPEC_CV_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47489,19 +48094,19 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER,
- ZEND_FETCH_RW_SPEC_CONST_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_RW_SPEC_CONST_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_RW_SPEC_CONST_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_RW_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_RW_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_RW_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_RW_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_RW_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47509,9 +48114,9 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_RW_SPEC_CV_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_RW_SPEC_CV_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_RW_SPEC_CV_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47564,19 +48169,19 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLER,
- ZEND_FETCH_IS_SPEC_CONST_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_IS_SPEC_CONST_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_IS_SPEC_CONST_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_IS_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_IS_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_IS_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_IS_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_IS_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47584,9 +48189,9 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_IS_SPEC_CV_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_IS_SPEC_CV_VAR_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,
@@ -47639,19 +48244,19 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CONST_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CONST_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_FUNC_ARG_SPEC_CONST_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_FUNC_ARG_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47659,9 +48264,9 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CV_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_FUNC_ARG_SPEC_CV_VAR_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,
@@ -47714,19 +48319,19 @@ void zend_init_opcodes_handlers(void)
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMPVAR_HANDLER,
ZEND_NULL_HANDLER,
ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CONST_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CONST_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_UNSET_SPEC_CONST_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_UNSET_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_UNSET_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_UNSET_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_UNSET_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_UNSET_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47734,9 +48339,9 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CV_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_UNSET_SPEC_CV_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_FETCH_UNSET_SPEC_CV_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47814,7 +48419,6 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_CONSTANT_SPEC_CONST_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -47824,7 +48428,8 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -48179,6 +48784,11 @@ void zend_init_opcodes_handlers(void)
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,
@@ -48187,21 +48797,16 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
+ ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_CONST_HANDLER,
- ZEND_NULL_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_VAR_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CONST_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_VAR_HANDLER,
ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_VAR_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_ISSET_ISEMPTY_VAR_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -48209,9 +48814,9 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_CONST_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_ISSET_ISEMPTY_VAR_SPEC_CV_VAR_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,
@@ -48797,12 +49402,12 @@ void zend_init_opcodes_handlers(void)
ZEND_INSTANCEOF_SPEC_TMPVAR_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_INSTANCEOF_SPEC_TMPVAR_VAR_HANDLER,
- ZEND_NULL_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_NULL_HANDLER,
+ ZEND_INSTANCEOF_SPEC_TMPVAR_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
@@ -48812,7 +49417,7 @@ void zend_init_opcodes_handlers(void)
ZEND_INSTANCEOF_SPEC_CV_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER,
- ZEND_NULL_HANDLER,
+ ZEND_INSTANCEOF_SPEC_CV_UNUSED_HANDLER,
ZEND_NULL_HANDLER,
ZEND_DECLARE_CLASS_SPEC_HANDLER,
ZEND_DECLARE_CLASS_SPEC_HANDLER,
@@ -49664,6 +50269,231 @@ void zend_init_opcodes_handlers(void)
ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_HANDLER,
ZEND_DECLARE_ANON_INHERITED_CLASS_SPEC_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_opcode_handlers = labels;
diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php
index 613b4c9338..17bcfdd8e1 100644
--- a/Zend/zend_vm_gen.php
+++ b/Zend/zend_vm_gen.php
@@ -54,6 +54,72 @@ define("ZEND_VM_KIND_CALL", 1);
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_NUM" => 1<<3,
+ "ZEND_VM_OP1_JMP_ADDR" => 1<<4,
+ "ZEND_VM_OP1_TRY_CATCH" => 1<<5,
+ "ZEND_VM_OP1_LIVE_RANGE" => 1<<6,
+
+ "ZEND_VM_OP2_SPEC" => 1<<8,
+ "ZEND_VM_OP2_CONST" => 1<<9,
+ "ZEND_VM_OP2_TMPVAR" => 1<<10,
+ "ZEND_VM_OP2_NUM" => 1<<11,
+ "ZEND_VM_OP2_JMP_ADDR" => 1<<12,
+ "ZEND_VM_OP2_TRY_CATCH" => 1<<13,
+ "ZEND_VM_OP2_LIVE_RANGE" => 1<<14,
+
+ "ZEND_VM_EXT_NUM" => 1<<16,
+ "ZEND_VM_EXT_VAR" => 1<<17,
+ "ZEND_VM_EXT_JMP_ADDR" => 1<<18,
+ "ZEND_VM_EXT_DIM_OBJ" => 1<<19,
+ "ZEND_VM_EXT_CLASS_FETCH" => 1<<20,
+ "ZEND_VM_EXT_CONST_FETCH" => 1<<21,
+ "ZEND_VM_EXT_VAR_FETCH" => 1<<22,
+ "ZEND_VM_EXT_ARRAY_INIT" => 1<<23,
+ "ZEND_VM_EXT_TYPE" => 1<<24,
+ "ZEND_VM_EXT_EVAL" => 1<<25,
+ "ZEND_VM_EXT_FAST_CALL" => 1<<26,
+ "ZEND_VM_EXT_FAST_RET" => 1<<27,
+ "ZEND_VM_EXT_ISSET" => 1<<28,
+);
+
+foreach ($vm_op_flags as $name => $val) {
+ define($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,
+);
+
+$vm_ext_decode = array(
+ "NUM" => ZEND_VM_EXT_NUM,
+ "VAR" => ZEND_VM_EXT_VAR,
+ "JMP_ADDR" => ZEND_VM_EXT_JMP_ADDR,
+ "DIM_OBJ" => ZEND_VM_EXT_DIM_OBJ,
+ "CLASS_FETCH" => ZEND_VM_EXT_CLASS_FETCH,
+ "CONST_FETCH" => ZEND_VM_EXT_CONST_FETCH,
+ "VAR_FETCH" => ZEND_VM_EXT_VAR_FETCH,
+ "ARRAY_INIT" => ZEND_VM_EXT_ARRAY_INIT,
+ "TYPE" => ZEND_VM_EXT_TYPE,
+ "EVAL" => ZEND_VM_EXT_EVAL,
+ "FAST_CALL" => ZEND_VM_EXT_FAST_CALL,
+ "FAST_RET" => ZEND_VM_EXT_FAST_RET,
+ "ISSET" => ZEND_VM_EXT_ISSET,
+);
+
$vm_kind_name = array(
ZEND_VM_KIND_CALL => "ZEND_VM_KIND_CALL",
ZEND_VM_KIND_SWITCH => "ZEND_VM_KIND_SWITCH",
@@ -1310,9 +1376,46 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
}
}
+function parse_operand_spec($def, $lineno, $str, &$flags) {
+ global $vm_op_decode;
+
+ $flags = 0;
+ $a = explode("|",$str);
+ foreach($a as $val) {
+ if (isset($vm_op_decode[$val])) {
+ $flags |= $vm_op_decode[$val];
+ } else {
+ die("ERROR ($def:$lineno): Wrong operand type '$str'\n");
+ }
+ }
+ if (!($flags & ZEND_VM_OP1_SPEC)) {
+ if (count($a) != 1) {
+ die("ERROR ($def:$lineno): Wrong operand type '$str'\n");
+ }
+ $a = array("ANY");
+ }
+ return array_flip($a);
+}
+
+function parse_ext_spec($def, $lineno, $str) {
+ global $vm_ext_decode;
+
+ $flags = 0;
+ $a = explode("|",$str);
+ foreach($a as $val) {
+ if (isset($vm_ext_decode[$val])) {
+ $flags |= $vm_ext_decode[$val];
+ } else {
+ die("ERROR ($def:$lineno): Wrong extended_value type '$str'\n");
+ }
+ }
+ return $flags;
+}
+
function gen_vm($def, $skel) {
global $definition_file, $skeleton_file, $executor_file,
- $op_types, $list, $opcodes, $helpers, $params, $opnames;
+ $op_types, $list, $opcodes, $helpers, $params, $opnames,
+ $vm_op_flags;
// Load definition file
$in = @file($def);
@@ -1342,7 +1445,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*\)/",
+ "/^ZEND_VM_HANDLER\(\s*([0-9]+)\s*,\s*([A-Z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*(,\s*([A-Z_|]+)\s*)?\)/",
$line,
$m) == 0) {
die("ERROR ($def:$lineno): Invalid ZEND_VM_HANDLER definition.\n");
@@ -1350,8 +1453,12 @@ function gen_vm($def, $skel) {
$code = (int)$m[1];
$op = $m[2];
$len = strlen($op);
- $op1 = array_flip(explode("|",$m[3]));
- $op2 = array_flip(explode("|",$m[4]));
+ $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])) {
+ $flags |= parse_ext_spec($def, $lineno, $m[6]);
+ }
if ($len > $max_opcode_len) {
$max_opcode_len = $len;
@@ -1365,7 +1472,7 @@ function gen_vm($def, $skel) {
if (isset($opnames[$op])) {
die("ERROR ($def:$lineno): Opcode with name '$op' is already defined.\n");
}
- $opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"");
+ $opcodes[$code] = array("op"=>$op,"op1"=>$op1,"op2"=>$op2,"code"=>"","flags"=>$flags);
$opnames[$op] = $code;
$handler = $code;
$helper = null;
@@ -1373,14 +1480,14 @@ function gen_vm($def, $skel) {
} else if (strpos($line,"ZEND_VM_HELPER(") === 0) {
// Parsing helper's definition
if (preg_match(
- "/^ZEND_VM_HELPER\(\s*([A-Za-z_]+)\s*,\s*([A-Z|]+)\s*,\s*([A-Z|]+)\s*\)/",
+ "/^ZEND_VM_HELPER\(\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*\)/",
$line,
$m) == 0) {
die("ERROR ($def:$lineno): Invalid ZEND_VM_HELPER definition.\n");
}
$helper = $m[1];
- $op1 = array_flip(explode("|",$m[2]));
- $op2 = array_flip(explode("|",$m[3]));
+ $op1 = parse_operand_spec($def, $lineno, $m[2], $flags1);
+ $op2 = parse_operand_spec($def, $lineno, $m[3], $flags2);
if (isset($helpers[$helper])) {
die("ERROR ($def:$lineno): Helper with name '$helper' is already defined.\n");
}
@@ -1390,14 +1497,14 @@ function gen_vm($def, $skel) {
} else if (strpos($line,"ZEND_VM_HELPER_EX(") === 0) {
// Parsing helper with parameter definition
if (preg_match(
- "/^ZEND_VM_HELPER_EX\(\s*([A-Za-z_]+)\s*,\s*([A-Z|]+)\s*,\s*([A-Z|]+)\s*,\s*(.*)\s*\)/",
+ "/^ZEND_VM_HELPER_EX\(\s*([A-Za-z_]+)\s*,\s*([A-Z_|]+)\s*,\s*([A-Z_|]+)\s*,\s*(.*)\s*\)/",
$line,
$m) == 0) {
die("ERROR ($def:$lineno): Invalid ZEND_VM_HELPER definition.\n");
}
$helper = $m[1];
- $op1 = array_flip(explode("|",$m[2]));
- $op2 = array_flip(explode("|",$m[3]));
+ $op1 = parse_operand_spec($def, $lineno, $m[2], $flags1);
+ $op2 = parse_operand_spec($def, $lineno, $m[3], $flags2);
$param = $m[4];
if (isset($helpers[$helper])) {
die("ERROR ($def:$lineno): Helper with name '$helper' is already defined.\n");
@@ -1493,8 +1600,13 @@ function gen_vm($def, $skel) {
fputs($f, "#define ZEND_VM_KIND_GOTO\t" . ZEND_VM_KIND_GOTO . "\n");
fputs($f, "#define ZEND_VM_KIND\t\t" . $GLOBALS["vm_kind_name"][ZEND_VM_KIND] . "\n");
fputs($f, "\n");
+ foreach($vm_op_flags as $name => $val) {
+ fprintf($f, "#define %-24s 0x%08x\n", $name, $val);
+ }
+ fputs($f, "\n");
fputs($f, "BEGIN_EXTERN_C()\n\n");
- fputs($f, "ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);\n\n");
+ fputs($f, "ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);\n");
+ fputs($f, "ZEND_API uint32_t zend_get_opcode_flags(zend_uchar opcode);\n\n");
fputs($f, "END_EXTERN_C()\n\n");
foreach ($opcodes as $code => $dsc) {
@@ -1503,6 +1615,10 @@ function gen_vm($def, $skel) {
fputs($f,"#define $op $code\n");
}
+ $code = str_pad((string)$max_opcode,$code_len," ",STR_PAD_LEFT);
+ $op = str_pad("ZEND_VM_LAST_OPCODE",$max_opcode_len);
+ fputs($f,"\n#define $op $code\n");
+
fputs($f, "\n#endif\n");
fclose($f);
echo "zend_vm_opcodes.h generated successfully.\n";
@@ -1515,14 +1631,24 @@ function gen_vm($def, $skel) {
fputs($f,"#include <stdio.h>\n");
fputs($f,"#include <zend.h>\n\n");
- fputs($f,"const char *zend_vm_opcodes_map[".($max_opcode + 1)."] = {\n");
+ fputs($f,"static const char *zend_vm_opcodes_names[".($max_opcode + 1)."] = {\n");
for ($i = 0; $i <= $max_opcode; $i++) {
fputs($f,"\t".(isset($opcodes[$i]["op"])?'"'.$opcodes[$i]["op"].'"':"NULL").",\n");
}
fputs($f, "};\n\n");
+ fputs($f,"static uint32_t zend_vm_opcodes_flags[".($max_opcode + 1)."] = {\n");
+ for ($i = 0; $i <= $max_opcode; $i++) {
+ fprintf($f, "\t0x%08x,\n", isset($opcodes[$i]["flags"]) ? $opcodes[$i]["flags"] : 0);
+ }
+ fputs($f, "};\n\n");
+
fputs($f, "ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {\n");
- fputs($f, "\treturn zend_vm_opcodes_map[opcode];\n");
+ fputs($f, "\treturn zend_vm_opcodes_names[opcode];\n");
+ fputs($f, "}\n");
+
+ fputs($f, "ZEND_API uint32_t zend_get_opcode_flags(zend_uchar opcode) {\n");
+ fputs($f, "\treturn zend_vm_opcodes_flags[opcode];\n");
fputs($f, "}\n");
fclose($f);
diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c
index 1f26f0439e..b56cd930ff 100644
--- a/Zend/zend_vm_opcodes.c
+++ b/Zend/zend_vm_opcodes.c
@@ -21,7 +21,7 @@
#include <stdio.h>
#include <zend.h>
-const char *zend_vm_opcodes_map[173] = {
+static const char *zend_vm_opcodes_names[182] = {
"ZEND_NOP",
"ZEND_ADD",
"ZEND_SUB",
@@ -195,8 +195,205 @@ const char *zend_vm_opcodes_map[173] = {
"ZEND_SPACESHIP",
"ZEND_DECLARE_ANON_CLASS",
"ZEND_DECLARE_ANON_INHERITED_CLASS",
+ "ZEND_FETCH_STATIC_PROP_R",
+ "ZEND_FETCH_STATIC_PROP_W",
+ "ZEND_FETCH_STATIC_PROP_RW",
+ "ZEND_FETCH_STATIC_PROP_IS",
+ "ZEND_FETCH_STATIC_PROP_FUNC_ARG",
+ "ZEND_FETCH_STATIC_PROP_UNSET",
+ "ZEND_UNSET_STATIC_PROP",
+ "ZEND_ISSET_ISEMPTY_STATIC_PROP",
+ "ZEND_FETCH_CLASS_CONSTANT",
+};
+
+static uint32_t zend_vm_opcodes_flags[182] = {
+ 0x00000000,
+ 0x00000707,
+ 0x00000707,
+ 0x00000707,
+ 0x00000707,
+ 0x00000707,
+ 0x00000707,
+ 0x00000707,
+ 0x00000707,
+ 0x00000707,
+ 0x00000707,
+ 0x00000707,
+ 0x00000007,
+ 0x00000007,
+ 0x00000707,
+ 0x00000303,
+ 0x00000303,
+ 0x00000707,
+ 0x00000707,
+ 0x00000707,
+ 0x00000707,
+ 0x01000003,
+ 0x00000003,
+ 0x00080701,
+ 0x00080701,
+ 0x00080701,
+ 0x00080701,
+ 0x00080701,
+ 0x00080701,
+ 0x00080701,
+ 0x00080701,
+ 0x00080701,
+ 0x00080701,
+ 0x00080701,
+ 0x00000001,
+ 0x00000001,
+ 0x00000001,
+ 0x00000001,
+ 0x00000301,
+ 0x00000101,
+ 0x00000007,
+ 0x00000000,
+ 0x00000010,
+ 0x00001007,
+ 0x00001007,
+ 0x00041007,
+ 0x00001007,
+ 0x00001007,
+ 0x00000707,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000007,
+ 0x00000707,
+ 0x00010701,
+ 0x00010701,
+ 0x00010701,
+ 0x00000000,
+ 0x00000001,
+ 0x00010300,
+ 0x00000000,
+ 0x00010300,
+ 0x00000003,
+ 0x00000008,
+ 0x00000308,
+ 0x00000803,
+ 0x00000801,
+ 0x00000801,
+ 0x00011003,
+ 0x00010300,
+ 0x00004005,
+ 0x00800703,
+ 0x00010703,
+ 0x02000007,
+ 0x00400107,
+ 0x00000701,
+ 0x00000701,
+ 0x00001003,
+ 0x00040001,
+ 0x00000007,
+ 0x00400107,
+ 0x00000707,
+ 0x00000703,
+ 0x00400107,
+ 0x00000701,
+ 0x00000701,
+ 0x00400107,
+ 0x00000701,
+ 0x00000701,
+ 0x00400107,
+ 0x00000707,
+ 0x00000707,
+ 0x00400107,
+ 0x00000703,
+ 0x00000703,
+ 0x00400107,
+ 0x00000701,
+ 0x00000701,
+ 0x00000307,
+ 0x00200301,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00010000,
+ 0x00000801,
+ 0x00040103,
+ 0x00000003,
+ 0x00100700,
+ 0x00000007,
+ 0x00000003,
+ 0x00010707,
+ 0x00010703,
+ 0x10400107,
+ 0x10000707,
+ 0x00000803,
+ 0x00000801,
+ 0x00010703,
+ 0x00000000,
+ 0x00000801,
+ 0x00000007,
+ 0x00000003,
+ 0x01000003,
+ 0x00000103,
+ 0x00001003,
+ 0x00040001,
+ 0x00004005,
+ 0x00010700,
+ 0x00000000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000701,
+ 0x00000701,
+ 0x00000701,
+ 0x00000701,
+ 0x00000701,
+ 0x00000000,
+ 0x00000305,
+ 0x00000000,
+ 0x00020000,
+ 0x00000000,
+ 0x00000003,
+ 0x00000303,
+ 0x00000300,
+ 0x00020000,
+ 0x00000000,
+ 0x00000701,
+ 0x10000707,
+ 0x00000000,
+ 0x00000000,
+ 0x00001000,
+ 0x00001003,
+ 0x00000103,
+ 0x00000000,
+ 0x00000000,
+ 0x00000101,
+ 0x00100000,
+ 0x00000000,
+ 0x00000000,
+ 0x00000303,
+ 0x00000003,
+ 0x04002010,
+ 0x08002000,
+ 0x00000008,
+ 0x00000000,
+ 0x00000707,
+ 0x00080701,
+ 0x00000301,
+ 0x00001003,
+ 0x00000707,
+ 0x00000010,
+ 0x00020010,
+ 0x00000307,
+ 0x00000307,
+ 0x00000307,
+ 0x00000307,
+ 0x00000307,
+ 0x00000307,
+ 0x00000307,
+ 0x10000307,
+ 0x00000303,
};
ZEND_API const char* zend_get_opcode_name(zend_uchar opcode) {
- return zend_vm_opcodes_map[opcode];
+ return zend_vm_opcodes_names[opcode];
+}
+ZEND_API uint32_t zend_get_opcode_flags(zend_uchar opcode) {
+ return zend_vm_opcodes_flags[opcode];
}
diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h
index bb2d7717bd..52b4d0b5aa 100644
--- a/Zend/zend_vm_opcodes.h
+++ b/Zend/zend_vm_opcodes.h
@@ -28,9 +28,38 @@
#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_NUM 0x00000008
+#define ZEND_VM_OP1_JMP_ADDR 0x00000010
+#define ZEND_VM_OP1_TRY_CATCH 0x00000020
+#define ZEND_VM_OP1_LIVE_RANGE 0x00000040
+#define ZEND_VM_OP2_SPEC 0x00000100
+#define ZEND_VM_OP2_CONST 0x00000200
+#define ZEND_VM_OP2_TMPVAR 0x00000400
+#define ZEND_VM_OP2_NUM 0x00000800
+#define ZEND_VM_OP2_JMP_ADDR 0x00001000
+#define ZEND_VM_OP2_TRY_CATCH 0x00002000
+#define ZEND_VM_OP2_LIVE_RANGE 0x00004000
+#define ZEND_VM_EXT_NUM 0x00010000
+#define ZEND_VM_EXT_VAR 0x00020000
+#define ZEND_VM_EXT_JMP_ADDR 0x00040000
+#define ZEND_VM_EXT_DIM_OBJ 0x00080000
+#define ZEND_VM_EXT_CLASS_FETCH 0x00100000
+#define ZEND_VM_EXT_CONST_FETCH 0x00200000
+#define ZEND_VM_EXT_VAR_FETCH 0x00400000
+#define ZEND_VM_EXT_ARRAY_INIT 0x00800000
+#define ZEND_VM_EXT_TYPE 0x01000000
+#define ZEND_VM_EXT_EVAL 0x02000000
+#define ZEND_VM_EXT_FAST_CALL 0x04000000
+#define ZEND_VM_EXT_FAST_RET 0x08000000
+#define ZEND_VM_EXT_ISSET 0x10000000
+
BEGIN_EXTERN_C()
ZEND_API const char *zend_get_opcode_name(zend_uchar opcode);
+ZEND_API uint32_t zend_get_opcode_flags(zend_uchar opcode);
END_EXTERN_C()
@@ -202,5 +231,16 @@ END_EXTERN_C()
#define ZEND_SPACESHIP 170
#define ZEND_DECLARE_ANON_CLASS 171
#define ZEND_DECLARE_ANON_INHERITED_CLASS 172
+#define ZEND_FETCH_STATIC_PROP_R 173
+#define ZEND_FETCH_STATIC_PROP_W 174
+#define ZEND_FETCH_STATIC_PROP_RW 175
+#define ZEND_FETCH_STATIC_PROP_IS 176
+#define ZEND_FETCH_STATIC_PROP_FUNC_ARG 177
+#define ZEND_FETCH_STATIC_PROP_UNSET 178
+#define ZEND_UNSET_STATIC_PROP 179
+#define ZEND_ISSET_ISEMPTY_STATIC_PROP 180
+#define ZEND_FETCH_CLASS_CONSTANT 181
+
+#define ZEND_VM_LAST_OPCODE 181
#endif
diff --git a/configure.in b/configure.in
index 859574f218..0d62c488b1 100644
--- a/configure.in
+++ b/configure.in
@@ -118,8 +118,8 @@ int zend_sprintf(char *buffer, const char *format, ...);
])
PHP_MAJOR_VERSION=7
-PHP_MINOR_VERSION=0
-PHP_RELEASE_VERSION=1
+PHP_MINOR_VERSION=1
+PHP_RELEASE_VERSION=0
PHP_EXTRA_VERSION="-dev"
PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION"
PHP_VERSION_ID=`expr [$]PHP_MAJOR_VERSION \* 10000 + [$]PHP_MINOR_VERSION \* 100 + [$]PHP_RELEASE_VERSION`
diff --git a/ext/date/tests/date_sun_info_003.phpt b/ext/date/tests/date_sun_info_003.phpt
new file mode 100644
index 0000000000..3ff7a06df1
--- /dev/null
+++ b/ext/date/tests/date_sun_info_003.phpt
@@ -0,0 +1,42 @@
+--TEST--
+Test basic date_sun_info()
+--CREDITS--
+edgarsandi - <edgar.r.sandi@gmail.com>
+--FILE--
+<?php
+date_default_timezone_set('America/Sao_Paulo');
+$sun_info = date_sun_info(strtotime("2015-01-12 00:00:00 UTC"), 89.00, 1.00);
+foreach ($sun_info as $key => $elem ) {
+ echo "$key: " . date("H:i:s", $elem) . "\n";
+}
+
+echo "\n";
+
+$sun_info = date_sun_info(strtotime("2015-09-12 00:00:00 UTC"), 89.00, 1.00);
+foreach ($sun_info as $key => $elem ) {
+ echo "$key: " . date("H:i:s", $elem) . "\n";
+}
+
+echo "Done\n";
+?>
+--EXPECTF--
+sunrise: 21:00:00
+sunset: 21:00:00
+transit: 10:04:02
+civil_twilight_begin: 21:00:00
+civil_twilight_end: 21:00:00
+nautical_twilight_begin: 21:00:00
+nautical_twilight_end: 21:00:00
+astronomical_twilight_begin: 21:00:00
+astronomical_twilight_end: 21:00:00
+
+sunrise: 21:00:01
+sunset: 21:00:01
+transit: 08:52:30
+civil_twilight_begin: 21:00:01
+civil_twilight_end: 21:00:01
+nautical_twilight_begin: 21:00:01
+nautical_twilight_end: 21:00:01
+astronomical_twilight_begin: 21:00:01
+astronomical_twilight_end: 21:00:01
+Done \ No newline at end of file
diff --git a/ext/dba/php_dba.h b/ext/dba/php_dba.h
index aef4ceae7d..38a5b7ca1a 100644
--- a/ext/dba/php_dba.h
+++ b/ext/dba/php_dba.h
@@ -129,8 +129,6 @@ typedef struct dba_handler {
DBA_SYNC_FUNC(x); \
DBA_INFO_FUNC(x)
-#define VALLEN(p) Z_STRVAL_PP(p), Z_STRLEN_PP(p)
-
PHP_FUNCTION(dba_open);
PHP_FUNCTION(dba_popen);
PHP_FUNCTION(dba_close);
diff --git a/ext/exif/exif.c b/ext/exif/exif.c
index a3f7d40585..8ffa55a596 100644
--- a/ext/exif/exif.c
+++ b/ext/exif/exif.c
@@ -4074,7 +4074,7 @@ PHP_FUNCTION(exif_read_data)
exif_discard_imageinfo(&ImageInfo);
#ifdef EXIF_DEBUG
- php_error_docref1(NULL, Z_STRVAL_PP(p_name), E_NOTICE, "done");
+ php_error_docref1(NULL, p_name, E_NOTICE, "done");
#endif
}
/* }}} */
diff --git a/ext/hash/config.m4 b/ext/hash/config.m4
index 5174db3b71..703cf14a30 100644
--- a/ext/hash/config.m4
+++ b/ext/hash/config.m4
@@ -27,11 +27,11 @@ if test "$PHP_HASH" != "no"; then
EXT_HASH_SOURCES="hash.c hash_md.c hash_sha.c hash_ripemd.c hash_haval.c \
hash_tiger.c hash_gost.c hash_snefru.c hash_whirlpool.c hash_adler32.c \
- hash_crc32.c hash_fnv.c hash_joaat.c"
+ hash_crc32.c hash_fnv.c hash_joaat.c hash_sha3.c"
EXT_HASH_HEADERS="php_hash.h php_hash_md.h php_hash_sha.h php_hash_ripemd.h \
php_hash_haval.h php_hash_tiger.h php_hash_gost.h php_hash_snefru.h \
php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h \
- php_hash_fnv.h php_hash_joaat.h"
+ php_hash_fnv.h php_hash_joaat.h php_hash_sha3.h"
PHP_NEW_EXTENSION(hash, $EXT_HASH_SOURCES, $ext_shared)
ifdef([PHP_INSTALL_HEADERS], [
diff --git a/ext/hash/config.w32 b/ext/hash/config.w32
index 8e9d4c3d48..17711facd8 100644
--- a/ext/hash/config.w32
+++ b/ext/hash/config.w32
@@ -15,10 +15,10 @@ if (PHP_HASH != "no") {
AC_DEFINE('HAVE_HASH_EXT', 1);
EXTENSION("hash", "hash.c hash_md.c hash_sha.c hash_ripemd.c hash_haval.c "
+ "hash_tiger.c hash_gost.c hash_snefru.c hash_whirlpool.c "
- + "hash_adler32.c hash_crc32.c hash_joaat.c hash_fnv.c");
+ + "hash_adler32.c hash_crc32.c hash_joaat.c hash_fnv.c hash_sha3.c");
PHP_INSTALL_HEADERS("ext/hash/", "php_hash.h php_hash_md.h php_hash_sha.h php_hash_ripemd.h " +
"php_hash_haval.h php_hash_tiger.h php_hash_gost.h php_hash_snefru.h " +
- "php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h");
+ "php_hash_whirlpool.h php_hash_adler32.h php_hash_crc32.h php_hash_sha3.h");
}
diff --git a/ext/hash/hash.c b/ext/hash/hash.c
index c1a94c2d09..cc94fb220d 100644
--- a/ext/hash/hash.c
+++ b/ext/hash/hash.c
@@ -1014,6 +1014,10 @@ PHP_MINIT_FUNCTION(hash)
php_hash_register_algo("sha256", &php_hash_sha256_ops);
php_hash_register_algo("sha384", &php_hash_sha384_ops);
php_hash_register_algo("sha512", &php_hash_sha512_ops);
+ php_hash_register_algo("sha3-224", &php_hash_sha3_224_ops);
+ php_hash_register_algo("sha3-256", &php_hash_sha3_256_ops);
+ php_hash_register_algo("sha3-384", &php_hash_sha3_384_ops);
+ php_hash_register_algo("sha3-512", &php_hash_sha3_512_ops);
php_hash_register_algo("ripemd128", &php_hash_ripemd128_ops);
php_hash_register_algo("ripemd160", &php_hash_ripemd160_ops);
php_hash_register_algo("ripemd256", &php_hash_ripemd256_ops);
diff --git a/ext/hash/hash_sha3.c b/ext/hash/hash_sha3.c
new file mode 100644
index 0000000000..a1d48390b6
--- /dev/null
+++ b/ext/hash/hash_sha3.c
@@ -0,0 +1,238 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sara Golemon <pollita@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#include "php_hash_sha3.h"
+
+#if (defined(__APPLE__) || defined(__APPLE_CC__)) && \
+ (defined(__BIG_ENDIAN__) || defined(__LITTLE_ENDIAN__))
+# if defined(__LITTLE_ENDIAN__)
+# undef WORDS_BIGENDIAN
+# else
+# if defined(__BIG_ENDIAN__)
+# define WORDS_BIGENDIAN
+# endif
+# endif
+#endif
+
+static inline php_hash_uint64 rol64(php_hash_uint64 v, unsigned char b) {
+ return (v << b) | (v >> (64 - b));
+}
+static inline unsigned char idx(unsigned char x, unsigned char y) {
+ return x + (5 * y);
+}
+
+#ifdef WORDS_BIGENDIAN
+static inline php_hash_uint64 load64(const unsigned char* x) {
+ unsigned char i;
+ php_hash_uint64 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) {
+ 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) {
+ 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)
+#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)
+#endif
+
+static inline char LFSR86540(unsigned char* pLFSR)
+{
+ unsigned char LFSR = *pLFSR;
+ char result = LFSR & 0x01;
+ if (LFSR & 0x80) {
+ // Primitive polynomial over GF(2): x^8+x^6+x^5+x^4+1
+ LFSR = (LFSR << 1) ^ 0x71;
+ } else {
+ LFSR <<= 1;
+ }
+ *pLFSR = LFSR;
+ return result;
+}
+
+static void permute(PHP_SHA3_CTX* ctx) {
+ unsigned char LFSRstate = 0x01;
+ unsigned char round;
+
+ for (round = 0; round < 24; ++round) {
+ { // Theta step (see [Keccak Reference, Section 2.3.2])
+ php_hash_uint64 C[5], D;
+ unsigned char x, y;
+ for (x = 0; x < 5; ++x) {
+ C[x] = readLane(x, 0) ^ readLane(x, 1) ^
+ readLane(x, 2) ^ readLane(x, 3) ^ readLane(x, 4);
+ }
+ for (x = 0; x < 5; ++x) {
+ D = C[(x+4)%5] ^ rol64(C[(x+1)%5], 1);
+ for (y = 0; y < 5; ++y) {
+ XORLane(x, y, D);
+ }
+ }
+ }
+
+ { // 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);
+ 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;
+ x = y;
+ y = Y;
+ temp = readLane(x, y);
+ writeLane(x, y, rol64(current, r));
+ current = temp;
+ }
+ }
+
+ { // X step (see [Keccak Reference, Section 2.3.1])
+ unsigned char x, y;
+ for (y = 0; y < 5; ++y) {
+ php_hash_uint64 temp[5];
+ for (x = 0; x < 5; ++x) {
+ temp[x] = readLane(x, y);
+ }
+ for (x = 0; x < 5; ++x) {
+ writeLane(x, y, temp[x] ^((~temp[(x+1)%5]) & temp[(x+2)%5]));
+ }
+ }
+ }
+
+ { // i step (see [Keccak Reference, Section 2.3.5])
+ 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);
+ }
+ }
+ }
+ }
+}
+
+// ==========================================================================
+
+static void PHP_SHA3_Init(PHP_SHA3_CTX* ctx,
+ int bits) {
+ memset(ctx, 0, sizeof(PHP_SHA3_CTX));
+}
+
+static void PHP_SHA3_Update(PHP_SHA3_CTX* ctx,
+ const unsigned char* buf,
+ unsigned int count,
+ int block_size) {
+ while (count > 0) {
+ int len = block_size - ctx->pos;
+ if (len > count) len = count;
+ count -= len;
+ while (len-- > 0) {
+ ctx->state[ctx->pos++] ^= *(buf++);
+ }
+ if (ctx->pos >= block_size) {
+ permute(ctx);
+ ctx->pos = 0;
+ }
+ }
+}
+
+static void PHP_SHA3_Final(unsigned char* digest,
+ PHP_SHA3_CTX* ctx,
+ int block_size,
+ int digest_size) {
+ int len = digest_size;
+
+ // Pad state to finalize
+ ctx->state[ctx->pos++] ^= 0x06;
+ ctx->state[block_size-1] ^= 0x80;
+ permute(ctx);
+
+ // Square output for digest
+ for(;;) {
+ int bs = (len < block_size) ? len : block_size;
+ memcpy(digest, ctx->state, bs);
+ digest += bs;
+ len -= bs;
+ if (!len) break;
+ permute(ctx);
+ }
+
+ // Zero out context
+ memset(ctx, 0, sizeof(PHP_SHA3_CTX));
+}
+
+// ==========================================================================
+
+#define DECLARE_SHA3_OPS(bits) \
+void PHP_SHA3##bits##Init(PHP_SHA3_##bits##_CTX* ctx) { \
+ PHP_SHA3_Init(ctx, bits); \
+} \
+void PHP_SHA3##bits##Update(PHP_SHA3_##bits##_CTX* ctx, \
+ const unsigned char* input, \
+ unsigned int inputLen) { \
+ PHP_SHA3_Update(ctx, input, inputLen, \
+ (1600 - (2 * bits)) >> 3); \
+} \
+void PHP_SHA3##bits##Final(unsigned char* digest, \
+ PHP_SHA3_##bits##_CTX* ctx) { \
+ PHP_SHA3_Final(digest, ctx, \
+ (1600 - (2 * bits)) >> 3, \
+ bits >> 3); \
+} \
+const php_hash_ops php_hash_sha3_##bits##_ops = { \
+ (php_hash_init_func_t) PHP_SHA3##bits##Init, \
+ (php_hash_update_func_t) PHP_SHA3##bits##Update, \
+ (php_hash_final_func_t) PHP_SHA3##bits##Final, \
+ php_hash_copy, \
+ bits >> 3, \
+ (1600 - (2 * bits)) >> 3, \
+ sizeof(PHP_SHA3_##bits##_CTX) \
+}
+
+DECLARE_SHA3_OPS(224);
+DECLARE_SHA3_OPS(256);
+DECLARE_SHA3_OPS(384);
+DECLARE_SHA3_OPS(512);
+
+#undef DECLARE_SHA3_OPS
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/hash/php_hash.h b/ext/hash/php_hash.h
index c8104710ba..2156116696 100644
--- a/ext/hash/php_hash.h
+++ b/ext/hash/php_hash.h
@@ -68,6 +68,10 @@ extern const php_hash_ops php_hash_sha224_ops;
extern const php_hash_ops php_hash_sha256_ops;
extern const php_hash_ops php_hash_sha384_ops;
extern const php_hash_ops php_hash_sha512_ops;
+extern const php_hash_ops php_hash_sha3_224_ops;
+extern const php_hash_ops php_hash_sha3_256_ops;
+extern const php_hash_ops php_hash_sha3_384_ops;
+extern const php_hash_ops php_hash_sha3_512_ops;
extern const php_hash_ops php_hash_ripemd128_ops;
extern const php_hash_ops php_hash_ripemd160_ops;
extern const php_hash_ops php_hash_ripemd256_ops;
diff --git a/ext/hash/php_hash_sha3.h b/ext/hash/php_hash_sha3.h
new file mode 100644
index 0000000000..c95efc9104
--- /dev/null
+++ b/ext/hash/php_hash_sha3.h
@@ -0,0 +1,59 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Sara Golemon <pollita@php.net> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef PHP_HASH_SHA3_H
+#define PHP_HASH_SHA3_H
+
+#include "php.h"
+#include "ext/hash/php_hash.h"
+
+typedef struct {
+ unsigned char state[200]; // 5 * 5 * sizeof(uint64)
+ php_hash_uint32 pos;
+} PHP_SHA3_CTX;
+
+typedef PHP_SHA3_CTX PHP_SHA3_224_CTX;
+typedef PHP_SHA3_CTX PHP_SHA3_256_CTX;
+typedef PHP_SHA3_CTX PHP_SHA3_384_CTX;
+typedef PHP_SHA3_CTX PHP_SHA3_512_CTX;
+
+PHP_HASH_API void PHP_SHA3224Init(PHP_SHA3_224_CTX*);
+PHP_HASH_API void PHP_SHA3224Update(PHP_SHA3_224_CTX*, const unsigned char*, unsigned int);
+PHP_HASH_API void PHP_SAH3224Final(unsigned char[32], PHP_SHA3_224_CTX*);
+
+PHP_HASH_API void PHP_SHA3256Init(PHP_SHA3_256_CTX*);
+PHP_HASH_API void PHP_SHA3256Update(PHP_SHA3_256_CTX*, const unsigned char*, unsigned int);
+PHP_HASH_API void PHP_SAH3256Final(unsigned char[32], PHP_SHA3_256_CTX*);
+
+PHP_HASH_API void PHP_SHA3384Init(PHP_SHA3_384_CTX*);
+PHP_HASH_API void PHP_SHA3384Update(PHP_SHA3_384_CTX*, const unsigned char*, unsigned int);
+PHP_HASH_API void PHP_SAH3384Final(unsigned char[32], PHP_SHA3_384_CTX*);
+
+PHP_HASH_API void PHP_SHA3512Init(PHP_SHA3_512_CTX*);
+PHP_HASH_API void PHP_SHA3512Update(PHP_SHA3_512_CTX*, const unsigned char*, unsigned int);
+PHP_HASH_API void PHP_SAH3512Final(unsigned char[32], PHP_SHA3_512_CTX*);
+
+#endif
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */
diff --git a/ext/hash/tests/hash_algos.phpt b/ext/hash/tests/hash_algos.phpt
index f2d6fc3ffb..ca1dcad456 100644
--- a/ext/hash/tests/hash_algos.phpt
+++ b/ext/hash/tests/hash_algos.phpt
@@ -18,7 +18,7 @@ var_dump(hash_algos());
===Done===
--EXPECTF--
*** Testing hash_algos() : basic functionality ***
-array(46) {
+array(50) {
[%d]=>
string(3) "md2"
[%d]=>
@@ -36,6 +36,14 @@ array(46) {
[%d]=>
string(6) "sha512"
[%d]=>
+ string(8) "sha3-224"
+ [%d]=>
+ string(8) "sha3-256"
+ [%d]=>
+ string(8) "sha3-384"
+ [%d]=>
+ string(8) "sha3-512"
+ [%d]=>
string(9) "ripemd128"
[%d]=>
string(9) "ripemd160"
diff --git a/ext/hash/tests/hash_copy_001.phpt b/ext/hash/tests/hash_copy_001.phpt
index f9fe7cc552..67d16aaf88 100644
--- a/ext/hash/tests/hash_copy_001.phpt
+++ b/ext/hash/tests/hash_copy_001.phpt
@@ -55,6 +55,18 @@ string(96) "6950d861ace4102b803ab8b3779d2f471968233010d2608974ab89804cef6f76162b
string(6) "sha512"
string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13"
string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13"
+string(8) "sha3-224"
+string(56) "7e1126cffee98e5c4b0e9dd5c6efabd5c9356d668e9a2d3cfab724d4"
+string(56) "7e1126cffee98e5c4b0e9dd5c6efabd5c9356d668e9a2d3cfab724d4"
+string(8) "sha3-256"
+string(64) "834abfed9197af09cbe66b7748c65a050a3755ef7a556d6764eb6eabc93b4c7a"
+string(64) "834abfed9197af09cbe66b7748c65a050a3755ef7a556d6764eb6eabc93b4c7a"
+string(8) "sha3-384"
+string(96) "c9016992586f7a8663c5379ed892349c1140ad258f7c44ee82f61f0b8cb75c675012ea94dc1314e06699be2d1465f67b"
+string(96) "c9016992586f7a8663c5379ed892349c1140ad258f7c44ee82f61f0b8cb75c675012ea94dc1314e06699be2d1465f67b"
+string(8) "sha3-512"
+string(128) "5f85341bc9c6621406bf1841c4ce01727ea8759fdf2927106c3e70a75ad9fffd095b87f995aeee844e1a2c287e1195ce809b9bdb1c31258f7fc098175b6de0b4"
+string(128) "5f85341bc9c6621406bf1841c4ce01727ea8759fdf2927106c3e70a75ad9fffd095b87f995aeee844e1a2c287e1195ce809b9bdb1c31258f7fc098175b6de0b4"
string(9) "ripemd128"
string(32) "5f1bc5f5aeaf747574dd34a6535cd94a"
string(32) "5f1bc5f5aeaf747574dd34a6535cd94a"
@@ -193,6 +205,18 @@ string(96) "0d44981d04bb11b1ef75d5c2932bd0aa2785e7bc454daac954d77e2ca10047879b58
string(6) "sha512"
string(128) "caced3db8e9e3a5543d5b933bcbe9e7834e6667545c3f5d4087b58ec8d78b4c8a4a5500c9b88f65f7368810ba9905e51f1cff3b25a5dccf76634108fb4e7ce13"
string(128) "28d7c721433782a880f840af0c3f3ea2cad4ef55de2114dda9d504cedeb110e1cf2519c49e4b5da3da4484bb6ba4fd1621ceadc6408f4410b2ebe9d83a4202c2"
+string(8) "sha3-224"
+string(56) "7e1126cffee98e5c4b0e9dd5c6efabd5c9356d668e9a2d3cfab724d4"
+string(56) "9a21a5464794c2c9784df50cf89cf72234e11941bddaee93f912753e"
+string(8) "sha3-256"
+string(64) "834abfed9197af09cbe66b7748c65a050a3755ef7a556d6764eb6eabc93b4c7a"
+string(64) "57aa7a90f29b5ab66592760592780da247fd39b4c911773687450f9df8cc8ed0"
+string(8) "sha3-384"
+string(96) "c9016992586f7a8663c5379ed892349c1140ad258f7c44ee82f61f0b8cb75c675012ea94dc1314e06699be2d1465f67b"
+string(96) "5d6d7e42b241288bc707b74c50f90a37d69a4afa854ca72021a22cb379356e53b6233aea1be2f33d393d6effa9b5e36c"
+string(8) "sha3-512"
+string(128) "5f85341bc9c6621406bf1841c4ce01727ea8759fdf2927106c3e70a75ad9fffd095b87f995aeee844e1a2c287e1195ce809b9bdb1c31258f7fc098175b6de0b4"
+string(128) "9b88c689bc13a36e6983b32e8ee9464d63b619f246ca451d1fe2a6c9670f01e71d0c8eb245f3204d27d27c056f2a0fef76a1e3bc30fb74cccbc984dbd4883ae6"
string(9) "ripemd128"
string(32) "5f1bc5f5aeaf747574dd34a6535cd94a"
string(32) "f95f5e22b8875ee0c48219ae97f0674b"
diff --git a/ext/hash/tests/sha3.phpt b/ext/hash/tests/sha3.phpt
new file mode 100644
index 0000000000..67fb22f988
--- /dev/null
+++ b/ext/hash/tests/sha3.phpt
@@ -0,0 +1,56 @@
+--TEST--
+sha3 algorithm
+--SKIPIF--
+<?php if(!extension_loaded("hash")) print "skip"; ?>
+--FILE--
+<?php
+
+// Test vectors taken from a combination of NIST FIPS-202,
+// Wikipedia reference vectors,
+// and output from reference implementation
+$subjects = [
+ '',
+ 'a',
+ 'The quick brown fox jumps over the lazy dog',
+ 'The quick brown fox jumps over the lazy dog.',
+ str_repeat('a', 257),
+ str_repeat("\xA3", 200),
+];
+foreach ($subjects as $subject) {
+ echo '== ', urlencode($subject), " ==\n";
+ foreach ([224, 256, 384, 512] as $bits) {
+ echo $bits, ': ', hash("sha3-$bits", $subject), "\n";
+ }
+}
+--EXPECT--
+== ==
+224: 6b4e03423667dbb73b6e15454f0eb1abd4597f9a1b078e3f5b5a6bc7
+256: a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a
+384: 0c63a75b845e4f7d01107d852e4c2485c51a50aaaa94fc61995e71bbee983a2ac3713831264adb47fb6bd1e058d5f004
+512: a69f73cca23a9ac5c8b567dc185a756e97c982164fe25859e0d1dcc1475c80a615b2123af1f5f94c11e3e9402c3ac558f500199d95b6d3e301758586281dcd26
+== a ==
+224: 9e86ff69557ca95f405f081269685b38e3a819b309ee942f482b6a8b
+256: 80084bf2fba02475726feb2cab2d8215eab14bc6bdd8bfb2c8151257032ecd8b
+384: 1815f774f320491b48569efec794d249eeb59aae46d22bf77dafe25c5edc28d7ea44f93ee1234aa88f61c91912a4ccd9
+512: 697f2d856172cb8309d6b8b97dac4de344b549d4dee61edfb4962d8698b7fa803f4f93ff24393586e28b5b957ac3d1d369420ce53332712f997bd336d09ab02a
+== The+quick+brown+fox+jumps+over+the+lazy+dog ==
+224: d15dadceaa4d5d7bb3b48f446421d542e08ad8887305e28d58335795
+256: 69070dda01975c8c120c3aada1b282394e7f032fa9cf32f4cb2259a0897dfc04
+384: 7063465e08a93bce31cd89d2e3ca8f602498696e253592ed26f07bf7e703cf328581e1471a7ba7ab119b1a9ebdf8be41
+512: 01dedd5de4ef14642445ba5f5b97c15e47b9ad931326e4b0727cd94cefc44fff23f07bf543139939b49128caf436dc1bdee54fcb24023a08d9403f9b4bf0d450
+== The+quick+brown+fox+jumps+over+the+lazy+dog. ==
+224: 2d0708903833afabdd232a20201176e8b58c5be8a6fe74265ac54db0
+256: a80f839cd4f83f6c3dafc87feae470045e4eb0d366397d5c6ce34ba1739f734d
+384: 1a34d81695b622df178bc74df7124fe12fac0f64ba5250b78b99c1273d4b080168e10652894ecad5f1f4d5b965437fb9
+512: 18f4f4bd419603f95538837003d9d254c26c23765565162247483f65c50303597bc9ce4d289f21d1c2f1f458828e33dc442100331b35e7eb031b5d38ba6460f8
+== aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa ==
+224: 10dd422d71c42ee102a0c4bd398b5b85470341a0794702c954b022ba
+256: 6d115e8744deef792419e8bdb8567d74844e0fa5c2d5e474a19de87ac001449f
+384: c9df41fa389101cde63447257835464d89fd3974e5813f3f58d30e0296e89486e2d4bfc2b4089cd3bb860a20263322b8
+512: 5008048b64c14975181175f157be4a780c3d443d2177edf323d57884bc7e3979b9b53bca1325e880df3da0d97c435693441cb5527fbe950f5585678dfbb37785
+== %A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3%A3 ==
+224: 9376816aba503f72f96ce7eb65ac095deee3be4bf9bbc2a1cb7e11e0
+256: 79f38adec5c20307a98ef76e8324afbfd46cfd81b22e3973c65fa1bd9de31787
+384: 1881de2ca7e41ef95dc4732b8f5f002b189cc1e42b74168ed1732649ce1dbcdd76197a31fd55ee989f2d7050dd473e8f
+512: e76dfad22084a8b1467fcf2ffa58361bec7628edf5f3fdc0e4805dc48caeeca81b7c13c30adf52a3659584739a2df46be589c51ca1a4a8416df6545a1ce8ba00
+
diff --git a/ext/mcrypt/tests/mcrypt_module_get_algo_block_size.phpt b/ext/mcrypt/tests/mcrypt_module_get_algo_block_size.phpt
index c89a44ad8a..93db98241a 100644
--- a/ext/mcrypt/tests/mcrypt_module_get_algo_block_size.phpt
+++ b/ext/mcrypt/tests/mcrypt_module_get_algo_block_size.phpt
@@ -8,12 +8,13 @@ var_dump(mcrypt_module_get_algo_block_size(MCRYPT_RIJNDAEL_256));
var_dump(mcrypt_module_get_algo_block_size(MCRYPT_RIJNDAEL_192));
var_dump(mcrypt_module_get_algo_block_size(MCRYPT_RC2));
var_dump(mcrypt_module_get_algo_block_size(MCRYPT_XTEA));
-var_dump(mcrypt_module_get_algo_block_size(MCRYPT_CAST_128));
+var_dump(mcrypt_module_get_algo_block_size(MCRYPT_CAST_256));
var_dump(mcrypt_module_get_algo_block_size(MCRYPT_BLOWFISH));
+?>
--EXPECT--
int(32)
int(24)
int(8)
int(8)
-int(8)
+int(16)
int(8)
diff --git a/ext/mcrypt/tests/mcrypt_module_get_algo_key_size.phpt b/ext/mcrypt/tests/mcrypt_module_get_algo_key_size.phpt
index 7d3841f3e2..35e4721055 100644
--- a/ext/mcrypt/tests/mcrypt_module_get_algo_key_size.phpt
+++ b/ext/mcrypt/tests/mcrypt_module_get_algo_key_size.phpt
@@ -8,12 +8,13 @@ var_dump(mcrypt_module_get_algo_key_size(MCRYPT_RIJNDAEL_256));
var_dump(mcrypt_module_get_algo_key_size(MCRYPT_RIJNDAEL_192));
var_dump(mcrypt_module_get_algo_key_size(MCRYPT_RC2));
var_dump(mcrypt_module_get_algo_key_size(MCRYPT_XTEA));
-var_dump(mcrypt_module_get_algo_key_size(MCRYPT_CAST_128));
+var_dump(mcrypt_module_get_algo_key_size(MCRYPT_CAST_256));
var_dump(mcrypt_module_get_algo_key_size(MCRYPT_BLOWFISH));
+?>
--EXPECT--
int(32)
int(32)
int(128)
int(16)
-int(16)
+int(32)
int(56)
diff --git a/ext/mysqli/mysqli_api.c b/ext/mysqli/mysqli_api.c
index 20f22297e8..911ff9c8d1 100644
--- a/ext/mysqli/mysqli_api.c
+++ b/ext/mysqli/mysqli_api.c
@@ -1267,7 +1267,11 @@ PHP_FUNCTION(mysqli_fetch_lengths)
MYSQL_RES *result;
zval *mysql_result;
unsigned int i;
- zend_ulong *ret;
+#if defined(MYSQLI_USE_MYSQLND)
+ const size_t *ret;
+#else
+ const zend_ulong *ret;
+#endif
if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "O", &mysql_result, mysqli_result_class_entry) == FAILURE) {
return;
diff --git a/ext/mysqli/mysqli_prop.c b/ext/mysqli/mysqli_prop.c
index 11f136e603..168edb9364 100644
--- a/ext/mysqli/mysqli_prop.c
+++ b/ext/mysqli/mysqli_prop.c
@@ -15,8 +15,6 @@
| Author: Georg Richter <georg@php.net> |
| Andrey Hristov <andrey@php.net> |
+----------------------------------------------------------------------+
-
- $Id$
*/
#ifdef HAVE_CONFIG_H
@@ -289,7 +287,11 @@ static zval *result_type_read(mysqli_object *obj, zval *retval)
static zval *result_lengths_read(mysqli_object *obj, zval *retval)
{
MYSQL_RES *p;
- zend_ulong *ret;
+#if defined(MYSQLI_USE_MYSQLND)
+ const size_t *ret;
+#else
+ const zend_ulong *ret;
+#endif
uint field_count;
CHECK_STATUS(MYSQLI_STATUS_VALID);
diff --git a/ext/mysqlnd/config.w32 b/ext/mysqlnd/config.w32
index ff102310dd..52be8f563c 100644
--- a/ext/mysqlnd/config.w32
+++ b/ext/mysqlnd/config.w32
@@ -6,23 +6,26 @@ if (PHP_MYSQLND != "no") {
if (CHECK_LIB("ws2_32.lib", "mysqlnd")) {
mysqlnd_source =
- "mysqlnd.c " +
"mysqlnd_alloc.c " +
"mysqlnd_auth.c " +
"mysqlnd_block_alloc.c " +
+ "mysqlnd_connection.c " +
"mysqlnd_charset.c " +
+ "mysqlnd_commands.c " +
"mysqlnd_debug.c " +
"mysqlnd_driver.c " +
"mysqlnd_ext_plugin.c " +
"mysqlnd_loaddata.c " +
"mysqlnd_reverse_api.c " +
- "mysqlnd_net.c " +
"mysqlnd_plugin.c " +
+ "mysqlnd_protocol_frame_codec.c " +
"mysqlnd_ps.c " +
"mysqlnd_ps_codec.c " +
+ "mysqlnd_read_buffer.c " +
"mysqlnd_result.c " +
"mysqlnd_result_meta.c " +
"mysqlnd_statistics.c " +
+ "mysqlnd_vio.c " +
"mysqlnd_wireprotocol.c " +
"php_mysqlnd.c ";
EXTENSION("mysqlnd", mysqlnd_source, false, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
diff --git a/ext/mysqlnd/config9.m4 b/ext/mysqlnd/config9.m4
index 92cab94367..b5f20a9c8b 100644
--- a/ext/mysqlnd/config9.m4
+++ b/ext/mysqlnd/config9.m4
@@ -18,11 +18,11 @@ fi
dnl If some extension uses mysqlnd it will get compiled in PHP core
if test "$PHP_MYSQLND" != "no" || test "$PHP_MYSQLND_ENABLED" = "yes"; then
mysqlnd_ps_sources="mysqlnd_ps.c mysqlnd_ps_codec.c"
- mysqlnd_base_sources="mysqlnd.c mysqlnd_alloc.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
- mysqlnd_loaddata.c mysqlnd_reverse_api.c mysqlnd_net.c \
+ mysqlnd_base_sources="mysqlnd_connection.c mysqlnd_alloc.c mysqlnd_charset.c mysqlnd_wireprotocol.c \
+ mysqlnd_loaddata.c mysqlnd_reverse_api.c mysqlnd_vio.c mysqlnd_protocol_frame_codec.c \
mysqlnd_statistics.c mysqlnd_driver.c mysqlnd_ext_plugin.c mysqlnd_auth.c \
- mysqlnd_result.c mysqlnd_result_meta.c mysqlnd_debug.c\
- mysqlnd_block_alloc.c mysqlnd_plugin.c php_mysqlnd.c"
+ mysqlnd_result.c mysqlnd_result_meta.c mysqlnd_debug.c mysqlnd_commands.c \
+ mysqlnd_block_alloc.c mysqlnd_read_buffer.c mysqlnd_plugin.c php_mysqlnd.c"
if test "$PHP_MYSQLND_COMPRESSION_SUPPORT" != "no"; then
diff --git a/ext/mysqlnd/mysqlnd.h b/ext/mysqlnd/mysqlnd.h
index 7e72f9690b..048af789fc 100644
--- a/ext/mysqlnd/mysqlnd.h
+++ b/ext/mysqlnd/mysqlnd.h
@@ -61,6 +61,7 @@
#include "mysqlnd_enum_n_def.h"
#include "mysqlnd_structs.h"
+#define MYSQLND_STR_W_LEN(str) str, (sizeof(str) - 1)
/* Library related */
PHPAPI void mysqlnd_library_init(void);
@@ -83,18 +84,23 @@ PHPAPI const MYSQLND_CHARSET * mysqlnd_find_charset_name(const char * const char
/* Connect */
-PHPAPI MYSQLND * mysqlnd_init(unsigned int client_flags, zend_bool persistent);
-PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn,
- const char * host, const char * user,
- const char * passwd, unsigned int passwd_len,
- const char * db, unsigned int db_len,
- unsigned int port,
- const char * socket_or_pipe,
- unsigned int mysql_flags,
- unsigned int client_api_flags
- );
-
-#define mysqlnd_change_user(conn, user, passwd, db, silent) ((conn)->data)->m->change_user((conn)->data, (user), (passwd), (db), (silent), strlen((passwd)))
+#define mysqlnd_init(flags, persistent) mysqlnd_connection_init((flags), (persistent), NULL /*use default factory*/)
+#define mysqlnd_connect(conn, host, user, pass, pass_len, db, db_len, port, socket, mysql_flags, client_api_flags) \
+ mysqlnd_connection_connect((conn), (host), (user), (pass), (pass_len), (db), (db_len), (port), (socket), (mysql_flags), (client_api_flags))
+
+PHPAPI MYSQLND * mysqlnd_connection_init(const size_t client_flags, const zend_bool persistent, MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) *object_factory);
+PHPAPI MYSQLND * mysqlnd_connection_connect(MYSQLND * conn,
+ const char * const host,
+ const char * const user,
+ const char * const passwd, unsigned int passwd_len,
+ const char * const db, unsigned int db_len,
+ unsigned int port,
+ const char * const socket_or_pipe,
+ unsigned int mysql_flags,
+ unsigned int client_api_flags
+ );
+
+#define mysqlnd_change_user(conn, user, passwd, db, silent) ((conn)->data)->m->change_user((conn)->data, (user), (passwd), (db), (silent), strlen((passwd)))
#define mysqlnd_change_user_ex(conn, user, passwd, db, silent, passwd_len) ((conn)->data)->m->change_user((conn)->data, (user), (passwd), (db), (silent), (passwd_len))
PHPAPI void mysqlnd_debug(const char *mode);
@@ -105,7 +111,7 @@ PHPAPI void mysqlnd_debug(const char *mode);
#define mysqlnd_fetch_all(result, flags, return_value) (result)->m.fetch_all((result), (flags), (return_value) ZEND_FILE_LINE_CC)
#define mysqlnd_result_fetch_field_data(res,offset,ret) (res)->m.fetch_field_data((res), (offset), (ret))
#define mysqlnd_get_connection_stats(conn, values) ((conn)->data)->m->get_statistics((conn)->data, (values) ZEND_FILE_LINE_CC)
-#define mysqlnd_get_client_stats(values) _mysqlnd_get_client_stats((values) ZEND_FILE_LINE_CC)
+#define mysqlnd_get_client_stats(values) _mysqlnd_get_client_stats(mysqlnd_global_stats, (values) ZEND_FILE_LINE_CC)
#define mysqlnd_close(conn,is_forced) (conn)->m->close((conn), (is_forced))
#define mysqlnd_query(conn, query_str, query_len) ((conn)->data)->m->query((conn)->data, (query_str), (query_len))
@@ -180,7 +186,7 @@ PHPAPI void mysqlnd_free_param_bind_dtor(MYSQLND_PARAM_BIND * param_bind);
PHPAPI void mysqlnd_free_result_bind_dtor(MYSQLND_RESULT_BIND * result_bind);
-PHPAPI const char * mysqlnd_field_type_name(enum mysqlnd_field_types field_type);
+PHPAPI const char * mysqlnd_field_type_name(const enum mysqlnd_field_types field_type);
/* LOAD DATA LOCAL */
void mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn);
@@ -193,7 +199,6 @@ void mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn);
#define mysqlnd_savepoint(conn, name) ((conn)->data)->m->tx_savepoint((conn)->data, (name))
#define mysqlnd_release_savepoint(conn, name) ((conn)->data)->m->tx_savepoint_release((conn)->data, (name))
#define mysqlnd_list_dbs(conn, wild) ((conn)->data)->m->list_method((conn)->data, wild? "SHOW DATABASES LIKE %s":"SHOW DATABASES", (wild), NULL)
-#define mysqlnd_list_fields(conn, tab,wild) ((conn)->data)->m->list_fields((conn)->data, (tab), (wild))
#define mysqlnd_list_processes(conn) ((conn)->data)->m->list_method((conn)->data, "SHOW PROCESSLIST", NULL, NULL)
#define mysqlnd_list_tables(conn, wild) ((conn)->data)->m->list_method((conn)->data, wild? "SHOW TABLES LIKE %s":"SHOW TABLES", (wild), NULL)
#define mysqlnd_dump_debug_info(conn) ((conn)->data)->m->server_dump_debug_information((conn)->data)
@@ -218,14 +223,14 @@ PHPAPI zend_ulong mysqlnd_old_escape_string(char * newstr, const char * escapest
/* PS */
-#define mysqlnd_stmt_init(conn) ((conn)->data)->m->stmt_init(((conn)->data))
-#define mysqlnd_stmt_store_result(stmt) (!mysqlnd_stmt_field_count((stmt)) ? PASS:((stmt)->m->store_result((stmt))? PASS:FAIL))
-#define mysqlnd_stmt_get_result(stmt) (stmt)->m->get_result((stmt))
-#define mysqlnd_stmt_more_results(stmt) (stmt)->m->more_results((stmt))
-#define mysqlnd_stmt_next_result(stmt) (stmt)->m->next_result((stmt))
-#define mysqlnd_stmt_data_seek(stmt, row) (stmt)->m->seek_data((stmt), (row))
-#define mysqlnd_stmt_prepare(stmt, q, qlen) (stmt)->m->prepare((stmt), (q), (qlen))
-#define mysqlnd_stmt_execute(stmt) (stmt)->m->execute((stmt))
+#define mysqlnd_stmt_init(conn) ((conn)->data)->m->stmt_init(((conn)->data))
+#define mysqlnd_stmt_store_result(stmt) (!mysqlnd_stmt_field_count((stmt)) ? PASS:((stmt)->m->store_result((stmt))? PASS:FAIL))
+#define mysqlnd_stmt_get_result(stmt) (stmt)->m->get_result((stmt))
+#define mysqlnd_stmt_more_results(stmt) (stmt)->m->more_results((stmt))
+#define mysqlnd_stmt_next_result(stmt) (stmt)->m->next_result((stmt))
+#define mysqlnd_stmt_data_seek(stmt, row) (stmt)->m->seek_data((stmt), (row))
+#define mysqlnd_stmt_prepare(stmt, q, qlen) (stmt)->m->prepare((stmt), (q), (qlen))
+#define mysqlnd_stmt_execute(stmt) (stmt)->m->execute((stmt))
#define mysqlnd_stmt_send_long_data(stmt,p,d,l) (stmt)->m->send_long_data((stmt), (p), (d), (l))
#define mysqlnd_stmt_alloc_param_bind(stmt) (stmt)->m->alloc_parameter_bind((stmt))
#define mysqlnd_stmt_free_param_bind(stmt,bind) (stmt)->m->free_parameter_bind((stmt), (bind))
@@ -239,10 +244,10 @@ PHPAPI zend_ulong mysqlnd_old_escape_string(char * newstr, const char * escapest
#define mysqlnd_stmt_param_metadata(stmt) (stmt)->m->get_parameter_metadata((stmt))
#define mysqlnd_stmt_result_metadata(stmt) (stmt)->m->get_result_metadata((stmt))
-#define mysqlnd_stmt_free_result(stmt) (stmt)->m->free_result((stmt))
-#define mysqlnd_stmt_close(stmt, implicit) (stmt)->m->dtor((stmt), (implicit))
-#define mysqlnd_stmt_reset(stmt) (stmt)->m->reset((stmt))
-#define mysqlnd_stmt_flush(stmt) (stmt)->m->flush((stmt))
+#define mysqlnd_stmt_free_result(stmt) (stmt)->m->free_result((stmt))
+#define mysqlnd_stmt_close(stmt, implicit) (stmt)->m->dtor((stmt), (implicit))
+#define mysqlnd_stmt_reset(stmt) (stmt)->m->reset((stmt))
+#define mysqlnd_stmt_flush(stmt) (stmt)->m->flush((stmt))
#define mysqlnd_stmt_attr_get(stmt, attr, value) (stmt)->m->get_attribute((stmt), (attr), (value))
@@ -252,11 +257,54 @@ PHPAPI zend_ulong mysqlnd_old_escape_string(char * newstr, const char * escapest
/* Performance statistics */
-PHPAPI void _mysqlnd_get_client_stats(zval *return_value ZEND_FILE_LINE_DC);
+PHPAPI extern MYSQLND_STATS * mysqlnd_global_stats;
+PHPAPI extern const MYSQLND_STRING mysqlnd_stats_values_names[];
+PHPAPI void _mysqlnd_get_client_stats(MYSQLND_STATS * stats, zval *return_value ZEND_FILE_LINE_DC);
+
+
+#ifndef MYSQLND_CORE_STATISTICS_DISABLED
+
+#define MYSQLND_INC_GLOBAL_STATISTIC(statistic) \
+ MYSQLND_INC_STATISTIC(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic))
+
+#define MYSQLND_DEC_GLOBAL_STATISTIC(statistic) \
+ MYSQLND_DEC_STATISTIC(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic))
+
+#define MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(statistic1, value1, statistic2, value2) \
+ MYSQLND_INC_STATISTIC_W_VALUE2(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic1), (value1), (statistic2), (value2))
+
+#define MYSQLND_INC_CONN_STATISTIC(conn_stats, statistic) \
+ MYSQLND_INC_STATISTIC(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic)); \
+ MYSQLND_INC_STATISTIC(MYSQLND_G(collect_statistics), (conn_stats), (statistic));
+
+#define MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn_stats, statistic, value) \
+ MYSQLND_INC_STATISTIC_W_VALUE(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic), (value)); \
+ MYSQLND_INC_STATISTIC_W_VALUE(MYSQLND_G(collect_statistics), (conn_stats), (statistic), (value));
+
+#define MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn_stats, statistic1, value1, statistic2, value2) \
+ MYSQLND_INC_STATISTIC_W_VALUE2(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic1), (value1), (statistic2), (value2)); \
+ MYSQLND_INC_STATISTIC_W_VALUE2(MYSQLND_G(collect_statistics), (conn_stats), (statistic1), (value1), (statistic2), (value2));
+
+#define MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats, statistic1, value1, statistic2, value2, statistic3, value3) \
+ MYSQLND_INC_STATISTIC_W_VALUE3(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic1), (value1), (statistic2), (value2), (statistic3), (value3)); \
+ MYSQLND_INC_STATISTIC_W_VALUE3(MYSQLND_G(collect_statistics), (conn_stats), (statistic1), (value1), (statistic2), (value2), (statistic3), (value3));
+
+#else
+
+#define MYSQLND_INC_GLOBAL_STATISTIC(statistic)
+#define MYSQLND_DEC_GLOBAL_STATISTIC(statistic)
+#define MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(statistic1, value1, statistic2, value2)
+#define MYSQLND_INC_CONN_STATISTIC(conn_stats, statistic)
+#define MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn_stats, statistic, value)
+#define MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn_stats, statistic1, value1, statistic2, value2)
+#define MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats, statistic1, value1, statistic2, value2, statistic3, value3)
+
+#endif /* MYSQLND_CORE_STATISTICS_DISABLED */
+
/* double check the class name to avoid naming conflicts when using these: */
-#define MYSQLND_METHOD(class, method) php_##class##_##method##_pub
-#define MYSQLND_METHOD_PRIVATE(class, method) php_##class##_##method##_priv
+#define MYSQLND_METHOD(class, method) mysqlnd_##class##_##method##_pub
+#define MYSQLND_METHOD_PRIVATE(class, method) mysqlnd_##class##_##method##_priv
ZEND_BEGIN_MODULE_GLOBALS(mysqlnd)
char * debug; /* The actual string */
diff --git a/ext/mysqlnd/mysqlnd_alloc.c b/ext/mysqlnd/mysqlnd_alloc.c
index c28044ca7f..db1d0a22b7 100644
--- a/ext/mysqlnd/mysqlnd_alloc.c
+++ b/ext/mysqlnd/mysqlnd_alloc.c
@@ -12,8 +12,7 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+----------------------------------------------------------------------+
*/
diff --git a/ext/mysqlnd/mysqlnd_alloc.h b/ext/mysqlnd/mysqlnd_alloc.h
index 958aff8934..6cac245c7d 100644
--- a/ext/mysqlnd/mysqlnd_alloc.h
+++ b/ext/mysqlnd/mysqlnd_alloc.h
@@ -12,15 +12,11 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+----------------------------------------------------------------------+
*/
-/* $Id: mysqlnd_debug.h 306938 2011-01-01 02:17:06Z felipe $ */
-/* $Id: mysqlnd_debug.h 306938 2011-01-01 02:17:06Z felipe $ */
-
#ifndef MYSQLND_ALLOC_H
#define MYSQLND_ALLOC_H
diff --git a/ext/mysqlnd/mysqlnd_auth.c b/ext/mysqlnd/mysqlnd_auth.c
index e4632496f9..13efc05461 100644
--- a/ext/mysqlnd/mysqlnd_auth.c
+++ b/ext/mysqlnd/mysqlnd_auth.c
@@ -12,22 +12,223 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-/* $Id: mysqlnd.c 307377 2011-01-11 13:02:57Z andrey $ */
#include "php.h"
#include "mysqlnd.h"
#include "mysqlnd_structs.h"
+#include "mysqlnd_auth.h"
#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_connection.h"
#include "mysqlnd_priv.h"
-#include "mysqlnd_result.h"
#include "mysqlnd_charset.h"
#include "mysqlnd_debug.h"
+static const char * const mysqlnd_old_passwd = "mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication. "
+"Please use an administration tool to reset your password with the command SET PASSWORD = PASSWORD('your_existing_password'). This will "
+"store a new, and more secure, hash value in mysql.user. If this user is used in other scripts executed by PHP 5.2 or earlier you might need to remove the old-passwords "
+"flag from your my.cnf file";
+
+
+/* {{{ mysqlnd_run_authentication */
+enum_func_status
+mysqlnd_run_authentication(
+ MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const MYSQLND_STRING auth_plugin_data,
+ const char * const auth_protocol,
+ unsigned int charset_no,
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ zend_ulong mysql_flags,
+ zend_bool silent,
+ zend_bool is_change_user
+ )
+{
+ enum_func_status ret = FAIL;
+ zend_bool first_call = TRUE;
+
+ char * switch_to_auth_protocol = NULL;
+ size_t switch_to_auth_protocol_len = 0;
+ char * requested_protocol = NULL;
+ zend_uchar * plugin_data;
+ size_t plugin_data_len;
+
+ DBG_ENTER("mysqlnd_run_authentication");
+
+ plugin_data_len = auth_plugin_data.l;
+ plugin_data = mnd_emalloc(plugin_data_len + 1);
+ if (!plugin_data) {
+ goto end;
+ }
+ memcpy(plugin_data, auth_plugin_data.s, plugin_data_len);
+ plugin_data[plugin_data_len] = '\0';
+
+ requested_protocol = mnd_pestrdup(auth_protocol? auth_protocol : MYSQLND_DEFAULT_AUTH_PROTOCOL, FALSE);
+ if (!requested_protocol) {
+ goto end;
+ }
+
+ do {
+ struct st_mysqlnd_authentication_plugin * auth_plugin = conn->m->fetch_auth_plugin_by_name(requested_protocol);
+
+ if (!auth_plugin) {
+ php_error_docref(NULL, E_WARNING, "The server requested authentication method unknown to the client [%s]", requested_protocol);
+ SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "The server requested authentication method unknown to the client");
+ goto end;
+ }
+ DBG_INF("plugin found");
+
+ {
+ zend_uchar * switch_to_auth_protocol_data = NULL;
+ size_t switch_to_auth_protocol_data_len = 0;
+ zend_uchar * scrambled_data = NULL;
+ size_t scrambled_data_len = 0;
+
+ switch_to_auth_protocol = NULL;
+ switch_to_auth_protocol_len = 0;
+
+ if (conn->authentication_plugin_data.s) {
+ mnd_pefree(conn->authentication_plugin_data.s, conn->persistent);
+ conn->authentication_plugin_data.s = NULL;
+ }
+ conn->authentication_plugin_data.l = plugin_data_len;
+ conn->authentication_plugin_data.s = mnd_pemalloc(conn->authentication_plugin_data.l, conn->persistent);
+ if (!conn->authentication_plugin_data.s) {
+ SET_OOM_ERROR(conn->error_info);
+ goto end;
+ }
+ memcpy(conn->authentication_plugin_data.s, plugin_data, plugin_data_len);
+
+ DBG_INF_FMT("salt(%d)=[%.*s]", plugin_data_len, plugin_data_len, plugin_data);
+ /* The data should be allocated with malloc() */
+ scrambled_data =
+ auth_plugin->methods.get_auth_data(NULL, &scrambled_data_len, conn, user, passwd, passwd_len,
+ plugin_data, plugin_data_len, session_options,
+ conn->protocol_frame_codec->data, mysql_flags);
+ if (conn->error_info->error_no) {
+ goto end;
+ }
+ if (FALSE == is_change_user) {
+ ret = mysqlnd_auth_handshake(conn, user, passwd, passwd_len, db, db_len, session_options, mysql_flags,
+ charset_no,
+ first_call,
+ requested_protocol,
+ scrambled_data, scrambled_data_len,
+ &switch_to_auth_protocol, &switch_to_auth_protocol_len,
+ &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len
+ );
+ } else {
+ ret = mysqlnd_auth_change_user(conn, user, strlen(user), passwd, passwd_len, db, db_len, silent,
+ first_call,
+ requested_protocol,
+ scrambled_data, scrambled_data_len,
+ &switch_to_auth_protocol, &switch_to_auth_protocol_len,
+ &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len
+ );
+ }
+ first_call = FALSE;
+ free(scrambled_data);
+
+ DBG_INF_FMT("switch_to_auth_protocol=%s", switch_to_auth_protocol? switch_to_auth_protocol:"n/a");
+ if (requested_protocol && switch_to_auth_protocol) {
+ mnd_efree(requested_protocol);
+ requested_protocol = switch_to_auth_protocol;
+ }
+
+ if (plugin_data) {
+ mnd_efree(plugin_data);
+ }
+ plugin_data_len = switch_to_auth_protocol_data_len;
+ plugin_data = switch_to_auth_protocol_data;
+ }
+ DBG_INF_FMT("conn->error_info->error_no = %d", conn->error_info->error_no);
+ } while (ret == FAIL && conn->error_info->error_no == 0 && switch_to_auth_protocol != NULL);
+
+ if (ret == PASS) {
+ DBG_INF_FMT("saving requested_protocol=%s", requested_protocol);
+ conn->m->set_client_option(conn, MYSQLND_OPT_AUTH_PROTOCOL, requested_protocol);
+ }
+end:
+ if (plugin_data) {
+ mnd_efree(plugin_data);
+ }
+ if (requested_protocol) {
+ mnd_efree(requested_protocol);
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_switch_to_ssl_if_needed */
+static enum_func_status
+mysqlnd_switch_to_ssl_if_needed(MYSQLND_CONN_DATA * conn,
+ unsigned int charset_no,
+ size_t server_capabilities,
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ zend_ulong mysql_flags)
+{
+ enum_func_status ret = FAIL;
+ const MYSQLND_CHARSET * charset;
+ DBG_ENTER("mysqlnd_switch_to_ssl_if_needed");
+
+ if (session_options->charset_name && (charset = mysqlnd_find_charset_name(session_options->charset_name))) {
+ charset_no = charset->nr;
+ }
+
+ {
+ size_t client_capabilities = mysql_flags;
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_ENABLE_SSL, conn, client_capabilities, server_capabilities, charset_no);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
+ }
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_connect_run_authentication */
+enum_func_status
+mysqlnd_connect_run_authentication(
+ MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const char * const db,
+ size_t db_len,
+ size_t passwd_len,
+ MYSQLND_STRING authentication_plugin_data,
+ const char * const authentication_protocol,
+ const unsigned int charset_no,
+ size_t server_capabilities,
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ zend_ulong mysql_flags
+ )
+{
+ enum_func_status ret = FAIL;
+ DBG_ENTER("mysqlnd_connect_run_authentication");
+
+ ret = mysqlnd_switch_to_ssl_if_needed(conn, charset_no, server_capabilities, session_options, mysql_flags);
+ if (PASS == ret) {
+ ret = mysqlnd_run_authentication(conn, user, passwd, passwd_len, db, db_len,
+ authentication_plugin_data, authentication_protocol,
+ charset_no, session_options, mysql_flags, FALSE /*silent*/, FALSE/*is_change*/);
+ }
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
/* {{{ mysqlnd_auth_handshake */
enum_func_status
mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
@@ -36,7 +237,7 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
const size_t passwd_len,
const char * const db,
const size_t db_len,
- const MYSQLND_OPTIONS * const options,
+ const MYSQLND_SESSION_OPTIONS * const session_options,
zend_ulong mysql_flags,
unsigned int server_charset_no,
zend_bool use_full_blown_auth_packet,
@@ -57,34 +258,34 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
DBG_ENTER("mysqlnd_auth_handshake");
- auth_resp_packet = conn->protocol->m.get_auth_response_packet(conn->protocol, FALSE);
+ auth_resp_packet = conn->payload_decoder_factory->m.get_auth_response_packet(conn->payload_decoder_factory, FALSE);
if (!auth_resp_packet) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
goto end;
}
if (use_full_blown_auth_packet != TRUE) {
- change_auth_resp_packet = conn->protocol->m.get_change_auth_response_packet(conn->protocol, FALSE);
+ change_auth_resp_packet = conn->payload_decoder_factory->m.get_change_auth_response_packet(conn->payload_decoder_factory, FALSE);
if (!change_auth_resp_packet) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
goto end;
}
change_auth_resp_packet->auth_data = auth_plugin_data;
change_auth_resp_packet->auth_data_len = auth_plugin_data_len;
- if (!PACKET_WRITE(change_auth_resp_packet, conn)) {
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
- SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ if (!PACKET_WRITE(change_auth_resp_packet)) {
+ SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
+ SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
goto end;
}
} else {
- auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE);
+ auth_packet = conn->payload_decoder_factory->m.get_auth_packet(conn->payload_decoder_factory, FALSE);
auth_packet->client_flags = mysql_flags;
- auth_packet->max_packet_size = options->max_allowed_packet;
- if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) {
+ auth_packet->max_packet_size = session_options->max_allowed_packet;
+ if (session_options->charset_name && (charset = mysqlnd_find_charset_name(session_options->charset_name))) {
auth_packet->charset_no = charset->nr;
} else {
auth_packet->charset_no = server_charset_no;
@@ -103,7 +304,7 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
auth_packet->connect_attr = conn->options->connect_attr;
}
- if (!PACKET_WRITE(auth_packet, conn)) {
+ if (!PACKET_WRITE(auth_packet)) {
goto end;
}
}
@@ -111,12 +312,12 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
conn->charset = mysqlnd_find_charset_nr(auth_packet->charset_no);
}
- if (FAIL == PACKET_READ(auth_resp_packet, conn) || auth_resp_packet->response_code >= 0xFE) {
+ if (FAIL == PACKET_READ(auth_resp_packet) || auth_resp_packet->response_code >= 0xFE) {
if (auth_resp_packet->response_code == 0xFE) {
/* old authentication with new server !*/
if (!auth_resp_packet->new_auth_protocol) {
DBG_ERR(mysqlnd_old_passwd);
- SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
+ SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
} else {
*switch_to_auth_protocol = mnd_pestrndup(auth_resp_packet->new_auth_protocol, auth_resp_packet->new_auth_protocol_len, FALSE);
*switch_to_auth_protocol_len = auth_resp_packet->new_auth_protocol_len;
@@ -134,12 +335,12 @@ mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
strlcpy(conn->error_info->sqlstate, auth_resp_packet->sqlstate, sizeof(conn->error_info->sqlstate));
DBG_ERR_FMT("ERROR:%u [SQLSTATE:%s] %s", auth_resp_packet->error_no, auth_resp_packet->sqlstate, auth_resp_packet->error);
}
- SET_CLIENT_ERROR(*conn->error_info, auth_resp_packet->error_no, UNKNOWN_SQLSTATE, auth_resp_packet->error);
+ SET_CLIENT_ERROR(conn->error_info, auth_resp_packet->error_no, UNKNOWN_SQLSTATE, auth_resp_packet->error);
}
goto end;
}
- SET_NEW_MESSAGE(conn->last_message, conn->last_message_len, auth_resp_packet->message, auth_resp_packet->message_len, conn->persistent);
+ SET_NEW_MESSAGE(conn->last_message.s, conn->last_message.l, auth_resp_packet->message, auth_resp_packet->message_len, conn->persistent);
ret = PASS;
end:
PACKET_FREE(change_auth_resp_packet);
@@ -178,33 +379,33 @@ mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
DBG_ENTER("mysqlnd_auth_change_user");
- chg_user_resp = conn->protocol->m.get_change_user_response_packet(conn->protocol, FALSE);
+ chg_user_resp = conn->payload_decoder_factory->m.get_change_user_response_packet(conn->payload_decoder_factory, FALSE);
if (!chg_user_resp) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
goto end;
}
if (use_full_blown_auth_packet != TRUE) {
- change_auth_resp_packet = conn->protocol->m.get_change_auth_response_packet(conn->protocol, FALSE);
+ change_auth_resp_packet = conn->payload_decoder_factory->m.get_change_auth_response_packet(conn->payload_decoder_factory, FALSE);
if (!change_auth_resp_packet) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
goto end;
}
change_auth_resp_packet->auth_data = auth_plugin_data;
change_auth_resp_packet->auth_data_len = auth_plugin_data_len;
- if (!PACKET_WRITE(change_auth_resp_packet, conn)) {
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
- SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ if (!PACKET_WRITE(change_auth_resp_packet)) {
+ SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
+ SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
goto end;
}
} else {
- auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE);
+ auth_packet = conn->payload_decoder_factory->m.get_auth_packet(conn->payload_decoder_factory, FALSE);
if (!auth_packet) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
goto end;
}
@@ -223,21 +424,21 @@ mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
auth_packet->charset_no = conn->charset->nr;
}
- if (!PACKET_WRITE(auth_packet, conn)) {
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
- SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ if (!PACKET_WRITE(auth_packet)) {
+ SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
+ SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
goto end;
}
}
- ret = PACKET_READ(chg_user_resp, conn);
- COPY_CLIENT_ERROR(*conn->error_info, chg_user_resp->error_info);
+ ret = PACKET_READ(chg_user_resp);
+ COPY_CLIENT_ERROR(conn->error_info, chg_user_resp->error_info);
if (0xFE == chg_user_resp->response_code) {
ret = FAIL;
if (!chg_user_resp->new_auth_protocol) {
DBG_ERR(mysqlnd_old_passwd);
- SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
+ SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
} else {
*switch_to_auth_protocol = mnd_pestrndup(chg_user_resp->new_auth_protocol, chg_user_resp->new_auth_protocol_len, FALSE);
*switch_to_auth_protocol_len = chg_user_resp->new_auth_protocol_len;
@@ -260,36 +461,36 @@ mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
When it gets fixed, there should be one more check here
*/
if (conn->m->get_server_version(conn) > 50113L &&conn->m->get_server_version(conn) < 50118L) {
- MYSQLND_PACKET_OK * redundant_error_packet = conn->protocol->m.get_ok_packet(conn->protocol, FALSE);
+ MYSQLND_PACKET_OK * redundant_error_packet = conn->payload_decoder_factory->m.get_ok_packet(conn->payload_decoder_factory, FALSE);
if (redundant_error_packet) {
- PACKET_READ(redundant_error_packet, conn);
+ PACKET_READ(redundant_error_packet);
PACKET_FREE(redundant_error_packet);
DBG_INF_FMT("Server is %u, buggy, sends two ERR messages", conn->m->get_server_version(conn));
} else {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
}
}
}
if (ret == PASS) {
char * tmp = NULL;
- /* if we get conn->user as parameter and then we first free it, then estrndup it, we will crash */
+ /* if we get conn->username as parameter and then we first free it, then estrndup it, we will crash */
tmp = mnd_pestrndup(user, user_len, conn->persistent);
- if (conn->user) {
- mnd_pefree(conn->user, conn->persistent);
+ if (conn->username.s) {
+ mnd_pefree(conn->username.s, conn->persistent);
}
- conn->user = tmp;
+ conn->username.s = tmp;
tmp = mnd_pestrdup(passwd, conn->persistent);
- if (conn->passwd) {
- mnd_pefree(conn->passwd, conn->persistent);
+ if (conn->password.s) {
+ mnd_pefree(conn->password.s, conn->persistent);
}
- conn->passwd = tmp;
+ conn->password.s = tmp;
- if (conn->last_message) {
- mnd_pefree(conn->last_message, conn->persistent);
- conn->last_message = NULL;
+ if (conn->last_message.s) {
+ mnd_pefree(conn->last_message.s, conn->persistent);
+ conn->last_message.s = NULL;
}
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
+ UPSERT_STATUS_RESET(conn->upsert_status);
/* set charset for old servers */
if (conn->m->get_server_version(conn) < 50123) {
ret = conn->m->set_charset(conn, old_cs->name);
@@ -297,7 +498,7 @@ mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
} else if (ret == FAIL && chg_user_resp->server_asked_323_auth == TRUE) {
/* old authentication with new server !*/
DBG_ERR(mysqlnd_old_passwd);
- SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
+ SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, mysqlnd_old_passwd);
}
end:
PACKET_FREE(change_auth_resp_packet);
@@ -325,7 +526,7 @@ php_mysqlnd_crypt(zend_uchar *buffer, const zend_uchar *s1, const zend_uchar *s2
/* {{{ php_mysqlnd_scramble */
-void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const password, size_t password_len)
+void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const password, const size_t password_len)
{
PHP_SHA1_CTX context;
zend_uchar sha1[SHA1_MAX_LENGTH];
@@ -359,8 +560,8 @@ mysqlnd_native_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self
size_t * auth_data_len,
MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd,
const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
- const MYSQLND_OPTIONS * const options,
- const MYSQLND_NET_OPTIONS * const net_options,
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ const MYSQLND_PFC_DATA * const pfc_data,
zend_ulong mysql_flags
)
{
@@ -371,7 +572,7 @@ mysqlnd_native_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self
/* 5.5.x reports 21 as scramble length because it needs to show the length of the data before the plugin name */
if (auth_plugin_data_len < SCRAMBLE_LENGTH) {
/* mysql_native_password only works with SCRAMBLE_LENGTH scramble */
- SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "The server sent wrong length for scramble");
+ SET_CLIENT_ERROR(conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "The server sent wrong length for scramble");
DBG_ERR_FMT("The server sent wrong length for scramble %u. Expected %u", auth_plugin_data_len, SCRAMBLE_LENGTH);
DBG_RETURN(NULL);
}
@@ -419,8 +620,8 @@ mysqlnd_pam_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self,
size_t * auth_data_len,
MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd,
const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
- const MYSQLND_OPTIONS * const options,
- const MYSQLND_NET_OPTIONS * const net_options,
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ const MYSQLND_PFC_DATA * const pfc_data,
zend_ulong mysql_flags
)
{
@@ -480,18 +681,18 @@ mysqlnd_xor_string(char * dst, const size_t dst_len, const char * xor_str, const
/* {{{ mysqlnd_sha256_get_rsa_key */
static RSA *
mysqlnd_sha256_get_rsa_key(MYSQLND_CONN_DATA * conn,
- const MYSQLND_OPTIONS * const options,
- const MYSQLND_NET_OPTIONS * const net_options
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ const MYSQLND_PFC_DATA * const pfc_data
)
{
RSA * ret = NULL;
- const char * fname = (net_options->sha256_server_public_key && net_options->sha256_server_public_key[0] != '\0')?
- net_options->sha256_server_public_key:
+ const char * fname = (pfc_data->sha256_server_public_key && pfc_data->sha256_server_public_key[0] != '\0')?
+ pfc_data->sha256_server_public_key:
MYSQLND_G(sha256_server_public_key);
php_stream * stream;
DBG_ENTER("mysqlnd_sha256_get_rsa_key");
DBG_INF_FMT("options_s256_pk=[%s] MYSQLND_G(sha256_server_public_key)=[%s]",
- net_options->sha256_server_public_key? net_options->sha256_server_public_key:"n/a",
+ pfc_data->sha256_server_public_key? pfc_data->sha256_server_public_key:"n/a",
MYSQLND_G(sha256_server_public_key)? MYSQLND_G(sha256_server_public_key):"n/a");
if (!fname || fname[0] == '\0') {
MYSQLND_PACKET_SHA256_PK_REQUEST * pk_req_packet = NULL;
@@ -499,28 +700,28 @@ mysqlnd_sha256_get_rsa_key(MYSQLND_CONN_DATA * conn,
do {
DBG_INF("requesting the public key from the server");
- pk_req_packet = conn->protocol->m.get_sha256_pk_request_packet(conn->protocol, FALSE);
+ pk_req_packet = conn->payload_decoder_factory->m.get_sha256_pk_request_packet(conn->payload_decoder_factory, FALSE);
if (!pk_req_packet) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
break;
}
- pk_resp_packet = conn->protocol->m.get_sha256_pk_request_response_packet(conn->protocol, FALSE);
+ pk_resp_packet = conn->payload_decoder_factory->m.get_sha256_pk_request_response_packet(conn->payload_decoder_factory, FALSE);
if (!pk_resp_packet) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
PACKET_FREE(pk_req_packet);
break;
}
- if (! PACKET_WRITE(pk_req_packet, conn)) {
+ if (! PACKET_WRITE(pk_req_packet)) {
DBG_ERR_FMT("Error while sending public key request packet");
php_error(E_WARNING, "Error while sending public key request packet. PID=%d", getpid());
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
break;
}
- if (FAIL == PACKET_READ(pk_resp_packet, conn) || NULL == pk_resp_packet->public_key) {
+ if (FAIL == PACKET_READ(pk_resp_packet) || NULL == pk_resp_packet->public_key) {
DBG_ERR_FMT("Error while receiving public key");
php_error(E_WARNING, "Error while receiving public key. PID=%d", getpid());
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
break;
}
DBG_INF_FMT("Public key(%d):\n%s", pk_resp_packet->public_key_len, pk_resp_packet->public_key);
@@ -537,7 +738,7 @@ mysqlnd_sha256_get_rsa_key(MYSQLND_CONN_DATA * conn,
DBG_INF_FMT("ret=%p", ret);
DBG_RETURN(ret);
- SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE,
"sha256_server_public_key is not set for the connection or as mysqlnd.sha256_server_public_key");
DBG_ERR("server_public_key is not set");
DBG_RETURN(NULL);
@@ -569,8 +770,8 @@ mysqlnd_sha256_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self
size_t * auth_data_len,
MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd,
const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
- const MYSQLND_OPTIONS * const options,
- const MYSQLND_NET_OPTIONS * const net_options,
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ const MYSQLND_PFC_DATA * const pfc_data,
zend_ulong mysql_flags
)
{
@@ -580,7 +781,7 @@ mysqlnd_sha256_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self
DBG_INF_FMT("salt(%d)=[%.*s]", auth_plugin_data_len, auth_plugin_data_len, auth_plugin_data);
- if (conn->net->data->ssl) {
+ if (conn->protocol_frame_codec->data->ssl) {
DBG_INF("simple clear text under SSL");
/* clear text under SSL */
*auth_data_len = passwd_len;
@@ -588,7 +789,7 @@ mysqlnd_sha256_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self
memcpy(ret, passwd, passwd_len);
} else {
*auth_data_len = 0;
- server_public_key = mysqlnd_sha256_get_rsa_key(conn, options, net_options);
+ server_public_key = mysqlnd_sha256_get_rsa_key(conn, session_options, pfc_data);
if (server_public_key) {
int server_public_key_len;
@@ -605,7 +806,7 @@ mysqlnd_sha256_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self
*/
if ((size_t) server_public_key_len - 41 <= passwd_len) {
/* password message is to long */
- SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long");
+ SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "password is too long");
DBG_ERR("password is too long");
DBG_RETURN(NULL);
}
diff --git a/ext/mysqlnd/mysqlnd_auth.h b/ext/mysqlnd/mysqlnd_auth.h
new file mode 100644
index 0000000000..02fa14b1f9
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_auth.h
@@ -0,0 +1,126 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef MYSQLND_AUTH_H
+#define MYSQLND_AUTH_H
+enum_func_status
+mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ zend_ulong mysql_flags,
+ unsigned int server_charset_no,
+ zend_bool use_full_blown_auth_packet,
+ const char * const auth_protocol,
+ const zend_uchar * const auth_plugin_data,
+ const size_t auth_plugin_data_len,
+ char ** switch_to_auth_protocol,
+ size_t * switch_to_auth_protocol_len,
+ zend_uchar ** switch_to_auth_protocol_data,
+ size_t * switch_to_auth_protocol_data_len
+ );
+
+enum_func_status
+mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ zend_ulong mysql_flags,
+ unsigned int server_charset_no,
+ zend_bool use_full_blown_auth_packet,
+ const char * const auth_protocol,
+ const zend_uchar * const auth_plugin_data,
+ const size_t auth_plugin_data_len,
+ char ** switch_to_auth_protocol,
+ size_t * switch_to_auth_protocol_len,
+ zend_uchar ** switch_to_auth_protocol_data,
+ size_t * switch_to_auth_protocol_data_len
+ );
+
+enum_func_status
+mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
+ const char * const user,
+ const size_t user_len,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const zend_bool silent,
+ zend_bool use_full_blown_auth_packet,
+ const char * const auth_protocol,
+ zend_uchar * auth_plugin_data,
+ size_t auth_plugin_data_len,
+ char ** switch_to_auth_protocol,
+ size_t * switch_to_auth_protocol_len,
+ zend_uchar ** switch_to_auth_protocol_data,
+ size_t * switch_to_auth_protocol_data_len
+ );
+
+
+enum_func_status
+mysqlnd_connect_run_authentication(
+ MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const char * const db,
+ size_t db_len,
+ size_t passwd_len,
+ MYSQLND_STRING authentication_plugin_data,
+ const char * const authentication_protocol,
+ const unsigned int charset_no,
+ size_t server_capabilities,
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ zend_ulong mysql_flags
+ );
+
+enum_func_status
+mysqlnd_run_authentication(
+ MYSQLND_CONN_DATA * conn,
+ const char * const user,
+ const char * const passwd,
+ const size_t passwd_len,
+ const char * const db,
+ const size_t db_len,
+ const MYSQLND_STRING auth_plugin_data,
+ const char * const auth_protocol,
+ unsigned int charset_no,
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ zend_ulong mysql_flags,
+ zend_bool silent,
+ zend_bool is_change_user
+ );
+
+PHPAPI void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass, const size_t pass_len);
+
+#endif /* MYSQLND_AUTH_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_block_alloc.c b/ext/mysqlnd/mysqlnd_block_alloc.c
index 9a7fdae0f7..95976fca3e 100644
--- a/ext/mysqlnd/mysqlnd_block_alloc.c
+++ b/ext/mysqlnd/mysqlnd_block_alloc.c
@@ -12,8 +12,7 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+----------------------------------------------------------------------+
*/
diff --git a/ext/mysqlnd/mysqlnd_block_alloc.h b/ext/mysqlnd/mysqlnd_block_alloc.h
index 50e4c90512..e56eb34cba 100644
--- a/ext/mysqlnd/mysqlnd_block_alloc.h
+++ b/ext/mysqlnd/mysqlnd_block_alloc.h
@@ -12,14 +12,11 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+----------------------------------------------------------------------+
*/
-/* $Id$ */
-
#ifndef MYSQLND_BLOCK_ALLOC_H
#define MYSQLND_BLOCK_ALLOC_H
diff --git a/ext/mysqlnd/mysqlnd_charset.c b/ext/mysqlnd/mysqlnd_charset.c
index b9f16e27cb..7aa7f2e7ef 100644
--- a/ext/mysqlnd/mysqlnd_charset.c
+++ b/ext/mysqlnd/mysqlnd_charset.c
@@ -12,13 +12,12 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
#include "php.h"
-#include "php_globals.h"
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
diff --git a/ext/mysqlnd/mysqlnd_charset.h b/ext/mysqlnd/mysqlnd_charset.h
index 8bdad7249e..59784948f1 100644
--- a/ext/mysqlnd/mysqlnd_charset.h
+++ b/ext/mysqlnd/mysqlnd_charset.h
@@ -12,12 +12,11 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+ | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-
#ifndef MYSQLND_CHARSET_H
#define MYSQLND_CHARSET_H
diff --git a/ext/mysqlnd/mysqlnd_commands.c b/ext/mysqlnd/mysqlnd_commands.c
new file mode 100644
index 0000000000..094f8de46f
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_commands.c
@@ -0,0 +1,1470 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_connection.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_auth.h"
+#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_statistics.h"
+#include "mysqlnd_debug.h"
+
+
+struct st_mysqlnd_protocol_no_params_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_protocol_no_params_command_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ } context;
+};
+
+/* {{{ mysqlnd_com_no_params_free_command */
+static void
+mysqlnd_com_no_params_free_command(void * command)
+{
+ DBG_ENTER("mysqlnd_com_no_params_free_command");
+ mnd_efree(command);
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/************************** COM_SET_OPTION ******************************************/
+struct st_mysqlnd_protocol_com_set_option_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_set_option_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ enum_mysqlnd_server_option option;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_set_option_run */
+enum_func_status
+mysqlnd_com_set_option_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_set_option_command * command = (struct st_mysqlnd_protocol_com_set_option_command *) cmd;
+ zend_uchar buffer[2];
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ enum_mysqlnd_server_option option = command->context.option;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
+
+ DBG_ENTER("mysqlnd_com_set_option_run");
+ int2store(buffer, (unsigned int) option);
+
+ ret = send_command(conn->payload_decoder_factory, COM_SET_OPTION, buffer, sizeof(buffer), FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+ if (PASS == ret) {
+ ret = send_command_handle_response(conn->payload_decoder_factory, PROT_EOF_PACKET, FALSE, COM_SET_OPTION, TRUE,
+ conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
+ }
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_set_option_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_set_option_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_set_option_command * command;
+ DBG_ENTER("mysqlnd_com_set_option_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_set_option_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.option = va_arg(args, enum_mysqlnd_server_option);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_set_option_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_DEBUG ******************************************/
+/* {{{ mysqlnd_com_debug_run */
+static enum_func_status
+mysqlnd_com_debug_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_no_params_command * command = (struct st_mysqlnd_protocol_no_params_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
+
+ DBG_ENTER("mysqlnd_com_debug_run");
+
+ ret = send_command(conn->payload_decoder_factory, COM_DEBUG, NULL, 0, FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+ if (PASS == ret) {
+ ret = send_command_handle_response(conn->payload_decoder_factory, PROT_EOF_PACKET, FALSE, COM_DEBUG, TRUE,
+ conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_debug_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_debug_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_no_params_command * command;
+ DBG_ENTER("mysqlnd_com_debug_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_no_params_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+
+ command->parent.run = mysqlnd_com_debug_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_INIT_DB ******************************************/
+struct st_mysqlnd_protocol_com_init_db_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_init_db_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ MYSQLND_CSTRING db;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_init_db_run */
+static enum_func_status
+mysqlnd_com_init_db_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_init_db_command * command = (struct st_mysqlnd_protocol_com_init_db_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ const MYSQLND_CSTRING db = command->context.db;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
+
+ DBG_ENTER("mysqlnd_com_init_db_run");
+
+ ret = send_command(conn->payload_decoder_factory, COM_INIT_DB, (zend_uchar*) command->context.db.s, command->context.db.l, FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+ if (PASS == ret) {
+ ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, FALSE, COM_INIT_DB, TRUE,
+ conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
+ }
+
+ /*
+ The server sends 0 but libmysql doesn't read it and has established
+ a protocol of giving back -1. Thus we have to follow it :(
+ */
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
+ if (ret == PASS) {
+ if (conn->connect_or_select_db.s) {
+ mnd_pefree(conn->connect_or_select_db.s, conn->persistent);
+ }
+ conn->connect_or_select_db.s = mnd_pestrndup(db.s, db.l, conn->persistent);
+ conn->connect_or_select_db.l = db.l;
+ if (!conn->connect_or_select_db.s) {
+ /* OOM */
+ SET_OOM_ERROR(conn->error_info);
+ ret = FAIL;
+ }
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_init_db_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_init_db_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_init_db_command * command;
+ DBG_ENTER("mysqlnd_com_init_db_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_init_db_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.db = va_arg(args, MYSQLND_CSTRING);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_init_db_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_PING ******************************************/
+/* {{{ mysqlnd_com_ping_run */
+static enum_func_status
+mysqlnd_com_ping_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_no_params_command * command = (struct st_mysqlnd_protocol_no_params_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
+
+ DBG_ENTER("mysqlnd_com_ping_run");
+
+ ret = send_command(conn->payload_decoder_factory, COM_PING, NULL, 0, TRUE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+ if (PASS == ret) {
+ ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, TRUE, COM_PING, TRUE,
+ conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
+ }
+ /*
+ The server sends 0 but libmysql doesn't read it and has established
+ a protocol of giving back -1. Thus we have to follow it :(
+ */
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_ping_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_ping_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_no_params_command * command;
+ DBG_ENTER("mysqlnd_com_ping_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_no_params_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+
+ command->parent.run = mysqlnd_com_ping_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_STATISTICS ******************************************/
+struct st_mysqlnd_protocol_com_statistics_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_statistics_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ zend_string ** message;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_statistics_run */
+static enum_func_status
+mysqlnd_com_statistics_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_statistics_command * command = (struct st_mysqlnd_protocol_com_statistics_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ zend_string **message = command->context.message;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+
+ DBG_ENTER("mysqlnd_com_statistics_run");
+
+ ret = send_command(conn->payload_decoder_factory, COM_STATISTICS, NULL, 0, FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+
+ if (PASS == ret) {
+ MYSQLND_PACKET_STATS * stats_header = conn->payload_decoder_factory->m.get_stats_packet(conn->payload_decoder_factory, FALSE);
+ if (!stats_header) {
+ SET_OOM_ERROR(conn->error_info);
+ } else {
+ if (PASS == (ret = PACKET_READ(stats_header))) {
+ /* will be freed by Zend, thus don't use the mnd_ allocator */
+ *message = zend_string_init(stats_header->message.s, stats_header->message.l, 0);
+ DBG_INF(ZSTR_VAL(*message));
+ }
+ PACKET_FREE(stats_header);
+ }
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_statistics_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_statistics_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_statistics_command * command;
+ DBG_ENTER("mysqlnd_com_statistics_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_statistics_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.message = va_arg(args, zend_string **);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_statistics_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+/************************** COM_PROCESS_KILL ******************************************/
+struct st_mysqlnd_protocol_com_process_kill_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_process_kill_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ unsigned int process_id;
+ zend_bool read_response;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_process_kill_run */
+enum_func_status
+mysqlnd_com_process_kill_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_process_kill_command * command = (struct st_mysqlnd_protocol_com_process_kill_command *) cmd;
+ zend_uchar buff[4];
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ zend_bool read_response = command->context.read_response;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
+
+ DBG_ENTER("mysqlnd_com_process_kill_run");
+ int4store(buff, command->context.process_id);
+
+ ret = send_command(conn->payload_decoder_factory, COM_PROCESS_KILL, buff, 4, FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+ if (PASS == ret && read_response) {
+ ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, FALSE, COM_PROCESS_KILL, TRUE,
+ conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
+ }
+
+ if (read_response) {
+ /*
+ The server sends 0 but libmysql doesn't read it and has established
+ a protocol of giving back -1. Thus we have to follow it :(
+ */
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
+ } else if (PASS == ret) {
+ SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
+ conn->m->send_close(conn);
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_process_kill_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_process_kill_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_process_kill_command * command;
+ DBG_ENTER("mysqlnd_com_process_kill_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_process_kill_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.process_id = va_arg(args, unsigned int);
+ command->context.read_response = va_arg(args, unsigned int)? TRUE:FALSE;
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_process_kill_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+/************************** COM_REFRESH ******************************************/
+struct st_mysqlnd_protocol_com_refresh_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_refresh_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ uint8_t options;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_refresh_run */
+enum_func_status
+mysqlnd_com_refresh_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_refresh_command * command = (struct st_mysqlnd_protocol_com_refresh_command *) cmd;
+ zend_uchar bits[1];
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
+
+ DBG_ENTER("mysqlnd_com_refresh_run");
+ int1store(bits, command->context.options);
+
+ ret = send_command(conn->payload_decoder_factory, COM_REFRESH, bits, 1, FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+ if (PASS == ret) {
+ ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, FALSE, COM_REFRESH, TRUE,
+ conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_refresh_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_refresh_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_refresh_command * command;
+ DBG_ENTER("mysqlnd_com_refresh_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_refresh_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.options = va_arg(args, unsigned int);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_refresh_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_SHUTDOWN ******************************************/
+struct st_mysqlnd_protocol_com_shutdown_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_shutdown_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ uint8_t level;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_shutdown_run */
+enum_func_status
+mysqlnd_com_shutdown_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_shutdown_command * command = (struct st_mysqlnd_protocol_com_shutdown_command *) cmd;
+ zend_uchar bits[1];
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
+
+ DBG_ENTER("mysqlnd_com_shutdown_run");
+ int1store(bits, command->context.level);
+
+ ret = send_command(conn->payload_decoder_factory, COM_SHUTDOWN, bits, 1, FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+ if (PASS == ret) {
+ ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, FALSE, COM_SHUTDOWN, TRUE,
+ conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_shutdown_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_shutdown_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_shutdown_command * command;
+ DBG_ENTER("mysqlnd_com_shutdown_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_shutdown_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.level = va_arg(args, unsigned int);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_shutdown_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_QUIT ******************************************/
+struct st_mysqlnd_protocol_com_quit_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_quit_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_quit_run */
+enum_func_status
+mysqlnd_com_quit_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_quit_command * command = (struct st_mysqlnd_protocol_com_quit_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+
+ DBG_ENTER("mysqlnd_com_quit_run");
+
+ ret = send_command(conn->payload_decoder_factory, COM_QUIT, NULL, 0, TRUE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_quit_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_quit_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_quit_command * command;
+ DBG_ENTER("mysqlnd_com_quit_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_quit_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_quit_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+/************************** COM_QUERY ******************************************/
+struct st_mysqlnd_protocol_com_query_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_query_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ MYSQLND_CSTRING query;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_query_run */
+static enum_func_status
+mysqlnd_com_query_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_query_command * command = (struct st_mysqlnd_protocol_com_query_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+
+ DBG_ENTER("mysqlnd_com_query_run");
+
+ ret = send_command(conn->payload_decoder_factory, COM_QUERY, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+
+ if (PASS == ret) {
+ SET_CONNECTION_STATE(&conn->state, CONN_QUERY_SENT);
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_query_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_query_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_query_command * command;
+ DBG_ENTER("mysqlnd_com_query_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_query_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.query = va_arg(args, MYSQLND_CSTRING);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_query_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+/************************** COM_CHANGE_USER ******************************************/
+struct st_mysqlnd_protocol_com_change_user_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_change_user_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ MYSQLND_CSTRING payload;
+ zend_bool silent;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_change_user_run */
+static enum_func_status
+mysqlnd_com_change_user_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_change_user_command * command = (struct st_mysqlnd_protocol_com_change_user_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+
+ DBG_ENTER("mysqlnd_com_change_user_run");
+
+ ret = send_command(conn->payload_decoder_factory, COM_CHANGE_USER, (zend_uchar*) command->context.payload.s, command->context.payload.l, command->context.silent,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_change_user_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_change_user_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_change_user_command * command;
+ DBG_ENTER("mysqlnd_com_change_user_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_change_user_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.payload = va_arg(args, MYSQLND_CSTRING);
+ command->context.silent = va_arg(args, unsigned int);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_change_user_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_REAP_RESULT ******************************************/
+struct st_mysqlnd_protocol_com_reap_result_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_reap_result_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_reap_result_run */
+static enum_func_status
+mysqlnd_com_reap_result_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_reap_result_command * command = (struct st_mysqlnd_protocol_com_reap_result_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ const enum_mysqlnd_connection_state state = GET_CONNECTION_STATE(&conn->state);
+
+ DBG_ENTER("mysqlnd_com_reap_result_run");
+ if (state <= CONN_READY || state == CONN_QUIT_SENT) {
+ php_error_docref(NULL, E_WARNING, "Connection not opened, clear or has been closed");
+ DBG_ERR_FMT("Connection not opened, clear or has been closed. State=%u", state);
+ DBG_RETURN(ret);
+ }
+ ret = conn->m->query_read_result_set_header(conn, NULL);
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_reap_result_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_reap_result_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_reap_result_command * command;
+ DBG_ENTER("mysqlnd_com_reap_result_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_reap_result_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_reap_result_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_STMT_PREPARE ******************************************/
+struct st_mysqlnd_protocol_com_stmt_prepare_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_stmt_prepare_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ MYSQLND_CSTRING query;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_stmt_prepare_run */
+static enum_func_status
+mysqlnd_com_stmt_prepare_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_stmt_prepare_command * command = (struct st_mysqlnd_protocol_com_stmt_prepare_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+
+ DBG_ENTER("mysqlnd_com_stmt_prepare_run");
+
+ ret = send_command(conn->payload_decoder_factory, COM_STMT_PREPARE, (zend_uchar*) command->context.query.s, command->context.query.l, FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_stmt_prepare_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_stmt_prepare_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_stmt_prepare_command * command;
+ DBG_ENTER("mysqlnd_com_stmt_prepare_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_prepare_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.query = va_arg(args, MYSQLND_CSTRING);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_stmt_prepare_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_STMT_EXECUTE ******************************************/
+struct st_mysqlnd_protocol_com_stmt_execute_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_stmt_execute_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ MYSQLND_CSTRING payload;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_stmt_execute_run */
+static enum_func_status
+mysqlnd_com_stmt_execute_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_stmt_execute_command * command = (struct st_mysqlnd_protocol_com_stmt_execute_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+
+ DBG_ENTER("mysqlnd_com_stmt_execute_run");
+
+ ret = send_command(conn->payload_decoder_factory, COM_STMT_EXECUTE, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_stmt_execute_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_stmt_execute_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_stmt_execute_command * command;
+ DBG_ENTER("mysqlnd_com_stmt_execute_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_execute_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.payload = va_arg(args, MYSQLND_CSTRING);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_stmt_execute_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_STMT_FETCH ******************************************/
+struct st_mysqlnd_protocol_com_stmt_fetch_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_stmt_fetch_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ MYSQLND_CSTRING payload;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_stmt_fetch_run */
+static enum_func_status
+mysqlnd_com_stmt_fetch_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_stmt_fetch_command * command = (struct st_mysqlnd_protocol_com_stmt_fetch_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+
+ DBG_ENTER("mysqlnd_com_stmt_fetch_run");
+
+ ret = send_command(conn->payload_decoder_factory, COM_STMT_FETCH, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_stmt_fetch_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_stmt_fetch_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_stmt_fetch_command * command;
+ DBG_ENTER("mysqlnd_com_stmt_fetch_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_fetch_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.payload = va_arg(args, MYSQLND_CSTRING);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_stmt_fetch_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_STMT_RESET ******************************************/
+struct st_mysqlnd_protocol_com_stmt_reset_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_stmt_reset_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ zend_ulong stmt_id;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_stmt_reset_run */
+static enum_func_status
+mysqlnd_com_stmt_reset_run(void *cmd)
+{
+ zend_uchar cmd_buf[MYSQLND_STMT_ID_LENGTH /* statement id */];
+ struct st_mysqlnd_protocol_com_stmt_reset_command * command = (struct st_mysqlnd_protocol_com_stmt_reset_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response = conn->payload_decoder_factory->m.send_command_handle_response;
+
+ DBG_ENTER("mysqlnd_com_stmt_reset_run");
+
+ int4store(cmd_buf, command->context.stmt_id);
+ ret = send_command(conn->payload_decoder_factory, COM_STMT_RESET, cmd_buf, sizeof(cmd_buf), FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+ if (PASS == ret) {
+ ret = send_command_handle_response(conn->payload_decoder_factory, PROT_OK_PACKET, FALSE, COM_STMT_RESET, TRUE,
+ conn->error_info, conn->upsert_status, &conn->last_message, conn->persistent);
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_stmt_reset_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_stmt_reset_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_stmt_reset_command * command;
+ DBG_ENTER("mysqlnd_com_stmt_reset_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_reset_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.stmt_id = va_arg(args, size_t);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_stmt_reset_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_STMT_SEND_LONG_DATA ******************************************/
+struct st_mysqlnd_protocol_com_stmt_send_long_data_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_stmt_send_long_data_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ MYSQLND_CSTRING payload;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_stmt_send_long_data_run */
+static enum_func_status
+mysqlnd_com_stmt_send_long_data_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_stmt_send_long_data_command * command = (struct st_mysqlnd_protocol_com_stmt_send_long_data_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+
+ DBG_ENTER("mysqlnd_com_stmt_send_long_data_run");
+
+ ret = send_command(conn->payload_decoder_factory, COM_STMT_SEND_LONG_DATA, (zend_uchar*) command->context.payload.s, command->context.payload.l, FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_stmt_send_long_data_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_stmt_send_long_data_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_stmt_send_long_data_command * command;
+ DBG_ENTER("mysqlnd_com_stmt_send_long_data_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_send_long_data_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.payload = va_arg(args, MYSQLND_CSTRING);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_stmt_send_long_data_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+/************************** COM_STMT_CLOSE ******************************************/
+struct st_mysqlnd_protocol_com_stmt_close_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_stmt_close_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ zend_ulong stmt_id;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_stmt_close_run */
+static enum_func_status
+mysqlnd_com_stmt_close_run(void *cmd)
+{
+ zend_uchar cmd_buf[MYSQLND_STMT_ID_LENGTH /* statement id */];
+ struct st_mysqlnd_protocol_com_stmt_close_command * command = (struct st_mysqlnd_protocol_com_stmt_close_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command = conn->payload_decoder_factory->m.send_command;
+
+ DBG_ENTER("mysqlnd_com_stmt_close_run");
+
+ int4store(cmd_buf, command->context.stmt_id);
+ ret = send_command(conn->payload_decoder_factory, COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf), FALSE,
+ &conn->state,
+ conn->error_info,
+ conn->upsert_status,
+ conn->stats,
+ conn->m->send_close,
+ conn);
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_stmt_close_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_stmt_close_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_stmt_close_command * command;
+ DBG_ENTER("mysqlnd_com_stmt_close_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_stmt_close_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.stmt_id = va_arg(args, size_t);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_stmt_close_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+
+/************************** COM_ENABLE_SSL ******************************************/
+struct st_mysqlnd_protocol_com_enable_ssl_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_enable_ssl_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ size_t client_capabilities;
+ size_t server_capabilities;
+ unsigned int charset_no;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_enable_ssl_run */
+static enum_func_status
+mysqlnd_com_enable_ssl_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_enable_ssl_command * command = (struct st_mysqlnd_protocol_com_enable_ssl_command *) cmd;
+ enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ MYSQLND_PACKET_AUTH * auth_packet;
+ size_t client_capabilities = command->context.client_capabilities;
+ size_t server_capabilities = command->context.server_capabilities;
+
+ DBG_ENTER("mysqlnd_com_enable_ssl_run");
+ DBG_INF_FMT("client_capability_flags=%lu", client_capabilities);
+ DBG_INF_FMT("CLIENT_LONG_PASSWORD= %d", client_capabilities & CLIENT_LONG_PASSWORD? 1:0);
+ DBG_INF_FMT("CLIENT_FOUND_ROWS= %d", client_capabilities & CLIENT_FOUND_ROWS? 1:0);
+ DBG_INF_FMT("CLIENT_LONG_FLAG= %d", client_capabilities & CLIENT_LONG_FLAG? 1:0);
+ DBG_INF_FMT("CLIENT_NO_SCHEMA= %d", client_capabilities & CLIENT_NO_SCHEMA? 1:0);
+ DBG_INF_FMT("CLIENT_COMPRESS= %d", client_capabilities & CLIENT_COMPRESS? 1:0);
+ DBG_INF_FMT("CLIENT_ODBC= %d", client_capabilities & CLIENT_ODBC? 1:0);
+ DBG_INF_FMT("CLIENT_LOCAL_FILES= %d", client_capabilities & CLIENT_LOCAL_FILES? 1:0);
+ DBG_INF_FMT("CLIENT_IGNORE_SPACE= %d", client_capabilities & CLIENT_IGNORE_SPACE? 1:0);
+ DBG_INF_FMT("CLIENT_PROTOCOL_41= %d", client_capabilities & CLIENT_PROTOCOL_41? 1:0);
+ DBG_INF_FMT("CLIENT_INTERACTIVE= %d", client_capabilities & CLIENT_INTERACTIVE? 1:0);
+ DBG_INF_FMT("CLIENT_SSL= %d", client_capabilities & CLIENT_SSL? 1:0);
+ DBG_INF_FMT("CLIENT_IGNORE_SIGPIPE= %d", client_capabilities & CLIENT_IGNORE_SIGPIPE? 1:0);
+ DBG_INF_FMT("CLIENT_TRANSACTIONS= %d", client_capabilities & CLIENT_TRANSACTIONS? 1:0);
+ DBG_INF_FMT("CLIENT_RESERVED= %d", client_capabilities & CLIENT_RESERVED? 1:0);
+ DBG_INF_FMT("CLIENT_SECURE_CONNECTION=%d", client_capabilities & CLIENT_SECURE_CONNECTION? 1:0);
+ DBG_INF_FMT("CLIENT_MULTI_STATEMENTS=%d", client_capabilities & CLIENT_MULTI_STATEMENTS? 1:0);
+ DBG_INF_FMT("CLIENT_MULTI_RESULTS= %d", client_capabilities & CLIENT_MULTI_RESULTS? 1:0);
+ DBG_INF_FMT("CLIENT_PS_MULTI_RESULTS=%d", client_capabilities & CLIENT_PS_MULTI_RESULTS? 1:0);
+ DBG_INF_FMT("CLIENT_CONNECT_ATTRS= %d", client_capabilities & CLIENT_PLUGIN_AUTH? 1:0);
+ DBG_INF_FMT("CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA= %d", client_capabilities & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA? 1:0);
+ DBG_INF_FMT("CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS= %d", client_capabilities & CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS? 1:0);
+ DBG_INF_FMT("CLIENT_SESSION_TRACK= %d", client_capabilities & CLIENT_SESSION_TRACK? 1:0);
+ DBG_INF_FMT("CLIENT_SSL_VERIFY_SERVER_CERT= %d", client_capabilities & CLIENT_SSL_VERIFY_SERVER_CERT? 1:0);
+ DBG_INF_FMT("CLIENT_REMEMBER_OPTIONS= %d", client_capabilities & CLIENT_REMEMBER_OPTIONS? 1:0);
+
+ auth_packet = conn->payload_decoder_factory->m.get_auth_packet(conn->payload_decoder_factory, FALSE);
+ if (!auth_packet) {
+ SET_OOM_ERROR(conn->error_info);
+ goto end;
+ }
+ auth_packet->client_flags = client_capabilities;
+ auth_packet->max_packet_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
+
+ auth_packet->charset_no = command->context.charset_no;
+
+#ifdef MYSQLND_SSL_SUPPORTED
+ if (client_capabilities & CLIENT_SSL) {
+ const zend_bool server_has_ssl = (server_capabilities & CLIENT_SSL)? TRUE:FALSE;
+ if (server_has_ssl == FALSE) {
+ goto close_conn;
+ } else {
+ enum mysqlnd_ssl_peer verify = client_capabilities & CLIENT_SSL_VERIFY_SERVER_CERT?
+ MYSQLND_SSL_PEER_VERIFY:
+ (client_capabilities & CLIENT_SSL_DONT_VERIFY_SERVER_CERT?
+ MYSQLND_SSL_PEER_DONT_VERIFY:
+ MYSQLND_SSL_PEER_DEFAULT);
+ DBG_INF("Switching to SSL");
+ if (!PACKET_WRITE(auth_packet)) {
+ goto close_conn;
+ }
+
+ conn->vio->data->m.set_client_option(conn->vio, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify);
+
+ if (FAIL == conn->vio->data->m.enable_ssl(conn->vio)) {
+ goto end;
+ }
+ }
+ }
+#else
+ auth_packet->client_flags &= ~CLIENT_SSL;
+ if (!PACKET_WRITE(auth_packet)) {
+ goto close_conn;
+ }
+#endif
+ ret = PASS;
+end:
+ PACKET_FREE(auth_packet);
+ DBG_RETURN(ret);
+
+close_conn:
+ SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
+ conn->m->send_close(conn);
+ SET_CLIENT_ERROR(conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ PACKET_FREE(auth_packet);
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_enable_ssl_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_enable_ssl_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_enable_ssl_command * command;
+ DBG_ENTER("mysqlnd_com_enable_ssl_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_enable_ssl_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.client_capabilities = va_arg(args, size_t);
+ command->context.server_capabilities = va_arg(args, size_t);
+ command->context.charset_no = va_arg(args, unsigned int);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_enable_ssl_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+/************************** COM_READ_HANDSHAKE ******************************************/
+struct st_mysqlnd_protocol_com_handshake_command
+{
+ struct st_mysqlnd_protocol_command parent;
+ struct st_mysqlnd_com_handshake_context
+ {
+ MYSQLND_CONN_DATA * conn;
+ MYSQLND_CSTRING user;
+ MYSQLND_CSTRING passwd;
+ MYSQLND_CSTRING database;
+ size_t client_flags;
+ } context;
+};
+
+
+/* {{{ mysqlnd_com_handshake_run */
+static enum_func_status
+mysqlnd_com_handshake_run(void *cmd)
+{
+ struct st_mysqlnd_protocol_com_handshake_command * command = (struct st_mysqlnd_protocol_com_handshake_command *) cmd;
+ const char * user = command->context.user.s;
+
+ const char * passwd = command->context.passwd.s;
+ size_t passwd_len = command->context.passwd.l;
+
+ const char * db = command->context.database.s;
+ size_t db_len = command->context.database.l;
+
+ size_t mysql_flags = command->context.client_flags;
+
+ MYSQLND_CONN_DATA * conn = command->context.conn;
+ MYSQLND_PACKET_GREET * greet_packet;
+
+ DBG_ENTER("mysqlnd_conn_data::connect_handshake");
+ DBG_INF_FMT("stream=%p", conn->vio->data->m.get_stream(conn->vio));
+ DBG_INF_FMT("[user=%s] [db=%s:%d] [flags=%llu]", user, db, db_len, mysql_flags);
+
+ greet_packet = conn->payload_decoder_factory->m.get_greet_packet(conn->payload_decoder_factory, FALSE);
+ if (!greet_packet) {
+ SET_OOM_ERROR(conn->error_info);
+ DBG_RETURN(FAIL); /* OOM */
+ }
+
+ if (FAIL == PACKET_READ(greet_packet)) {
+ DBG_ERR("Error while reading greeting packet");
+ php_error_docref(NULL, E_WARNING, "Error while reading greeting packet. PID=%d", getpid());
+ goto err;
+ } else if (greet_packet->error_no) {
+ DBG_ERR_FMT("errorno=%u error=%s", greet_packet->error_no, greet_packet->error);
+ SET_CLIENT_ERROR(conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error);
+ goto err;
+ } else if (greet_packet->pre41) {
+ DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s", greet_packet->server_version);
+ php_error_docref(NULL, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 "
+ " is not supported. Server is %-.32s", greet_packet->server_version);
+ SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
+ "Connecting to 3.22, 3.23 & 4.0 servers is not supported");
+ goto err;
+ }
+
+ conn->thread_id = greet_packet->thread_id;
+ conn->protocol_version = greet_packet->protocol_version;
+ conn->server_version = mnd_pestrdup(greet_packet->server_version, conn->persistent);
+
+ conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no);
+ if (!conn->greet_charset) {
+ php_error_docref(NULL, E_WARNING,
+ "Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no);
+ SET_CLIENT_ERROR(conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
+ "Server sent charset unknown to the client. Please, report to the developers");
+ goto err;
+ }
+
+ conn->server_capabilities = greet_packet->server_capabilities;
+
+ if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
+ greet_packet->authentication_plugin_data, greet_packet->auth_protocol,
+ greet_packet->charset_no, greet_packet->server_capabilities,
+ conn->options, mysql_flags))
+ {
+ goto err;
+ }
+
+ UPSERT_STATUS_RESET(conn->upsert_status);
+ UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, greet_packet->server_status);
+
+ PACKET_FREE(greet_packet);
+ DBG_RETURN(PASS);
+err:
+ conn->server_capabilities = 0;
+ PACKET_FREE(greet_packet);
+ DBG_RETURN(FAIL);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_com_handshake_create_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_com_handshake_create_command(va_list args)
+{
+ struct st_mysqlnd_protocol_com_handshake_command * command;
+ DBG_ENTER("mysqlnd_com_handshake_create_command");
+ command = mnd_ecalloc(1, sizeof(struct st_mysqlnd_protocol_com_handshake_command));
+ if (command) {
+ command->context.conn = va_arg(args, MYSQLND_CONN_DATA *);
+ command->context.user = *va_arg(args, const MYSQLND_CSTRING *);
+ command->context.passwd = *va_arg(args, const MYSQLND_CSTRING *);
+ command->context.database = *va_arg(args, const MYSQLND_CSTRING *);
+ command->context.client_flags = va_arg(args, size_t);
+
+ command->parent.free_command = mysqlnd_com_no_params_free_command;
+ command->parent.run = mysqlnd_com_handshake_run;
+ }
+
+ DBG_RETURN((struct st_mysqlnd_protocol_command *) command);
+}
+/* }}} */
+
+
+
+/* {{{ mysqlnd_get_command */
+static struct st_mysqlnd_protocol_command *
+mysqlnd_get_command(enum php_mysqlnd_server_command command, ...)
+{
+ struct st_mysqlnd_protocol_command * ret;
+ va_list args;
+ DBG_ENTER("mysqlnd_get_command");
+
+ va_start(args, command);
+ switch (command) {
+ case COM_SET_OPTION:
+ ret = mysqlnd_com_set_option_create_command(args);
+ break;
+ case COM_DEBUG:
+ ret = mysqlnd_com_debug_create_command(args);
+ break;
+ case COM_INIT_DB:
+ ret = mysqlnd_com_init_db_create_command(args);
+ break;
+ case COM_PING:
+ ret = mysqlnd_com_ping_create_command(args);
+ break;
+ case COM_STATISTICS:
+ ret = mysqlnd_com_statistics_create_command(args);
+ break;
+ case COM_PROCESS_KILL:
+ ret = mysqlnd_com_process_kill_create_command(args);
+ break;
+ case COM_REFRESH:
+ ret = mysqlnd_com_refresh_create_command(args);
+ break;
+ case COM_SHUTDOWN:
+ ret = mysqlnd_com_shutdown_create_command(args);
+ break;
+ case COM_QUIT:
+ ret = mysqlnd_com_quit_create_command(args);
+ break;
+ case COM_QUERY:
+ ret = mysqlnd_com_query_create_command(args);
+ break;
+ case COM_REAP_RESULT:
+ ret = mysqlnd_com_reap_result_create_command(args);
+ break;
+ case COM_CHANGE_USER:
+ ret = mysqlnd_com_change_user_create_command(args);
+ break;
+ case COM_STMT_PREPARE:
+ ret = mysqlnd_com_stmt_prepare_create_command(args);
+ break;
+ case COM_STMT_EXECUTE:
+ ret = mysqlnd_com_stmt_execute_create_command(args);
+ break;
+ case COM_STMT_FETCH:
+ ret = mysqlnd_com_stmt_fetch_create_command(args);
+ break;
+ case COM_STMT_RESET:
+ ret = mysqlnd_com_stmt_reset_create_command(args);
+ break;
+ case COM_STMT_SEND_LONG_DATA:
+ ret = mysqlnd_com_stmt_send_long_data_create_command(args);
+ break;
+ case COM_STMT_CLOSE:
+ ret = mysqlnd_com_stmt_close_create_command(args);
+ break;
+ case COM_ENABLE_SSL:
+ ret = mysqlnd_com_enable_ssl_create_command(args);
+ break;
+ case COM_HANDSHAKE:
+ ret = mysqlnd_com_handshake_create_command(args);
+ break;
+ default:
+ break;
+ }
+ va_end(args);
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+func_mysqlnd__command_factory mysqlnd_command_factory = mysqlnd_get_command;
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_commands.h b/ext/mysqlnd/mysqlnd_commands.h
new file mode 100644
index 0000000000..d035132e75
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_commands.h
@@ -0,0 +1,34 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef MYSQLND_COMMANDS_H
+#define MYSQLND_COMMANDS_H
+
+extern func_mysqlnd__command_factory mysqlnd_command_factory;
+
+#endif /* MYSQLND_COMMANDS_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd.c b/ext/mysqlnd/mysqlnd_connection.c
index 7e80e8299f..910420bfe9 100644
--- a/ext/mysqlnd/mysqlnd.c
+++ b/ext/mysqlnd/mysqlnd_connection.c
@@ -18,46 +18,24 @@
+----------------------------------------------------------------------+
*/
-/* $Id$ */
#include "php.h"
#include "mysqlnd.h"
+#include "mysqlnd_connection.h"
+#include "mysqlnd_vio.h"
+#include "mysqlnd_protocol_frame_codec.h"
+#include "mysqlnd_auth.h"
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_result.h"
#include "mysqlnd_statistics.h"
#include "mysqlnd_charset.h"
#include "mysqlnd_debug.h"
+#include "mysqlnd_ext_plugin.h"
#include "zend_smart_str.h"
-/*
- TODO :
- - Don't bind so tightly the metadata with the result set. This means
- that the metadata reading should not expect a MYSQLND_RES pointer, it
- does not need it, but return a pointer to the metadata (MYSQLND_FIELD *).
- For normal statements we will then just assign it to a member of
- MYSQLND_RES. For PS statements, it will stay as part of the statement
- (MYSQLND_STMT) between prepare and execute. At execute the new metadata
- will be sent by the server, so we will discard the old one and then
- finally attach it to the result set. This will make the code more clean,
- as a prepared statement won't have anymore stmt->result != NULL, as it
- is now, just to have where to store the metadata.
-
- - Change mysqlnd_simple_command to accept a heap dynamic array of MYSQLND_STRING
- terminated by a string with ptr being NULL. Thus, multi-part messages can be
- sent to the network like writev() and this can save at least for
- mysqlnd_stmt_send_long_data() new malloc. This change will probably make the
- code in few other places cleaner.
-*/
extern MYSQLND_CHARSET *mysqlnd_charsets;
-
-
-PHPAPI const char * const mysqlnd_old_passwd = "mysqlnd cannot connect to MySQL 4.1+ using the old insecure authentication. "
-"Please use an administration tool to reset your password with the command SET PASSWORD = PASSWORD('your_existing_password'). This will "
-"store a new, and more secure, hash value in mysql.user. If this user is used in other scripts executed by PHP 5.2 or earlier you might need to remove the old-passwords "
-"flag from your my.cnf file";
-
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";
@@ -65,6 +43,177 @@ PHPAPI const char * const mysqlnd_out_of_memory = "Out of memory";
PHPAPI MYSQLND_STATS *mysqlnd_global_stats = NULL;
+/* {{{ mysqlnd_upsert_status::reset */
+void
+MYSQLND_METHOD(mysqlnd_upsert_status, reset)(MYSQLND_UPSERT_STATUS * const upsert_status)
+{
+ upsert_status->warning_count = 0;
+ upsert_status->server_status = 0;
+ upsert_status->affected_rows = 0;
+ upsert_status->last_insert_id = 0;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_upsert_status::set_affected_rows_to_error */
+void
+MYSQLND_METHOD(mysqlnd_upsert_status, set_affected_rows_to_error)(MYSQLND_UPSERT_STATUS * upsert_status)
+{
+ upsert_status->affected_rows = (uint64_t) ~0;
+}
+/* }}} */
+
+
+MYSQLND_CLASS_METHODS_START(mysqlnd_upsert_status)
+ MYSQLND_METHOD(mysqlnd_upsert_status, reset),
+ MYSQLND_METHOD(mysqlnd_upsert_status, set_affected_rows_to_error),
+MYSQLND_CLASS_METHODS_END;
+
+
+/* {{{ mysqlnd_upsert_status_init */
+void
+mysqlnd_upsert_status_init(MYSQLND_UPSERT_STATUS * const upsert_status)
+{
+ upsert_status->m = &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_upsert_status);
+ upsert_status->m->reset(upsert_status);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_error_list_pdtor */
+static void
+mysqlnd_error_list_pdtor(void * pDest)
+{
+ MYSQLND_ERROR_LIST_ELEMENT * element = (MYSQLND_ERROR_LIST_ELEMENT *) pDest;
+
+ DBG_ENTER("mysqlnd_error_list_pdtor");
+ if (element->error) {
+ mnd_pefree(element->error, TRUE);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_error_info::reset */
+static void
+MYSQLND_METHOD(mysqlnd_error_info, reset)(MYSQLND_ERROR_INFO * const info)
+{
+ DBG_ENTER("mysqlnd_error_info::reset");
+
+ info->error_no = 0;
+ info->error[0] = '\0';
+ memset(info->sqlstate, 0, sizeof(info->sqlstate));
+ if (info->error_list) {
+ zend_llist_clean(info->error_list);
+ }
+
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_error_info::set_client_error */
+static void
+MYSQLND_METHOD(mysqlnd_error_info, set_client_error)(MYSQLND_ERROR_INFO * const info,
+ const unsigned int err_no,
+ const char * const sqlstate,
+ const char * const error)
+{
+ DBG_ENTER("mysqlnd_error_info::set_client_error");
+ if (err_no) {
+ info->error_no = err_no;
+ strlcpy(info->sqlstate, sqlstate, sizeof(info->sqlstate));
+ strlcpy(info->error, error, sizeof(info->error));
+ if (info->error_list) {
+ MYSQLND_ERROR_LIST_ELEMENT error_for_the_list = {0};
+
+ error_for_the_list.error_no = err_no;
+ strlcpy(error_for_the_list.sqlstate, sqlstate, sizeof(error_for_the_list.sqlstate));
+ error_for_the_list.error = mnd_pestrdup(error, TRUE);
+ if (error_for_the_list.error) {
+ DBG_INF_FMT("adding error [%s] to the list", error_for_the_list.error);
+ zend_llist_add_element(info->error_list, &error_for_the_list);
+ }
+ }
+ } else {
+ info->m->reset(info);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+MYSQLND_CLASS_METHODS_START(mysqlnd_error_info)
+ MYSQLND_METHOD(mysqlnd_error_info, reset),
+ MYSQLND_METHOD(mysqlnd_error_info, set_client_error),
+MYSQLND_CLASS_METHODS_END;
+
+
+
+/* {{{ mysqlnd_error_info_init */
+enum_func_status
+mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, zend_bool persistent)
+{
+ DBG_ENTER("mysqlnd_error_info_init");
+ info->m = mysqlnd_error_info_get_methods();
+ info->m->reset(info);
+
+ info->error_list = mnd_pecalloc(1, sizeof(zend_llist), 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);
+ }
+
+ DBG_RETURN(info->error_list? PASS:FAIL);
+}
+/* }}} */
+
+
+
+
+/* {{{ mysqlnd_connection_state::get */
+static enum mysqlnd_connection_state
+MYSQLND_METHOD(mysqlnd_connection_state, get)(const struct st_mysqlnd_connection_state * const state_struct)
+{
+ DBG_ENTER("mysqlnd_connection_state::get");
+ DBG_INF_FMT("State=%u", state_struct->state);
+ DBG_RETURN(state_struct->state);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_connection_state::set */
+static void
+MYSQLND_METHOD(mysqlnd_connection_state, set)(struct st_mysqlnd_connection_state * const state_struct, const enum mysqlnd_connection_state state)
+{
+ DBG_ENTER("mysqlnd_connection_state::set");
+ DBG_INF_FMT("New state=%u", state);
+ state_struct->state = state;
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+MYSQLND_CLASS_METHODS_START(mysqlnd_connection_state)
+ MYSQLND_METHOD(mysqlnd_connection_state, get),
+ MYSQLND_METHOD(mysqlnd_connection_state, set),
+MYSQLND_CLASS_METHODS_END;
+
+
+
+
+/* {{{ mysqlnd_upsert_status_init */
+void
+mysqlnd_connection_state_init(struct st_mysqlnd_connection_state * const state)
+{
+ DBG_ENTER("mysqlnd_error_info_init");
+ state->m = &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_connection_state);
+ state->state = CONN_ALLOCED;
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
/* {{{ mysqlnd_conn_data::free_options */
static void
MYSQLND_METHOD(mysqlnd_conn_data, free_options)(MYSQLND_CONN_DATA * conn)
@@ -118,36 +267,40 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn)
conn->current_result = NULL;
}
- if (conn->net) {
- conn->net->data->m.free_contents(conn->net);
+ if (conn->protocol_frame_codec) {
+ conn->protocol_frame_codec->data->m.free_contents(conn->protocol_frame_codec);
+ }
+
+ if (conn->vio) {
+ conn->vio->data->m.free_contents(conn->vio);
}
DBG_INF("Freeing memory of members");
- if (conn->host) {
- mnd_pefree(conn->host, pers);
- conn->host = NULL;
+ if (conn->hostname.s) {
+ mnd_pefree(conn->hostname.s, pers);
+ conn->hostname.s = NULL;
}
- if (conn->user) {
- mnd_pefree(conn->user, pers);
- conn->user = NULL;
+ if (conn->username.s) {
+ mnd_pefree(conn->username.s, pers);
+ conn->username.s = NULL;
}
- if (conn->passwd) {
- mnd_pefree(conn->passwd, pers);
- conn->passwd = NULL;
+ if (conn->password.s) {
+ mnd_pefree(conn->password.s, pers);
+ conn->password.s = NULL;
}
- if (conn->connect_or_select_db) {
- mnd_pefree(conn->connect_or_select_db, pers);
- conn->connect_or_select_db = NULL;
+ if (conn->connect_or_select_db.s) {
+ mnd_pefree(conn->connect_or_select_db.s, pers);
+ conn->connect_or_select_db.s = NULL;
}
- if (conn->unix_socket) {
- mnd_pefree(conn->unix_socket, pers);
- conn->unix_socket = NULL;
+ if (conn->unix_socket.s) {
+ mnd_pefree(conn->unix_socket.s, pers);
+ conn->unix_socket.s = NULL;
}
- DBG_INF_FMT("scheme=%s", conn->scheme);
- if (conn->scheme) {
- mnd_pefree(conn->scheme, pers);
- conn->scheme = NULL;
+ DBG_INF_FMT("scheme=%s", conn->scheme.s);
+ if (conn->scheme.s) {
+ mnd_pefree(conn->scheme.s, pers);
+ conn->scheme.s = NULL;
}
if (conn->server_version) {
mnd_pefree(conn->server_version, pers);
@@ -157,13 +310,13 @@ MYSQLND_METHOD(mysqlnd_conn_data, free_contents)(MYSQLND_CONN_DATA * conn)
mnd_pefree(conn->host_info, pers);
conn->host_info = NULL;
}
- if (conn->auth_plugin_data) {
- mnd_pefree(conn->auth_plugin_data, pers);
- conn->auth_plugin_data = NULL;
+ if (conn->authentication_plugin_data.s) {
+ mnd_pefree(conn->authentication_plugin_data.s, pers);
+ conn->authentication_plugin_data.s = NULL;
}
- if (conn->last_message) {
- mnd_pefree(conn->last_message, pers);
- conn->last_message = NULL;
+ if (conn->last_message.s) {
+ 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);
@@ -188,14 +341,19 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, dtor)(MYSQLND_CONN_DATA * conn)
conn->m->free_contents(conn);
conn->m->free_options(conn);
- if (conn->net) {
- mysqlnd_net_free(conn->net, conn->stats, conn->error_info);
- conn->net = NULL;
+ if (conn->protocol_frame_codec) {
+ mysqlnd_pfc_free(conn->protocol_frame_codec, conn->stats, conn->error_info);
+ conn->protocol_frame_codec = NULL;
+ }
+
+ if (conn->vio) {
+ mysqlnd_vio_free(conn->vio, conn->stats, conn->error_info);
+ conn->vio = NULL;
}
- if (conn->protocol) {
- mysqlnd_protocol_free(conn->protocol);
- conn->protocol = NULL;
+ if (conn->payload_decoder_factory) {
+ mysqlnd_protocol_payload_decoder_factory_free(conn->payload_decoder_factory);
+ conn->payload_decoder_factory = NULL;
}
if (conn->stats) {
@@ -209,197 +367,19 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, dtor)(MYSQLND_CONN_DATA * conn)
/* }}} */
-/* {{{ mysqlnd_conn_data::simple_command_handle_response */
-static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn_data, simple_command_handle_response)(MYSQLND_CONN_DATA * conn, enum mysqlnd_packet_type ok_packet,
- zend_bool silent, enum php_mysqlnd_server_command command,
- zend_bool ignore_upsert_status)
-{
- enum_func_status ret = FAIL;
-
- DBG_ENTER("mysqlnd_conn_data::simple_command_handle_response");
- DBG_INF_FMT("silent=%u packet=%u command=%s", silent, ok_packet, mysqlnd_command_to_text[command]);
-
- switch (ok_packet) {
- case PROT_OK_PACKET:{
- MYSQLND_PACKET_OK * ok_response = conn->protocol->m.get_ok_packet(conn->protocol, FALSE);
- if (!ok_response) {
- SET_OOM_ERROR(*conn->error_info);
- break;
- }
- if (FAIL == (ret = PACKET_READ(ok_response, conn))) {
- if (!silent) {
- DBG_ERR_FMT("Error while reading %s's OK packet", mysqlnd_command_to_text[command]);
- php_error_docref(NULL, E_WARNING, "Error while reading %s's OK packet. PID=%u",
- mysqlnd_command_to_text[command], getpid());
- }
- } else {
- DBG_INF_FMT("OK from server");
- if (0xFF == ok_response->field_count) {
- /* The server signalled error. Set the error */
- SET_CLIENT_ERROR(*conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
- ret = FAIL;
- /*
- Cover a protocol design error: error packet does not
- contain the server status. Therefore, the client has no way
- to find out whether there are more result sets of
- a multiple-result-set statement pending. Luckily, in 5.0 an
- error always aborts execution of a statement, wherever it is
- a multi-statement or a stored procedure, so it should be
- safe to unconditionally turn off the flag here.
- */
- conn->upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
- SET_ERROR_AFF_ROWS(conn);
- } else {
- SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
- ok_response->message, ok_response->message_len,
- conn->persistent);
-
- if (!ignore_upsert_status) {
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
- conn->upsert_status->warning_count = ok_response->warning_count;
- conn->upsert_status->server_status = ok_response->server_status;
- conn->upsert_status->affected_rows = ok_response->affected_rows;
- conn->upsert_status->last_insert_id = ok_response->last_insert_id;
- }
- }
- }
- PACKET_FREE(ok_response);
- break;
- }
- case PROT_EOF_PACKET:{
- MYSQLND_PACKET_EOF * ok_response = conn->protocol->m.get_eof_packet(conn->protocol, FALSE);
- if (!ok_response) {
- SET_OOM_ERROR(*conn->error_info);
- break;
- }
- if (FAIL == (ret = PACKET_READ(ok_response, conn))) {
- SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE,
- "Malformed packet");
- if (!silent) {
- DBG_ERR_FMT("Error while reading %s's EOF packet", mysqlnd_command_to_text[command]);
- php_error_docref(NULL, E_WARNING, "Error while reading %s's EOF packet. PID=%d",
- mysqlnd_command_to_text[command], getpid());
- }
- } else if (0xFF == ok_response->field_count) {
- /* The server signalled error. Set the error */
- SET_CLIENT_ERROR(*conn->error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
- SET_ERROR_AFF_ROWS(conn);
- } else if (0xFE != ok_response->field_count) {
- SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
- if (!silent) {
- DBG_ERR_FMT("EOF packet expected, field count wasn't 0xFE but 0x%2X", ok_response->field_count);
- php_error_docref(NULL, E_WARNING, "EOF packet expected, field count wasn't 0xFE but 0x%2X",
- ok_response->field_count);
- }
- } else {
- DBG_INF_FMT("OK from server");
- }
- PACKET_FREE(ok_response);
- break;
- }
- default:
- SET_CLIENT_ERROR(*conn->error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
- php_error_docref(NULL, E_ERROR, "Wrong response packet %u passed to the function", ok_packet);
- break;
- }
- DBG_INF(ret == PASS ? "PASS":"FAIL");
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_conn_data::simple_command_send_request */
-static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn_data, simple_command_send_request)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command,
- const zend_uchar * const arg, size_t arg_len, zend_bool silent, zend_bool ignore_upsert_status)
-{
- enum_func_status ret = PASS;
- MYSQLND_PACKET_COMMAND * cmd_packet;
-
- DBG_ENTER("mysqlnd_conn_data::simple_command_send_request");
- DBG_INF_FMT("command=%s silent=%u", mysqlnd_command_to_text[command], silent);
- DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status);
- DBG_INF_FMT("sending %u bytes", arg_len + 1); /* + 1 is for the command */
-
- switch (CONN_GET_STATE(conn)) {
- case CONN_READY:
- break;
- case CONN_QUIT_SENT:
- SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
- DBG_ERR("Server is gone");
- DBG_RETURN(FAIL);
- default:
- SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
- DBG_ERR_FMT("Command out of sync. State=%u", CONN_GET_STATE(conn));
- DBG_RETURN(FAIL);
- }
-
- SET_ERROR_AFF_ROWS(conn);
- SET_EMPTY_ERROR(*conn->error_info);
-
- cmd_packet = conn->protocol->m.get_command_packet(conn->protocol, FALSE);
- if (!cmd_packet) {
- SET_OOM_ERROR(*conn->error_info);
- DBG_RETURN(FAIL);
- }
-
- cmd_packet->command = command;
- if (arg && arg_len) {
- cmd_packet->argument = arg;
- cmd_packet->arg_len = arg_len;
- }
-
- MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_COM_QUIT + command - 1 /* because of COM_SLEEP */ );
-
- if (! PACKET_WRITE(cmd_packet, conn)) {
- if (!silent) {
- DBG_ERR_FMT("Error while sending %s packet", mysqlnd_command_to_text[command]);
- php_error(E_WARNING, "Error while sending %s packet. PID=%d", mysqlnd_command_to_text[command], getpid());
- }
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
- conn->m->send_close(conn);
- DBG_ERR("Server is gone");
- ret = FAIL;
- }
- PACKET_FREE(cmd_packet);
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_conn_data::simple_command */
-static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn_data, simple_command)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command,
- const zend_uchar * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent,
- zend_bool ignore_upsert_status)
-{
- enum_func_status ret;
- DBG_ENTER("mysqlnd_conn_data::simple_command");
-
- ret = conn->m->simple_command_send_request(conn, command, arg, arg_len, silent, ignore_upsert_status);
- if (PASS == ret && ok_packet != PROT_LAST) {
- ret = conn->m->simple_command_handle_response(conn, ok_packet, silent, command, ignore_upsert_status);
- }
-
- DBG_INF(ret == PASS ? "PASS":"FAIL");
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
/* {{{ mysqlnd_conn_data::set_server_option */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, set_server_option)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_server_option option)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_server_option);
- zend_uchar buffer[2];
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), set_server_option);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::set_server_option");
if (PASS == conn->m->local_tx_start(conn, this_func)) {
-
- int2store(buffer, (unsigned int) option);
- ret = conn->m->simple_command(conn, COM_SET_OPTION, buffer, sizeof(buffer), PROT_EOF_PACKET, FALSE, TRUE);
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_SET_OPTION, conn, option);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
conn->m->local_tx_end(conn, this_func, ret);
}
@@ -415,9 +395,9 @@ MYSQLND_METHOD(mysqlnd_conn_data, restart_psession)(MYSQLND_CONN_DATA * conn)
DBG_ENTER("mysqlnd_conn_data::restart_psession");
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CONNECT_REUSED);
/* Free here what should not be seen by the next script */
- if (conn->last_message) {
- mnd_pefree(conn->last_message, conn->persistent);
- conn->last_message = NULL;
+ if (conn->last_message.s) {
+ mnd_pefree(conn->last_message.s, conn->persistent);
+ conn->last_message.s = NULL;
}
DBG_RETURN(PASS);
}
@@ -434,103 +414,6 @@ MYSQLND_METHOD(mysqlnd_conn_data, end_psession)(MYSQLND_CONN_DATA * conn)
/* }}} */
-/* {{{ mysqlnd_switch_to_ssl_if_needed */
-static enum_func_status
-mysqlnd_switch_to_ssl_if_needed(
- MYSQLND_CONN_DATA * conn,
- const MYSQLND_PACKET_GREET * const greet_packet,
- const MYSQLND_OPTIONS * const options,
- zend_ulong mysql_flags)
-{
- enum_func_status ret = FAIL;
- const MYSQLND_CHARSET * charset;
- MYSQLND_PACKET_AUTH * auth_packet;
- DBG_ENTER("mysqlnd_switch_to_ssl_if_needed");
- DBG_INF_FMT("client_capability_flags=%lu", mysql_flags);
- DBG_INF_FMT("CLIENT_LONG_PASSWORD= %d", mysql_flags & CLIENT_LONG_PASSWORD? 1:0);
- DBG_INF_FMT("CLIENT_FOUND_ROWS= %d", mysql_flags & CLIENT_FOUND_ROWS? 1:0);
- DBG_INF_FMT("CLIENT_LONG_FLAG= %d", mysql_flags & CLIENT_LONG_FLAG? 1:0);
- DBG_INF_FMT("CLIENT_NO_SCHEMA= %d", mysql_flags & CLIENT_NO_SCHEMA? 1:0);
- DBG_INF_FMT("CLIENT_COMPRESS= %d", mysql_flags & CLIENT_COMPRESS? 1:0);
- DBG_INF_FMT("CLIENT_ODBC= %d", mysql_flags & CLIENT_ODBC? 1:0);
- DBG_INF_FMT("CLIENT_LOCAL_FILES= %d", mysql_flags & CLIENT_LOCAL_FILES? 1:0);
- DBG_INF_FMT("CLIENT_IGNORE_SPACE= %d", mysql_flags & CLIENT_IGNORE_SPACE? 1:0);
- DBG_INF_FMT("CLIENT_PROTOCOL_41= %d", mysql_flags & CLIENT_PROTOCOL_41? 1:0);
- DBG_INF_FMT("CLIENT_INTERACTIVE= %d", mysql_flags & CLIENT_INTERACTIVE? 1:0);
- DBG_INF_FMT("CLIENT_SSL= %d", mysql_flags & CLIENT_SSL? 1:0);
- DBG_INF_FMT("CLIENT_IGNORE_SIGPIPE= %d", mysql_flags & CLIENT_IGNORE_SIGPIPE? 1:0);
- DBG_INF_FMT("CLIENT_TRANSACTIONS= %d", mysql_flags & CLIENT_TRANSACTIONS? 1:0);
- DBG_INF_FMT("CLIENT_RESERVED= %d", mysql_flags & CLIENT_RESERVED? 1:0);
- DBG_INF_FMT("CLIENT_SECURE_CONNECTION=%d", mysql_flags & CLIENT_SECURE_CONNECTION? 1:0);
- DBG_INF_FMT("CLIENT_MULTI_STATEMENTS=%d", mysql_flags & CLIENT_MULTI_STATEMENTS? 1:0);
- DBG_INF_FMT("CLIENT_MULTI_RESULTS= %d", mysql_flags & CLIENT_MULTI_RESULTS? 1:0);
- DBG_INF_FMT("CLIENT_PS_MULTI_RESULTS=%d", mysql_flags & CLIENT_PS_MULTI_RESULTS? 1:0);
- DBG_INF_FMT("CLIENT_CONNECT_ATTRS= %d", mysql_flags & CLIENT_PLUGIN_AUTH? 1:0);
- DBG_INF_FMT("CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA= %d", mysql_flags & CLIENT_PLUGIN_AUTH_LENENC_CLIENT_DATA? 1:0);
- DBG_INF_FMT("CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS= %d", mysql_flags & CLIENT_CAN_HANDLE_EXPIRED_PASSWORDS? 1:0);
- DBG_INF_FMT("CLIENT_SESSION_TRACK= %d", mysql_flags & CLIENT_SESSION_TRACK? 1:0);
- DBG_INF_FMT("CLIENT_SSL_DONT_VERIFY_SERVER_CERT= %d", mysql_flags & CLIENT_SSL_DONT_VERIFY_SERVER_CERT? 1:0);
- DBG_INF_FMT("CLIENT_SSL_VERIFY_SERVER_CERT= %d", mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT? 1:0);
- DBG_INF_FMT("CLIENT_REMEMBER_OPTIONS= %d", mysql_flags & CLIENT_REMEMBER_OPTIONS? 1:0);
-
- auth_packet = conn->protocol->m.get_auth_packet(conn->protocol, FALSE);
- if (!auth_packet) {
- SET_OOM_ERROR(*conn->error_info);
- goto end;
- }
- auth_packet->client_flags = mysql_flags;
- auth_packet->max_packet_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
-
- if (options->charset_name && (charset = mysqlnd_find_charset_name(options->charset_name))) {
- auth_packet->charset_no = charset->nr;
- } else {
- auth_packet->charset_no = greet_packet->charset_no;
- }
-
-#ifdef MYSQLND_SSL_SUPPORTED
- if (mysql_flags & CLIENT_SSL) {
- zend_bool server_has_ssl = (greet_packet->server_capabilities & CLIENT_SSL)? TRUE:FALSE;
- if (server_has_ssl == FALSE) {
- goto close_conn;
- } else {
- enum mysqlnd_ssl_peer verify = mysql_flags & CLIENT_SSL_VERIFY_SERVER_CERT?
- MYSQLND_SSL_PEER_VERIFY:
- (mysql_flags & CLIENT_SSL_DONT_VERIFY_SERVER_CERT?
- MYSQLND_SSL_PEER_DONT_VERIFY:
- MYSQLND_SSL_PEER_DEFAULT);
- DBG_INF("Switching to SSL");
- if (!PACKET_WRITE(auth_packet, conn)) {
- goto close_conn;
- }
-
- conn->net->data->m.set_client_option(conn->net, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, (const char *) &verify);
-
- if (FAIL == conn->net->data->m.enable_ssl(conn->net)) {
- goto end;
- }
- }
- }
-#else
- auth_packet->client_flags &= ~CLIENT_SSL;
- if (!PACKET_WRITE(auth_packet, conn)) {
- goto close_conn;
- }
-#endif
- ret = PASS;
-end:
- PACKET_FREE(auth_packet);
- DBG_RETURN(ret);
-
-close_conn:
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
- conn->m->send_close(conn);
- SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
- PACKET_FREE(auth_packet);
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
/* {{{ mysqlnd_conn_data::fetch_auth_plugin_by_name */
static struct st_mysqlnd_authentication_plugin *
MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name)(const char * const requested_protocol)
@@ -549,169 +432,6 @@ MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name)(const char * const
/* }}} */
-/* {{{ mysqlnd_run_authentication */
-static enum_func_status
-mysqlnd_run_authentication(
- MYSQLND_CONN_DATA * conn,
- const char * const user,
- const char * const passwd,
- const size_t passwd_len,
- const char * const db,
- const size_t db_len,
- const zend_uchar * const auth_plugin_data,
- const size_t auth_plugin_data_len,
- const char * const auth_protocol,
- unsigned int charset_no,
- const MYSQLND_OPTIONS * const options,
- zend_ulong mysql_flags,
- zend_bool silent,
- zend_bool is_change_user
- )
-{
- enum_func_status ret = FAIL;
- zend_bool first_call = TRUE;
-
- char * switch_to_auth_protocol = NULL;
- size_t switch_to_auth_protocol_len = 0;
- char * requested_protocol = NULL;
- zend_uchar * plugin_data;
- size_t plugin_data_len;
-
- DBG_ENTER("mysqlnd_run_authentication");
-
- plugin_data_len = auth_plugin_data_len;
- plugin_data = mnd_emalloc(plugin_data_len + 1);
- if (!plugin_data) {
- goto end;
- }
- memcpy(plugin_data, auth_plugin_data, plugin_data_len);
- plugin_data[plugin_data_len] = '\0';
-
- requested_protocol = mnd_pestrdup(auth_protocol? auth_protocol : MYSQLND_DEFAULT_AUTH_PROTOCOL, FALSE);
- if (!requested_protocol) {
- goto end;
- }
-
- do {
- struct st_mysqlnd_authentication_plugin * auth_plugin = conn->m->fetch_auth_plugin_by_name(requested_protocol);
-
- if (!auth_plugin) {
- php_error_docref(NULL, E_WARNING, "The server requested authentication method unknown to the client [%s]", requested_protocol);
- SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "The server requested authentication method unknown to the client");
- goto end;
- }
- DBG_INF("plugin found");
-
- {
- zend_uchar * switch_to_auth_protocol_data = NULL;
- size_t switch_to_auth_protocol_data_len = 0;
- zend_uchar * scrambled_data = NULL;
- size_t scrambled_data_len = 0;
-
- switch_to_auth_protocol = NULL;
- switch_to_auth_protocol_len = 0;
-
- if (conn->auth_plugin_data) {
- mnd_pefree(conn->auth_plugin_data, conn->persistent);
- conn->auth_plugin_data = NULL;
- }
- conn->auth_plugin_data_len = plugin_data_len;
- conn->auth_plugin_data = mnd_pemalloc(conn->auth_plugin_data_len, conn->persistent);
- if (!conn->auth_plugin_data) {
- SET_OOM_ERROR(*conn->error_info);
- goto end;
- }
- memcpy(conn->auth_plugin_data, plugin_data, plugin_data_len);
-
- DBG_INF_FMT("salt(%d)=[%.*s]", plugin_data_len, plugin_data_len, plugin_data);
- /* The data should be allocated with malloc() */
- scrambled_data =
- auth_plugin->methods.get_auth_data(NULL, &scrambled_data_len, conn, user, passwd, passwd_len,
- plugin_data, plugin_data_len, options, &conn->net->data->options, mysql_flags);
- if (conn->error_info->error_no) {
- goto end;
- }
- if (FALSE == is_change_user) {
- ret = mysqlnd_auth_handshake(conn, user, passwd, passwd_len, db, db_len, options, mysql_flags,
- charset_no,
- first_call,
- requested_protocol,
- scrambled_data, scrambled_data_len,
- &switch_to_auth_protocol, &switch_to_auth_protocol_len,
- &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len
- );
- } else {
- ret = mysqlnd_auth_change_user(conn, user, strlen(user), passwd, passwd_len, db, db_len, silent,
- first_call,
- requested_protocol,
- scrambled_data, scrambled_data_len,
- &switch_to_auth_protocol, &switch_to_auth_protocol_len,
- &switch_to_auth_protocol_data, &switch_to_auth_protocol_data_len
- );
- }
- first_call = FALSE;
- free(scrambled_data);
-
- DBG_INF_FMT("switch_to_auth_protocol=%s", switch_to_auth_protocol? switch_to_auth_protocol:"n/a");
- if (requested_protocol && switch_to_auth_protocol) {
- mnd_efree(requested_protocol);
- requested_protocol = switch_to_auth_protocol;
- }
-
- if (plugin_data) {
- mnd_efree(plugin_data);
- }
- plugin_data_len = switch_to_auth_protocol_data_len;
- plugin_data = switch_to_auth_protocol_data;
- }
- DBG_INF_FMT("conn->error_info->error_no = %d", conn->error_info->error_no);
- } while (ret == FAIL && conn->error_info->error_no == 0 && switch_to_auth_protocol != NULL);
-
- if (ret == PASS) {
- DBG_INF_FMT("saving requested_protocol=%s", requested_protocol);
- conn->m->set_client_option(conn, MYSQLND_OPT_AUTH_PROTOCOL, requested_protocol);
- }
-end:
- if (plugin_data) {
- mnd_efree(plugin_data);
- }
- if (requested_protocol) {
- mnd_efree(requested_protocol);
- }
-
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_connect_run_authentication */
-static enum_func_status
-mysqlnd_connect_run_authentication(
- MYSQLND_CONN_DATA * conn,
- const char * const user,
- const char * const passwd,
- const char * const db,
- size_t db_len,
- size_t passwd_len,
- const MYSQLND_PACKET_GREET * const greet_packet,
- const MYSQLND_OPTIONS * const options,
- zend_ulong mysql_flags
- )
-{
- enum_func_status ret = FAIL;
- DBG_ENTER("mysqlnd_connect_run_authentication");
-
- ret = mysqlnd_switch_to_ssl_if_needed(conn, greet_packet, options, mysql_flags);
- if (PASS == ret) {
- ret = mysqlnd_run_authentication(conn, user, passwd, passwd_len, db, db_len,
- greet_packet->auth_plugin_data, greet_packet->auth_plugin_data_len, greet_packet->auth_protocol,
- greet_packet->charset_no, options, mysql_flags, FALSE /*silent*/, FALSE/*is_change*/);
- }
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
/* {{{ mysqlnd_conn_data::execute_init_commands */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, execute_init_commands)(MYSQLND_CONN_DATA * conn)
@@ -748,7 +468,10 @@ MYSQLND_METHOD(mysqlnd_conn_data, execute_init_commands)(MYSQLND_CONN_DATA * con
static unsigned int
MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags)(MYSQLND_CONN_DATA * conn, unsigned int mysql_flags)
{
- MYSQLND_NET * net = conn->net;
+#ifdef MYSQLND_COMPRESSION_ENABLED
+ MYSQLND_PFC * pfc = conn->protocol_frame_codec;
+#endif
+ MYSQLND_VIO * vio = conn->vio;
DBG_ENTER("mysqlnd_conn_data::get_updated_connect_flags");
/* we allow load data local infile by default */
@@ -761,7 +484,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags)(MYSQLND_CONN_DATA *
mysql_flags &= ~CLIENT_COMPRESS;
}
#else
- if (net && net->data->options.flags & MYSQLND_NET_FLAG_USE_COMPRESSION) {
+ if (pfc && pfc->data->flags & MYSQLND_PROTOCOL_FLAG_USE_COMPRESSION) {
mysql_flags |= CLIENT_COMPRESS;
}
#endif
@@ -770,8 +493,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags)(MYSQLND_CONN_DATA *
mysql_flags &= ~CLIENT_SSL;
}
#else
- if (net && (net->data->options.ssl_key || net->data->options.ssl_cert ||
- net->data->options.ssl_ca || net->data->options.ssl_capath || net->data->options.ssl_cipher))
+ if (vio && (vio->data->options.ssl_key ||
+ vio->data->options.ssl_cert ||
+ vio->data->options.ssl_ca ||
+ vio->data->options.ssl_capath ||
+ vio->data->options.ssl_cipher))
{
mysql_flags |= CLIENT_SSL;
}
@@ -785,80 +511,62 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags)(MYSQLND_CONN_DATA *
/* {{{ mysqlnd_conn_data::connect_handshake */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake)(MYSQLND_CONN_DATA * conn,
- const char * const host, const char * const user,
- const char * const passwd, const unsigned int passwd_len,
- const char * const db, const unsigned int db_len,
+ const MYSQLND_CSTRING * const scheme,
+ const MYSQLND_CSTRING * const username,
+ const MYSQLND_CSTRING * const password,
+ const MYSQLND_CSTRING * const database,
const unsigned int mysql_flags)
{
- MYSQLND_PACKET_GREET * greet_packet;
- MYSQLND_NET * net = conn->net;
-
+ enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::connect_handshake");
- greet_packet = conn->protocol->m.get_greet_packet(conn->protocol, FALSE);
- if (!greet_packet) {
- SET_OOM_ERROR(*conn->error_info);
- DBG_RETURN(FAIL); /* OOM */
- }
-
- if (FAIL == net->data->m.connect_ex(conn->net, conn->scheme, conn->scheme_len, conn->persistent,
- conn->stats, conn->error_info))
+ if (PASS == conn->vio->data->m.connect(conn->vio, *scheme, conn->persistent, conn->stats, conn->error_info) &&
+ PASS == conn->protocol_frame_codec->data->m.reset(conn->protocol_frame_codec, conn->stats, conn->error_info))
{
- goto err;
- }
-
- DBG_INF_FMT("stream=%p", net->data->m.get_stream(net));
-
- if (FAIL == PACKET_READ(greet_packet, conn)) {
- DBG_ERR("Error while reading greeting packet");
- php_error_docref(NULL, E_WARNING, "Error while reading greeting packet. PID=%d", getpid());
- goto err;
- } else if (greet_packet->error_no) {
- DBG_ERR_FMT("errorno=%u error=%s", greet_packet->error_no, greet_packet->error);
- SET_CLIENT_ERROR(*conn->error_info, greet_packet->error_no, greet_packet->sqlstate, greet_packet->error);
- goto err;
- } else if (greet_packet->pre41) {
- DBG_ERR_FMT("Connecting to 3.22, 3.23 & 4.0 is not supported. Server is %-.32s", greet_packet->server_version);
- php_error_docref(NULL, E_WARNING, "Connecting to 3.22, 3.23 & 4.0 "
- " is not supported. Server is %-.32s", greet_packet->server_version);
- SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
- "Connecting to 3.22, 3.23 & 4.0 servers is not supported");
- goto err;
- }
-
- conn->thread_id = greet_packet->thread_id;
- conn->protocol_version = greet_packet->protocol_version;
- conn->server_version = mnd_pestrdup(greet_packet->server_version, conn->persistent);
-
- conn->greet_charset = mysqlnd_find_charset_nr(greet_packet->charset_no);
- if (!conn->greet_charset) {
- php_error_docref(NULL, E_WARNING,
- "Server sent charset (%d) unknown to the client. Please, report to the developers", greet_packet->charset_no);
- SET_CLIENT_ERROR(*conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE,
- "Server sent charset unknown to the client. Please, report to the developers");
- goto err;
+ size_t client_flags = mysql_flags;
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_HANDSHAKE, conn, username, password, database, client_flags);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
}
+ DBG_RETURN(ret);
+}
+/* }}} */
- conn->client_flag = mysql_flags;
- conn->server_capabilities = greet_packet->server_capabilities;
-
- if (FAIL == mysqlnd_connect_run_authentication(conn, user, passwd, db, db_len, (size_t) passwd_len,
- greet_packet, conn->options, mysql_flags))
- {
- goto err;
+/* {{{ mysqlnd_conn_data::connect */
+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_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);
+ }
+ 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);
+ }
+ transport.l = mnd_sprintf(&transport.s, 0, "pipe://%s", socket_or_pipe.s);
+ *named_pipe = TRUE;
+#endif
+ } else {
+ if (!port) {
+ port = 3306;
+ }
+ transport.l = mnd_sprintf(&transport.s, 0, "tcp://%s:%u", hostname.s, port);
}
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
- conn->upsert_status->warning_count = 0;
- conn->upsert_status->server_status = greet_packet->server_status;
- conn->upsert_status->affected_rows = 0;
-
- PACKET_FREE(greet_packet);
- DBG_RETURN(PASS);
-err:
- conn->client_flag = 0;
- conn->server_capabilities = 0;
- PACKET_FREE(greet_packet);
- DBG_RETURN(FAIL);
+ DBG_INF_FMT("transport=%s", transport.s? transport.s:"OOM");
+ DBG_RETURN(transport);
}
/* }}} */
@@ -866,22 +574,23 @@ err:
/* {{{ mysqlnd_conn_data::connect */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
- const char *host, const char *user,
- const char *passwd, unsigned int passwd_len,
- const char *db, unsigned int db_len,
- unsigned int port,
- const char *socket_or_pipe,
- unsigned int mysql_flags
- )
-{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, connect);
- size_t host_len;
+ MYSQLND_CSTRING hostname,
+ MYSQLND_CSTRING username,
+ MYSQLND_CSTRING password,
+ MYSQLND_CSTRING database,
+ unsigned int port,
+ MYSQLND_CSTRING socket_or_pipe,
+ unsigned int mysql_flags
+ )
+{
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), connect);
zend_bool unix_socket = FALSE;
zend_bool named_pipe = FALSE;
zend_bool reconnect = FALSE;
zend_bool saved_compression = FALSE;
zend_bool local_tx_started = FALSE;
- MYSQLND_NET * net = conn->net;
+ MYSQLND_PFC * pfc = conn->protocol_frame_codec;
+ MYSQLND_STRING transport = { NULL, 0 };
DBG_ENTER("mysqlnd_conn_data::connect");
DBG_INF_FMT("conn=%p", conn);
@@ -891,189 +600,161 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
}
local_tx_started = TRUE;
- SET_EMPTY_ERROR(*conn->error_info);
- SET_ERROR_AFF_ROWS(conn);
+ SET_EMPTY_ERROR(conn->error_info);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u persistent=%u state=%u",
- host?host:"", user?user:"", db?db:"", port, mysql_flags,
- conn? conn->persistent:0, conn? CONN_GET_STATE(conn):-1);
+ hostname.s?hostname.s:"", username.s?username.s:"", database.s?database.s:"", port, mysql_flags,
+ conn? conn->persistent:0, conn? GET_CONNECTION_STATE(&conn->state):-1);
- if (CONN_GET_STATE(conn) > CONN_ALLOCED && CONN_GET_STATE(conn) ) {
+ if (GET_CONNECTION_STATE(&conn->state) > CONN_ALLOCED) {
DBG_INF("Connecting on a connected handle.");
- if (CONN_GET_STATE(conn) < CONN_QUIT_SENT) {
+ if (GET_CONNECTION_STATE(&conn->state) < CONN_QUIT_SENT) {
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CLOSE_IMPLICIT);
reconnect = TRUE;
conn->m->send_close(conn);
}
conn->m->free_contents(conn);
- MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_CONNECTIONS);
- if (conn->persistent) {
- MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_PERSISTENT_CONNECTIONS);
- }
/* Now reconnect using the same handle */
- if (net->data->compressed) {
+ if (pfc->data->compressed) {
/*
- we need to save the state. As we will re-connect, net->compressed should be off, or
+ we need to save the state. As we will re-connect, pfc->compressed should be off, or
we will look for a compression header as part of the greet message, but there will
be none.
*/
saved_compression = TRUE;
- net->data->compressed = FALSE;
+ pfc->data->compressed = FALSE;
}
- if (net->data->ssl) {
- net->data->ssl = FALSE;
+ if (pfc->data->ssl) {
+ pfc->data->ssl = FALSE;
}
} else {
unsigned int max_allowed_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
conn->m->set_client_option(conn, MYSQLND_OPT_MAX_ALLOWED_PACKET, (char *)&max_allowed_size);
}
- if (!host || !host[0]) {
- host = "localhost";
+ if (!hostname.s || !hostname.s[0]) {
+ hostname.s = "localhost";
+ hostname.l = strlen(hostname.s);
}
- if (!user) {
+ if (!username.s) {
DBG_INF_FMT("no user given, using empty string");
- user = "";
+ username.s = "";
+ username.l = 0;
}
- if (!passwd) {
+ if (!password.s) {
DBG_INF_FMT("no password given, using empty string");
- passwd = "";
- passwd_len = 0;
+ password.s = "";
+ password.l = 0;
}
- if (!db) {
+ if (!database.s) {
DBG_INF_FMT("no db given, using empty string");
- db = "";
- db_len = 0;
+ database.s = "";
+ database.l = 0;
} else {
mysql_flags |= CLIENT_CONNECT_WITH_DB;
}
- host_len = strlen(host);
- {
- char * transport = NULL;
- int transport_len;
-#ifndef PHP_WIN32
- if (host_len == sizeof("localhost") - 1 && !strncasecmp(host, "localhost", host_len)) {
- DBG_INF_FMT("socket=%s", socket_or_pipe? socket_or_pipe:"n/a");
- if (!socket_or_pipe) {
- socket_or_pipe = "/tmp/mysql.sock";
- }
- transport_len = mnd_sprintf(&transport, 0, "unix://%s", socket_or_pipe);
- unix_socket = TRUE;
-#else
- if (host_len == sizeof(".") - 1 && host[0] == '.') {
- /* named pipe in socket */
- if (!socket_or_pipe) {
- socket_or_pipe = "\\\\.\\pipe\\MySQL";
- }
- transport_len = mnd_sprintf(&transport, 0, "pipe://%s", socket_or_pipe);
- named_pipe = TRUE;
-#endif
- } else {
- if (!port) {
- port = 3306;
- }
- transport_len = mnd_sprintf(&transport, 0, "tcp://%s:%u", host, port);
- }
- if (!transport) {
- SET_OOM_ERROR(*conn->error_info);
- goto err; /* OOM */
- }
- DBG_INF_FMT("transport=%s conn->scheme=%s", transport, conn->scheme);
- conn->scheme = mnd_pestrndup(transport, transport_len, conn->persistent);
- conn->scheme_len = transport_len;
- mnd_sprintf_free(transport);
- transport = NULL;
- if (!conn->scheme) {
- goto err; /* OOM */
- }
- }
+ 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);
- if (FAIL == conn->m->connect_handshake(conn, host, user, passwd, passwd_len, db, db_len, mysql_flags)) {
- goto err;
+ {
+ const MYSQLND_CSTRING scheme = { transport.s, transport.l };
+ if (FAIL == conn->m->connect_handshake(conn, &scheme, &username, &password, &database, mysql_flags)) {
+ goto err;
+ }
}
{
- CONN_SET_STATE(conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
if (saved_compression) {
- net->data->compressed = TRUE;
+ pfc->data->compressed = TRUE;
}
/*
If a connect on a existing handle is performed and mysql_flags is
passed which doesn't CLIENT_COMPRESS, then we need to overwrite the value
which we set based on saved_compression.
*/
- net->data->compressed = mysql_flags & CLIENT_COMPRESS? TRUE:FALSE;
+ pfc->data->compressed = mysql_flags & CLIENT_COMPRESS? TRUE:FALSE;
- conn->user_len = strlen(user);
- conn->user = mnd_pestrndup(user, conn->user_len, conn->persistent);
- conn->passwd = mnd_pestrndup(passwd, passwd_len, conn->persistent);
- conn->passwd_len = passwd_len;
+
+ conn->scheme.s = mnd_pestrndup(transport.s, transport.l, conn->persistent);
+ conn->scheme.l = transport.l;
+ if (transport.s) {
+ mnd_sprintf_free(transport.s);
+ transport.s = NULL;
+ }
+
+ if (!conn->scheme.s) {
+ goto err; /* OOM */
+ }
+
+ conn->username.l = username.l;
+ conn->username.s = mnd_pestrndup(username.s, conn->username.l, conn->persistent);
+ conn->password.l = password.l;
+ conn->password.s = mnd_pestrndup(password.s, conn->password.l, conn->persistent);
conn->port = port;
- conn->connect_or_select_db = mnd_pestrndup(db, db_len, conn->persistent);
- conn->connect_or_select_db_len = db_len;
+ conn->connect_or_select_db.l = database.l;
+ conn->connect_or_select_db.s = mnd_pestrndup(database.s, conn->connect_or_select_db.l, conn->persistent);
- if (!conn->user || !conn->passwd || !conn->connect_or_select_db) {
- SET_OOM_ERROR(*conn->error_info);
+ if (!conn->username.s || !conn->password.s|| !conn->connect_or_select_db.s) {
+ SET_OOM_ERROR(conn->error_info);
goto err; /* OOM */
}
if (!unix_socket && !named_pipe) {
- conn->host = mnd_pestrndup(host, host_len, conn->persistent);
- if (!conn->host) {
- SET_OOM_ERROR(*conn->error_info);
+ conn->hostname.s = mnd_pestrndup(hostname.s, hostname.l, conn->persistent);
+ if (!conn->hostname.s) {
+ SET_OOM_ERROR(conn->error_info);
goto err; /* OOM */
}
- conn->host_len = host_len;
+ conn->hostname.l = hostname.l;
{
char *p;
- mnd_sprintf(&p, 0, "%s via TCP/IP", conn->host);
+ mnd_sprintf(&p, 0, "%s via TCP/IP", conn->hostname);
if (!p) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
goto err; /* OOM */
}
conn->host_info = mnd_pestrdup(p, conn->persistent);
mnd_sprintf_free(p);
if (!conn->host_info) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
goto err; /* OOM */
}
}
} else {
- conn->unix_socket = mnd_pestrdup(socket_or_pipe, conn->persistent);
+ conn->unix_socket.s = mnd_pestrdup(socket_or_pipe.s, conn->persistent);
if (unix_socket) {
conn->host_info = mnd_pestrdup("Localhost via UNIX socket", conn->persistent);
} else if (named_pipe) {
char *p;
- mnd_sprintf(&p, 0, "%s via named pipe", conn->unix_socket);
+ mnd_sprintf(&p, 0, "%s via named pipe", conn->unix_socket.s);
if (!p) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
goto err; /* OOM */
}
conn->host_info = mnd_pestrdup(p, conn->persistent);
mnd_sprintf_free(p);
if (!conn->host_info) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
goto err; /* OOM */
}
} else {
php_error_docref(NULL, E_WARNING, "Impossible. Should be either socket or a pipe. Report a bug!");
}
- if (!conn->unix_socket || !conn->host_info) {
- SET_OOM_ERROR(*conn->error_info);
+ if (!conn->unix_socket.s || !conn->host_info) {
+ SET_OOM_ERROR(conn->error_info);
goto err; /* OOM */
}
- conn->unix_socket_len = strlen(conn->unix_socket);
+ conn->unix_socket.l = strlen(conn->unix_socket.s);
}
- conn->max_packet_size = MYSQLND_ASSEMBLED_PACKET_MAX_SIZE;
- /* todo: check if charset is available */
- SET_EMPTY_ERROR(*conn->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
mysqlnd_local_infile_default(conn);
@@ -1095,12 +776,15 @@ MYSQLND_METHOD(mysqlnd_conn_data, connect)(MYSQLND_CONN_DATA * conn,
DBG_RETURN(PASS);
}
err:
+ if (transport.s) {
+ mnd_sprintf_free(transport.s);
+ transport.s = NULL;
+ }
- DBG_ERR_FMT("[%u] %.128s (trying to connect via %s)", conn->error_info->error_no, conn->error_info->error, conn->scheme);
+ DBG_ERR_FMT("[%u] %.128s (trying to connect via %s)", conn->error_info->error_no, conn->error_info->error, conn->scheme.s);
if (!conn->error_info->error_no) {
- SET_CLIENT_ERROR(*conn->error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, conn->error_info->error? conn->error_info->error:"Unknown error");
- php_error_docref(NULL, E_WARNING, "[%u] %.128s (trying to connect via %s)",
- conn->error_info->error_no, conn->error_info->error, conn->scheme);
+ SET_CLIENT_ERROR(conn->error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, conn->error_info->error? conn->error_info->error:"Unknown error");
+ php_error_docref(NULL, E_WARNING, "[%u] %.128s (trying to connect via %s)", conn->error_info->error_no, conn->error_info->error, conn->scheme.s);
}
conn->m->free_contents(conn);
@@ -1117,15 +801,15 @@ err:
/* {{{ mysqlnd_conn::connect */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
- const char * host, const char * user,
- const char * passwd, unsigned int passwd_len,
- const char * db, unsigned int db_len,
- unsigned int port,
- const char * socket_or_pipe,
- unsigned int mysql_flags
- )
-{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, connect);
+ const MYSQLND_CSTRING hostname,
+ const MYSQLND_CSTRING username,
+ const MYSQLND_CSTRING password,
+ const MYSQLND_CSTRING database,
+ unsigned int port,
+ const MYSQLND_CSTRING socket_or_pipe,
+ unsigned int mysql_flags)
+{
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), connect);
enum_func_status ret = FAIL;
MYSQLND_CONN_DATA * conn = conn_handle->data;
@@ -1133,7 +817,7 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
if (PASS == conn->m->local_tx_start(conn, this_func)) {
mysqlnd_options4(conn_handle, MYSQL_OPT_CONNECT_ATTR_ADD, "_client_name", "mysqlnd");
- ret = conn->m->connect(conn, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags);
+ ret = conn->m->connect(conn, hostname, username, password, database, port, socket_or_pipe, mysql_flags);
conn->m->local_tx_end(conn, this_func, FAIL);
}
@@ -1142,57 +826,15 @@ MYSQLND_METHOD(mysqlnd_conn, connect)(MYSQLND * conn_handle,
/* }}} */
-/* {{{ mysqlnd_connect */
-PHPAPI MYSQLND * mysqlnd_connect(MYSQLND * conn_handle,
- const char * host, const char * user,
- const char * passwd, unsigned int passwd_len,
- const char * db, unsigned int db_len,
- unsigned int port,
- const char * socket_or_pipe,
- unsigned int mysql_flags,
- unsigned int client_api_flags
- )
-{
- enum_func_status ret = FAIL;
- zend_bool self_alloced = FALSE;
-
- DBG_ENTER("mysqlnd_connect");
- DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u", host?host:"", user?user:"", db?db:"", port, mysql_flags);
-
- if (!conn_handle) {
- self_alloced = TRUE;
- if (!(conn_handle = mysqlnd_init(client_api_flags, FALSE))) {
- /* OOM */
- DBG_RETURN(NULL);
- }
- }
-
- ret = conn_handle->m->connect(conn_handle, host, user, passwd, passwd_len, db, db_len, port, socket_or_pipe, mysql_flags);
-
- if (ret == FAIL) {
- if (self_alloced) {
- /*
- We have alloced, thus there are no references to this
- object - we are free to kill it!
- */
- conn_handle->m->dtor(conn_handle);
- }
- DBG_RETURN(NULL);
- }
- DBG_RETURN(conn_handle);
-}
-/* }}} */
-
-
/* {{{ mysqlnd_conn_data::query */
/*
If conn->error_info->error_no is not zero, then we had an error.
Still the result from the query is PASS
*/
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn_data, query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int query_len)
+MYSQLND_METHOD(mysqlnd_conn_data, query)(MYSQLND_CONN_DATA * conn, const char * const query, const size_t query_len)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, query);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), query);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::query");
DBG_INF_FMT("conn=%p conn=%llu query=%s", conn, conn->thread_id, query);
@@ -1202,8 +844,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, query)(MYSQLND_CONN_DATA * conn, const char *
PASS == conn->m->reap_query(conn, MYSQLND_REAP_RESULT_IMPLICIT))
{
ret = PASS;
- if (conn->last_query_type == QUERY_UPSERT && conn->upsert_status->affected_rows) {
- MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, conn->upsert_status->affected_rows);
+ if (conn->last_query_type == QUERY_UPSERT && UPSERT_STATUS_GET_AFFECTED_ROWS(conn->upsert_status)) {
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, UPSERT_STATUS_GET_AFFECTED_ROWS(conn->upsert_status));
}
}
conn->m->local_tx_end(conn, this_func, ret);
@@ -1215,25 +857,29 @@ MYSQLND_METHOD(mysqlnd_conn_data, query)(MYSQLND_CONN_DATA * conn, const char *
/* {{{ mysqlnd_conn_data::send_query */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn_data, send_query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int query_len,
+MYSQLND_METHOD(mysqlnd_conn_data, send_query)(MYSQLND_CONN_DATA * conn, const char * const query, const size_t query_len,
enum_mysqlnd_send_query_type type, zval *read_cb, zval *err_cb)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, send_query);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), send_query);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::send_query");
DBG_INF_FMT("conn=%llu query=%s", conn->thread_id, query);
- DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status);
+ DBG_INF_FMT("conn->server_status=%u", UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status));
- if (PASS == conn->m->local_tx_start(conn, this_func)) {
- ret = conn->m->simple_command(conn, COM_QUERY, (zend_uchar *) query, query_len,
- PROT_LAST /* we will handle the OK packet*/,
- FALSE, FALSE);
- if (PASS == ret) {
- CONN_SET_STATE(conn, CONN_QUERY_SENT);
+ if (type == MYSQLND_SEND_QUERY_IMPLICIT || PASS == conn->m->local_tx_start(conn, this_func))
+ {
+ const MYSQLND_CSTRING query_string = {query, query_len};
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_QUERY, conn, query_string);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
+
+ if (type == MYSQLND_SEND_QUERY_EXPLICIT) {
+ conn->m->local_tx_end(conn, this_func, ret);
}
- conn->m->local_tx_end(conn, this_func, ret);
}
- DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status);
+ DBG_INF_FMT("conn->server_status=%u", UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status));
DBG_RETURN(ret);
}
/* }}} */
@@ -1243,302 +889,35 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_query)(MYSQLND_CONN_DATA * conn, const ch
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, reap_query)(MYSQLND_CONN_DATA * conn, enum_mysqlnd_reap_result_type type)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, reap_query);
- enum_mysqlnd_connection_state state = CONN_GET_STATE(conn);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), reap_query);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::reap_query");
DBG_INF_FMT("conn=%llu", conn->thread_id);
- DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status);
- if (PASS == conn->m->local_tx_start(conn, this_func)) {
- if (state <= CONN_READY || state == CONN_QUIT_SENT) {
- php_error_docref(NULL, E_WARNING, "Connection not opened, clear or has been closed");
- DBG_ERR_FMT("Connection not opened, clear or has been closed. State=%u", state);
- DBG_RETURN(ret);
- }
- ret = conn->m->query_read_result_set_header(conn, NULL);
-
- conn->m->local_tx_end(conn, this_func, ret);
- }
- DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status);
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
-#include "php_network.h"
-
-/* {{{ mysqlnd_stream_array_to_fd_set */
-MYSQLND ** mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array)
-{
- int cnt = 0;
- MYSQLND **p = conn_array, **p_p;
- MYSQLND **ret = NULL;
-
- while (*p) {
- if (CONN_GET_STATE((*p)->data) <= CONN_READY || CONN_GET_STATE((*p)->data) == CONN_QUIT_SENT) {
- cnt++;
- }
- p++;
- }
- if (cnt) {
- MYSQLND **ret_p = ret = ecalloc(cnt + 1, sizeof(MYSQLND *));
- p_p = p = conn_array;
- while (*p) {
- if (CONN_GET_STATE((*p)->data) <= CONN_READY || CONN_GET_STATE((*p)->data) == CONN_QUIT_SENT) {
- *ret_p = *p;
- *p = NULL;
- ret_p++;
- } else {
- *p_p = *p;
- p_p++;
- }
- p++;
- }
- *ret_p = NULL;
- }
- return ret;
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_stream_array_to_fd_set */
-static int mysqlnd_stream_array_to_fd_set(MYSQLND ** conn_array, fd_set * fds, php_socket_t * max_fd)
-{
- php_socket_t this_fd;
- php_stream *stream = NULL;
- unsigned int cnt = 0;
- MYSQLND **p = conn_array;
- DBG_ENTER("mysqlnd_stream_array_to_fd_set");
-
- while (*p) {
- /* get the fd.
- * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag
- * when casting. It is only used here so that the buffered data warning
- * is not displayed.
- * */
- stream = (*p)->data->net->data->m.get_stream((*p)->data->net);
- DBG_INF_FMT("conn=%llu stream=%p", (*p)->data->thread_id, stream);
- if (stream != NULL && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
- (void*)&this_fd, 1) && ZEND_VALID_SOCKET(this_fd)) {
-
- PHP_SAFE_FD_SET(this_fd, fds);
-
- if (this_fd > *max_fd) {
- *max_fd = this_fd;
- }
- cnt++;
+ DBG_INF_FMT("conn->server_status=%u", UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status));
+ if (type == MYSQLND_REAP_RESULT_IMPLICIT || PASS == conn->m->local_tx_start(conn, this_func))
+ {
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_REAP_RESULT, conn);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
}
- p++;
- }
- DBG_RETURN(cnt ? 1 : 0);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_stream_array_from_fd_set */
-static int mysqlnd_stream_array_from_fd_set(MYSQLND ** conn_array, fd_set * fds)
-{
- php_socket_t this_fd;
- php_stream *stream = NULL;
- int ret = 0;
- zend_bool disproportion = FALSE;
- MYSQLND **fwd = conn_array, **bckwd = conn_array;
- DBG_ENTER("mysqlnd_stream_array_from_fd_set");
- while (*fwd) {
- stream = (*fwd)->data->net->data->m.get_stream((*fwd)->data->net);
- DBG_INF_FMT("conn=%llu stream=%p", (*fwd)->data->thread_id, stream);
- if (stream != NULL && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
- (void*)&this_fd, 1) && ZEND_VALID_SOCKET(this_fd)) {
- if (PHP_SAFE_FD_ISSET(this_fd, fds)) {
- if (disproportion) {
- *bckwd = *fwd;
- }
- bckwd++;
- fwd++;
- ret++;
- continue;
- }
+ if (type == MYSQLND_REAP_RESULT_EXPLICIT) {
+ conn->m->local_tx_end(conn, this_func, ret);
}
- disproportion = TRUE;
- fwd++;
}
- *bckwd = NULL;/* NULL-terminate the list */
-
+ DBG_INF_FMT("conn->server_status=%u", UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status));
DBG_RETURN(ret);
}
/* }}} */
-#ifndef PHP_WIN32
-#define php_select(m, r, w, e, t) select(m, r, w, e, t)
-#else
-#include "win32/select.h"
-#endif
-
-
-/* {{{ mysqlnd_poll */
-PHPAPI enum_func_status
-mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long sec, long usec, int * desc_num)
-{
- struct timeval tv;
- struct timeval *tv_p = NULL;
- fd_set rfds, wfds, efds;
- php_socket_t max_fd = 0;
- int retval, sets = 0;
- int set_count, max_set_count = 0;
-
- DBG_ENTER("_mysqlnd_poll");
- if (sec < 0 || usec < 0) {
- php_error_docref(NULL, E_WARNING, "Negative values passed for sec and/or usec");
- DBG_RETURN(FAIL);
- }
-
- FD_ZERO(&rfds);
- FD_ZERO(&wfds);
- FD_ZERO(&efds);
-
- if (r_array != NULL) {
- *dont_poll = mysqlnd_stream_array_check_for_readiness(r_array);
- set_count = mysqlnd_stream_array_to_fd_set(r_array, &rfds, &max_fd);
- if (set_count > max_set_count) {
- max_set_count = set_count;
- }
- sets += set_count;
- }
-
- if (e_array != NULL) {
- set_count = mysqlnd_stream_array_to_fd_set(e_array, &efds, &max_fd);
- if (set_count > max_set_count) {
- max_set_count = set_count;
- }
- sets += set_count;
- }
-
- if (!sets) {
- php_error_docref(NULL, E_WARNING, *dont_poll ? "All arrays passed are clear":"No stream arrays were passed");
- DBG_ERR_FMT(*dont_poll ? "All arrays passed are clear":"No stream arrays were passed");
- DBG_RETURN(FAIL);
- }
-
- PHP_SAFE_MAX_FD(max_fd, max_set_count);
-
- /* Solaris + BSD do not like microsecond values which are >= 1 sec */
- if (usec > 999999) {
- tv.tv_sec = sec + (usec / 1000000);
- tv.tv_usec = usec % 1000000;
- } else {
- tv.tv_sec = sec;
- tv.tv_usec = usec;
- }
-
- tv_p = &tv;
-
- retval = php_select(max_fd + 1, &rfds, &wfds, &efds, tv_p);
-
- if (retval == -1) {
- php_error_docref(NULL, E_WARNING, "unable to select [%d]: %s (max_fd=%d)",
- errno, strerror(errno), max_fd);
- DBG_RETURN(FAIL);
- }
-
- if (r_array != NULL) {
- mysqlnd_stream_array_from_fd_set(r_array, &rfds);
- }
- if (e_array != NULL) {
- mysqlnd_stream_array_from_fd_set(e_array, &efds);
- }
-
- *desc_num = retval;
- DBG_RETURN(PASS);
-}
-/* }}} */
-
-
-/*
- COM_FIELD_LIST is special, different from a SHOW FIELDS FROM :
- - There is no result set header - status from the command, which
- impacts us to allocate big chunk of memory for reading the metadata.
- - The EOF packet is consumed by the metadata packet reader.
-*/
-
-/* {{{ mysqlnd_conn_data::list_fields */
-MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_conn_data, list_fields)(MYSQLND_CONN_DATA * conn, const char *table, const char *achtung_wild)
-{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, list_fields);
- /* db + \0 + wild + \0 (for wild) */
- zend_uchar buff[MYSQLND_MAX_ALLOWED_DB_LEN * 2 + 1 + 1], *p;
- size_t table_len, wild_len;
- MYSQLND_RES * result = NULL;
- DBG_ENTER("mysqlnd_conn_data::list_fields");
- DBG_INF_FMT("conn=%llu table=%s wild=%s", conn->thread_id, table? table:"",achtung_wild? achtung_wild:"");
-
- if (PASS == conn->m->local_tx_start(conn, this_func)) {
- do {
- p = buff;
- if (table && (table_len = strlen(table))) {
- size_t to_copy = MIN(table_len, MYSQLND_MAX_ALLOWED_DB_LEN);
- memcpy(p, table, to_copy);
- p += to_copy;
- *p++ = '\0';
- }
-
- if (achtung_wild && (wild_len = strlen(achtung_wild))) {
- size_t to_copy = MIN(wild_len, MYSQLND_MAX_ALLOWED_DB_LEN);
- memcpy(p, achtung_wild, to_copy);
- p += to_copy;
- *p++ = '\0';
- }
-
- if (PASS != conn->m->simple_command(conn, COM_FIELD_LIST, buff, p - buff,
- PROT_LAST /* we will handle the OK packet*/,
- FALSE, TRUE)) {
- conn->m->local_tx_end(conn, 0, FAIL);
- break;
- }
-
- /*
- Prepare for the worst case.
- MyISAM goes to 2500 BIT columns, double it for safety.
- */
- result = conn->m->result_init(5000, conn->persistent);
- if (!result) {
- break;
- }
-
- if (FAIL == result->m.read_result_metadata(result, conn)) {
- DBG_ERR("Error occurred while reading metadata");
- result->m.free_result(result, TRUE);
- result = NULL;
- break;
- }
-
- result->type = MYSQLND_RES_NORMAL;
- result->unbuf = mysqlnd_result_unbuffered_init(result->field_count, FALSE, result->persistent);
- if (!result->unbuf) {
- /* OOM */
- SET_OOM_ERROR(*conn->error_info);
- result->m.free_result(result, TRUE);
- result = NULL;
- break;
- }
- result->unbuf->eof_reached = TRUE;
- } while (0);
- conn->m->local_tx_end(conn, this_func, result == NULL? FAIL:PASS);
- }
-
- DBG_RETURN(result);
-}
-/* }}} */
-
-
/* {{{ mysqlnd_conn_data::list_method */
MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_conn_data, list_method)(MYSQLND_CONN_DATA * conn, const char * query, const char *achtung_wild, char *par1)
+MYSQLND_METHOD(mysqlnd_conn_data, list_method)(MYSQLND_CONN_DATA * conn, const char * const query, const char * const achtung_wild, const char * const par1)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, list_method);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), list_method);
char * show_query = NULL;
size_t show_query_len;
MYSQLND_RES * result = NULL;
@@ -1574,9 +953,9 @@ MYSQLND_METHOD(mysqlnd_conn_data, list_method)(MYSQLND_CONN_DATA * conn, const c
/* }}} */
-/* {{{ mysqlnd_conn_data::errno */
+/* {{{ mysqlnd_conn_data::err_no */
static unsigned int
-MYSQLND_METHOD(mysqlnd_conn_data, errno)(const MYSQLND_CONN_DATA * const conn)
+MYSQLND_METHOD(mysqlnd_conn_data, err_no)(const MYSQLND_CONN_DATA * const conn)
{
return conn->error_info->error_no;
}
@@ -1616,17 +995,17 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, ssl_set)(MYSQLND_CONN_DATA * const conn, const char * key, const char * const cert,
const char * const ca, const char * const capath, const char * const cipher)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, ssl_set);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), ssl_set);
enum_func_status ret = FAIL;
- MYSQLND_NET * net = conn->net;
+ MYSQLND_VIO * vio = conn->vio;
DBG_ENTER("mysqlnd_conn_data::ssl_set");
if (PASS == conn->m->local_tx_start(conn, this_func)) {
- ret = (PASS == net->data->m.set_client_option(net, MYSQLND_OPT_SSL_KEY, key) &&
- PASS == net->data->m.set_client_option(net, MYSQLND_OPT_SSL_CERT, cert) &&
- PASS == net->data->m.set_client_option(net, MYSQLND_OPT_SSL_CA, ca) &&
- PASS == net->data->m.set_client_option(net, MYSQLND_OPT_SSL_CAPATH, capath) &&
- PASS == net->data->m.set_client_option(net, MYSQLND_OPT_SSL_CIPHER, cipher)) ? PASS : FAIL;
+ ret = (PASS == vio->data->m.set_client_option(vio, MYSQLND_OPT_SSL_KEY, key) &&
+ PASS == vio->data->m.set_client_option(vio, MYSQLND_OPT_SSL_CERT, cert) &&
+ PASS == vio->data->m.set_client_option(vio, MYSQLND_OPT_SSL_CA, ca) &&
+ PASS == vio->data->m.set_client_option(vio, MYSQLND_OPT_SSL_CAPATH, capath) &&
+ PASS == vio->data->m.set_client_option(vio, MYSQLND_OPT_SSL_CIPHER, cipher)) ? PASS : FAIL;
conn->m->local_tx_end(conn, this_func, ret);
}
@@ -1639,14 +1018,14 @@ MYSQLND_METHOD(mysqlnd_conn_data, ssl_set)(MYSQLND_CONN_DATA * const conn, const
static zend_ulong
MYSQLND_METHOD(mysqlnd_conn_data, escape_string)(MYSQLND_CONN_DATA * const conn, char * newstr, const char * escapestr, size_t escapestr_len)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, escape_string);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), escape_string);
zend_ulong ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::escape_string");
DBG_INF_FMT("conn=%llu", conn->thread_id);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
- DBG_INF_FMT("server_status=%u", conn->upsert_status->server_status);
- if (conn->upsert_status->server_status & SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
+ DBG_INF_FMT("server_status=%u", UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status));
+ if (UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_STATUS_NO_BACKSLASH_ESCAPES) {
ret = mysqlnd_cset_escape_quotes(conn->charset, newstr, escapestr, escapestr_len);
} else {
ret = mysqlnd_cset_escape_slashes(conn->charset, newstr, escapestr, escapestr_len);
@@ -1662,12 +1041,16 @@ MYSQLND_METHOD(mysqlnd_conn_data, escape_string)(MYSQLND_CONN_DATA * const conn,
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, dump_debug_info)(MYSQLND_CONN_DATA * const conn)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, server_dump_debug_information);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), server_dump_debug_information);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::dump_debug_info");
DBG_INF_FMT("conn=%llu", conn->thread_id);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
- ret = conn->m->simple_command(conn, COM_DEBUG, NULL, 0, PROT_EOF_PACKET, FALSE, TRUE);
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_DEBUG, conn);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
conn->m->local_tx_end(conn, this_func, ret);
}
@@ -1679,33 +1062,22 @@ MYSQLND_METHOD(mysqlnd_conn_data, dump_debug_info)(MYSQLND_CONN_DATA * const con
/* {{{ mysqlnd_conn_data::select_db */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn_data, select_db)(MYSQLND_CONN_DATA * const conn, const char * const db, unsigned int db_len)
+MYSQLND_METHOD(mysqlnd_conn_data, select_db)(MYSQLND_CONN_DATA * const conn, const char * const db, const size_t db_len)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, select_db);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), select_db);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::select_db");
DBG_INF_FMT("conn=%llu db=%s", conn->thread_id, db);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
- ret = conn->m->simple_command(conn, COM_INIT_DB, (zend_uchar*) db, db_len, PROT_OK_PACKET, FALSE, TRUE);
- /*
- The server sends 0 but libmysql doesn't read it and has established
- a protocol of giving back -1. Thus we have to follow it :(
- */
- SET_ERROR_AFF_ROWS(conn);
- if (ret == PASS) {
- if (conn->connect_or_select_db) {
- mnd_pefree(conn->connect_or_select_db, conn->persistent);
- }
- conn->connect_or_select_db = mnd_pestrndup(db, db_len, conn->persistent);
- conn->connect_or_select_db_len = db_len;
- if (!conn->connect_or_select_db) {
- /* OOM */
- SET_OOM_ERROR(*conn->error_info);
- ret = FAIL;
- }
+ const MYSQLND_CSTRING database = {db, db_len};
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_INIT_DB, conn, database);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
}
+
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_RETURN(ret);
@@ -1717,20 +1089,18 @@ MYSQLND_METHOD(mysqlnd_conn_data, select_db)(MYSQLND_CONN_DATA * const conn, con
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, ping)(MYSQLND_CONN_DATA * const conn)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, ping);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), ping);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::ping");
DBG_INF_FMT("conn=%llu", conn->thread_id);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
- ret = conn->m->simple_command(conn, COM_PING, NULL, 0, PROT_OK_PACKET, TRUE, TRUE);
- /*
- The server sends 0 but libmysql doesn't read it and has established
- a protocol of giving back -1. Thus we have to follow it :(
- */
- SET_ERROR_AFF_ROWS(conn);
-
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_PING, conn);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_INF_FMT("ret=%u", ret);
@@ -1743,33 +1113,18 @@ MYSQLND_METHOD(mysqlnd_conn_data, ping)(MYSQLND_CONN_DATA * const conn)
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, statistic)(MYSQLND_CONN_DATA * conn, zend_string **message)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, get_server_statistics);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), get_server_statistics);
enum_func_status ret = FAIL;
- MYSQLND_PACKET_STATS * stats_header;
DBG_ENTER("mysqlnd_conn_data::statistic");
DBG_INF_FMT("conn=%llu", conn->thread_id);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
- do {
- ret = conn->m->simple_command(conn, COM_STATISTICS, NULL, 0, PROT_LAST, FALSE, TRUE);
- if (FAIL == ret) {
- break;
- }
- stats_header = conn->protocol->m.get_stats_packet(conn->protocol, FALSE);
- if (!stats_header) {
- SET_OOM_ERROR(*conn->error_info);
- break;
- }
-
- if (PASS == (ret = PACKET_READ(stats_header, conn))) {
- /* will be freed by Zend, thus don't use the mnd_ allocator */
- *message = zend_string_init(stats_header->message, stats_header->message_len, 0);
- DBG_INF(ZSTR_VAL(*message));
- }
- PACKET_FREE(stats_header);
- } while (0);
-
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_STATISTICS, conn, message);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_RETURN(ret);
@@ -1781,29 +1136,21 @@ MYSQLND_METHOD(mysqlnd_conn_data, statistic)(MYSQLND_CONN_DATA * conn, zend_stri
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, kill)(MYSQLND_CONN_DATA * conn, unsigned int pid)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, kill_connection);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), kill_connection);
enum_func_status ret = FAIL;
- zend_uchar buff[4];
DBG_ENTER("mysqlnd_conn_data::kill");
DBG_INF_FMT("conn=%llu pid=%u", conn->thread_id, pid);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
- int4store(buff, pid);
-
- /* If we kill ourselves don't expect OK packet, PROT_LAST will skip it */
- if (pid != conn->thread_id) {
- ret = conn->m->simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_OK_PACKET, FALSE, TRUE);
- /*
- The server sends 0 but libmysql doesn't read it and has established
- a protocol of giving back -1. Thus we have to follow it :(
- */
- SET_ERROR_AFF_ROWS(conn);
- } else if (PASS == (ret = conn->m->simple_command(conn, COM_PROCESS_KILL, buff, 4, PROT_LAST, FALSE, TRUE))) {
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
- conn->m->send_close(conn);
+ unsigned int process_id = pid;
+ /* 'unsigned char' is promoted to 'int' when passed through '...' */
+ unsigned int read_response = (pid != conn->thread_id);
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_PROCESS_KILL, conn, process_id, read_response);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
}
-
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_RETURN(ret);
@@ -1815,7 +1162,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, kill)(MYSQLND_CONN_DATA * conn, unsigned int p
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, set_charset)(MYSQLND_CONN_DATA * const conn, const char * const csname)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_charset);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), set_charset);
enum_func_status ret = FAIL;
const MYSQLND_CHARSET * const charset = mysqlnd_find_charset_name(csname);
@@ -1823,7 +1170,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_charset)(MYSQLND_CONN_DATA * const conn, c
DBG_INF_FMT("conn=%llu cs=%s", conn->thread_id, csname);
if (!charset) {
- SET_CLIENT_ERROR(*conn->error_info, CR_CANT_FIND_CHARSET, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(conn->error_info, CR_CANT_FIND_CHARSET, UNKNOWN_SQLSTATE,
"Invalid characterset or character set not supported");
DBG_RETURN(ret);
}
@@ -1854,17 +1201,18 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_charset)(MYSQLND_CONN_DATA * const conn, c
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, refresh)(MYSQLND_CONN_DATA * const conn, uint8_t options)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, refresh_server);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), refresh_server);
enum_func_status ret = FAIL;
- zend_uchar bits[1];
DBG_ENTER("mysqlnd_conn_data::refresh");
DBG_INF_FMT("conn=%llu options=%lu", conn->thread_id, options);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
- int1store(bits, options);
-
- ret = conn->m->simple_command(conn, COM_REFRESH, bits, 1, PROT_OK_PACKET, FALSE, TRUE);
-
+ unsigned int options_param = (unsigned int) options;
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_REFRESH, conn, options_param);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_RETURN(ret);
@@ -1876,17 +1224,18 @@ MYSQLND_METHOD(mysqlnd_conn_data, refresh)(MYSQLND_CONN_DATA * const conn, uint8
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, shutdown)(MYSQLND_CONN_DATA * const conn, uint8_t level)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, shutdown_server);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), shutdown_server);
enum_func_status ret = FAIL;
- zend_uchar bits[1];
DBG_ENTER("mysqlnd_conn_data::shutdown");
DBG_INF_FMT("conn=%llu level=%lu", conn->thread_id, level);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
- int1store(bits, level);
-
- ret = conn->m->simple_command(conn, COM_SHUTDOWN, bits, 1, PROT_OK_PACKET, FALSE, TRUE);
-
+ unsigned int level_param = (unsigned int) level;
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_SHUTDOWN, conn, level_param);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
conn->m->local_tx_end(conn, this_func, ret);
}
DBG_RETURN(ret);
@@ -1899,29 +1248,32 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, send_close)(MYSQLND_CONN_DATA * const conn)
{
enum_func_status ret = PASS;
- MYSQLND_NET * net = conn->net;
- php_stream * net_stream = net->data->m.get_stream(net);
- enum mysqlnd_connection_state state;
+ MYSQLND_VIO * vio = conn->vio;
+ php_stream * net_stream = vio->data->m.get_stream(vio);
+ enum mysqlnd_connection_state state = GET_CONNECTION_STATE(&conn->state);
DBG_ENTER("mysqlnd_send_close");
- DBG_INF_FMT("conn=%llu net->data->stream->abstract=%p", conn->thread_id, net_stream? net_stream->abstract:NULL);
+ DBG_INF_FMT("conn=%llu vio->data->stream->abstract=%p", conn->thread_id, net_stream? net_stream->abstract:NULL);
+ DBG_INF_FMT("state=%u", state);
- if (CONN_GET_STATE(conn) >= CONN_READY) {
- MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_CONNECTIONS);
+ if (state >= CONN_READY) {
+ MYSQLND_DEC_GLOBAL_STATISTIC(STAT_OPENED_CONNECTIONS);
if (conn->persistent) {
- MYSQLND_DEC_CONN_STATISTIC(conn->stats, STAT_OPENED_PERSISTENT_CONNECTIONS);
+ MYSQLND_DEC_GLOBAL_STATISTIC(STAT_OPENED_PERSISTENT_CONNECTIONS);
}
}
- state = CONN_GET_STATE(conn);
- DBG_INF_FMT("state=%u", state);
switch (state) {
case CONN_READY:
DBG_INF("Connection clean, sending COM_QUIT");
if (net_stream) {
- ret = conn->m->simple_command(conn, COM_QUIT, NULL, 0, PROT_LAST, TRUE, TRUE);
- net->data->m.close_stream(net, conn->stats, conn->error_info);
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_QUIT, conn);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
+ vio->data->m.close_stream(vio, conn->stats, conn->error_info);
}
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
break;
case CONN_SENDING_LOAD_DATA:
/*
@@ -1932,7 +1284,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_close)(MYSQLND_CONN_DATA * const conn)
case CONN_QUERY_SENT:
case CONN_FETCHING_DATA:
MYSQLND_INC_GLOBAL_STATISTIC(STAT_CLOSE_IN_MIDDLE);
- DBG_ERR_FMT("Brutally closing connection [%p][%s]", conn, conn->scheme);
+ DBG_ERR_FMT("Brutally closing connection [%p][%s]", conn, conn->scheme.s);
/*
Do nothing, the connection will be brutally closed
and the server will catch it and free close from its side.
@@ -1945,11 +1297,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, send_close)(MYSQLND_CONN_DATA * const conn)
Fall-through
*/
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
/* Fall-through */
case CONN_QUIT_SENT:
/* The user has killed its own connection */
- net->data->m.close_stream(net, conn->stats, conn->error_info);
+ vio->data->m.close_stream(vio, conn->stats, conn->error_info);
break;
}
@@ -1991,28 +1343,6 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, free_reference)(MYSQLND_CONN_DATA * co
/* }}} */
-/* {{{ mysqlnd_conn_data::get_state */
-static enum mysqlnd_connection_state
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_state)(const MYSQLND_CONN_DATA * const conn)
-{
- DBG_ENTER("mysqlnd_conn_data::get_state");
- DBG_RETURN(conn->state);
-}
-/* }}} */
-
-
-/* {{{ mysqlnd_conn_data::set_state */
-static void
-MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, set_state)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_connection_state new_state)
-{
- DBG_ENTER("mysqlnd_conn_data::set_state");
- DBG_INF_FMT("New state=%u", new_state);
- conn->state = new_state;
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
/* {{{ mysqlnd_conn_data::field_count */
static unsigned int
MYSQLND_METHOD(mysqlnd_conn_data, field_count)(const MYSQLND_CONN_DATA * const conn)
@@ -2026,7 +1356,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, field_count)(const MYSQLND_CONN_DATA * const c
static unsigned int
MYSQLND_METHOD(mysqlnd_conn_data, server_status)(const MYSQLND_CONN_DATA * const conn)
{
- return conn->upsert_status->server_status;
+ return UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status);
}
/* }}} */
@@ -2035,7 +1365,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, server_status)(const MYSQLND_CONN_DATA * const
static uint64_t
MYSQLND_METHOD(mysqlnd_conn_data, insert_id)(const MYSQLND_CONN_DATA * const conn)
{
- return conn->upsert_status->last_insert_id;
+ return UPSERT_STATUS_GET_LAST_INSERT_ID(conn->upsert_status);
}
/* }}} */
@@ -2044,7 +1374,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, insert_id)(const MYSQLND_CONN_DATA * const con
static uint64_t
MYSQLND_METHOD(mysqlnd_conn_data, affected_rows)(const MYSQLND_CONN_DATA * const conn)
{
- return conn->upsert_status->affected_rows;
+ return UPSERT_STATUS_GET_AFFECTED_ROWS(conn->upsert_status);
}
/* }}} */
@@ -2053,7 +1383,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, affected_rows)(const MYSQLND_CONN_DATA * const
static unsigned int
MYSQLND_METHOD(mysqlnd_conn_data, warning_count)(const MYSQLND_CONN_DATA * const conn)
{
- return conn->upsert_status->warning_count;
+ return UPSERT_STATUS_GET_WARNINGS(conn->upsert_status);
}
/* }}} */
@@ -2062,10 +1392,11 @@ MYSQLND_METHOD(mysqlnd_conn_data, warning_count)(const MYSQLND_CONN_DATA * const
static const char *
MYSQLND_METHOD(mysqlnd_conn_data, info)(const MYSQLND_CONN_DATA * const conn)
{
- return conn->last_message;
+ return conn->last_message.s;
}
/* }}} */
+
/* {{{ mysqlnd_get_client_info */
PHPAPI const char * mysqlnd_get_client_info()
{
@@ -2155,7 +1486,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, more_results)(const MYSQLND_CONN_DATA * const
{
DBG_ENTER("mysqlnd_conn_data::more_results");
/* (conn->state == CONN_NEXT_RESULT_PENDING) too */
- DBG_RETURN(conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS? TRUE:FALSE);
+ DBG_RETURN(UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_MORE_RESULTS_EXISTS? TRUE:FALSE);
}
/* }}} */
@@ -2164,7 +1495,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, more_results)(const MYSQLND_CONN_DATA * const
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, next_result)(MYSQLND_CONN_DATA * const conn)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, next_result);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), next_result);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::next_result");
@@ -2172,12 +1503,12 @@ MYSQLND_METHOD(mysqlnd_conn_data, next_result)(MYSQLND_CONN_DATA * const conn)
if (PASS == conn->m->local_tx_start(conn, this_func)) {
do {
- if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING) {
+ if (GET_CONNECTION_STATE(&conn->state) != CONN_NEXT_RESULT_PENDING) {
break;
}
- SET_EMPTY_ERROR(*conn->error_info);
- SET_ERROR_AFF_ROWS(conn);
+ SET_EMPTY_ERROR(conn->error_info);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
/*
We are sure that there is a result set, since conn->state is set accordingly
in mysqlnd_store_result() or mysqlnd_fetch_row_unbuffered()
@@ -2190,15 +1521,15 @@ MYSQLND_METHOD(mysqlnd_conn_data, next_result)(MYSQLND_CONN_DATA * const conn)
if (!conn->error_info->error_no) {
DBG_ERR_FMT("Serious error. %s::%u", __FILE__, __LINE__);
php_error_docref(NULL, E_WARNING, "Serious error. PID=%d", getpid());
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CONNECTION_STATE(&conn->state, CONN_QUIT_SENT);
conn->m->send_close(conn);
} else {
DBG_INF_FMT("Error from the server : (%u) %s", conn->error_info->error_no, conn->error_info->error);
}
break;
}
- if (conn->last_query_type == QUERY_UPSERT && conn->upsert_status->affected_rows) {
- MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, conn->upsert_status->affected_rows);
+ if (conn->last_query_type == QUERY_UPSERT && UPSERT_STATUS_GET_AFFECTED_ROWS(conn->upsert_status)) {
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_NORMAL, UPSERT_STATUS_GET_AFFECTED_ROWS(conn->upsert_status));
}
} while (0);
conn->m->local_tx_end(conn, this_func, ret);
@@ -2210,7 +1541,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, next_result)(MYSQLND_CONN_DATA * const conn)
/* {{{ mysqlnd_field_type_name */
-PHPAPI const char *mysqlnd_field_type_name(enum mysqlnd_field_types field_type)
+PHPAPI const char * mysqlnd_field_type_name(const enum mysqlnd_field_types field_type)
{
switch(field_type) {
case FIELD_TYPE_JSON:
@@ -2265,14 +1596,14 @@ PHPAPI const char *mysqlnd_field_type_name(enum mysqlnd_field_types field_type)
/* {{{ mysqlnd_conn_data::change_user */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn,
- const char * user,
- const char * passwd,
- const char * db,
- zend_bool silent,
- size_t passwd_len
- )
-{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, change_user);
+ const char * user,
+ const char * passwd,
+ const char * db,
+ zend_bool silent,
+ size_t passwd_len
+ )
+{
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), change_user);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::change_user");
@@ -2283,14 +1614,15 @@ MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn,
goto end;
}
- SET_EMPTY_ERROR(*conn->error_info);
- SET_ERROR_AFF_ROWS(conn);
+ SET_EMPTY_ERROR(conn->error_info);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
if (!user) {
user = "";
}
if (!passwd) {
passwd = "";
+ passwd_len = 0;
}
if (!db) {
db = "";
@@ -2298,7 +1630,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, change_user)(MYSQLND_CONN_DATA * const conn,
/* XXX: passwords that have \0 inside work during auth, but in this case won't work with change user */
ret = mysqlnd_run_authentication(conn, user, passwd, passwd_len, db, strlen(db),
- conn->auth_plugin_data, conn->auth_plugin_data_len, conn->options->auth_protocol,
+ conn->authentication_plugin_data, conn->options->auth_protocol,
0 /*charset not used*/, conn->options, conn->server_capabilities, silent, TRUE/*is_change*/);
/*
@@ -2316,11 +1648,11 @@ end:
/* {{{ mysqlnd_conn_data::set_client_option */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const conn,
- enum mysqlnd_option option,
+ enum_mysqlnd_client_option option,
const char * const value
)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_client_option);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), set_client_option);
enum_func_status ret = PASS;
DBG_ENTER("mysqlnd_conn_data::set_client_option");
DBG_INF_FMT("conn=%llu option=%u", conn->thread_id, option);
@@ -2329,7 +1661,6 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c
goto end;
}
switch (option) {
- case MYSQL_OPT_COMPRESS:
#ifdef WHEN_SUPPORTED_BY_MYSQLI
case MYSQL_OPT_READ_TIMEOUT:
case MYSQL_OPT_WRITE_TIMEOUT:
@@ -2341,10 +1672,13 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c
case MYSQLND_OPT_SSL_CIPHER:
case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
case MYSQL_OPT_CONNECT_TIMEOUT:
- case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
+ ret = conn->vio->data->m.set_client_option(conn->vio, option, value);
+ break;
+ case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
+ case MYSQL_OPT_COMPRESS:
case MYSQL_SERVER_PUBLIC_KEY:
- ret = conn->net->data->m.set_client_option(conn->net, option, value);
+ ret = conn->protocol_frame_codec->data->m.set_client_option(conn->protocol_frame_codec, option, value);
break;
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
case MYSQLND_OPT_INT_AND_FLOAT_NATIVE:
@@ -2389,7 +1723,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c
{
char * new_charset_name;
if (!mysqlnd_find_charset_name(value)) {
- SET_CLIENT_ERROR(*conn->error_info, CR_CANT_FIND_CHARSET, UNKNOWN_SQLSTATE, "Unknown character set");
+ SET_CLIENT_ERROR(conn->error_info, CR_CANT_FIND_CHARSET, UNKNOWN_SQLSTATE, "Unknown character set");
ret = FAIL;
break;
}
@@ -2475,7 +1809,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option)(MYSQLND_CONN_DATA * const c
conn->m->local_tx_end(conn, this_func, ret);
DBG_RETURN(ret);
oom:
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
conn->m->local_tx_end(conn, this_func, FAIL);
end:
DBG_RETURN(FAIL);
@@ -2486,12 +1820,12 @@ end:
/* {{{ mysqlnd_conn_data::set_client_option_2d */
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)(MYSQLND_CONN_DATA * const conn,
- enum mysqlnd_option option,
+ const enum_mysqlnd_client_option option,
const char * const key,
const char * const value
)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_client_option_2d);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), set_client_option_2d);
enum_func_status ret = PASS;
DBG_ENTER("mysqlnd_conn_data::set_client_option_2d");
DBG_INF_FMT("conn=%llu option=%u", conn->thread_id, option);
@@ -2522,7 +1856,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)(MYSQLND_CONN_DATA * cons
conn->m->local_tx_end(conn, this_func, ret);
DBG_RETURN(ret);
oom:
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
conn->m->local_tx_end(conn, this_func, FAIL);
end:
DBG_RETURN(FAIL);
@@ -2534,7 +1868,7 @@ end:
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_conn_data, use_result)(MYSQLND_CONN_DATA * const conn, const unsigned int flags)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, use_result);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), use_result);
MYSQLND_RES * result = NULL;
DBG_ENTER("mysqlnd_conn_data::use_result");
@@ -2547,8 +1881,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, use_result)(MYSQLND_CONN_DATA * const conn, co
}
/* Nothing to store for UPSERT/LOAD DATA */
- if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ if (conn->last_query_type != QUERY_SELECT || GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA) {
+ SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR("Command out of sync");
break;
}
@@ -2576,7 +1910,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, use_result)(MYSQLND_CONN_DATA * const conn, co
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn, const unsigned int flags)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, store_result);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), store_result);
MYSQLND_RES * result = NULL;
DBG_ENTER("mysqlnd_conn_data::store_result");
@@ -2590,8 +1924,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn,
}
/* Nothing to store for UPSERT/LOAD DATA*/
- if (conn->last_query_type != QUERY_SELECT || CONN_GET_STATE(conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ if (conn->last_query_type != QUERY_SELECT || GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA) {
+ SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR("Command out of sync");
break;
}
@@ -2611,7 +1945,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn,
}
}
if (!(f & (MYSQLND_STORE_NO_COPY | MYSQLND_STORE_COPY))) {
- SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Unknown fetch mode");
+ SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Unknown fetch mode");
DBG_ERR("Unknown fetch mode");
break;
}
@@ -2632,7 +1966,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, store_result)(MYSQLND_CONN_DATA * const conn,
/* {{{ mysqlnd_conn_data::get_connection_stats */
static void
MYSQLND_METHOD(mysqlnd_conn_data, get_connection_stats)(const MYSQLND_CONN_DATA * const conn,
- zval * return_value ZEND_FILE_LINE_DC)
+ zval * return_value ZEND_FILE_LINE_DC)
{
DBG_ENTER("mysqlnd_conn_data::get_connection_stats");
mysqlnd_fill_stats_hash(conn->stats, mysqlnd_stats_values_names, return_value ZEND_FILE_LINE_CC);
@@ -2645,7 +1979,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_connection_stats)(const MYSQLND_CONN_DATA
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, set_autocommit)(MYSQLND_CONN_DATA * conn, unsigned int mode)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, set_autocommit);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), set_autocommit);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::set_autocommit");
@@ -2756,7 +2090,7 @@ mysqlnd_escape_string_for_tx_name_in_comment(const char * const name)
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, tx_commit_or_rollback)(MYSQLND_CONN_DATA * conn, const zend_bool commit, const unsigned int flags, const char * const name)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, tx_commit_or_rollback);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), tx_commit_or_rollback);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::tx_commit_or_rollback");
@@ -2780,7 +2114,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_commit_or_rollback)(MYSQLND_CONN_DATA * con
name_esc = NULL;
}
if (!query) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
break;
}
@@ -2800,7 +2134,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_commit_or_rollback)(MYSQLND_CONN_DATA * con
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, tx_begin)(MYSQLND_CONN_DATA * conn, const unsigned int mode, const char * const name)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, tx_begin);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), tx_begin);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::tx_begin");
@@ -2843,7 +2177,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_begin)(MYSQLND_CONN_DATA * conn, const unsi
name_esc = NULL;
}
if (!query) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
break;
}
ret = conn->m->query(conn, query, query_len);
@@ -2862,7 +2196,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_begin)(MYSQLND_CONN_DATA * conn, const unsi
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, tx_savepoint)(MYSQLND_CONN_DATA * conn, const char * const name)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, tx_savepoint);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), tx_savepoint);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::tx_savepoint");
@@ -2871,12 +2205,12 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_savepoint)(MYSQLND_CONN_DATA * conn, const
char * query;
unsigned int query_len;
if (!name) {
- SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Savepoint name not provided");
+ SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Savepoint name not provided");
break;
}
query_len = mnd_sprintf(&query, 0, "SAVEPOINT `%s`", name);
if (!query) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
break;
}
ret = conn->m->query(conn, query, query_len);
@@ -2894,7 +2228,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_savepoint)(MYSQLND_CONN_DATA * conn, const
static enum_func_status
MYSQLND_METHOD(mysqlnd_conn_data, tx_savepoint_release)(MYSQLND_CONN_DATA * conn, const char * const name)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_data_methods, tx_savepoint_release);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data), tx_savepoint_release);
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_conn_data::tx_savepoint_release");
@@ -2903,12 +2237,12 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_savepoint_release)(MYSQLND_CONN_DATA * conn
char * query;
unsigned int query_len;
if (!name) {
- SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Savepoint name not provided");
+ SET_CLIENT_ERROR(conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Savepoint name not provided");
break;
}
query_len = mnd_sprintf(&query, 0, "RELEASE SAVEPOINT `%s`", name);
if (!query) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
break;
}
ret = conn->m->query(conn, query, query_len);
@@ -2923,8 +2257,8 @@ MYSQLND_METHOD(mysqlnd_conn_data, tx_savepoint_release)(MYSQLND_CONN_DATA * conn
/* {{{ mysqlnd_conn_data::negotiate_client_api_capabilities */
-static unsigned int
-MYSQLND_METHOD(mysqlnd_conn_data, negotiate_client_api_capabilities)(MYSQLND_CONN_DATA * const conn, const unsigned int flags)
+static size_t
+MYSQLND_METHOD(mysqlnd_conn_data, negotiate_client_api_capabilities)(MYSQLND_CONN_DATA * const conn, const size_t flags)
{
unsigned int ret = 0;
DBG_ENTER("mysqlnd_conn_data::negotiate_client_api_capabilities");
@@ -2939,7 +2273,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, negotiate_client_api_capabilities)(MYSQLND_CON
/* {{{ mysqlnd_conn_data::get_client_api_capabilities */
-static unsigned int
+static size_t
MYSQLND_METHOD(mysqlnd_conn_data, get_client_api_capabilities)(const MYSQLND_CONN_DATA * const conn)
{
DBG_ENTER("mysqlnd_conn_data::get_client_api_capabilities");
@@ -2950,18 +2284,17 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_client_api_capabilities)(const MYSQLND_CON
/* {{{ mysqlnd_conn_data::local_tx_start */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn_data, local_tx_start)(MYSQLND_CONN_DATA * conn, size_t this_func)
+MYSQLND_METHOD(mysqlnd_conn_data, local_tx_start)(MYSQLND_CONN_DATA * conn, const size_t this_func)
{
- enum_func_status ret = PASS;
DBG_ENTER("mysqlnd_conn_data::local_tx_start");
- DBG_RETURN(ret);
+ DBG_RETURN(PASS);
}
/* }}} */
/* {{{ mysqlnd_conn_data::local_tx_end */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn_data, local_tx_end)(MYSQLND_CONN_DATA * conn, size_t this_func, enum_func_status status)
+MYSQLND_METHOD(mysqlnd_conn_data, local_tx_end)(MYSQLND_CONN_DATA * conn, const size_t this_func, const enum_func_status status)
{
DBG_ENTER("mysqlnd_conn_data::local_tx_end");
DBG_RETURN(status);
@@ -2969,27 +2302,19 @@ MYSQLND_METHOD(mysqlnd_conn_data, local_tx_end)(MYSQLND_CONN_DATA * conn, size_t
/* }}} */
-/* {{{ mysqlnd_conn_data::init */
-static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn_data, init)(MYSQLND_CONN_DATA * conn)
+/* {{{ _mysqlnd_stmt_init */
+MYSQLND_STMT *
+MYSQLND_METHOD(mysqlnd_conn_data, stmt_init)(MYSQLND_CONN_DATA * const conn)
{
- DBG_ENTER("mysqlnd_conn_data::init");
- mysqlnd_stats_init(&conn->stats, STAT_LAST, conn->persistent);
- SET_ERROR_AFF_ROWS(conn);
-
- conn->net = mysqlnd_net_init(conn->persistent, conn->stats, conn->error_info);
- conn->protocol = mysqlnd_protocol_init(conn->persistent);
-
- DBG_RETURN(conn->stats && conn->net && conn->protocol? PASS:FAIL);
+ MYSQLND_STMT * ret;
+ DBG_ENTER("mysqlnd_conn_data::stmt_init");
+ ret = conn->object_factory.get_prepared_statement(conn, conn->persistent);
+ DBG_RETURN(ret);
}
/* }}} */
-MYSQLND_STMT * _mysqlnd_stmt_init(MYSQLND_CONN_DATA * const conn);
-
-
MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
- MYSQLND_METHOD(mysqlnd_conn_data, init),
MYSQLND_METHOD(mysqlnd_conn_data, connect),
MYSQLND_METHOD(mysqlnd_conn_data, escape_string),
@@ -3002,7 +2327,7 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
MYSQLND_METHOD(mysqlnd_conn_data, next_result),
MYSQLND_METHOD(mysqlnd_conn_data, more_results),
- _mysqlnd_stmt_init,
+ MYSQLND_METHOD(mysqlnd_conn_data, stmt_init),
MYSQLND_METHOD(mysqlnd_conn_data, shutdown),
MYSQLND_METHOD(mysqlnd_conn_data, refresh),
@@ -3013,7 +2338,7 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
MYSQLND_METHOD(mysqlnd_conn_data, dump_debug_info),
MYSQLND_METHOD(mysqlnd_conn_data, change_user),
- MYSQLND_METHOD(mysqlnd_conn_data, errno),
+ MYSQLND_METHOD(mysqlnd_conn_data, err_no),
MYSQLND_METHOD(mysqlnd_conn_data, error),
MYSQLND_METHOD(mysqlnd_conn_data, sqlstate),
MYSQLND_METHOD(mysqlnd_conn_data, thread_id),
@@ -3027,7 +2352,6 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
MYSQLND_METHOD(mysqlnd_conn_data, get_proto_info),
MYSQLND_METHOD(mysqlnd_conn_data, info),
MYSQLND_METHOD(mysqlnd_conn_data, charset_name),
- MYSQLND_METHOD(mysqlnd_conn_data, list_fields),
MYSQLND_METHOD(mysqlnd_conn_data, list_method),
MYSQLND_METHOD(mysqlnd_conn_data, insert_id),
@@ -3048,11 +2372,7 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_reference),
MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, free_reference),
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, get_state),
- MYSQLND_METHOD_PRIVATE(mysqlnd_conn_data, set_state),
- MYSQLND_METHOD(mysqlnd_conn_data, simple_command),
- MYSQLND_METHOD(mysqlnd_conn_data, simple_command_handle_response),
MYSQLND_METHOD(mysqlnd_conn_data, restart_psession),
MYSQLND_METHOD(mysqlnd_conn_data, end_psession),
MYSQLND_METHOD(mysqlnd_conn_data, send_close),
@@ -3073,13 +2393,14 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn_data)
MYSQLND_METHOD(mysqlnd_conn_data, execute_init_commands),
MYSQLND_METHOD(mysqlnd_conn_data, get_updated_connect_flags),
MYSQLND_METHOD(mysqlnd_conn_data, connect_handshake),
- MYSQLND_METHOD(mysqlnd_conn_data, simple_command_send_request),
MYSQLND_METHOD(mysqlnd_conn_data, fetch_auth_plugin_by_name),
MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d),
MYSQLND_METHOD(mysqlnd_conn_data, negotiate_client_api_capabilities),
- MYSQLND_METHOD(mysqlnd_conn_data, get_client_api_capabilities)
+ MYSQLND_METHOD(mysqlnd_conn_data, get_client_api_capabilities),
+
+ MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)
MYSQLND_CLASS_METHODS_END;
@@ -3089,7 +2410,7 @@ MYSQLND_METHOD(mysqlnd_conn, clone_object)(MYSQLND * const conn)
{
MYSQLND * ret;
DBG_ENTER("mysqlnd_conn::get_reference");
- ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).clone_connection_object(conn);
+ ret = conn->data->object_factory.clone_connection_object(conn);
DBG_RETURN(ret);
}
/* }}} */
@@ -3113,9 +2434,9 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_conn, dtor)(MYSQLND * conn)
/* {{{ mysqlnd_conn_data::close */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_conn, close)(MYSQLND * conn_handle, enum_connection_close_type close_type)
+MYSQLND_METHOD(mysqlnd_conn, close)(MYSQLND * conn_handle, const enum_connection_close_type close_type)
{
- size_t this_func = STRUCT_OFFSET(struct st_mysqlnd_conn_methods, close);
+ const size_t this_func = STRUCT_OFFSET(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn), close);
MYSQLND_CONN_DATA * conn = conn_handle->data;
enum_func_status ret = FAIL;
@@ -3123,7 +2444,7 @@ MYSQLND_METHOD(mysqlnd_conn, close)(MYSQLND * conn_handle, enum_connection_close
DBG_INF_FMT("conn=%llu", conn->thread_id);
if (PASS == conn->m->local_tx_start(conn, this_func)) {
- if (CONN_GET_STATE(conn) >= CONN_READY) {
+ if (GET_CONNECTION_STATE(&conn->state) >= CONN_READY) {
static enum_mysqlnd_collected_stats close_type_to_stat_map[MYSQLND_CLOSE_LAST] = {
STAT_CLOSE_EXPLICIT,
STAT_CLOSE_IMPLICIT,
@@ -3138,7 +2459,7 @@ MYSQLND_METHOD(mysqlnd_conn, close)(MYSQLND * conn_handle, enum_connection_close
*/
ret = conn->m->send_close(conn);
- /* do it after free_reference/dtor and we might crash */
+ /* If we do it after free_reference/dtor then we might crash */
conn->m->local_tx_end(conn, this_func, ret);
conn_handle->m->dtor(conn_handle);
@@ -3156,20 +2477,267 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_conn)
MYSQLND_CLASS_METHODS_END;
-/* {{{ mysqlnd_init */
+#include "php_network.h"
+
+/* {{{ mysqlnd_stream_array_to_fd_set */
+MYSQLND **
+mysqlnd_stream_array_check_for_readiness(MYSQLND ** conn_array)
+{
+ unsigned int cnt = 0;
+ MYSQLND **p = conn_array, **p_p;
+ MYSQLND **ret = NULL;
+
+ while (*p) {
+ const enum mysqlnd_connection_state conn_state = GET_CONNECTION_STATE(&((*p)->data->state));
+ if (conn_state <= CONN_READY || conn_state == CONN_QUIT_SENT) {
+ cnt++;
+ }
+ p++;
+ }
+ if (cnt) {
+ MYSQLND **ret_p = ret = ecalloc(cnt + 1, sizeof(MYSQLND *));
+ p_p = p = conn_array;
+ while (*p) {
+ const enum mysqlnd_connection_state conn_state = GET_CONNECTION_STATE(&((*p)->data->state));
+ if (conn_state <= CONN_READY || conn_state == CONN_QUIT_SENT) {
+ *ret_p = *p;
+ *p = NULL;
+ ret_p++;
+ } else {
+ *p_p = *p;
+ p_p++;
+ }
+ p++;
+ }
+ *ret_p = NULL;
+ }
+ return ret;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_stream_array_to_fd_set */
+static unsigned int
+mysqlnd_stream_array_to_fd_set(MYSQLND ** conn_array, fd_set * fds, php_socket_t * max_fd)
+{
+ php_socket_t this_fd;
+ php_stream *stream = NULL;
+ unsigned int cnt = 0;
+ MYSQLND **p = conn_array;
+ DBG_ENTER("mysqlnd_stream_array_to_fd_set");
+
+ while (*p) {
+ /* get the fd.
+ * NB: Most other code will NOT use the PHP_STREAM_CAST_INTERNAL flag
+ * when casting. It is only used here so that the buffered data warning
+ * is not displayed.
+ * */
+ stream = (*p)->data->vio->data->m.get_stream((*p)->data->vio);
+ DBG_INF_FMT("conn=%llu stream=%p", (*p)->data->thread_id, stream);
+ if (stream != NULL &&
+ SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL, (void*)&this_fd, 1) &&
+ ZEND_VALID_SOCKET(this_fd))
+ {
+
+ PHP_SAFE_FD_SET(this_fd, fds);
+
+ if (this_fd > *max_fd) {
+ *max_fd = this_fd;
+ }
+ ++cnt;
+ }
+ ++p;
+ }
+ DBG_RETURN(cnt ? 1 : 0);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_stream_array_from_fd_set */
+static unsigned int
+mysqlnd_stream_array_from_fd_set(MYSQLND ** conn_array, fd_set * fds)
+{
+ php_socket_t this_fd;
+ php_stream *stream = NULL;
+ unsigned int ret = 0;
+ zend_bool disproportion = FALSE;
+ MYSQLND **fwd = conn_array, **bckwd = conn_array;
+ DBG_ENTER("mysqlnd_stream_array_from_fd_set");
+
+ while (*fwd) {
+ stream = (*fwd)->data->vio->data->m.get_stream((*fwd)->data->vio);
+ DBG_INF_FMT("conn=%llu stream=%p", (*fwd)->data->thread_id, stream);
+ if (stream != NULL && SUCCESS == php_stream_cast(stream, PHP_STREAM_AS_FD_FOR_SELECT | PHP_STREAM_CAST_INTERNAL,
+ (void*)&this_fd, 1) && ZEND_VALID_SOCKET(this_fd)) {
+ if (PHP_SAFE_FD_ISSET(this_fd, fds)) {
+ if (disproportion) {
+ *bckwd = *fwd;
+ }
+ ++bckwd;
+ ++fwd;
+ ++ret;
+ continue;
+ }
+ }
+ disproportion = TRUE;
+ ++fwd;
+ }
+ *bckwd = NULL;/* NULL-terminate the list */
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+#ifndef PHP_WIN32
+#define php_select(m, r, w, e, t) select(m, r, w, e, t)
+#else
+#include "win32/select.h"
+#endif
+
+
+/* {{{ mysqlnd_poll */
+PHPAPI enum_func_status
+mysqlnd_poll(MYSQLND **r_array, MYSQLND **e_array, MYSQLND ***dont_poll, long sec, long usec, int * desc_num)
+{
+ struct timeval tv;
+ struct timeval *tv_p = NULL;
+ fd_set rfds, wfds, efds;
+ php_socket_t max_fd = 0;
+ int retval, sets = 0;
+ int set_count, max_set_count = 0;
+
+ DBG_ENTER("_mysqlnd_poll");
+ if (sec < 0 || usec < 0) {
+ php_error_docref(NULL, E_WARNING, "Negative values passed for sec and/or usec");
+ DBG_RETURN(FAIL);
+ }
+
+ FD_ZERO(&rfds);
+ FD_ZERO(&wfds);
+ FD_ZERO(&efds);
+
+ if (r_array != NULL) {
+ *dont_poll = mysqlnd_stream_array_check_for_readiness(r_array);
+ set_count = mysqlnd_stream_array_to_fd_set(r_array, &rfds, &max_fd);
+ if (set_count > max_set_count) {
+ max_set_count = set_count;
+ }
+ sets += set_count;
+ }
+
+ if (e_array != NULL) {
+ set_count = mysqlnd_stream_array_to_fd_set(e_array, &efds, &max_fd);
+ if (set_count > max_set_count) {
+ max_set_count = set_count;
+ }
+ sets += set_count;
+ }
+
+ if (!sets) {
+ php_error_docref(NULL, E_WARNING, *dont_poll ? "All arrays passed are clear":"No stream arrays were passed");
+ DBG_ERR_FMT(*dont_poll ? "All arrays passed are clear":"No stream arrays were passed");
+ DBG_RETURN(FAIL);
+ }
+
+ PHP_SAFE_MAX_FD(max_fd, max_set_count);
+
+ /* Solaris + BSD do not like microsecond values which are >= 1 sec */
+ if (usec > 999999) {
+ tv.tv_sec = sec + (usec / 1000000);
+ tv.tv_usec = usec % 1000000;
+ } else {
+ tv.tv_sec = sec;
+ tv.tv_usec = usec;
+ }
+
+ tv_p = &tv;
+
+ retval = php_select(max_fd + 1, &rfds, &wfds, &efds, tv_p);
+
+ if (retval == -1) {
+ php_error_docref(NULL, E_WARNING, "unable to select [%d]: %s (max_fd=%d)",
+ errno, strerror(errno), max_fd);
+ DBG_RETURN(FAIL);
+ }
+
+ if (r_array != NULL) {
+ mysqlnd_stream_array_from_fd_set(r_array, &rfds);
+ }
+ if (e_array != NULL) {
+ mysqlnd_stream_array_from_fd_set(e_array, &efds);
+ }
+
+ *desc_num = retval;
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_connect */
+PHPAPI MYSQLND * mysqlnd_connection_connect(MYSQLND * conn_handle,
+ const char * const host,
+ const char * const user,
+ const char * const passwd, unsigned int passwd_len,
+ const char * const db, unsigned int db_len,
+ unsigned int port,
+ const char * const sock_or_pipe,
+ unsigned int mysql_flags,
+ unsigned int client_api_flags
+ )
+{
+ enum_func_status ret = FAIL;
+ zend_bool self_alloced = FALSE;
+ MYSQLND_CSTRING hostname = { host, host? strlen(host) : 0 };
+ MYSQLND_CSTRING username = { user, user? strlen(user) : 0 };
+ MYSQLND_CSTRING password = { passwd, passwd_len };
+ MYSQLND_CSTRING database = { db, db_len };
+ MYSQLND_CSTRING socket_or_pipe = { sock_or_pipe, sock_or_pipe? strlen(sock_or_pipe) : 0 };
+
+ DBG_ENTER("mysqlnd_connect");
+ DBG_INF_FMT("host=%s user=%s db=%s port=%u flags=%u", host? host:"", user? user:"", db? db:"", port, mysql_flags);
+
+ if (!conn_handle) {
+ self_alloced = TRUE;
+ if (!(conn_handle = mysqlnd_connection_init(client_api_flags, FALSE, NULL))) {
+ /* OOM */
+ DBG_RETURN(NULL);
+ }
+ }
+
+ ret = conn_handle->m->connect(conn_handle, hostname, username, password, database, port, socket_or_pipe, mysql_flags);
+
+ if (ret == FAIL) {
+ if (self_alloced) {
+ /*
+ We have alloced, thus there are no references to this
+ object - we are free to kill it!
+ */
+ conn_handle->m->dtor(conn_handle);
+ }
+ DBG_RETURN(NULL);
+ }
+ DBG_RETURN(conn_handle);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_connection_init */
PHPAPI MYSQLND *
-mysqlnd_init(unsigned int flags, zend_bool persistent)
+mysqlnd_connection_init(const size_t client_flags, const zend_bool persistent, MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) *object_factory)
{
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) *factory = object_factory? object_factory : &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory);
MYSQLND * ret;
- DBG_ENTER("mysqlnd_init");
- ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_connection(persistent);
+ DBG_ENTER("mysqlnd_connection_init");
+ ret = factory->get_connection(factory, persistent);
if (ret && ret->data) {
- ret->data->m->negotiate_client_api_capabilities(ret->data, flags);
+ ret->data->m->negotiate_client_api_capabilities(ret->data, client_flags);
}
DBG_RETURN(ret);
}
/* }}} */
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_connection.h b/ext/mysqlnd/mysqlnd_connection.h
new file mode 100644
index 0000000000..7036131beb
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_connection.h
@@ -0,0 +1,86 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef MYSQLND_CONNECTION_H
+#define MYSQLND_CONNECTION_H
+
+PHPAPI extern const char * const mysqlnd_out_of_sync;
+PHPAPI extern const char * const mysqlnd_server_gone;
+PHPAPI extern const char * const mysqlnd_out_of_memory;
+
+
+void mysqlnd_upsert_status_init(MYSQLND_UPSERT_STATUS * const upsert_status);
+
+#define UPSERT_STATUS_RESET(status) (status)->m->reset((status))
+
+#define UPSERT_STATUS_GET_SERVER_STATUS(status) (status)->server_status
+#define UPSERT_STATUS_SET_SERVER_STATUS(status, server_st) (status)->server_status = (server_st)
+
+#define UPSERT_STATUS_GET_WARNINGS(status) (status)->warning_count
+#define UPSERT_STATUS_SET_WARNINGS(status, warnings) (status)->warning_count = (warnings)
+
+#define UPSERT_STATUS_GET_AFFECTED_ROWS(status) (status)->affected_rows
+#define UPSERT_STATUS_SET_AFFECTED_ROWS(status, rows) (status)->affected_rows = (rows)
+#define UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(status) (status)->m->set_affected_rows_to_error((status))
+
+#define UPSERT_STATUS_GET_LAST_INSERT_ID(status) (status)->last_insert_id
+#define UPSERT_STATUS_SET_LAST_INSERT_ID(status, id) (status)->last_insert_id = (id)
+
+
+/* Error handling */
+#define SET_NEW_MESSAGE(buf, buf_len, message, len, persistent) \
+ {\
+ if ((buf)) { \
+ mnd_pefree((buf), (persistent)); \
+ } \
+ if ((message)) { \
+ (buf) = mnd_pestrndup((message), (len), (persistent)); \
+ } else { \
+ (buf) = NULL; \
+ } \
+ (buf_len) = (len); \
+ }
+
+#define SET_EMPTY_MESSAGE(buf, buf_len, persistent) \
+ {\
+ if ((buf)) { \
+ mnd_pefree((buf), (persistent)); \
+ (buf) = NULL; \
+ } \
+ (buf_len) = 0; \
+ }
+
+
+enum_func_status mysqlnd_error_info_init(MYSQLND_ERROR_INFO * const info, zend_bool persistent);
+
+#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);
+
+#endif /* MYSQLND_CONNECTION_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_debug.c b/ext/mysqlnd/mysqlnd_debug.c
index 886a6d8ac6..87d8fe35d7 100644
--- a/ext/mysqlnd/mysqlnd_debug.c
+++ b/ext/mysqlnd/mysqlnd_debug.c
@@ -12,14 +12,10 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id$ */
-
#include "php.h"
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
diff --git a/ext/mysqlnd/mysqlnd_debug.h b/ext/mysqlnd/mysqlnd_debug.h
index 1a57143507..7354d35a3c 100644
--- a/ext/mysqlnd/mysqlnd_debug.h
+++ b/ext/mysqlnd/mysqlnd_debug.h
@@ -12,14 +12,10 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id$ */
-
#ifndef MYSQLND_DEBUG_H
#define MYSQLND_DEBUG_H
@@ -70,6 +66,17 @@ void mysqlnd_debug_trace_plugin_register(void);
PHPAPI MYSQLND_DEBUG * mysqlnd_debug_init(const char * skip_functions[]);
+#define MYSQLND_DEBUG_DUMP_TIME 1
+#define MYSQLND_DEBUG_DUMP_TRACE 2
+#define MYSQLND_DEBUG_DUMP_PID 4
+#define MYSQLND_DEBUG_DUMP_LINE 8
+#define MYSQLND_DEBUG_DUMP_FILE 16
+#define MYSQLND_DEBUG_DUMP_LEVEL 32
+#define MYSQLND_DEBUG_APPEND 64
+#define MYSQLND_DEBUG_FLUSH 128
+#define MYSQLND_DEBUG_TRACE_MEMORY_CALLS 256
+#define MYSQLND_DEBUG_PROFILE_CALLS 512
+
#if defined(__GNUC__) || defined(PHP_WIN32)
#ifdef PHP_WIN32
diff --git a/ext/mysqlnd/mysqlnd_driver.c b/ext/mysqlnd/mysqlnd_driver.c
index 628e02659d..fe7d3f1d85 100644
--- a/ext/mysqlnd/mysqlnd_driver.c
+++ b/ext/mysqlnd/mysqlnd_driver.c
@@ -17,15 +17,16 @@
| Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id: mysqlnd.c 317989 2011-10-10 20:49:28Z andrey $ */
#include "php.h"
#include "mysqlnd.h"
+#include "mysqlnd_vio.h"
+#include "mysqlnd_protocol_frame_codec.h"
#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_connection.h"
+#include "mysqlnd_ps.h"
+#include "mysqlnd_plugin.h"
#include "mysqlnd_priv.h"
-#include "mysqlnd_result.h"
#include "mysqlnd_statistics.h"
-#include "mysqlnd_charset.h"
#include "mysqlnd_debug.h"
#include "mysqlnd_reverse_api.h"
#include "mysqlnd_ext_plugin.h"
@@ -93,25 +94,9 @@ PHPAPI void mysqlnd_library_init(void)
/* }}} */
-
-/* {{{ mysqlnd_error_list_pdtor */
-static void
-mysqlnd_error_list_pdtor(void * pDest)
-{
- MYSQLND_ERROR_LIST_ELEMENT * element = (MYSQLND_ERROR_LIST_ELEMENT *) pDest;
-
- DBG_ENTER("mysqlnd_error_list_pdtor");
- if (element->error) {
- mnd_pefree(element->error, TRUE);
- }
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
/* {{{ mysqlnd_object_factory::get_connection */
static MYSQLND *
-MYSQLND_METHOD(mysqlnd_object_factory, get_connection)(zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_object_factory, get_connection)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) *factory, const zend_bool persistent)
{
size_t alloc_size_ret = sizeof(MYSQLND) + mysqlnd_plugin_count() * sizeof(void *);
size_t alloc_size_ret_data = sizeof(MYSQLND_CONN_DATA) + mysqlnd_plugin_count() * sizeof(void *);
@@ -133,26 +118,36 @@ MYSQLND_METHOD(mysqlnd_object_factory, get_connection)(zend_bool persistent)
new_object->m = mysqlnd_conn_get_methods();
data = new_object->data;
- data->error_info = &(data->error_info_impl);
+ if (FAIL == mysqlnd_error_info_init(&data->error_info_impl, persistent)) {
+ new_object->m->dtor(new_object);
+ DBG_RETURN(NULL);
+ }
+ data->error_info = &data->error_info_impl;
+
data->options = &(data->options_impl);
+
+ mysqlnd_upsert_status_init(&data->upsert_status_impl);
data->upsert_status = &(data->upsert_status_impl);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(data->upsert_status);
data->persistent = persistent;
data->m = mysqlnd_conn_data_get_methods();
- CONN_SET_STATE(data, CONN_ALLOCED);
+ data->object_factory = *factory;
+
+ mysqlnd_connection_state_init(&data->state);
+
data->m->get_reference(data);
- if (PASS != data->m->init(data)) {
- new_object->m->dtor(new_object);
- DBG_RETURN(NULL);
- }
+ mysqlnd_stats_init(&data->stats, STAT_LAST, persistent);
+
+ data->protocol_frame_codec = mysqlnd_pfc_init(persistent, data->stats, data->error_info);
+ data->vio = mysqlnd_vio_init(persistent, data->stats, data->error_info);
+ data->payload_decoder_factory = mysqlnd_protocol_payload_decoder_factory_init(data, persistent);
+ data->command_factory = mysqlnd_command_factory_get();
- data->error_info->error_list = mnd_pecalloc(1, sizeof(zend_llist), persistent);
- if (!data->error_info->error_list) {
+ if (!data->protocol_frame_codec || !data->vio || !data->payload_decoder_factory || !data->command_factory) {
new_object->m->dtor(new_object);
DBG_RETURN(NULL);
- } else {
- zend_llist_init(data->error_info->error_list, sizeof(MYSQLND_ERROR_LIST_ELEMENT), (llist_dtor_func_t)mysqlnd_error_list_pdtor, persistent);
}
DBG_RETURN(new_object);
@@ -191,7 +186,7 @@ MYSQLND_METHOD(mysqlnd_object_factory, clone_connection_object)(MYSQLND * to_be_
/* {{{ mysqlnd_object_factory::get_prepared_statement */
static MYSQLND_STMT *
-MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement)(MYSQLND_CONN_DATA * const conn)
+MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement)(MYSQLND_CONN_DATA * const conn, const zend_bool persistent)
{
size_t alloc_size = sizeof(MYSQLND_STMT) + mysqlnd_plugin_count() * sizeof(void *);
MYSQLND_STMT * ret = mnd_pecalloc(1, alloc_size, conn->persistent);
@@ -205,13 +200,19 @@ MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement)(MYSQLND_CONN_DATA
ret->m = mysqlnd_stmt_get_methods();
ret->persistent = conn->persistent;
- stmt = ret->data = mnd_pecalloc(1, sizeof(MYSQLND_STMT_DATA), conn->persistent);
+ stmt = ret->data = mnd_pecalloc(1, sizeof(MYSQLND_STMT_DATA), persistent);
DBG_INF_FMT("stmt=%p", stmt);
if (!stmt) {
break;
}
- stmt->persistent = conn->persistent;
- stmt->error_info = &(stmt->error_info_impl);
+ stmt->persistent = persistent;
+
+ if (FAIL == mysqlnd_error_info_init(&stmt->error_info_impl, persistent)) {
+ break;
+ }
+ stmt->error_info = &stmt->error_info_impl;
+
+ mysqlnd_upsert_status_init(&stmt->upsert_status_impl);
stmt->upsert_status = &(stmt->upsert_status_impl);
stmt->state = MYSQLND_STMT_INITTED;
stmt->execute_cmd_buffer.length = 4096;
@@ -221,23 +222,18 @@ MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement)(MYSQLND_CONN_DATA
}
stmt->prefetch_rows = MYSQLND_DEFAULT_PREFETCH_ROWS;
+
/*
Mark that we reference the connection, thus it won't be
be destructed till there is open statements. The last statement
or normal query result will close it then.
*/
stmt->conn = conn->m->get_reference(conn);
- stmt->error_info->error_list = mnd_pecalloc(1, sizeof(zend_llist), ret->persistent);
- if (!stmt->error_info->error_list) {
- break;
- }
-
- zend_llist_init(stmt->error_info->error_list, sizeof(MYSQLND_ERROR_LIST_ELEMENT), (llist_dtor_func_t) mysqlnd_error_list_pdtor, conn->persistent);
DBG_RETURN(ret);
} while (0);
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
if (ret) {
ret->m->dtor(ret, TRUE);
ret = NULL;
@@ -247,53 +243,89 @@ MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement)(MYSQLND_CONN_DATA
/* }}} */
-/* {{{ mysqlnd_object_factory::get_io_channel */
-PHPAPI MYSQLND_NET *
-MYSQLND_METHOD(mysqlnd_object_factory, get_io_channel)(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info)
+/* {{{ mysqlnd_object_factory::get_pfc */
+static MYSQLND_PFC *
+MYSQLND_METHOD(mysqlnd_object_factory, get_pfc)(const zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info)
+{
+ size_t pfc_alloc_size = sizeof(MYSQLND_PFC) + mysqlnd_plugin_count() * sizeof(void *);
+ size_t pfc_data_alloc_size = sizeof(MYSQLND_PFC_DATA) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND_PFC * pfc = mnd_pecalloc(1, pfc_alloc_size, persistent);
+ MYSQLND_PFC_DATA * pfc_data = mnd_pecalloc(1, pfc_data_alloc_size, persistent);
+
+ DBG_ENTER("mysqlnd_object_factory::get_pfc");
+ DBG_INF_FMT("persistent=%u", persistent);
+ if (pfc && pfc_data) {
+ pfc->data = pfc_data;
+ pfc->persistent = pfc->data->persistent = persistent;
+ pfc->data->m = *mysqlnd_pfc_get_methods();
+
+ if (PASS != pfc->data->m.init(pfc, stats, error_info)) {
+ pfc->data->m.dtor(pfc, stats, error_info);
+ pfc = NULL;
+ }
+ } else {
+ if (pfc_data) {
+ mnd_pefree(pfc_data, persistent);
+ pfc_data = NULL;
+ }
+ if (pfc) {
+ mnd_pefree(pfc, persistent);
+ pfc = NULL;
+ }
+ }
+ DBG_RETURN(pfc);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_object_factory::get_vio */
+static MYSQLND_VIO *
+MYSQLND_METHOD(mysqlnd_object_factory, get_vio)(const zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info)
{
- size_t net_alloc_size = sizeof(MYSQLND_NET) + mysqlnd_plugin_count() * sizeof(void *);
- size_t net_data_alloc_size = sizeof(MYSQLND_NET_DATA) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_NET * net = mnd_pecalloc(1, net_alloc_size, persistent);
- MYSQLND_NET_DATA * net_data = mnd_pecalloc(1, net_data_alloc_size, persistent);
+ size_t vio_alloc_size = sizeof(MYSQLND_VIO) + mysqlnd_plugin_count() * sizeof(void *);
+ size_t vio_data_alloc_size = sizeof(MYSQLND_VIO_DATA) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND_VIO * vio = mnd_pecalloc(1, vio_alloc_size, persistent);
+ MYSQLND_VIO_DATA * vio_data = mnd_pecalloc(1, vio_data_alloc_size, persistent);
- DBG_ENTER("mysqlnd_object_factory::get_io_channel");
+ DBG_ENTER("mysqlnd_object_factory::get_vio");
DBG_INF_FMT("persistent=%u", persistent);
- if (net && net_data) {
- net->data = net_data;
- net->persistent = net->data->persistent = persistent;
- net->data->m = *mysqlnd_net_get_methods();
-
- if (PASS != net->data->m.init(net, stats, error_info)) {
- net->data->m.dtor(net, stats, error_info);
- net = NULL;
+ if (vio && vio_data) {
+ vio->data = vio_data;
+ vio->persistent = vio->data->persistent = persistent;
+ vio->data->m = *mysqlnd_vio_get_methods();
+
+ if (PASS != vio->data->m.init(vio, stats, error_info)) {
+ vio->data->m.dtor(vio, stats, error_info);
+ vio = NULL;
}
} else {
- if (net_data) {
- mnd_pefree(net_data, persistent);
- net_data = NULL;
+ if (vio_data) {
+ mnd_pefree(vio_data, persistent);
+ vio_data = NULL;
}
- if (net) {
- mnd_pefree(net, persistent);
- net = NULL;
+ if (vio) {
+ mnd_pefree(vio, persistent);
+ vio = NULL;
}
}
- DBG_RETURN(net);
+ DBG_RETURN(vio);
}
/* }}} */
-/* {{{ mysqlnd_object_factory::get_protocol_decoder */
-static MYSQLND_PROTOCOL *
-MYSQLND_METHOD(mysqlnd_object_factory, get_protocol_decoder)(zend_bool persistent)
+/* {{{ mysqlnd_object_factory::get_protocol_payload_decoder_factory */
+static MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY *
+MYSQLND_METHOD(mysqlnd_object_factory, get_protocol_payload_decoder_factory)(MYSQLND_CONN_DATA * conn, const zend_bool persistent)
{
- size_t alloc_size = sizeof(MYSQLND_PROTOCOL) + mysqlnd_plugin_count() * sizeof(void *);
- MYSQLND_PROTOCOL *ret = mnd_pecalloc(1, alloc_size, persistent);
+ size_t alloc_size = sizeof(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY) + mysqlnd_plugin_count() * sizeof(void *);
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY *ret = mnd_pecalloc(1, alloc_size, persistent);
- DBG_ENTER("mysqlnd_object_factory::get_protocol_decoder");
+ DBG_ENTER("mysqlnd_object_factory::get_protocol_payload_decoder_factory");
DBG_INF_FMT("persistent=%u", persistent);
if (ret) {
ret->persistent = persistent;
- ret->m = mysqlnd_mysqlnd_protocol_methods;
+ ret->conn = conn;
+ ret->m = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_protocol_payload_decoder_factory);
}
DBG_RETURN(ret);
@@ -305,8 +337,9 @@ PHPAPI MYSQLND_CLASS_METHODS_START(mysqlnd_object_factory)
MYSQLND_METHOD(mysqlnd_object_factory, get_connection),
MYSQLND_METHOD(mysqlnd_object_factory, clone_connection_object),
MYSQLND_METHOD(mysqlnd_object_factory, get_prepared_statement),
- MYSQLND_METHOD(mysqlnd_object_factory, get_io_channel),
- MYSQLND_METHOD(mysqlnd_object_factory, get_protocol_decoder)
+ MYSQLND_METHOD(mysqlnd_object_factory, get_pfc),
+ MYSQLND_METHOD(mysqlnd_object_factory, get_vio),
+ MYSQLND_METHOD(mysqlnd_object_factory, get_protocol_payload_decoder_factory)
MYSQLND_CLASS_METHODS_END;
/*
diff --git a/ext/mysqlnd/mysqlnd_enum_n_def.h b/ext/mysqlnd/mysqlnd_enum_n_def.h
index dd80311390..0bde8a969b 100644
--- a/ext/mysqlnd/mysqlnd_enum_n_def.h
+++ b/ext/mysqlnd/mysqlnd_enum_n_def.h
@@ -18,7 +18,6 @@
+----------------------------------------------------------------------+
*/
-/* $Id$ */
#ifndef MYSQLND_ENUM_N_DEF_H
#define MYSQLND_ENUM_N_DEF_H
@@ -49,6 +48,9 @@
#define MYSQLND_NET_CMD_BUFFER_MIN_SIZE 4096
#define MYSQLND_NET_CMD_BUFFER_MIN_SIZE_STR "4096"
+#define MYSQLND_STMT_ID_LENGTH 4
+
+
#define SERVER_STATUS_IN_TRANS 1 /* Transaction has started */
#define SERVER_STATUS_AUTOCOMMIT 2 /* Server in auto_commit mode */
#define SERVER_MORE_RESULTS_EXISTS 8 /* Multi query - next query exists */
@@ -112,7 +114,29 @@
CLIENT_PROTOCOL_41 | CLIENT_SECURE_CONNECTION | \
CLIENT_MULTI_RESULTS | CLIENT_LOCAL_FILES | CLIENT_PLUGIN_AUTH)
-#define MYSQLND_NET_FLAG_USE_COMPRESSION 1
+#define MYSQLND_PROTOCOL_FLAG_USE_COMPRESSION 1
+
+
+/* Client Error codes */
+#define CR_UNKNOWN_ERROR 2000
+#define CR_CONNECTION_ERROR 2002
+#define CR_SERVER_GONE_ERROR 2006
+#define CR_OUT_OF_MEMORY 2008
+#define CR_SERVER_LOST 2013
+#define CR_COMMANDS_OUT_OF_SYNC 2014
+#define CR_CANT_FIND_CHARSET 2019
+#define CR_MALFORMED_PACKET 2027
+#define CR_NOT_IMPLEMENTED 2054
+#define CR_NO_PREPARE_STMT 2030
+#define CR_PARAMS_NOT_BOUND 2031
+#define CR_INVALID_PARAMETER_NO 2034
+#define CR_INVALID_BUFFER_USE 2035
+
+#define MYSQLND_EE_FILENOTFOUND 7890
+
+#define UNKNOWN_SQLSTATE "HY000"
+
+#define MAX_CHARSET_LEN 32
#define TRANS_START_NO_OPT 0
@@ -186,7 +210,7 @@ typedef enum mysqlnd_parse_exec_response_type
MYSQLND_PARSE_EXEC_RESPONSE_EXPLICIT,
} enum_mysqlnd_parse_exec_response_type;
-typedef enum mysqlnd_option
+typedef enum mysqlnd_client_option
{
MYSQL_OPT_CONNECT_TIMEOUT,
MYSQL_OPT_COMPRESS,
@@ -232,9 +256,9 @@ typedef enum mysqlnd_option
MYSQLND_OPT_SSL_PASSPHRASE = 209,
MYSQLND_OPT_MAX_ALLOWED_PACKET = 210,
MYSQLND_OPT_AUTH_PROTOCOL = 211
-} enum_mysqlnd_option;
+} enum_mysqlnd_client_option;
-typedef enum mysqlnd_protocol_type
+typedef enum mysqlnd_session_protocol_type
{
MYSQL_PROTOCOL_DEFAULT = 0,
MYSQL_PROTOCOL_TCP, /* all, supported */
@@ -242,7 +266,7 @@ typedef enum mysqlnd_protocol_type
MYSQL_PROTOCOL_PIPE, /* win32, not-supported */
MYSQL_PROTOCOL_MEMORY, /* win32, not-supported */
MYSQL_PROTOCOL_LAST
-} enum_mysqlnd_protocol_type;
+} enum_mysqlnd_session_protocol_type;
typedef enum mysqlnd_field_types
{
@@ -635,7 +659,11 @@ enum php_mysqlnd_server_command
COM_BINLOG_DUMP_GTID = 30,
COM_RESET_CONNECTION = 31,
COM_STMT_EXECUTE_BATCH = 32,
- COM_END
+ COM_END,
+ /* Here follow own, non-protocol, commands */
+ COM_REAP_RESULT=240, /* own command */
+ COM_ENABLE_SSL, /* own command */
+ COM_HANDSHAKE, /* own command */
};
diff --git a/ext/mysqlnd/mysqlnd_ext_plugin.c b/ext/mysqlnd/mysqlnd_ext_plugin.c
index ec88c29ced..b48cf033e3 100644
--- a/ext/mysqlnd/mysqlnd_ext_plugin.c
+++ b/ext/mysqlnd/mysqlnd_ext_plugin.c
@@ -14,26 +14,25 @@
+----------------------------------------------------------------------+
| Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
- | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id: mysqlnd.c 318221 2011-10-19 15:04:12Z andrey $ */
#include "php.h"
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_result.h"
#include "mysqlnd_debug.h"
+#include "mysqlnd_commands.h"
+#include "mysqlnd_ext_plugin.h"
static struct st_mysqlnd_conn_methods * mysqlnd_conn_methods;
static struct st_mysqlnd_conn_data_methods * mysqlnd_conn_data_methods;
static struct st_mysqlnd_stmt_methods * mysqlnd_stmt_methods;
-/* {{{ _mysqlnd_plugin_get_plugin_connection_data */
-PHPAPI void **
-_mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id)
+/* {{{ mysqlnd_plugin__get_plugin_connection_data */
+static void **
+mysqlnd_plugin__get_plugin_connection_data(const MYSQLND * conn, const unsigned int plugin_id)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_connection_data");
+ DBG_ENTER("mysqlnd_plugin__get_plugin_connection_data");
DBG_INF_FMT("plugin_id=%u", plugin_id);
if (!conn || plugin_id >= mysqlnd_plugin_count()) {
return NULL;
@@ -43,11 +42,11 @@ _mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int pl
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_connection_data_data */
-PHPAPI void **
-_mysqlnd_plugin_get_plugin_connection_data_data(const MYSQLND_CONN_DATA * conn, unsigned int plugin_id)
+/* {{{ mysqlnd_plugin__get_plugin_connection_data_data */
+static void **
+mysqlnd_plugin__get_plugin_connection_data_data(const MYSQLND_CONN_DATA * conn, const unsigned int plugin_id)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_connection_data_data");
+ DBG_ENTER("mysqlnd_plugin__get_plugin_connection_data_data");
DBG_INF_FMT("plugin_id=%u", plugin_id);
if (!conn || plugin_id >= mysqlnd_plugin_count()) {
return NULL;
@@ -57,10 +56,11 @@ _mysqlnd_plugin_get_plugin_connection_data_data(const MYSQLND_CONN_DATA * conn,
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_result_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id)
+/* {{{ mysqlnd_plugin__get_plugin_result_data */
+static void **
+mysqlnd_plugin__get_plugin_result_data(const MYSQLND_RES * result, const unsigned int plugin_id)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_result_data");
+ DBG_ENTER("mysqlnd_plugin__get_plugin_result_data");
DBG_INF_FMT("plugin_id=%u", plugin_id);
if (!result || plugin_id >= mysqlnd_plugin_count()) {
return NULL;
@@ -70,10 +70,11 @@ PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_result_unbuffered_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_unbuffered_data(const MYSQLND_RES_UNBUFFERED * result, unsigned int plugin_id)
+/* {{{ _mysqlnd_plugin__get_plugin_result_unbuffered_data */
+static void **
+mysqlnd_plugin__get_plugin_result_unbuffered_data(const MYSQLND_RES_UNBUFFERED * result, const unsigned int plugin_id)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_result_data");
+ DBG_ENTER("mysqlnd_plugin__get_plugin_result_data");
DBG_INF_FMT("plugin_id=%u", plugin_id);
if (!result || plugin_id >= mysqlnd_plugin_count()) {
return NULL;
@@ -83,10 +84,11 @@ PHPAPI void ** _mysqlnd_plugin_get_plugin_result_unbuffered_data(const MYSQLND_R
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_result_buffered_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data_zval(const MYSQLND_RES_BUFFERED_ZVAL * result, unsigned int plugin_id)
+/* {{{ _mysqlnd_plugin__get_plugin_result_buffered_data */
+static void **
+mysqlnd_plugin__get_plugin_result_buffered_data_zval(const MYSQLND_RES_BUFFERED_ZVAL * result, const unsigned int plugin_id)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_result_data");
+ DBG_ENTER("_mysqlnd_plugin__get_plugin_result_data");
DBG_INF_FMT("plugin_id=%u", plugin_id);
if (!result || plugin_id >= mysqlnd_plugin_count()) {
return NULL;
@@ -95,10 +97,11 @@ PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data_zval(const MYSQLN
}
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_result_buffered_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data_c(const MYSQLND_RES_BUFFERED_C * result, unsigned int plugin_id)
+/* {{{ mysqlnd_plugin__get_plugin_result_buffered_data */
+static void **
+mysqlnd_plugin__get_plugin_result_buffered_data_c(const MYSQLND_RES_BUFFERED_C * result, const unsigned int plugin_id)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_result_data");
+ DBG_ENTER("mysqlnd_plugin__get_plugin_result_data");
DBG_INF_FMT("plugin_id=%u", plugin_id);
if (!result || plugin_id >= mysqlnd_plugin_count()) {
return NULL;
@@ -108,24 +111,25 @@ PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data_c(const MYSQLND_R
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_protocol_data */
-PHPAPI void **
-_mysqlnd_plugin_get_plugin_protocol_data(const MYSQLND_PROTOCOL * protocol, unsigned int plugin_id)
+/* {{{ mysqlnd_plugin__get_plugin_protocol_data */
+static void **
+mysqlnd_plugin__get_plugin_protocol_data(const MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * factory, const unsigned int plugin_id)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_protocol_data");
+ DBG_ENTER("mysqlnd_plugin__get_plugin_protocol_data");
DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!protocol || plugin_id >= mysqlnd_plugin_count()) {
+ if (!factory || plugin_id >= mysqlnd_plugin_count()) {
return NULL;
}
- DBG_RETURN((void *)((char *)protocol + sizeof(MYSQLND_PROTOCOL) + plugin_id * sizeof(void *)));
+ DBG_RETURN((void *)((char *)factory + sizeof(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY) + plugin_id * sizeof(void *)));
}
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_stmt_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, unsigned int plugin_id)
+/* {{{ mysqlnd_plugin__get_plugin_stmt_data */
+static void **
+mysqlnd_plugin__get_plugin_stmt_data(const MYSQLND_STMT * stmt, const unsigned int plugin_id)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_stmt_data");
+ DBG_ENTER("mysqlnd_plugin__get_plugin_stmt_data");
DBG_INF_FMT("plugin_id=%u", plugin_id);
if (!stmt || plugin_id >= mysqlnd_plugin_count()) {
return NULL;
@@ -135,160 +139,314 @@ PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, u
/* }}} */
-/* {{{ _mysqlnd_plugin_get_plugin_net_data */
-PHPAPI void ** _mysqlnd_plugin_get_plugin_net_data(const MYSQLND_NET * net, unsigned int plugin_id)
+/* {{{ mysqlnd_plugin__get_plugin_pfc_data */
+static void **
+mysqlnd_plugin__get_plugin_pfc_data(const MYSQLND_PFC * pfc, const unsigned int plugin_id)
{
- DBG_ENTER("_mysqlnd_plugin_get_plugin_net_data");
+ DBG_ENTER("mysqlnd_plugin__get_plugin_pfc_data");
DBG_INF_FMT("plugin_id=%u", plugin_id);
- if (!net || plugin_id >= mysqlnd_plugin_count()) {
+ if (!pfc || plugin_id >= mysqlnd_plugin_count()) {
return NULL;
}
- DBG_RETURN((void *)((char *)net + sizeof(MYSQLND_NET) + plugin_id * sizeof(void *)));
+ DBG_RETURN((void *)((char *)pfc + sizeof(MYSQLND_PFC) + plugin_id * sizeof(void *)));
}
/* }}} */
+/* {{{ _mysqlnd_plugin__get_plugin_vio_data */
+static void **
+mysqlnd_plugin__get_plugin_vio_data(const MYSQLND_VIO * vio, const unsigned int plugin_id)
+{
+ DBG_ENTER("_mysqlnd_plugin__get_plugin_vio_data");
+ DBG_INF_FMT("plugin_id=%u", plugin_id);
+ if (!vio || plugin_id >= mysqlnd_plugin_count()) {
+ return NULL;
+ }
+ DBG_RETURN((void *)((char *)vio + sizeof(MYSQLND_VIO) + plugin_id * sizeof(void *)));
+}
+/* }}} */
-/* {{{ mysqlnd_conn_get_methods */
-PHPAPI struct st_mysqlnd_conn_methods *
-mysqlnd_conn_get_methods()
+struct st_mysqlnd_plugin__plugin_area_getters mysqlnd_plugin_area_getters =
{
- return mysqlnd_conn_methods;
+ mysqlnd_plugin__get_plugin_connection_data,
+ mysqlnd_plugin__get_plugin_connection_data_data,
+ mysqlnd_plugin__get_plugin_result_data,
+ mysqlnd_plugin__get_plugin_result_unbuffered_data,
+ mysqlnd_plugin__get_plugin_result_buffered_data_zval,
+ mysqlnd_plugin__get_plugin_result_buffered_data_c,
+ mysqlnd_plugin__get_plugin_stmt_data,
+ mysqlnd_plugin__get_plugin_protocol_data,
+ mysqlnd_plugin__get_plugin_pfc_data,
+ mysqlnd_plugin__get_plugin_vio_data,
+};
+
+
+
+/* {{{ _mysqlnd_object_factory_get_methods */
+static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) *
+_mysqlnd_object_factory_get_methods()
+{
+ return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory);
}
/* }}} */
/* {{{ mysqlnd_conn_set_methods */
-PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods *methods)
+static void
+_mysqlnd_object_factory_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) *methods)
+{
+ MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory) = *methods;
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_conn_get_methods */
+static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn) *
+_mysqlnd_conn_get_methods()
+{
+ return mysqlnd_conn_methods;
+}
+/* }}} */
+
+/* {{{ _mysqlnd_conn_set_methods */
+static void
+_mysqlnd_conn_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn) *methods)
{
mysqlnd_conn_methods = methods;
}
/* }}} */
-/* {{{ mysqlnd_conn_get_methods */
-PHPAPI struct st_mysqlnd_conn_data_methods *
-mysqlnd_conn_data_get_methods()
+/* {{{ _mysqlnd_conn_data_get_methods */
+static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data) *
+_mysqlnd_conn_data_get_methods()
{
return mysqlnd_conn_data_methods;
}
/* }}} */
-/* {{{ mysqlnd_conn_set_methods */
-PHPAPI void mysqlnd_conn_data_set_methods(struct st_mysqlnd_conn_data_methods * methods)
+/* {{{ _mysqlnd_conn_data_set_methods */
+static void
+_mysqlnd_conn_data_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data) * methods)
{
mysqlnd_conn_data_methods = methods;
}
/* }}} */
-/* {{{ mysqlnd_result_get_methods */
-PHPAPI struct st_mysqlnd_res_methods *
-mysqlnd_result_get_methods()
+/* {{{ _mysqlnd_result_get_methods */
+static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_res) *
+_mysqlnd_result_get_methods()
{
return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_res);
}
/* }}} */
-/* {{{ mysqlnd_result_set_methods */
-PHPAPI void
-mysqlnd_result_set_methods(struct st_mysqlnd_res_methods * methods)
+/* {{{ _mysqlnd_result_set_methods */
+static void
+_mysqlnd_result_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_res) * methods)
{
MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_res) = *methods;
}
/* }}} */
-/* {{{ mysqlnd_result_unbuffered_get_methods */
-PHPAPI struct st_mysqlnd_result_unbuffered_methods *
-mysqlnd_result_unbuffered_get_methods()
+/* {{{ _mysqlnd_result_unbuffered_get_methods */
+static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_unbuffered) *
+_mysqlnd_result_unbuffered_get_methods()
{
return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_result_unbuffered);
}
/* }}} */
-/* {{{ mysqlnd_result_unbuffered_set_methods */
-PHPAPI void
-mysqlnd_result_unbuffered_set_methods(struct st_mysqlnd_result_unbuffered_methods * methods)
+/* {{{ _mysqlnd_result_unbuffered_set_methods */
+static void
+_mysqlnd_result_unbuffered_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_unbuffered) * methods)
{
MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_result_unbuffered) = *methods;
}
/* }}} */
-/* {{{ mysqlnd_result_buffered_get_methods */
-PHPAPI struct st_mysqlnd_result_buffered_methods *
-mysqlnd_result_buffered_get_methods()
+/* {{{ _mysqlnd_result_buffered_get_methods */
+static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_buffered) *
+_mysqlnd_result_buffered_get_methods()
{
return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_result_buffered);
}
/* }}} */
-/* {{{ mysqlnd_result_buffered_set_methods */
-PHPAPI void
-mysqlnd_result_buffered_set_methods(struct st_mysqlnd_result_buffered_methods * methods)
+/* {{{ _mysqlnd_result_buffered_set_methods */
+static void
+_mysqlnd_result_buffered_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_buffered) * methods)
{
MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_result_buffered) = *methods;
}
/* }}} */
-/* {{{ mysqlnd_stmt_get_methods */
-PHPAPI struct st_mysqlnd_stmt_methods *
-mysqlnd_stmt_get_methods()
+/* {{{ _mysqlnd_stmt_get_methods */
+static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_stmt) *
+_mysqlnd_stmt_get_methods()
{
return mysqlnd_stmt_methods;
}
/* }}} */
-/* {{{ mysqlnd_stmt_set_methods */
-PHPAPI void
-mysqlnd_stmt_set_methods(struct st_mysqlnd_stmt_methods *methods)
+/* {{{ _mysqlnd_stmt_set_methods */
+static void
+_mysqlnd_stmt_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_stmt) *methods)
{
mysqlnd_stmt_methods = methods;
}
/* }}} */
-/* {{{ mysqlnd_protocol_get_methods */
-PHPAPI struct st_mysqlnd_protocol_methods *
-mysqlnd_protocol_get_methods()
+/* {{{ _mysqlnd_protocol_payload_decoder_factory_get_methods */
+static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_payload_decoder_factory) *
+_mysqlnd_protocol_payload_decoder_factory_get_methods()
+{
+ return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_protocol_payload_decoder_factory);
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_protocol_payload_decoder_factory_set_methods */
+static void
+_mysqlnd_protocol_payload_decoder_factory_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_payload_decoder_factory) * methods)
+{
+ MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_protocol_payload_decoder_factory) = *methods;
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pfc_get_methods */
+static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_packet_frame_codec) *
+_mysqlnd_pfc_get_methods()
+{
+ return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_protocol_packet_frame_codec);
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_pfc_set_methods */
+static void
+_mysqlnd_pfc_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_packet_frame_codec) * methods)
+{
+ MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_protocol_packet_frame_codec) = *methods;
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_vio_get_methods */
+static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_vio) *
+_mysqlnd_vio_get_methods()
{
- return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_protocol);
+ return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_vio);
}
/* }}} */
-/* {{{ mysqlnd_protocol_set_methods */
-PHPAPI void
-mysqlnd_protocol_set_methods(struct st_mysqlnd_protocol_methods * methods)
+/* {{{ _mysqlnd_vio_set_methods */
+static void
+_mysqlnd_vio_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_vio) * methods)
{
- MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_protocol) = *methods;
+ MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_vio) = *methods;
}
/* }}} */
-/* {{{ mysqlnd_net_get_methods */
-PHPAPI struct st_mysqlnd_net_methods *
-mysqlnd_net_get_methods()
+/* {{{ mysqlnd_command_factory_get */
+static func_mysqlnd__command_factory
+_mysqlnd_command_factory_get()
{
- return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_net);
+ return mysqlnd_command_factory;
}
/* }}} */
-/* {{{ mysqlnd_net_set_methods */
-PHPAPI void
-mysqlnd_net_set_methods(struct st_mysqlnd_net_methods * methods)
+/* {{{ mysqlnd_command_factory_set */
+static void
+_mysqlnd_command_factory_set(func_mysqlnd__command_factory factory)
{
- MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_net) = *methods;
+ mysqlnd_command_factory = factory;
}
/* }}} */
+/* {{{ _mysqlnd_error_info_get_methods */
+static MYSQLND_CLASS_METHODS_TYPE(mysqlnd_error_info) *
+_mysqlnd_error_info_get_methods()
+{
+ return &MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_error_info);
+}
+/* }}} */
+
+
+/* {{{ _mysqlnd_error_info_set_methods */
+static void
+_mysqlnd_error_info_set_methods(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_error_info) *methods)
+{
+ MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_error_info) = *methods;
+}
+/* }}} */
+
+
+struct st_mysqlnd_plugin_methods_xetters mysqlnd_plugin_methods_xetters =
+{
+ {
+ _mysqlnd_object_factory_get_methods,
+ _mysqlnd_object_factory_set_methods
+ },
+ {
+ _mysqlnd_conn_get_methods,
+ _mysqlnd_conn_set_methods,
+ },
+ {
+ _mysqlnd_conn_data_get_methods,
+ _mysqlnd_conn_data_set_methods,
+ },
+ {
+ _mysqlnd_result_get_methods,
+ _mysqlnd_result_set_methods,
+ },
+ {
+ _mysqlnd_result_unbuffered_get_methods,
+ _mysqlnd_result_unbuffered_set_methods,
+ },
+ {
+ _mysqlnd_result_buffered_get_methods,
+ _mysqlnd_result_buffered_set_methods,
+ },
+ {
+ _mysqlnd_stmt_get_methods,
+ _mysqlnd_stmt_set_methods,
+ },
+ {
+ _mysqlnd_protocol_payload_decoder_factory_get_methods,
+ _mysqlnd_protocol_payload_decoder_factory_set_methods,
+ },
+ {
+ _mysqlnd_pfc_get_methods,
+ _mysqlnd_pfc_set_methods,
+ },
+ {
+ _mysqlnd_vio_get_methods,
+ _mysqlnd_vio_set_methods,
+ },
+ {
+ _mysqlnd_error_info_get_methods,
+ _mysqlnd_error_info_set_methods,
+ },
+ {
+ _mysqlnd_command_factory_get,
+ _mysqlnd_command_factory_set,
+ },
+};
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_ext_plugin.h b/ext/mysqlnd/mysqlnd_ext_plugin.h
index 2fee96e6c5..a7f99ef588 100644
--- a/ext/mysqlnd/mysqlnd_ext_plugin.h
+++ b/ext/mysqlnd/mysqlnd_ext_plugin.h
@@ -14,66 +14,152 @@
+----------------------------------------------------------------------+
| Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
- | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-/* $Id: mysqlnd.h 318221 2011-10-19 15:04:12Z andrey $ */
-
#ifndef MYSQLND_EXT_PLUGIN_H
#define MYSQLND_EXT_PLUGIN_H
-PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data(const MYSQLND * conn, unsigned int plugin_id);
-#define mysqlnd_plugin_get_plugin_connection_data(c, p_id) _mysqlnd_plugin_get_plugin_connection_data((c), (p_id))
-
-PHPAPI void ** _mysqlnd_plugin_get_plugin_connection_data_data(const MYSQLND_CONN_DATA * conn, unsigned int plugin_id);
-#define mysqlnd_plugin_get_plugin_connection_data_data(c, p_id) _mysqlnd_plugin_get_plugin_connection_data_data((c), (p_id))
-
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_data(const MYSQLND_RES * result, unsigned int plugin_id);
-#define mysqlnd_plugin_get_plugin_result_data(r, p_id) _mysqlnd_plugin_get_plugin_result_data((r), (p_id))
-
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_unbuffered_data(const MYSQLND_RES_UNBUFFERED * result, unsigned int plugin_id);
-#define mysqlnd_plugin_get_plugin_result_unbuffered_data(r, p_id) _mysqlnd_plugin_get_plugin_result_unbuffered_data((r), (p_id))
-
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data_zval(const MYSQLND_RES_BUFFERED_ZVAL * result, unsigned int plugin_id);
-#define mysqlnd_plugin_get_plugin_result_buffered_data_zval(r, p_id) _mysqlnd_plugin_get_plugin_result_buffered_data_zval((r), (p_id))
-
-PHPAPI void ** _mysqlnd_plugin_get_plugin_result_buffered_data_c(const MYSQLND_RES_BUFFERED_C * result, unsigned int plugin_id);
-#define mysqlnd_plugin_get_plugin_result_buffered_data_c(r, p_id) _mysqlnd_plugin_get_plugin_result_buffered_data_c((r), (p_id))
-
-PHPAPI void ** _mysqlnd_plugin_get_plugin_stmt_data(const MYSQLND_STMT * stmt, unsigned int plugin_id);
-#define mysqlnd_plugin_get_plugin_stmt_data(s, p_id) _mysqlnd_plugin_get_plugin_stmt_data((s), (p_id))
-
-PHPAPI void ** _mysqlnd_plugin_get_plugin_protocol_data(const MYSQLND_PROTOCOL * protocol, unsigned int plugin_id);
-#define mysqlnd_plugin_get_plugin_protocol_data(p, p_id) _mysqlnd_plugin_get_plugin_protocol_data((p), (p_id))
-
-PHPAPI void ** _mysqlnd_plugin_get_plugin_net_data(const MYSQLND_NET * net, unsigned int plugin_id);
-#define mysqlnd_plugin_get_plugin_net_data(n, p_id) _mysqlnd_plugin_get_plugin_net_data((n), (p_id))
-
-
-PHPAPI struct st_mysqlnd_conn_methods * mysqlnd_conn_get_methods();
-PHPAPI void mysqlnd_conn_set_methods(struct st_mysqlnd_conn_methods * methods);
-
-PHPAPI struct st_mysqlnd_conn_data_methods * mysqlnd_conn_data_get_methods();
-PHPAPI void mysqlnd_conn_data_set_methods(struct st_mysqlnd_conn_data_methods * methods);
-
-PHPAPI struct st_mysqlnd_res_methods * mysqlnd_result_get_methods();
-PHPAPI void mysqlnd_result_set_methods(struct st_mysqlnd_res_methods * methods);
-
-PHPAPI struct st_mysqlnd_result_unbuffered_methods * mysqlnd_result_unbuffered_get_methods();
-PHPAPI void mysqlnd_result_unbuffered_set_methods(struct st_mysqlnd_result_unbuffered_methods * methods);
-
-PHPAPI struct st_mysqlnd_result_buffered_methods * mysqlnd_result_buffered_get_methods();
-PHPAPI void mysqlnd_result_buffered_set_methods(struct st_mysqlnd_result_buffered_methods * methods);
-
-PHPAPI struct st_mysqlnd_stmt_methods * mysqlnd_stmt_get_methods();
-PHPAPI void mysqlnd_stmt_set_methods(struct st_mysqlnd_stmt_methods * methods);
-
-PHPAPI struct st_mysqlnd_protocol_methods * mysqlnd_protocol_get_methods();
-PHPAPI void mysqlnd_protocol_set_methods(struct st_mysqlnd_protocol_methods * methods);
-
-PHPAPI struct st_mysqlnd_net_methods * mysqlnd_net_get_methods();
-PHPAPI void mysqlnd_net_set_methods(struct st_mysqlnd_net_methods * methods);
-
+struct st_mysqlnd_plugin__plugin_area_getters
+{
+ void ** (*get_connection_area)(const MYSQLND * conn, const unsigned int plugin_id);
+ void ** (*get_connection_data_area)(const MYSQLND_CONN_DATA * conn, const unsigned int plugin_id);
+ void ** (*get_result_area)(const MYSQLND_RES * result, const unsigned int plugin_id);
+ void ** (*get_unbuffered_area)(const MYSQLND_RES_UNBUFFERED * result, const unsigned int plugin_id);
+ void ** (*get_result_buffered_area)(const MYSQLND_RES_BUFFERED_ZVAL * result, const unsigned int plugin_id);
+ void ** (*get_result_buffered_aread_c)(const MYSQLND_RES_BUFFERED_C * result, const unsigned int plugin_id);
+ void ** (*get_stmt_area)(const MYSQLND_STMT * stmt, const unsigned int plugin_id);
+ void ** (*get_protocol_decoder_area)(const MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * factory, const unsigned int plugin_id);
+ void ** (*get_pfc_area)(const MYSQLND_PFC * pfc, const unsigned int plugin_id);
+ void ** (*get_vio_area)(const MYSQLND_VIO * vio, const unsigned int plugin_id);
+};
+
+extern struct st_mysqlnd_plugin__plugin_area_getters mysqlnd_plugin_area_getters;
+
+#define mysqlnd_plugin_get_plugin_connection_data(c, p_id) mysqlnd_plugin_area_getters.get_connection_area((c), (p_id))
+#define mysqlnd_plugin_get_plugin_connection_data_data(c, p_id) mysqlnd_plugin_area_getters.get_connection_data_area((c), (p_id))
+#define mysqlnd_plugin_get_plugin_result_data(res, p_id) mysqlnd_plugin_area_getters.get_result_area((res), (p_id))
+#define mysqlnd_plugin_get_plugin_result_unbuffered_data(res, p_id) mysqlnd_plugin_area_getters.get_unbuffered_area((res), (p_id))
+#define mysqlnd_plugin_get_plugin_result_buffered_data_zval(res, p_id) mysqlnd_plugin_area_getters.get_result_buffered_area((res), (p_id))
+#define mysqlnd_plugin_get_plugin_result_buffered_data_c(res, p_id) mysqlnd_plugin_area_getters.get_result_buffered_aread_c((res), (p_id))
+#define mysqlnd_plugin_get_plugin_stmt_data(stmt, p_id) mysqlnd_plugin_area_getters.get_stmt_area((stmt), (p_id))
+#define mysqlnd_plugin_get_plugin_protocol_data(proto, p_id) mysqlnd_plugin_area_getters.get_protocol_decoder_area((proto), (p_id))
+#define mysqlnd_plugin_get_plugin_pfc_data(pfc, p_id) mysqlnd_plugin_area_getters.get_pfc_area((pfc), (p_id))
+#define mysqlnd_plugin_get_plugin_vio_data(vio, p_id) mysqlnd_plugin_area_getters.get_pfc_area((vio), (p_id))
+
+
+struct st_mysqlnd_plugin_methods_xetters
+{
+ struct st_mnd_object_factory_xetters
+ {
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) * (*get)();
+ void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) *methods);
+ } object_factory;
+
+ struct st_mnd_connection_xetters
+ {
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn) * (*get)();
+ void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn) *methods);
+ } connection;
+
+ struct st_mnd_connection_data_xetters
+ {
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data) * (*get)();
+ void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data) *methods);
+ } connection_data;
+
+ struct st_mnd_result_xetters
+ {
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_res) * (*get)();
+ void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_res) *methods);
+ } result;
+
+ struct st_mnd_unbuffered_result_xetters
+ {
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_unbuffered) * (*get)();
+ void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_unbuffered) *methods);
+ } unbuffered_result;
+
+ struct st_mnd_buffered_result_xetters
+ {
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_buffered)* (*get)();
+ void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_buffered) *methods);
+ } buffered_result;
+
+ struct st_mnd_stmt_xetters
+ {
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_stmt) * (*get)();
+ void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_stmt) * methods);
+ } statement;
+
+ struct st_mnd_protocol_xetters
+ {
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_payload_decoder_factory)* (*get)();
+ void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_payload_decoder_factory) *methods);
+ } protocol;
+
+ struct st_mnd_pfc_xetters
+ {
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_packet_frame_codec) * (*get)();
+ void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_packet_frame_codec) * methods);
+ } pfc;
+
+ struct st_mnd_vio_xetters
+ {
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_vio) * (*get)();
+ void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_vio) * methods);
+ } vio;
+
+ struct st_mnd_error_info_xetters
+ {
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_error_info) * (*get)();
+ void (*set)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_error_info) * methods);
+ } error_info;
+
+ struct st_mnd_command_factory_xetters
+ {
+ func_mysqlnd__command_factory (*get)();
+ void (*set)(func_mysqlnd__command_factory factory);
+ } command_factory;
+};
+
+extern struct st_mysqlnd_plugin_methods_xetters mysqlnd_plugin_methods_xetters;
+
+
+#define mysqlnd_object_factory_get_methods() mysqlnd_plugin_methods_xetters.object_factory.get()
+#define mysqlnd_object_factory_set_methods(m) mysqlnd_plugin_methods_xetters.object_factory.set((m))
+
+#define mysqlnd_conn_get_methods() mysqlnd_plugin_methods_xetters.connection.get()
+#define mysqlnd_conn_set_methods(m) mysqlnd_plugin_methods_xetters.connection.set((m))
+
+#define mysqlnd_conn_data_get_methods() mysqlnd_plugin_methods_xetters.connection_data.get()
+#define mysqlnd_conn_data_set_methods(m) mysqlnd_plugin_methods_xetters.connection_data.set((m))
+
+#define mysqlnd_result_get_methods() mysqlnd_plugin_methods_xetters.result.get()
+#define mysqlnd_result_set_methods(m) mysqlnd_plugin_methods_xetters.result.set((m))
+
+#define mysqlnd_result_unbuffered_get_methods() mysqlnd_plugin_methods_xetters.unbuffered_result.get()
+#define mysqlnd_result_unbuffered_set_methods(m) mysqlnd_plugin_methods_xetters.unbuffered_result.set((m))
+
+#define mysqlnd_result_buffered_get_methods() mysqlnd_plugin_methods_xetters.buffered_result.get()
+#define mysqlnd_result_buffered_set_methods(m) mysqlnd_plugin_methods_xetters.buffered_result.set((m))
+
+#define mysqlnd_stmt_get_methods() mysqlnd_plugin_methods_xetters.statement.get()
+#define mysqlnd_stmt_set_methods(m) mysqlnd_plugin_methods_xetters.statement.set((m))
+
+#define mysqlnd_protocol_get_methods() mysqlnd_plugin_methods_xetters.protocol.get()
+#define mysqlnd_protocol_set_methods(m) mysqlnd_plugin_methods_xetters.protocol.set((m))
+
+#define mysqlnd_pfc_get_methods() mysqlnd_plugin_methods_xetters.pfc.get()
+#define mysqlnd_pfc_set_methods(m) mysqlnd_plugin_methods_xetters.pfc.set((m))
+
+#define mysqlnd_vio_get_methods() mysqlnd_plugin_methods_xetters.vio.get()
+#define mysqlnd_vio_set_methods(m) mysqlnd_plugin_methods_xetters.vio.set((m))
+
+#define mysqlnd_command_factory_get() mysqlnd_plugin_methods_xetters.command_factory.get()
+#define mysqlnd_command_factory_set(m) mysqlnd_plugin_methods_xetters.command_factory.set((m))
+
+#define mysqlnd_error_info_get_methods() mysqlnd_plugin_methods_xetters.error_info.get()
+#define mysqlnd_error_info_set_methods(m) mysqlnd_plugin_methods_xetters.error_info.set((m))
#endif /* MYSQLND_EXT_PLUGIN_H */
diff --git a/ext/mysqlnd/mysqlnd_libmysql_compat.h b/ext/mysqlnd/mysqlnd_libmysql_compat.h
index 377cf37cc3..a7d98827d4 100644
--- a/ext/mysqlnd/mysqlnd_libmysql_compat.h
+++ b/ext/mysqlnd/mysqlnd_libmysql_compat.h
@@ -18,7 +18,6 @@
+----------------------------------------------------------------------+
*/
-
#ifndef MYSQLND_LIBMYSQL_COMPAT_H
#define MYSQLND_LIBMYSQL_COMPAT_H
@@ -59,11 +58,10 @@
#define mysql_field_count(r) mysqlnd_field_count((r))
#define mysql_field_seek(r,o) mysqlnd_field_seek((r), (o))
#define mysql_field_tell(r) mysqlnd_field_tell((r))
-#define mysql_init(a) mysqlnd_init((a))
+#define mysql_init(a) mysqlnd_connection_init((a), false)
#define mysql_insert_id(r) mysqlnd_insert_id((r))
#define mysql_kill(r,n) mysqlnd_kill((r), (n))
#define mysql_list_dbs(c, wild) mysqlnd_list_dbs((c), (wild))
-#define mysql_list_fields(c, tab, wild) mysqlnd_list_fields((c), (tab), (wild))
#define mysql_list_processes(c) mysqlnd_list_processes((c))
#define mysql_list_tables(c, wild) mysqlnd_list_tables((c), (wild))
#define mysql_more_results(r) mysqlnd_more_results((r))
diff --git a/ext/mysqlnd/mysqlnd_loaddata.c b/ext/mysqlnd/mysqlnd_loaddata.c
index 9679bec4df..d9ad4824d4 100644
--- a/ext/mysqlnd/mysqlnd_loaddata.c
+++ b/ext/mysqlnd/mysqlnd_loaddata.c
@@ -17,9 +17,7 @@
| Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-
#include "php.h"
-#include "php_globals.h"
#include "mysqlnd.h"
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_priv.h"
@@ -136,12 +134,12 @@ mysqlnd_local_infile_default(MYSQLND_CONN_DATA * conn)
/* }}} */
-static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of local file";
+static const char *lost_conn = "Lost connection to MySQL server during LOAD DATA of a local file";
/* {{{ mysqlnd_handle_local_infile */
enum_func_status
-mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zend_bool * is_warning)
+mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * const filename, zend_bool * is_warning)
{
zend_uchar *buf = NULL;
zend_uchar empty_packet[MYSQLND_HEADER_SIZE];
@@ -151,14 +149,15 @@ mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zen
int bufsize;
size_t ret;
MYSQLND_INFILE infile;
- MYSQLND_NET * net = conn->net;
+ MYSQLND_PFC * net = conn->protocol_frame_codec;
+ MYSQLND_VIO * vio = conn->vio;
DBG_ENTER("mysqlnd_handle_local_infile");
if (!(conn->options->flags & CLIENT_LOCAL_FILES)) {
php_error_docref(NULL, E_WARNING, "LOAD DATA LOCAL INFILE forbidden");
/* write empty packet to server */
- ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info);
+ ret = net->data->m.send(net, vio, empty_packet, 0, conn->stats, conn->error_info);
*is_warning = TRUE;
goto infile_error;
}
@@ -176,24 +175,24 @@ mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zen
*is_warning = TRUE;
/* error occurred */
tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
- SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
+ SET_CLIENT_ERROR(conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
/* write empty packet to server */
- ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info);
+ ret = net->data->m.send(net, vio, empty_packet, 0, conn->stats, conn->error_info);
goto infile_error;
}
/* read data */
while ((bufsize = infile.local_infile_read (info, buf + MYSQLND_HEADER_SIZE, buflen - MYSQLND_HEADER_SIZE)) > 0) {
- if ((ret = net->data->m.send_ex(net, buf, bufsize, conn->stats, conn->error_info)) == 0) {
+ if ((ret = net->data->m.send(net, vio, buf, bufsize, conn->stats, conn->error_info)) == 0) {
DBG_ERR_FMT("Error during read : %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
- SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
+ SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
goto infile_error;
}
}
/* send empty packet for eof */
- if ((ret = net->data->m.send_ex(net, empty_packet, 0, conn->stats, conn->error_info)) == 0) {
- SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
+ if ((ret = net->data->m.send(net, vio, empty_packet, 0, conn->stats, conn->error_info)) == 0) {
+ SET_CLIENT_ERROR(conn->error_info, CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
goto infile_error;
}
@@ -204,7 +203,7 @@ mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zen
*is_warning = TRUE;
DBG_ERR_FMT("Bufsize < 0, warning, %d %s %s", CR_SERVER_LOST, UNKNOWN_SQLSTATE, lost_conn);
tmp_error_no = infile.local_infile_error(info, tmp_buf, sizeof(tmp_buf));
- SET_CLIENT_ERROR(*conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
+ SET_CLIENT_ERROR(conn->error_info, tmp_error_no, UNKNOWN_SQLSTATE, tmp_buf);
goto infile_error;
}
@@ -212,7 +211,13 @@ mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zen
infile_error:
/* get response from server and update upsert values */
- if (FAIL == conn->m->simple_command_handle_response(conn, PROT_OK_PACKET, FALSE, COM_QUERY, FALSE)) {
+ if (FAIL == conn->payload_decoder_factory->m.send_command_handle_response(
+ conn->payload_decoder_factory,
+ PROT_OK_PACKET, FALSE, COM_QUERY, FALSE,
+ conn->error_info,
+ conn->upsert_status,
+ &conn->last_message,
+ conn->persistent)) {
result = FAIL;
}
diff --git a/ext/mysqlnd/mysqlnd_plugin.h b/ext/mysqlnd/mysqlnd_plugin.h
new file mode 100644
index 0000000000..eab21175c1
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_plugin.h
@@ -0,0 +1,40 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+#ifndef MYSQLND_PLUGIN_H
+#define MYSQLND_PLUGIN_H
+
+
+void mysqlnd_plugin_subsystem_init(void);
+void mysqlnd_plugin_subsystem_end(void);
+
+void mysqlnd_register_builtin_authentication_plugins(void);
+
+void mysqlnd_example_plugin_register(void);
+
+#endif /* MYSQLND_PLUGIN_H */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_priv.h b/ext/mysqlnd/mysqlnd_priv.h
index 683670f307..7e88688773 100644
--- a/ext/mysqlnd/mysqlnd_priv.h
+++ b/ext/mysqlnd/mysqlnd_priv.h
@@ -14,235 +14,25 @@
+----------------------------------------------------------------------+
| Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
- | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id$ */
-
#ifndef MYSQLND_PRIV_H
#define MYSQLND_PRIV_H
-
-#ifndef Z_ADDREF_P
-/* PHP 5.2, old GC */
-#define Z_ADDREF_P(pz) (++(pz)->refcount)
-#define Z_DELREF_P(pz) (--(pz)->refcount)
-#define Z_REFCOUNT_P(pz) ((pz)->refcount)
-#define Z_SET_REFCOUNT_P(pz, rc) ((pz)->refcount = rc)
-#define Z_REFCOUNT_PP(ppz) Z_REFCOUNT_P(*(ppz))
-#define Z_DELREF_PP(ppz) Z_DELREF_P(*(ppz))
-#endif
-
-#ifdef ZTS
-#include "TSRM.h"
-#endif
-
-#ifndef pestrndup
-#define pestrndup(s, length, persistent) ((persistent)?zend_strndup((s),(length)):estrndup((s),(length)))
-#endif
-
-#define MYSQLND_STR_W_LEN(str) str, (sizeof(str) - 1)
-
-#define MYSQLND_DEBUG_DUMP_TIME 1
-#define MYSQLND_DEBUG_DUMP_TRACE 2
-#define MYSQLND_DEBUG_DUMP_PID 4
-#define MYSQLND_DEBUG_DUMP_LINE 8
-#define MYSQLND_DEBUG_DUMP_FILE 16
-#define MYSQLND_DEBUG_DUMP_LEVEL 32
-#define MYSQLND_DEBUG_APPEND 64
-#define MYSQLND_DEBUG_FLUSH 128
-#define MYSQLND_DEBUG_TRACE_MEMORY_CALLS 256
-#define MYSQLND_DEBUG_PROFILE_CALLS 512
-
-
-/* Client Error codes */
-#define CR_UNKNOWN_ERROR 2000
-#define CR_CONNECTION_ERROR 2002
-#define CR_SERVER_GONE_ERROR 2006
-#define CR_OUT_OF_MEMORY 2008
-#define CR_SERVER_LOST 2013
-#define CR_COMMANDS_OUT_OF_SYNC 2014
-#define CR_CANT_FIND_CHARSET 2019
-#define CR_MALFORMED_PACKET 2027
-#define CR_NOT_IMPLEMENTED 2054
-#define CR_NO_PREPARE_STMT 2030
-#define CR_PARAMS_NOT_BOUND 2031
-#define CR_INVALID_PARAMETER_NO 2034
-#define CR_INVALID_BUFFER_USE 2035
-
-#define MYSQLND_EE_FILENOTFOUND 7890
-
-#define UNKNOWN_SQLSTATE "HY000"
-
-#define MAX_CHARSET_LEN 32
-
-
-#define SET_ERROR_AFF_ROWS(s) (s)->upsert_status->affected_rows = (uint64_t) ~0
-
-/* Error handling */
-#define SET_NEW_MESSAGE(buf, buf_len, message, len, persistent) \
- {\
- if ((buf)) { \
- mnd_pefree((buf), (persistent)); \
- } \
- if ((message)) { \
- (buf) = mnd_pestrndup((message), (len), (persistent)); \
- } else { \
- (buf) = NULL; \
- } \
- (buf_len) = (len); \
- }
-
-#define SET_EMPTY_MESSAGE(buf, buf_len, persistent) \
- {\
- if ((buf)) { \
- mnd_pefree((buf), (persistent)); \
- (buf) = NULL; \
- } \
- (buf_len) = 0; \
- }
-
-
-#define SET_EMPTY_ERROR(error_info) \
- { \
- (error_info).error_no = 0; \
- (error_info).error[0] = '\0'; \
- strlcpy((error_info).sqlstate, "00000", sizeof((error_info).sqlstate)); \
- if ((error_info).error_list) { \
- zend_llist_clean((error_info).error_list); \
- } \
- }
-
-
-#define SET_CLIENT_ERROR(error_info, a, b, c) \
-{ \
- if (0 == (a)) { \
- SET_EMPTY_ERROR((error_info)); \
- } else { \
- (error_info).error_no = (a); \
- strlcpy((error_info).sqlstate, (b), sizeof((error_info).sqlstate)); \
- strlcpy((error_info).error, (c), sizeof((error_info).error)); \
- if ((error_info).error_list) {\
- MYSQLND_ERROR_LIST_ELEMENT error_for_the_list = {0}; \
- \
- error_for_the_list.error_no = (a); \
- strlcpy(error_for_the_list.sqlstate, (b), sizeof(error_for_the_list.sqlstate)); \
- error_for_the_list.error = mnd_pestrdup((c), TRUE); \
- if (error_for_the_list.error) { \
- DBG_INF_FMT("adding error [%s] to the list", error_for_the_list.error); \
- zend_llist_add_element((error_info).error_list, &error_for_the_list); \
- } \
- } \
- } \
-}
-
-
-#define COPY_CLIENT_ERROR(error_info_to, error_info_from) \
- { \
- SET_CLIENT_ERROR((error_info_to), (error_info_from).error_no, (error_info_from).sqlstate, (error_info_from).error); \
- }
-
-
-#define SET_OOM_ERROR(error_info) SET_CLIENT_ERROR((error_info), CR_OUT_OF_MEMORY, UNKNOWN_SQLSTATE, mysqlnd_out_of_memory)
-
-
-#define SET_STMT_ERROR(stmt, a, b, c) SET_CLIENT_ERROR(*(stmt)->error_info, a, b, c)
-
-#define CONN_GET_STATE(c) (c)->m->get_state((c))
-#define CONN_SET_STATE(c, s) (c)->m->set_state((c), (s))
-
-/* PS stuff */
-typedef void (*ps_field_fetch_func)(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row);
-struct st_mysqlnd_perm_bind {
- ps_field_fetch_func func;
- /* should be signed int */
- int pack_len;
- unsigned int php_type;
- zend_bool is_possibly_blob;
- zend_bool can_ret_as_str_in_uni;
-};
-
-extern struct st_mysqlnd_perm_bind mysqlnd_ps_fetch_functions[MYSQL_TYPE_LAST + 1];
-
-enum_func_status mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything);
-enum_func_status mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything);
-
-
-PHPAPI extern const char * const mysqlnd_old_passwd;
-PHPAPI extern const char * const mysqlnd_out_of_sync;
-PHPAPI extern const char * const mysqlnd_server_gone;
-PHPAPI extern const char * const mysqlnd_out_of_memory;
-
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_object_factory);
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_conn);
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_conn_data);
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_res);
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_result_unbuffered);
PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_result_buffered);
-PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_protocol);
-PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_net);
-
-enum_func_status mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * filename, zend_bool * is_warning);
-
-
-
-void _mysqlnd_init_ps_subsystem();/* This one is private, mysqlnd_library_init() will call it */
-void _mysqlnd_init_ps_fetch_subsystem();
-
-void ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row, unsigned int byte_count);
-
-void mysqlnd_plugin_subsystem_init(void);
-void mysqlnd_plugin_subsystem_end(void);
-
-void mysqlnd_register_builtin_authentication_plugins(void);
-
-void mysqlnd_example_plugin_register(void);
-
-struct st_mysqlnd_packet_greet;
-struct st_mysqlnd_authentication_plugin;
-
-enum_func_status
-mysqlnd_auth_handshake(MYSQLND_CONN_DATA * conn,
- const char * const user,
- const char * const passwd,
- const size_t passwd_len,
- const char * const db,
- const size_t db_len,
- const MYSQLND_OPTIONS * const options,
- zend_ulong mysql_flags,
- unsigned int server_charset_no,
- zend_bool use_full_blown_auth_packet,
- const char * const auth_protocol,
- const zend_uchar * const auth_plugin_data,
- const size_t auth_plugin_data_len,
- char ** switch_to_auth_protocol,
- size_t * switch_to_auth_protocol_len,
- zend_uchar ** switch_to_auth_protocol_data,
- size_t * switch_to_auth_protocol_data_len
- );
-
-enum_func_status
-mysqlnd_auth_change_user(MYSQLND_CONN_DATA * const conn,
- const char * const user,
- const size_t user_len,
- const char * const passwd,
- const size_t passwd_len,
- const char * const db,
- const size_t db_len,
- const zend_bool silent,
- zend_bool use_full_blown_auth_packet,
- const char * const auth_protocol,
- zend_uchar * auth_plugin_data,
- size_t auth_plugin_data_len,
- char ** switch_to_auth_protocol,
- size_t * switch_to_auth_protocol_len,
- zend_uchar ** switch_to_auth_protocol_data,
- size_t * switch_to_auth_protocol_data_len
- );
+PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_protocol_payload_decoder_factory);
+PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_protocol_packet_frame_codec);
+PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_vio);
+PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_upsert_status);
+PHPAPI extern MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(mysqlnd_error_info);
+enum_func_status mysqlnd_handle_local_infile(MYSQLND_CONN_DATA * conn, const char * const filename, zend_bool * is_warning);
#endif /* MYSQLND_PRIV_H */
-
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_protocol_frame_codec.c b/ext/mysqlnd/mysqlnd_protocol_frame_codec.c
new file mode 100644
index 0000000000..a6b03df0c3
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_protocol_frame_codec.c
@@ -0,0 +1,506 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_connection.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_read_buffer.h"
+#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_statistics.h"
+#include "mysqlnd_debug.h"
+#ifdef MYSQLND_COMPRESSION_ENABLED
+#include <zlib.h>
+#endif
+
+
+/* {{{ mysqlnd_pfc::reset */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_pfc, reset)(MYSQLND_PFC * const pfc, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ DBG_ENTER("mysqlnd_pfc::reset");
+ pfc->data->packet_no = pfc->data->compressed_envelope_packet_no = 0;
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* We assume that MYSQLND_HEADER_SIZE is 4 bytes !! */
+#define COPY_HEADER(T,A) do { \
+ *(((char *)(T))) = *(((char *)(A)));\
+ *(((char *)(T))+1) = *(((char *)(A))+1);\
+ *(((char *)(T))+2) = *(((char *)(A))+2);\
+ *(((char *)(T))+3) = *(((char *)(A))+3); } while (0)
+#define STORE_HEADER_SIZE(safe_storage, buffer) COPY_HEADER((safe_storage), (buffer))
+#define RESTORE_HEADER_SIZE(buffer, safe_storage) STORE_HEADER_SIZE((safe_storage), (buffer))
+
+
+/* {{{ mysqlnd_pfc::send */
+/*
+ IMPORTANT : It's expected that buffer has place in the beginning for MYSQLND_HEADER_SIZE !!!!
+ This is done for performance reasons in the caller of this function.
+ Otherwise we will have to do send two TCP packets, or do new alloc and memcpy.
+ Neither are quick, thus the clients of this function are obligated to do
+ what they are asked for.
+
+ `count` is actually the length of the payload data. Thus :
+ count + MYSQLND_HEADER_SIZE = sizeof(buffer) (not the pointer but the actual buffer)
+*/
+static size_t
+MYSQLND_METHOD(mysqlnd_pfc, send)(MYSQLND_PFC * const pfc, MYSQLND_VIO * const vio, zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ zend_uchar safe_buf[((MYSQLND_HEADER_SIZE) + (sizeof(zend_uchar)) - 1) / (sizeof(zend_uchar))];
+ zend_uchar * safe_storage = safe_buf;
+ size_t bytes_sent, packets_sent = 1;
+ size_t left = count;
+ zend_uchar * p = (zend_uchar *) buffer;
+ zend_uchar * compress_buf = NULL;
+ size_t to_be_sent;
+
+ DBG_ENTER("mysqlnd_pfc::send");
+ DBG_INF_FMT("count=" MYSQLND_SZ_T_SPEC " compression=%u", count, pfc->data->compressed);
+
+ if (pfc->data->compressed == TRUE) {
+ size_t comp_buf_size = MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE + MIN(left, MYSQLND_MAX_PACKET_SIZE);
+ DBG_INF_FMT("compress_buf_size="MYSQLND_SZ_T_SPEC, comp_buf_size);
+ compress_buf = mnd_emalloc(comp_buf_size);
+ }
+
+ do {
+ to_be_sent = MIN(left, MYSQLND_MAX_PACKET_SIZE);
+ DBG_INF_FMT("to_be_sent=%u", to_be_sent);
+ DBG_INF_FMT("packets_sent=%u", packets_sent);
+ DBG_INF_FMT("compressed_envelope_packet_no=%u", pfc->data->compressed_envelope_packet_no);
+ DBG_INF_FMT("packet_no=%u", pfc->data->packet_no);
+#ifdef MYSQLND_COMPRESSION_ENABLED
+ if (pfc->data->compressed == TRUE) {
+ /* here we need to compress the data and then write it, first comes the compressed header */
+ size_t tmp_complen = to_be_sent;
+ size_t payload_size;
+ zend_uchar * uncompressed_payload = p; /* should include the header */
+
+ STORE_HEADER_SIZE(safe_storage, uncompressed_payload);
+ int3store(uncompressed_payload, to_be_sent);
+ int1store(uncompressed_payload + 3, pfc->data->packet_no);
+ if (PASS == pfc->data->m.encode((compress_buf + COMPRESSED_HEADER_SIZE + MYSQLND_HEADER_SIZE), &tmp_complen,
+ uncompressed_payload, to_be_sent + MYSQLND_HEADER_SIZE))
+ {
+ int3store(compress_buf + MYSQLND_HEADER_SIZE, to_be_sent + MYSQLND_HEADER_SIZE);
+ payload_size = tmp_complen;
+ } else {
+ int3store(compress_buf + MYSQLND_HEADER_SIZE, 0);
+ memcpy(compress_buf + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, uncompressed_payload, to_be_sent + MYSQLND_HEADER_SIZE);
+ payload_size = to_be_sent + MYSQLND_HEADER_SIZE;
+ }
+ RESTORE_HEADER_SIZE(uncompressed_payload, safe_storage);
+
+ int3store(compress_buf, payload_size);
+ int1store(compress_buf + 3, pfc->data->packet_no);
+ DBG_INF_FMT("writing "MYSQLND_SZ_T_SPEC" bytes to the network", payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE);
+ bytes_sent = vio->data->m.network_write(vio, compress_buf, payload_size + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, conn_stats, error_info);
+ pfc->data->compressed_envelope_packet_no++;
+ #if WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY
+ if (res == Z_OK) {
+ size_t decompressed_size = left + MYSQLND_HEADER_SIZE;
+ zend_uchar * decompressed_data = mnd_malloc(decompressed_size);
+ int error = pfc->data->m.decode(decompressed_data, decompressed_size,
+ compress_buf + MYSQLND_HEADER_SIZE + COMPRESSED_HEADER_SIZE, payload_size);
+ if (error == Z_OK) {
+ int i;
+ DBG_INF("success decompressing");
+ for (i = 0 ; i < decompressed_size; i++) {
+ if (i && (i % 30 == 0)) {
+ printf("\n\t\t");
+ }
+ printf("%.2X ", (int)*((char*)&(decompressed_data[i])));
+ DBG_INF_FMT("%.2X ", (int)*((char*)&(decompressed_data[i])));
+ }
+ } else {
+ DBG_INF("error decompressing");
+ }
+ mnd_free(decompressed_data);
+ }
+ #endif /* WHEN_WE_NEED_TO_CHECK_WHETHER_COMPRESSION_WORKS_CORRECTLY */
+ } else
+#endif /* MYSQLND_COMPRESSION_ENABLED */
+ {
+ DBG_INF("no compression");
+ STORE_HEADER_SIZE(safe_storage, p);
+ int3store(p, to_be_sent);
+ int1store(p + 3, pfc->data->packet_no);
+ bytes_sent = vio->data->m.network_write(vio, p, to_be_sent + MYSQLND_HEADER_SIZE, conn_stats, error_info);
+ RESTORE_HEADER_SIZE(p, safe_storage);
+ pfc->data->compressed_envelope_packet_no++;
+ }
+ pfc->data->packet_no++;
+
+ p += to_be_sent;
+ left -= to_be_sent;
+ packets_sent++;
+ /*
+ if left is 0 then there is nothing more to send, but if the last packet was exactly
+ with the size MYSQLND_MAX_PACKET_SIZE we need to send additional packet, which has
+ empty payload. Thus if left == 0 we check for to_be_sent being the max size. If it is
+ indeed it then loop once more, then to_be_sent will become 0, left will stay 0. Empty
+ packet will be sent and this loop will end.
+ */
+ } while (bytes_sent && (left > 0 || to_be_sent == MYSQLND_MAX_PACKET_SIZE));
+
+ DBG_INF_FMT("packet_size="MYSQLND_SZ_T_SPEC" packet_no=%u", left, pfc->data->packet_no);
+
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats,
+ STAT_BYTES_SENT, count + packets_sent * MYSQLND_HEADER_SIZE,
+ STAT_PROTOCOL_OVERHEAD_OUT, packets_sent * MYSQLND_HEADER_SIZE,
+ STAT_PACKETS_SENT, packets_sent);
+
+ if (compress_buf) {
+ mnd_efree(compress_buf);
+ }
+
+ /* Even for zero size payload we have to send a packet */
+ if (!bytes_sent) {
+ DBG_ERR_FMT("Can't %u send bytes", count);
+ SET_CLIENT_ERROR(error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ }
+ DBG_RETURN(bytes_sent);
+}
+/* }}} */
+
+
+#ifdef MYSQLND_COMPRESSION_ENABLED
+
+/* {{{ mysqlnd_pfc::read_compressed_packet_from_stream_and_fill_read_buffer */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_pfc, read_compressed_packet_from_stream_and_fill_read_buffer)
+ (MYSQLND_PFC * pfc, MYSQLND_VIO * vio, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info)
+{
+ size_t decompressed_size;
+ enum_func_status retval = PASS;
+ zend_uchar * compressed_data = NULL;
+ zend_uchar comp_header[COMPRESSED_HEADER_SIZE];
+ DBG_ENTER("mysqlnd_pfc::read_compressed_packet_from_stream_and_fill_read_buffer");
+
+ /* Read the compressed header */
+ if (FAIL == vio->data->m.network_read(vio, comp_header, COMPRESSED_HEADER_SIZE, conn_stats, error_info)) {
+ DBG_RETURN(FAIL);
+ }
+ decompressed_size = uint3korr(comp_header);
+
+ /* When decompressed_size is 0, then the data is not compressed, and we have wasted 3 bytes */
+ /* we need to decompress the data */
+
+ if (decompressed_size) {
+ compressed_data = mnd_emalloc(net_payload_size);
+ if (FAIL == vio->data->m.network_read(vio, compressed_data, net_payload_size, conn_stats, error_info)) {
+ retval = FAIL;
+ goto end;
+ }
+ pfc->data->uncompressed_data = mysqlnd_create_read_buffer(decompressed_size);
+ retval = pfc->data->m.decode(pfc->data->uncompressed_data->data, decompressed_size, compressed_data, net_payload_size);
+ if (FAIL == retval) {
+ goto end;
+ }
+ } else {
+ DBG_INF_FMT("The server decided not to compress the data. Our job is easy. Copying %u bytes", net_payload_size);
+ pfc->data->uncompressed_data = mysqlnd_create_read_buffer(net_payload_size);
+ if (FAIL == vio->data->m.network_read(vio, pfc->data->uncompressed_data->data, net_payload_size, conn_stats, error_info)) {
+ retval = FAIL;
+ goto end;
+ }
+ }
+end:
+ if (compressed_data) {
+ mnd_efree(compressed_data);
+ }
+ DBG_RETURN(retval);
+}
+/* }}} */
+#endif /* MYSQLND_COMPRESSION_ENABLED */
+
+
+/* {{{ mysqlnd_pfc::decode */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_pfc, decode)(zend_uchar * uncompressed_data, const size_t uncompressed_data_len,
+ const zend_uchar * const compressed_data, const size_t compressed_data_len)
+{
+#ifdef MYSQLND_COMPRESSION_ENABLED
+ int error;
+ uLongf tmp_complen = uncompressed_data_len;
+ DBG_ENTER("mysqlnd_pfc::decode");
+ error = uncompress(uncompressed_data, &tmp_complen, compressed_data, compressed_data_len);
+
+ DBG_INF_FMT("compressed data: decomp_len=%lu compressed_size="MYSQLND_SZ_T_SPEC, tmp_complen, compressed_data_len);
+ if (error != Z_OK) {
+ DBG_INF_FMT("decompression NOT successful. error=%d Z_OK=%d Z_BUF_ERROR=%d Z_MEM_ERROR=%d", error, Z_OK, Z_BUF_ERROR, Z_MEM_ERROR);
+ }
+ DBG_RETURN(error == Z_OK? PASS:FAIL);
+#else
+ DBG_ENTER("mysqlnd_pfc::decode");
+ DBG_RETURN(FAIL);
+#endif
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_pfc::encode */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_pfc, encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len,
+ const zend_uchar * const uncompressed_data, const size_t uncompressed_data_len)
+{
+#ifdef MYSQLND_COMPRESSION_ENABLED
+ int error;
+ uLongf tmp_complen = *compress_buffer_len;
+ DBG_ENTER("mysqlnd_pfc::encode");
+ error = compress(compress_buffer, &tmp_complen, uncompressed_data, uncompressed_data_len);
+
+ if (error != Z_OK) {
+ DBG_INF_FMT("compression NOT successful. error=%d Z_OK=%d Z_BUF_ERROR=%d Z_MEM_ERROR=%d", error, Z_OK, Z_BUF_ERROR, Z_MEM_ERROR);
+ } else {
+ *compress_buffer_len = tmp_complen;
+ DBG_INF_FMT("compression successful. compressed size=%lu", tmp_complen);
+ }
+
+ DBG_RETURN(error == Z_OK? PASS:FAIL);
+#else
+ DBG_ENTER("mysqlnd_pfc::encode");
+ DBG_RETURN(FAIL);
+#endif
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_pfc::receive */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_pfc, receive)(MYSQLND_PFC * const pfc, MYSQLND_VIO * const vio, zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ size_t to_read = count;
+ zend_uchar * p = buffer;
+
+ DBG_ENTER("mysqlnd_pfc::receive");
+#ifdef MYSQLND_COMPRESSION_ENABLED
+ if (pfc->data->compressed) {
+ if (pfc->data->uncompressed_data) {
+ size_t to_read_from_buffer = MIN(pfc->data->uncompressed_data->bytes_left(pfc->data->uncompressed_data), to_read);
+ DBG_INF_FMT("reading "MYSQLND_SZ_T_SPEC" from uncompressed_data buffer", to_read_from_buffer);
+ if (to_read_from_buffer) {
+ pfc->data->uncompressed_data->read(pfc->data->uncompressed_data, to_read_from_buffer, (zend_uchar *) p);
+ p += to_read_from_buffer;
+ to_read -= to_read_from_buffer;
+ }
+ DBG_INF_FMT("left "MYSQLND_SZ_T_SPEC" to read", to_read);
+ if (TRUE == pfc->data->uncompressed_data->is_empty(pfc->data->uncompressed_data)) {
+ /* Everything was consumed. This should never happen here, but for security */
+ pfc->data->uncompressed_data->free_buffer(&pfc->data->uncompressed_data);
+ }
+ }
+ if (to_read) {
+ zend_uchar net_header[MYSQLND_HEADER_SIZE];
+ size_t net_payload_size;
+ zend_uchar packet_no;
+
+ if (FAIL == vio->data->m.network_read(vio, net_header, MYSQLND_HEADER_SIZE, conn_stats, error_info)) {
+ DBG_RETURN(FAIL);
+ }
+ net_payload_size = uint3korr(net_header);
+ packet_no = uint1korr(net_header + 3);
+ if (pfc->data->compressed_envelope_packet_no != packet_no) {
+ DBG_ERR_FMT("Transport level: packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
+ pfc->data->compressed_envelope_packet_no, packet_no, net_payload_size);
+
+ php_error(E_WARNING, "Packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
+ pfc->data->compressed_envelope_packet_no, packet_no, net_payload_size);
+ DBG_RETURN(FAIL);
+ }
+ pfc->data->compressed_envelope_packet_no++;
+#ifdef MYSQLND_DUMP_HEADER_N_BODY
+ DBG_INF_FMT("HEADER: hwd_packet_no=%u size=%3u", packet_no, (zend_ulong) net_payload_size);
+#endif
+ /* Now let's read from the wire, decompress it and fill the read buffer */
+ pfc->data->m.read_compressed_packet_from_stream_and_fill_read_buffer(pfc, vio, net_payload_size, conn_stats, error_info);
+
+ /*
+ Now a bit of recursion - read from the read buffer,
+ if the data which we have just read from the wire
+ is not enough, then the recursive call will try to
+ satisfy it until it is satisfied.
+ */
+ DBG_RETURN(pfc->data->m.receive(pfc, vio, p, to_read, conn_stats, error_info));
+ }
+ DBG_RETURN(PASS);
+ }
+#endif /* MYSQLND_COMPRESSION_ENABLED */
+ DBG_RETURN(vio->data->m.network_read(vio, p, to_read, conn_stats, error_info));
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_pfc::set_client_option */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_pfc, set_client_option)(MYSQLND_PFC * const pfc, enum_mysqlnd_client_option option, const char * const value)
+{
+ DBG_ENTER("mysqlnd_pfc::set_client_option");
+ DBG_INF_FMT("option=%u", option);
+ switch (option) {
+ case MYSQL_OPT_COMPRESS:
+ pfc->data->flags |= MYSQLND_PROTOCOL_FLAG_USE_COMPRESSION;
+ break;
+ case MYSQL_SERVER_PUBLIC_KEY: {
+ const zend_bool pers = pfc->persistent;
+ if (pfc->data->sha256_server_public_key) {
+ mnd_pefree(pfc->data->sha256_server_public_key, pers);
+ }
+ pfc->data->sha256_server_public_key = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ case MYSQLND_OPT_NET_CMD_BUFFER_SIZE:
+ DBG_INF("MYSQLND_OPT_NET_CMD_BUFFER_SIZE");
+ if (*(unsigned int*) value < MYSQLND_NET_CMD_BUFFER_MIN_SIZE) {
+ DBG_RETURN(FAIL);
+ }
+ pfc->cmd_buffer.length = *(unsigned int*) value;
+ DBG_INF_FMT("new_length="MYSQLND_SZ_T_SPEC, pfc->cmd_buffer.length);
+ if (!pfc->cmd_buffer.buffer) {
+ pfc->cmd_buffer.buffer = mnd_pemalloc(pfc->cmd_buffer.length, pfc->persistent);
+ } else {
+ pfc->cmd_buffer.buffer = mnd_perealloc(pfc->cmd_buffer.buffer, pfc->cmd_buffer.length, pfc->persistent);
+ }
+ break;
+ }
+ default:
+ DBG_RETURN(FAIL);
+ }
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_pfc::free_contents */
+static void
+MYSQLND_METHOD(mysqlnd_pfc, free_contents)(MYSQLND_PFC * pfc)
+{
+ DBG_ENTER("mysqlnd_pfc::free_contents");
+
+#ifdef MYSQLND_COMPRESSION_ENABLED
+ if (pfc->data->uncompressed_data) {
+ pfc->data->uncompressed_data->free_buffer(&pfc->data->uncompressed_data);
+ }
+#endif
+ if (pfc->data->sha256_server_public_key) {
+ mnd_pefree(pfc->data->sha256_server_public_key, pfc->persistent);
+ pfc->data->sha256_server_public_key = NULL;
+ }
+
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_pfc::init */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_pfc, init)(MYSQLND_PFC * const pfc, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ unsigned int buf_size;
+ DBG_ENTER("mysqlnd_pfc::init");
+
+ buf_size = MYSQLND_G(net_cmd_buffer_size); /* this is long, cast to unsigned int*/
+ pfc->data->m.set_client_option(pfc, MYSQLND_OPT_NET_CMD_BUFFER_SIZE, (char *) &buf_size);
+
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_pfc::dtor */
+static void
+MYSQLND_METHOD(mysqlnd_pfc, dtor)(MYSQLND_PFC * const pfc, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ DBG_ENTER("mysqlnd_pfc::dtor");
+ if (pfc) {
+ pfc->data->m.free_contents(pfc);
+
+ if (pfc->cmd_buffer.buffer) {
+ DBG_INF("Freeing cmd buffer");
+ mnd_pefree(pfc->cmd_buffer.buffer, pfc->persistent);
+ pfc->cmd_buffer.buffer = NULL;
+ }
+
+ mnd_pefree(pfc->data, pfc->data->persistent);
+ mnd_pefree(pfc, pfc->persistent);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+MYSQLND_CLASS_METHODS_START(mysqlnd_protocol_packet_frame_codec)
+ MYSQLND_METHOD(mysqlnd_pfc, init),
+ MYSQLND_METHOD(mysqlnd_pfc, dtor),
+ MYSQLND_METHOD(mysqlnd_pfc, reset),
+
+ MYSQLND_METHOD(mysqlnd_pfc, set_client_option),
+
+ MYSQLND_METHOD(mysqlnd_pfc, decode),
+ MYSQLND_METHOD(mysqlnd_pfc, encode),
+
+ MYSQLND_METHOD(mysqlnd_pfc, send),
+ MYSQLND_METHOD(mysqlnd_pfc, receive),
+
+#ifdef MYSQLND_COMPRESSION_ENABLED
+ MYSQLND_METHOD(mysqlnd_pfc, read_compressed_packet_from_stream_and_fill_read_buffer),
+#else
+ NULL,
+#endif
+
+ MYSQLND_METHOD(mysqlnd_pfc, free_contents),
+MYSQLND_CLASS_METHODS_END;
+
+
+/* {{{ mysqlnd_pfc_init */
+PHPAPI MYSQLND_PFC *
+mysqlnd_pfc_init(const zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info)
+{
+ MYSQLND_PFC * pfc;
+ DBG_ENTER("mysqlnd_pfc_init");
+ pfc = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_protocol_frame_codec(persistent, stats, error_info);
+ DBG_RETURN(pfc);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_pfc_free */
+PHPAPI void
+mysqlnd_pfc_free(MYSQLND_PFC * const pfc, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info)
+{
+ DBG_ENTER("mysqlnd_pfc_free");
+ if (pfc) {
+ pfc->data->m.dtor(pfc, stats, error_info);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_protocol_frame_codec.h b/ext/mysqlnd/mysqlnd_protocol_frame_codec.h
new file mode 100644
index 0000000000..49bb8da9e5
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_protocol_frame_codec.h
@@ -0,0 +1,35 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef MYSQLND_PROTOCOL_FRAME_CODEC_H
+#define MYSQLND_PROTOCOL_FRAME_CODEC_H
+
+PHPAPI MYSQLND_PFC * mysqlnd_pfc_init(const zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info);
+PHPAPI void mysqlnd_pfc_free(MYSQLND_PFC * const net, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info);
+
+#endif /* MYSQLND_PROTOCOL_FRAME_CODEC_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index 767ba34ab0..4e8c9cf9ac 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -17,12 +17,12 @@
| Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id$ */
#include "php.h"
#include "mysqlnd.h"
#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_connection.h"
#include "mysqlnd_priv.h"
+#include "mysqlnd_ps.h"
#include "mysqlnd_result.h"
#include "mysqlnd_result_meta.h"
#include "mysqlnd_statistics.h"
@@ -30,9 +30,6 @@
#include "mysqlnd_block_alloc.h"
#include "mysqlnd_ext_plugin.h"
-#define MYSQLND_SILENT
-
-
const char * const mysqlnd_not_bound_as_blob = "Can't send long data for non-string/non-binary data types";
const char * const mysqlnd_stmt_not_prepared = "Statement not prepared";
@@ -41,25 +38,23 @@ enum_func_status mysqlnd_stmt_execute_generate_request(MYSQLND_STMT * const s, z
enum_func_status mysqlnd_stmt_execute_batch_generate_request(MYSQLND_STMT * const s, zend_uchar ** request, size_t *request_len, zend_bool * free_buffer);
static void mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const stmt);
-static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, unsigned int param_no);
+static void mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const stmt, const unsigned int param_no);
/* {{{ mysqlnd_stmt::store_result */
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret;
- MYSQLND_CONN_DATA * conn;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
MYSQLND_RES * result;
DBG_ENTER("mysqlnd_stmt::store_result");
- if (!stmt || !stmt->conn || !stmt->result) {
+ if (!stmt || !conn || !stmt->result) {
DBG_RETURN(NULL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- conn = stmt->conn;
-
/* be compliant with libmysql - NULL will turn */
if (!stmt->field_count) {
DBG_RETURN(NULL);
@@ -71,18 +66,16 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
}
/* Nothing to store for UPSERT/LOAD DATA*/
- if (CONN_GET_STATE(conn) != CONN_FETCHING_DATA ||
- stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE)
+ if (GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA || stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE)
{
- SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
- UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(NULL);
}
stmt->default_rset_handler = s->m->store_result;
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_PS_BUFFERED_SETS);
result = stmt->result;
@@ -91,7 +84,7 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_zval_init(result->field_count, TRUE, result->persistent);
if (!result->stored_data) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
DBG_RETURN(NULL);
}
@@ -100,19 +93,18 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
result->stored_data->m.fetch_row = mysqlnd_stmt_fetch_row_buffered;
if (PASS == ret) {
- /* Overflow ? */
if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_ZVAL) {
MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data;
if (result->stored_data->row_count) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (result->stored_data->row_count * result->meta->field_count * sizeof(zval *) > SIZE_MAX) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
DBG_RETURN(NULL);
}
/* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */
set->data = mnd_emalloc((size_t)(result->stored_data->row_count * result->meta->field_count * sizeof(zval)));
if (!set->data) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
DBG_RETURN(NULL);
}
memset(set->data, 0, (size_t)(result->stored_data->row_count * result->meta->field_count * sizeof(zval)));
@@ -124,11 +116,11 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
}
/* libmysql API docs say it should be so for SELECT statements */
- stmt->upsert_status->affected_rows = stmt->result->stored_data->row_count;
+ UPSERT_STATUS_SET_AFFECTED_ROWS(stmt->upsert_status, stmt->result->stored_data->row_count);
stmt->state = MYSQLND_STMT_USE_OR_STORE_CALLED;
} else {
- COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info);
+ COPY_CLIENT_ERROR(conn->error_info, result->stored_data->error_info);
stmt->result->m.free_result_contents(stmt->result);
mnd_efree(stmt->result);
stmt->result = NULL;
@@ -144,18 +136,16 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND_CONN_DATA * conn;
- MYSQLND_RES *result;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
+ MYSQLND_RES * result;
DBG_ENTER("mysqlnd_stmt::get_result");
- if (!stmt || !stmt->conn || !stmt->result) {
+ if (!stmt || !conn || !stmt->result) {
DBG_RETURN(NULL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- conn = stmt->conn;
-
/* be compliant with libmysql - NULL will turn */
if (!stmt->field_count) {
DBG_RETURN(NULL);
@@ -167,35 +157,34 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s)
}
/* Nothing to store for UPSERT/LOAD DATA*/
- if (CONN_GET_STATE(conn) != CONN_FETCHING_DATA || stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) {
- SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
- UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ if (GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA || stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE) {
+ SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(NULL);
}
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_BUFFERED_SETS);
do {
result = conn->m->result_init(stmt->result->field_count, stmt->persistent);
if (!result) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
break;
}
result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE);
if (!result->meta) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
break;
}
if ((result = result->m.store_result(result, conn, MYSQLND_STORE_PS | MYSQLND_STORE_NO_COPY))) {
- stmt->upsert_status->affected_rows = result->stored_data->row_count;
+ UPSERT_STATUS_SET_AFFECTED_ROWS(stmt->upsert_status, result->stored_data->row_count);
stmt->state = MYSQLND_STMT_PREPARED;
result->type = MYSQLND_RES_PS_BUF;
} else {
- COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
+ COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
stmt->state = MYSQLND_STMT_PREPARED;
break;
}
@@ -214,12 +203,11 @@ MYSQLND_METHOD(mysqlnd_stmt, get_result)(MYSQLND_STMT * const s)
static zend_bool
MYSQLND_METHOD(mysqlnd_stmt, more_results)(const MYSQLND_STMT * s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
DBG_ENTER("mysqlnd_stmt::more_results");
/* (conn->state == CONN_NEXT_RESULT_PENDING) too */
- DBG_RETURN((stmt && stmt->conn && (stmt->conn->m->get_server_status(stmt->conn) & SERVER_MORE_RESULTS_EXISTS))?
- TRUE:
- FALSE);
+ DBG_RETURN((stmt && conn && (conn->m->get_server_status(conn) & SERVER_MORE_RESULTS_EXISTS))? TRUE: FALSE);
}
/* }}} */
@@ -228,21 +216,20 @@ MYSQLND_METHOD(mysqlnd_stmt, more_results)(const MYSQLND_STMT * s)
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, next_result)(MYSQLND_STMT * s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND_CONN_DATA * conn;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
DBG_ENTER("mysqlnd_stmt::next_result");
- if (!stmt || !stmt->conn || !stmt->result) {
+ if (!stmt || !conn || !stmt->result) {
DBG_RETURN(FAIL);
}
- conn = stmt->conn;
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- if (CONN_GET_STATE(conn) != CONN_NEXT_RESULT_PENDING || !(conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS)) {
+ if (GET_CONNECTION_STATE(&conn->state) != CONN_NEXT_RESULT_PENDING || !(UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_MORE_RESULTS_EXISTS)) {
DBG_RETURN(FAIL);
}
- DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status, stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS);
+ DBG_INF_FMT("server_status=%u cursor=%u", UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status), UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_STATUS_CURSOR_EXISTS);
/* Free space for next result */
s->m->free_stmt_result(s);
@@ -258,27 +245,28 @@ MYSQLND_METHOD(mysqlnd_stmt, next_result)(MYSQLND_STMT * s)
static enum_func_status
mysqlnd_stmt_skip_metadata(MYSQLND_STMT * s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
/* Follows parameter metadata, we have just to skip it, as libmysql does */
unsigned int i = 0;
enum_func_status ret = FAIL;
MYSQLND_PACKET_RES_FIELD * field_packet;
DBG_ENTER("mysqlnd_stmt_skip_metadata");
- if (!stmt || !stmt->conn || !stmt->conn->protocol) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- field_packet = stmt->conn->protocol->m.get_result_field_packet(stmt->conn->protocol, FALSE);
+ field_packet = conn->payload_decoder_factory->m.get_result_field_packet(conn->payload_decoder_factory, FALSE);
if (!field_packet) {
- SET_OOM_ERROR(*stmt->error_info);
- SET_OOM_ERROR(*stmt->conn->error_info);
+ SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(conn->error_info);
} else {
ret = PASS;
field_packet->skip_parsing = TRUE;
for (;i < stmt->param_count; i++) {
- if (FAIL == PACKET_READ(field_packet, stmt->conn)) {
+ if (FAIL == PACKET_READ(field_packet)) {
ret = FAIL;
break;
}
@@ -295,38 +283,39 @@ mysqlnd_stmt_skip_metadata(MYSQLND_STMT * s)
static enum_func_status
mysqlnd_stmt_read_prepare_response(MYSQLND_STMT * s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
MYSQLND_PACKET_PREPARE_RESPONSE * prepare_resp;
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_stmt_read_prepare_response");
- if (!stmt || !stmt->conn || !stmt->conn->protocol) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- prepare_resp = stmt->conn->protocol->m.get_prepare_response_packet(stmt->conn->protocol, FALSE);
+ prepare_resp = conn->payload_decoder_factory->m.get_prepare_response_packet(conn->payload_decoder_factory, FALSE);
if (!prepare_resp) {
- SET_OOM_ERROR(*stmt->error_info);
- SET_OOM_ERROR(*stmt->conn->error_info);
+ SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(conn->error_info);
goto done;
}
- if (FAIL == PACKET_READ(prepare_resp, stmt->conn)) {
+ if (FAIL == PACKET_READ(prepare_resp)) {
goto done;
}
if (0xFF == prepare_resp->error_code) {
- COPY_CLIENT_ERROR(*stmt->error_info, prepare_resp->error_info);
- COPY_CLIENT_ERROR(*stmt->conn->error_info, prepare_resp->error_info);
+ COPY_CLIENT_ERROR(stmt->error_info, prepare_resp->error_info);
+ COPY_CLIENT_ERROR(conn->error_info, prepare_resp->error_info);
goto done;
}
ret = PASS;
stmt->stmt_id = prepare_resp->stmt_id;
- stmt->warning_count = stmt->conn->upsert_status->warning_count = prepare_resp->warning_count;
- stmt->field_count = stmt->conn->field_count = prepare_resp->field_count;
+ UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, prepare_resp->warning_count);
+ UPSERT_STATUS_SET_AFFECTED_ROWS(stmt->upsert_status, 0); /* be like libmysql */
+ stmt->field_count = conn->field_count = prepare_resp->field_count;
stmt->param_count = prepare_resp->param_count;
- stmt->upsert_status->affected_rows = 0; /* be like libmysql */
done:
PACKET_FREE(prepare_resp);
@@ -339,31 +328,37 @@ done:
static enum_func_status
mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
MYSQLND_PACKET_EOF * fields_eof;
enum_func_status ret = FAIL;
DBG_ENTER("mysqlnd_stmt_prepare_read_eof");
- if (!stmt || !stmt->conn || !stmt->conn->protocol) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- fields_eof = stmt->conn->protocol->m.get_eof_packet(stmt->conn->protocol, FALSE);
+ fields_eof = conn->payload_decoder_factory->m.get_eof_packet(conn->payload_decoder_factory, FALSE);
if (!fields_eof) {
- SET_OOM_ERROR(*stmt->error_info);
- SET_OOM_ERROR(*stmt->conn->error_info);
+ SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(conn->error_info);
} else {
- if (FAIL == (ret = PACKET_READ(fields_eof, stmt->conn))) {
+ if (FAIL == (ret = PACKET_READ(fields_eof))) {
if (stmt->result) {
stmt->result->m.free_result_contents(stmt->result);
mnd_efree(stmt->result);
+ /* XXX: This will crash, because we will null also the methods.
+ But seems it happens in extreme cases or doesn't. Should be fixed by exporting a function
+ (from mysqlnd_driver.c?) to do the reset.
+ This bad handling is also in mysqlnd_result.c
+ */
memset(stmt, 0, sizeof(MYSQLND_STMT_DATA));
stmt->state = MYSQLND_STMT_INITTED;
}
} else {
- stmt->upsert_status->server_status = fields_eof->server_status;
- stmt->upsert_status->warning_count = fields_eof->warning_count;
+ UPSERT_STATUS_SET_SERVER_STATUS(stmt->upsert_status, fields_eof->server_status);
+ UPSERT_STATUS_SET_WARNINGS(stmt->upsert_status, fields_eof->warning_count);
stmt->state = MYSQLND_STMT_PREPARED;
}
PACKET_FREE(fields_eof);
@@ -376,24 +371,25 @@ mysqlnd_stmt_prepare_read_eof(MYSQLND_STMT * s)
/* {{{ mysqlnd_stmt::prepare */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const query, unsigned int query_len)
+MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const query, const size_t query_len)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
MYSQLND_STMT * s_to_prepare = s;
MYSQLND_STMT_DATA * stmt_to_prepare = stmt;
DBG_ENTER("mysqlnd_stmt::prepare");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
DBG_INF_FMT("query=%s", query);
- SET_ERROR_AFF_ROWS(stmt);
- SET_ERROR_AFF_ROWS(stmt->conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(stmt->upsert_status);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
if (stmt->state > MYSQLND_STMT_INITTED) {
/* See if we have to clean the wire */
@@ -410,16 +406,27 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
Create a new test statement, which we will prepare, but if anything
fails, we will scrap it.
*/
- s_to_prepare = stmt->conn->m->stmt_init(stmt->conn);
+ s_to_prepare = conn->m->stmt_init(conn);
if (!s_to_prepare) {
goto fail;
}
stmt_to_prepare = s_to_prepare->data;
}
- if (FAIL == stmt_to_prepare->conn->m->simple_command(stmt_to_prepare->conn, COM_STMT_PREPARE, (const zend_uchar *) query, query_len, PROT_LAST, FALSE, TRUE) ||
- FAIL == mysqlnd_stmt_read_prepare_response(s_to_prepare))
{
+ enum_func_status ret = FAIL;
+ const MYSQLND_CSTRING query_string = {query, query_len};
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_STMT_PREPARE, conn, query_string);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
+ if (FAIL == ret) {
+ goto fail;
+ }
+ }
+
+ if (FAIL == mysqlnd_stmt_read_prepare_response(s_to_prepare)) {
goto fail;
}
@@ -437,19 +444,19 @@ MYSQLND_METHOD(mysqlnd_stmt, prepare)(MYSQLND_STMT * const s, const char * const
no metadata at prepare.
*/
if (stmt_to_prepare->field_count) {
- MYSQLND_RES * result = stmt->conn->m->result_init(stmt_to_prepare->field_count, stmt_to_prepare->persistent);
+ MYSQLND_RES * result = conn->m->result_init(stmt_to_prepare->field_count, stmt_to_prepare->persistent);
if (!result) {
- SET_OOM_ERROR(*stmt->conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
goto fail;
}
/* Allocate the result now as it is needed for the reading of metadata */
stmt_to_prepare->result = result;
- result->conn = stmt_to_prepare->conn->m->get_reference(stmt_to_prepare->conn);
+ result->conn = conn->m->get_reference(conn);
result->type = MYSQLND_RES_PS_BUF;
- if (FAIL == result->m.read_result_metadata(result, stmt_to_prepare->conn) ||
+ if (FAIL == result->m.read_result_metadata(result, conn) ||
FAIL == mysqlnd_stmt_prepare_read_eof(s_to_prepare))
{
goto fail;
@@ -491,23 +498,22 @@ fail:
static enum_func_status
mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_exec_response_type type)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
enum_func_status ret;
- MYSQLND_CONN_DATA * conn;
DBG_ENTER("mysqlnd_stmt_execute_parse_response");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
- conn = stmt->conn;
- CONN_SET_STATE(conn, CONN_QUERY_SENT);
+ SET_CONNECTION_STATE(&conn->state, CONN_QUERY_SENT);
- ret = mysqlnd_query_read_result_set_header(stmt->conn, s);
+ ret = conn->m->query_read_result_set_header(conn, s);
if (ret == FAIL) {
- COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
- memset(stmt->upsert_status, 0, sizeof(*stmt->upsert_status));
- stmt->upsert_status->affected_rows = conn->upsert_status->affected_rows;
- if (CONN_GET_STATE(conn) == CONN_QUIT_SENT) {
+ COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
+ UPSERT_STATUS_RESET(stmt->upsert_status);
+ UPSERT_STATUS_SET_AFFECTED_ROWS(stmt->upsert_status, UPSERT_STATUS_GET_AFFECTED_ROWS(conn->upsert_status));
+ if (GET_CONNECTION_STATE(&conn->state) == CONN_QUIT_SENT) {
/* close the statement here, the connection has been closed */
}
stmt->state = MYSQLND_STMT_PREPARED;
@@ -520,9 +526,13 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e
value is > LONG_MAX or < LONG_MIN, there is string conversion and we have
to resend the types. Next execution will also need to resend the type.
*/
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
- *stmt->upsert_status = *conn->upsert_status; /* copy status */
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
+ UPSERT_STATUS_SET_WARNINGS(stmt->upsert_status, UPSERT_STATUS_GET_WARNINGS(conn->upsert_status));
+ UPSERT_STATUS_SET_AFFECTED_ROWS(stmt->upsert_status, UPSERT_STATUS_GET_AFFECTED_ROWS(conn->upsert_status));
+ UPSERT_STATUS_SET_SERVER_STATUS(stmt->upsert_status, UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status));
+ UPSERT_STATUS_SET_LAST_INSERT_ID(stmt->upsert_status, UPSERT_STATUS_GET_LAST_INSERT_ID(conn->upsert_status));
+
stmt->state = MYSQLND_STMT_EXECUTED;
if (conn->last_query_type == QUERY_UPSERT || conn->last_query_type == QUERY_LOAD_LOCAL) {
DBG_INF("PASS");
@@ -535,7 +545,7 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e
For SHOW we don't create (bypasses PS in server)
a result set at prepare and thus a connection was missing
*/
- stmt->result->conn = stmt->conn->m->get_reference(stmt->conn);
+ stmt->result->conn = conn->m->get_reference(conn);
}
/* Update stmt->field_count as SHOW sets it to 0 at prepare */
@@ -552,13 +562,13 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e
use_result() or store_result() and we should be able to scrap the
data on the line, if he just decides to close the statement.
*/
- DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status,
- stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS);
+ DBG_INF_FMT("server_status=%u cursor=%u", UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status),
+ UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) & SERVER_STATUS_CURSOR_EXISTS);
- if (stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS) {
+ if (UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) & SERVER_STATUS_CURSOR_EXISTS) {
DBG_INF("cursor exists");
stmt->cursor_exists = TRUE;
- CONN_SET_STATE(conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
/* Only cursor read */
stmt->default_rset_handler = s->m->use_result;
DBG_INF("use_result");
@@ -586,7 +596,7 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e
}
}
#ifndef MYSQLND_DONT_SKIP_OUT_PARAMS_RESULTSET
- if (stmt->upsert_status->server_status & SERVER_PS_OUT_PARAMS) {
+ if (UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) & SERVER_PS_OUT_PARAMS) {
s->m->free_stmt_content(s);
DBG_INF("PS OUT Variable RSet, skipping");
/* OUT params result set. Skip for now to retain compatibility */
@@ -594,10 +604,10 @@ mysqlnd_stmt_execute_parse_response(MYSQLND_STMT * const s, enum_mysqlnd_parse_e
}
#endif
- DBG_INF_FMT("server_status=%u cursor=%u", stmt->upsert_status->server_status, stmt->upsert_status->server_status & SERVER_STATUS_CURSOR_EXISTS);
+ DBG_INF_FMT("server_status=%u cursor=%u", UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status), UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) & SERVER_STATUS_CURSOR_EXISTS);
- if (ret == PASS && conn->last_query_type == QUERY_UPSERT && stmt->upsert_status->affected_rows) {
- MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_PS, stmt->upsert_status->affected_rows);
+ if (ret == PASS && conn->last_query_type == QUERY_UPSERT && UPSERT_STATUS_GET_AFFECTED_ROWS(stmt->upsert_status)) {
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn->stats, STAT_ROWS_AFFECTED_PS, UPSERT_STATUS_GET_AFFECTED_ROWS(stmt->upsert_status));
}
DBG_INF(ret == PASS? "PASS":"FAIL");
@@ -623,24 +633,23 @@ MYSQLND_METHOD(mysqlnd_stmt, execute)(MYSQLND_STMT * const s)
/* {{{ mysqlnd_stmt::send_execute */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_send_execute_type type, zval * read_cb, zval * err_cb)
+MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, const enum_mysqlnd_send_execute_type type, zval * read_cb, zval * err_cb)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
enum_func_status ret;
- MYSQLND_CONN_DATA * conn;
zend_uchar *request = NULL;
size_t request_len;
zend_bool free_request;
DBG_ENTER("mysqlnd_stmt::send_execute");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
- conn = stmt->conn;
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- SET_ERROR_AFF_ROWS(stmt);
- SET_ERROR_AFF_ROWS(stmt->conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(stmt->upsert_status);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
if (stmt->result && stmt->state >= MYSQLND_STMT_PREPARED && stmt->field_count) {
/*
@@ -688,9 +697,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_
stmt->state = MYSQLND_STMT_PREPARED;
} else if (stmt->state < MYSQLND_STMT_PREPARED) {
/* Only initted - error */
- SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
- mysqlnd_out_of_sync);
- SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_INF("FAIL");
DBG_RETURN(FAIL);
}
@@ -698,8 +705,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_
if (stmt->param_count) {
unsigned int i, not_bound = 0;
if (!stmt->param_bind) {
- SET_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE,
- "No data supplied for parameters in prepared statement");
+ SET_CLIENT_ERROR(stmt->error_info, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE, "No data supplied for parameters in prepared statement");
DBG_INF("FAIL");
DBG_RETURN(FAIL);
}
@@ -712,7 +718,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_
char * msg;
mnd_sprintf(&msg, 0, "No data supplied for %u parameter%s in prepared statement",
not_bound, not_bound>1 ?"s":"");
- SET_STMT_ERROR(stmt, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE, msg);
+ SET_CLIENT_ERROR(stmt->error_info, CR_PARAMS_NOT_BOUND, UNKNOWN_SQLSTATE, msg);
if (msg) {
mnd_sprintf_free(msg);
}
@@ -722,12 +728,15 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_
}
ret = s->m->generate_execute_request(s, &request, &request_len, &free_request);
if (ret == PASS) {
- /* support for buffer types should be added here ! */
- ret = stmt->conn->m->simple_command(stmt->conn, COM_STMT_EXECUTE, request, request_len,
- PROT_LAST /* we will handle the response packet*/,
- FALSE, FALSE);
+ const MYSQLND_CSTRING payload = {(const char*) request, request_len};
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_STMT_EXECUTE, conn, payload);
+ ret = FAIL;
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ }
} else {
- SET_STMT_ERROR(stmt, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Couldn't generate the request. Possibly OOM.");
+ SET_CLIENT_ERROR(stmt->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, "Couldn't generate the request. Possibly OOM.");
}
if (free_request) {
@@ -735,7 +744,7 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_
}
if (ret == FAIL) {
- COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
+ COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
DBG_INF("FAIL");
DBG_RETURN(FAIL);
}
@@ -748,10 +757,10 @@ MYSQLND_METHOD(mysqlnd_stmt, send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_
/* {{{ mysqlnd_stmt_fetch_row_buffered */
enum_func_status
-mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything)
+mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything)
{
MYSQLND_STMT * s = (MYSQLND_STMT *) param;
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
const MYSQLND_RES_METADATA * const meta = result->meta;
unsigned int field_count = meta->field_count;
@@ -849,12 +858,13 @@ mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, unsigned int
/* {{{ mysqlnd_stmt_fetch_row_unbuffered */
enum_func_status
-mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything)
+mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything)
{
enum_func_status ret;
MYSQLND_STMT * s = (MYSQLND_STMT *) param;
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
MYSQLND_PACKET_ROW * row_packet;
+ MYSQLND_CONN_DATA * conn = result->conn;
const MYSQLND_RES_METADATA * const meta = result->meta;
DBG_ENTER("mysqlnd_stmt_fetch_row_unbuffered");
@@ -866,9 +876,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i
DBG_INF("EOF already reached");
DBG_RETURN(PASS);
}
- if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
- UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ if (GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA) {
+ SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR("command out of sync");
DBG_RETURN(FAIL);
}
@@ -883,11 +892,11 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i
If we skip rows (stmt == NULL || stmt->result_bind == NULL) we have to
result->unbuf->m.free_last_data() before it. The function returns always true.
*/
- if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
+ if (PASS == (ret = PACKET_READ(row_packet)) && !row_packet->eof) {
unsigned int i, field_count = result->field_count;
if (!row_packet->skip_extraction) {
- result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL);
+ result->unbuf->m.free_last_data(result->unbuf, conn->stats);
result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
@@ -898,8 +907,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i
result->unbuf->last_row_data,
row_packet->field_count,
row_packet->fields_metadata,
- result->conn->options->int_and_float_native,
- result->conn->stats))
+ conn->options->int_and_float_native,
+ conn->stats))
{
DBG_RETURN(FAIL);
}
@@ -918,8 +927,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i
zval_dtor(result);
#endif
if (!Z_ISNULL_P(data)) {
- if ((Z_TYPE_P(data) == IS_STRING) &&
- (meta->fields[i].max_length < (zend_ulong) Z_STRLEN_P(data))) {
+ if ((Z_TYPE_P(data) == IS_STRING) && (meta->fields[i].max_length < (zend_ulong) Z_STRLEN_P(data))){
meta->fields[i].max_length = Z_STRLEN_P(data);
}
ZVAL_COPY_VALUE(result, data);
@@ -930,7 +938,7 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i
}
}
}
- MYSQLND_INC_CONN_STATISTIC(stmt->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_PS_UNBUF);
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_PS_UNBUF);
} else {
DBG_INF("skipping extraction");
/*
@@ -947,26 +955,27 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i
*fetched_anything = TRUE;
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- COPY_CLIENT_ERROR(*stmt->conn->error_info, row_packet->error_info);
- COPY_CLIENT_ERROR(*stmt->error_info, row_packet->error_info);
+ COPY_CLIENT_ERROR(conn->error_info, row_packet->error_info);
+ COPY_CLIENT_ERROR(stmt->error_info, row_packet->error_info);
}
- CONN_SET_STATE(result->conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
} else if (row_packet->eof) {
DBG_INF("EOF");
/* Mark the connection as usable again */
result->unbuf->eof_reached = TRUE;
- memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status));
- result->conn->upsert_status->warning_count = row_packet->warning_count;
- result->conn->upsert_status->server_status = row_packet->server_status;
+ UPSERT_STATUS_RESET(conn->upsert_status);
+ UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, row_packet->warning_count);
+ UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet->server_status);
+
/*
result->row_packet will be cleaned when
destroying the result object
*/
- if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
- CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING);
+ if (UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_MORE_RESULTS_EXISTS) {
+ SET_CONNECTION_STATE(&conn->state, CONN_NEXT_RESULT_PENDING);
} else {
- CONN_SET_STATE(result->conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
}
}
@@ -980,32 +989,29 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, use_result)(MYSQLND_STMT * s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
MYSQLND_RES * result;
- MYSQLND_CONN_DATA * conn;
DBG_ENTER("mysqlnd_stmt::use_result");
- if (!stmt || !stmt->conn || !stmt->result) {
+ if (!stmt || !conn || !stmt->result) {
DBG_RETURN(NULL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- conn = stmt->conn;
-
if (!stmt->field_count ||
- (!stmt->cursor_exists && CONN_GET_STATE(conn) != CONN_FETCHING_DATA) ||
- (stmt->cursor_exists && CONN_GET_STATE(conn) != CONN_READY) ||
+ (!stmt->cursor_exists && GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA) ||
+ (stmt->cursor_exists && GET_CONNECTION_STATE(&conn->state) != CONN_READY) ||
(stmt->state != MYSQLND_STMT_WAITING_USE_OR_STORE))
{
- SET_CLIENT_ERROR(*conn->error_info, CR_COMMANDS_OUT_OF_SYNC,
- UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR("command out of sync");
DBG_RETURN(NULL);
}
- SET_EMPTY_ERROR(*stmt->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
- MYSQLND_INC_CONN_STATISTIC(stmt->conn->stats, STAT_PS_UNBUFFERED_SETS);
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_PS_UNBUFFERED_SETS);
result = stmt->result;
result->m.use_result(stmt->result, TRUE);
@@ -1019,16 +1025,15 @@ MYSQLND_METHOD(mysqlnd_stmt, use_result)(MYSQLND_STMT * s)
/* }}} */
-#define STMT_ID_LENGTH 4
-
/* {{{ mysqlnd_fetch_row_cursor */
enum_func_status
mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything)
{
enum_func_status ret;
MYSQLND_STMT * s = (MYSQLND_STMT *) param;
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- zend_uchar buf[STMT_ID_LENGTH /* statement id */ + 4 /* number of rows to fetch */];
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
+ zend_uchar buf[MYSQLND_STMT_ID_LENGTH /* statement id */ + 4 /* number of rows to fetch */];
MYSQLND_PACKET_ROW * row_packet;
DBG_ENTER("mysqlnd_fetch_stmt_row_cursor");
@@ -1037,13 +1042,11 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f
DBG_ERR("no statement");
DBG_RETURN(FAIL);
}
-
DBG_INF_FMT("stmt=%lu flags=%u", stmt->stmt_id, flags);
if (stmt->state < MYSQLND_STMT_USER_FETCHING) {
/* Only initted - error */
- SET_CLIENT_ERROR(*stmt->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE,
- mysqlnd_out_of_sync);
+ SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR("command out of sync");
DBG_RETURN(FAIL);
}
@@ -1051,28 +1054,38 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
int4store(buf, stmt->stmt_id);
- int4store(buf + STMT_ID_LENGTH, 1); /* for now fetch only one row */
+ int4store(buf + MYSQLND_STMT_ID_LENGTH, 1); /* for now fetch only one row */
+
+ {
+ const MYSQLND_CSTRING payload = {(const char*) buf, sizeof(buf)};
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_STMT_FETCH, conn, payload);
+ ret = FAIL;
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ if (ret == FAIL) {
+ COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
+ }
+ }
+ if (FAIL == ret) {
+ DBG_RETURN(FAIL);
+ }
- if (FAIL == stmt->conn->m->simple_command(stmt->conn, COM_STMT_FETCH, buf, sizeof(buf),
- PROT_LAST /* we will handle the response packet*/,
- FALSE, TRUE)) {
- COPY_CLIENT_ERROR(*stmt->error_info, *stmt->conn->error_info);
- DBG_RETURN(FAIL);
}
row_packet->skip_extraction = stmt->result_bind? FALSE:TRUE;
- memset(stmt->upsert_status, 0, sizeof(*stmt->upsert_status));
- if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
+ UPSERT_STATUS_RESET(stmt->upsert_status);
+ if (PASS == (ret = PACKET_READ(row_packet)) && !row_packet->eof) {
const MYSQLND_RES_METADATA * const meta = result->meta;
unsigned int i, field_count = result->field_count;
if (!row_packet->skip_extraction) {
- result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL);
+ result->unbuf->m.free_last_data(result->unbuf, conn->stats);
result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
@@ -1083,8 +1096,8 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f
result->unbuf->last_row_data,
row_packet->field_count,
row_packet->fields_metadata,
- result->conn->options->int_and_float_native,
- result->conn->stats))
+ conn->options->int_and_float_native,
+ conn->stats))
{
DBG_RETURN(FAIL);
}
@@ -1130,34 +1143,30 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f
row_packet->row_buffer = NULL;
}
/* We asked for one row, the next one should be EOF, eat it */
- ret = PACKET_READ(row_packet, result->conn);
+ ret = PACKET_READ(row_packet);
if (row_packet->row_buffer) {
row_packet->row_buffer->free_chunk(row_packet->row_buffer);
row_packet->row_buffer = NULL;
}
- MYSQLND_INC_CONN_STATISTIC(stmt->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_PS_CURSOR);
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_PS_CURSOR);
result->unbuf->row_count++;
*fetched_anything = TRUE;
} else {
*fetched_anything = FALSE;
+ UPSERT_STATUS_SET_WARNINGS(stmt->upsert_status, row_packet->warning_count);
+ UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, row_packet->warning_count);
- stmt->upsert_status->warning_count =
- stmt->conn->upsert_status->warning_count =
- row_packet->warning_count;
-
- stmt->upsert_status->server_status =
- stmt->conn->upsert_status->server_status =
- row_packet->server_status;
+ UPSERT_STATUS_SET_SERVER_STATUS(stmt->upsert_status, row_packet->server_status);
+ UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet->server_status);
result->unbuf->eof_reached = row_packet->eof;
}
- stmt->upsert_status->warning_count =
- stmt->conn->upsert_status->warning_count =
- row_packet->warning_count;
- stmt->upsert_status->server_status =
- stmt->conn->upsert_status->server_status =
- row_packet->server_status;
+ UPSERT_STATUS_SET_WARNINGS(stmt->upsert_status, row_packet->warning_count);
+ UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, row_packet->warning_count);
+
+ UPSERT_STATUS_SET_SERVER_STATUS(stmt->upsert_status, row_packet->server_status);
+ UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet->server_status);
DBG_INF_FMT("ret=%s fetched=%u server_status=%u warnings=%u eof=%u",
ret == PASS? "PASS":"FAIL", *fetched_anything,
@@ -1172,7 +1181,8 @@ mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, unsigned int f
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fetched_anything)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
enum_func_status ret;
DBG_ENTER("mysqlnd_stmt::fetch");
if (!stmt || !stmt->conn) {
@@ -1180,10 +1190,8 @@ MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fe
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- if (!stmt->result ||
- stmt->state < MYSQLND_STMT_WAITING_USE_OR_STORE) {
- SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
-
+ if (!stmt->result || stmt->state < MYSQLND_STMT_WAITING_USE_OR_STORE) {
+ SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR("command out of sync");
DBG_RETURN(FAIL);
} else if (stmt->state == MYSQLND_STMT_WAITING_USE_OR_STORE) {
@@ -1193,8 +1201,8 @@ MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fe
}
stmt->state = MYSQLND_STMT_USER_FETCHING;
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
DBG_INF_FMT("result_bind=%p separated_once=%u", &stmt->result_bind, stmt->result_zvals_separated_once);
/*
@@ -1228,18 +1236,18 @@ MYSQLND_METHOD(mysqlnd_stmt, fetch)(MYSQLND_STMT * const s, zend_bool * const fe
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret = PASS;
- zend_uchar cmd_buf[STMT_ID_LENGTH /* statement id */];
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
DBG_ENTER("mysqlnd_stmt::reset");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
if (stmt->stmt_id) {
MYSQLND_CONN_DATA * conn = stmt->conn;
@@ -1262,12 +1270,18 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s)
be separated before that.
*/
- int4store(cmd_buf, stmt->stmt_id);
- if (CONN_GET_STATE(conn) == CONN_READY &&
- FAIL == (ret = conn->m->simple_command(conn, COM_STMT_RESET, cmd_buf,
- sizeof(cmd_buf), PROT_OK_PACKET,
- FALSE, TRUE))) {
- COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
+ if (GET_CONNECTION_STATE(&conn->state) == CONN_READY) {
+ size_t stmt_id = stmt->stmt_id;
+ struct st_mysqlnd_protocol_command * command = stmt->conn->command_factory(COM_STMT_RESET, stmt->conn, stmt_id);
+ ret = FAIL;
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+
+ if (ret == FAIL) {
+ COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
+ }
+ }
}
*stmt->upsert_status = *conn->upsert_status;
}
@@ -1281,11 +1295,12 @@ MYSQLND_METHOD(mysqlnd_stmt, reset)(MYSQLND_STMT * const s)
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, flush)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret = PASS;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
DBG_ENTER("mysqlnd_stmt::flush");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
@@ -1318,76 +1333,72 @@ MYSQLND_METHOD(mysqlnd_stmt, flush)(MYSQLND_STMT * const s)
/* {{{ mysqlnd_stmt::send_long_data */
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned int param_no,
- const char * const data, zend_ulong length)
+ const char * const data, zend_ulong data_length)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
enum_func_status ret = FAIL;
- MYSQLND_CONN_DATA * conn;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
zend_uchar * cmd_buf;
- enum php_mysqlnd_server_command cmd = COM_STMT_SEND_LONG_DATA;
DBG_ENTER("mysqlnd_stmt::send_long_data");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
- DBG_INF_FMT("stmt=%lu param_no=%u data_len=%lu", stmt->stmt_id, param_no, length);
-
- conn = stmt->conn;
+ DBG_INF_FMT("stmt=%lu param_no=%u data_len=%lu", stmt->stmt_id, param_no, data_length);
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
if (stmt->state < MYSQLND_STMT_PREPARED) {
- SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
+ SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
DBG_ERR("not prepared");
DBG_RETURN(FAIL);
}
if (!stmt->param_bind) {
- SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_ERR("command out of sync");
DBG_RETURN(FAIL);
}
if (param_no >= stmt->param_count) {
- SET_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number");
+ SET_CLIENT_ERROR(stmt->error_info, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number");
DBG_ERR("invalid param_no");
DBG_RETURN(FAIL);
}
if (stmt->param_bind[param_no].type != MYSQL_TYPE_LONG_BLOB) {
- SET_STMT_ERROR(stmt, CR_INVALID_BUFFER_USE, UNKNOWN_SQLSTATE, mysqlnd_not_bound_as_blob);
+ SET_CLIENT_ERROR(stmt->error_info, CR_INVALID_BUFFER_USE, UNKNOWN_SQLSTATE, mysqlnd_not_bound_as_blob);
DBG_ERR("param_no is not of a blob type");
DBG_RETURN(FAIL);
}
- /*
- XXX: Unfortunately we have to allocate additional buffer to be able the
- additional data, which is like a header inside the payload.
- This should be optimised, but it will be a pervasive change, so
- conn->m->simple_command() will accept not a buffer, but actually MYSQLND_STRING*
- terminated by NULL, to send. If the strings are not big, we can collapse them
- on the buffer every connection has, but otherwise we will just send them
- one by one to the wire.
- */
-
- if (CONN_GET_STATE(conn) == CONN_READY) {
- size_t packet_len;
- cmd_buf = mnd_emalloc(packet_len = STMT_ID_LENGTH + 2 + length);
+ if (GET_CONNECTION_STATE(&conn->state) == CONN_READY) {
+ const size_t packet_len = MYSQLND_STMT_ID_LENGTH + 2 + data_length;
+ cmd_buf = mnd_emalloc(packet_len);
if (cmd_buf) {
stmt->param_bind[param_no].flags |= MYSQLND_PARAM_BIND_BLOB_USED;
int4store(cmd_buf, stmt->stmt_id);
- int2store(cmd_buf + STMT_ID_LENGTH, param_no);
- memcpy(cmd_buf + STMT_ID_LENGTH + 2, data, length);
+ int2store(cmd_buf + MYSQLND_STMT_ID_LENGTH, param_no);
+ memcpy(cmd_buf + MYSQLND_STMT_ID_LENGTH + 2, data, data_length);
- /* COM_STMT_SEND_LONG_DATA doesn't send an OK packet*/
- ret = conn->m->simple_command(conn, cmd, cmd_buf, packet_len, PROT_LAST , FALSE, TRUE);
- mnd_efree(cmd_buf);
- if (FAIL == ret) {
- COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
+ /* COM_STMT_SEND_LONG_DATA doesn't acknowledge with an OK packet */
+ {
+ const MYSQLND_CSTRING payload = {(const char *) cmd_buf, packet_len};
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_STMT_SEND_LONG_DATA, conn, payload);
+ ret = FAIL;
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+ if (ret == FAIL) {
+ COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
+ }
+ }
}
+
+ mnd_efree(cmd_buf);
} else {
ret = FAIL;
- SET_OOM_ERROR(*stmt->error_info);
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(stmt->error_info);
+ SET_OOM_ERROR(conn->error_info);
}
/*
Cover protocol error: COM_STMT_SEND_LONG_DATA was designed to be quick and not
@@ -1409,12 +1420,12 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
#if HAVE_USLEEP && !defined(PHP_WIN32)
usleep(120000);
#endif
- if ((packet_len = conn->net->m.consume_uneaten_data(conn->net, cmd))) {
+ if ((packet_len = conn->protocol_frame_codec->m.consume_uneaten_data(conn->protocol_frame_codec, COM_STMT_SEND_LONG_DATA))) {
php_error_docref(NULL, E_WARNING, "There was an error "
"while sending long data. Probably max_allowed_packet_size "
"is smaller than the data. You have to increase it or send "
"smaller chunks of data. Answer was "MYSQLND_SZ_T_SPEC" bytes long.", packet_len);
- SET_STMT_ERROR(stmt, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE,
+ SET_CLIENT_ERROR(stmt->error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE,
"Server responded to COM_STMT_SEND_LONG_DATA.");
ret = FAIL;
}
@@ -1431,15 +1442,17 @@ MYSQLND_METHOD(mysqlnd_stmt, send_long_data)(MYSQLND_STMT * const s, unsigned in
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const s, MYSQLND_PARAM_BIND * const param_bind)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
+
DBG_ENTER("mysqlnd_stmt::bind_param");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu param_count=%u", stmt->stmt_id, stmt->param_count);
if (stmt->state < MYSQLND_STMT_PREPARED) {
- SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
+ SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
DBG_ERR("not prepared");
if (param_bind) {
s->m->free_parameter_bind(s, param_bind);
@@ -1447,14 +1460,14 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_parameters)(MYSQLND_STMT * const s, MYSQLND_PA
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
if (stmt->param_count) {
unsigned int i = 0;
if (!param_bind) {
- SET_STMT_ERROR(stmt, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, "Re-binding (still) not supported");
+ SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, "Re-binding (still) not supported");
DBG_ERR("Re-binding (still) not supported");
DBG_RETURN(FAIL);
} else if (stmt->param_bind) {
@@ -1500,26 +1513,28 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigned int param_no,
zval * const zv, zend_uchar type)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
+
DBG_ENTER("mysqlnd_stmt::bind_one_parameter");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu param_no=%u param_count=%u type=%u", stmt->stmt_id, param_no, stmt->param_count, type);
if (stmt->state < MYSQLND_STMT_PREPARED) {
- SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
+ SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
DBG_ERR("not prepared");
DBG_RETURN(FAIL);
}
if (param_no >= stmt->param_count) {
- SET_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number");
+ SET_CLIENT_ERROR(stmt->error_info, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number");
DBG_ERR("invalid param_no");
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
if (stmt->param_count) {
if (!stmt->param_bind) {
@@ -1554,21 +1569,23 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_parameter)(MYSQLND_STMT * const s, unsigne
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, refresh_bind_param)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
+
DBG_ENTER("mysqlnd_stmt::refresh_bind_param");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu param_count=%u", stmt->stmt_id, stmt->param_count);
if (stmt->state < MYSQLND_STMT_PREPARED) {
- SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
+ SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
DBG_ERR("not prepared");
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
if (stmt->param_count) {
stmt->send_types_to_server = 1;
@@ -1583,15 +1600,17 @@ static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const s,
MYSQLND_RESULT_BIND * const result_bind)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
+
DBG_ENTER("mysqlnd_stmt::bind_result");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu field_count=%u", stmt->stmt_id, stmt->field_count);
if (stmt->state < MYSQLND_STMT_PREPARED) {
- SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
+ SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
if (result_bind) {
s->m->free_result_bind(s, result_bind);
}
@@ -1599,8 +1618,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const s,
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
if (stmt->field_count) {
unsigned int i = 0;
@@ -1639,27 +1658,29 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_result)(MYSQLND_STMT * const s,
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, bind_one_result)(MYSQLND_STMT * const s, unsigned int param_no)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
+
DBG_ENTER("mysqlnd_stmt::bind_result");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu field_count=%u", stmt->stmt_id, stmt->field_count);
if (stmt->state < MYSQLND_STMT_PREPARED) {
- SET_STMT_ERROR(stmt, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
+ SET_CLIENT_ERROR(stmt->error_info, CR_NO_PREPARE_STMT, UNKNOWN_SQLSTATE, mysqlnd_stmt_not_prepared);
DBG_ERR("not prepared");
DBG_RETURN(FAIL);
}
if (param_no >= stmt->field_count) {
- SET_STMT_ERROR(stmt, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number");
+ SET_CLIENT_ERROR(stmt->error_info, CR_INVALID_PARAMETER_NO, UNKNOWN_SQLSTATE, "Invalid parameter number");
DBG_ERR("invalid param_no");
DBG_RETURN(FAIL);
}
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
if (stmt->field_count) {
mysqlnd_stmt_separate_one_result_bind(s, param_no);
@@ -1690,8 +1711,8 @@ MYSQLND_METHOD(mysqlnd_stmt, bind_one_result)(MYSQLND_STMT * const s, unsigned i
static uint64_t
MYSQLND_METHOD(mysqlnd_stmt, insert_id)(const MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status->last_insert_id : 0;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ return stmt? UPSERT_STATUS_GET_LAST_INSERT_ID(stmt->upsert_status) : 0;
}
/* }}} */
@@ -1700,8 +1721,8 @@ MYSQLND_METHOD(mysqlnd_stmt, insert_id)(const MYSQLND_STMT * const s)
static uint64_t
MYSQLND_METHOD(mysqlnd_stmt, affected_rows)(const MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status->affected_rows : 0;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ return stmt? UPSERT_STATUS_GET_AFFECTED_ROWS(stmt->upsert_status) : 0;
}
/* }}} */
@@ -1710,7 +1731,7 @@ MYSQLND_METHOD(mysqlnd_stmt, affected_rows)(const MYSQLND_STMT * const s)
static uint64_t
MYSQLND_METHOD(mysqlnd_stmt, num_rows)(const MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
return stmt && stmt->result? mysqlnd_num_rows(stmt->result):0;
}
/* }}} */
@@ -1720,8 +1741,8 @@ MYSQLND_METHOD(mysqlnd_stmt, num_rows)(const MYSQLND_STMT * const s)
static unsigned int
MYSQLND_METHOD(mysqlnd_stmt, warning_count)(const MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status->warning_count : 0;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ return stmt? UPSERT_STATUS_GET_WARNINGS(stmt->upsert_status) : 0;
}
/* }}} */
@@ -1730,8 +1751,8 @@ MYSQLND_METHOD(mysqlnd_stmt, warning_count)(const MYSQLND_STMT * const s)
static unsigned int
MYSQLND_METHOD(mysqlnd_stmt, server_status)(const MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- return stmt? stmt->upsert_status->server_status : 0;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ return stmt? UPSERT_STATUS_GET_SERVER_STATUS(stmt->upsert_status) : 0;
}
/* }}} */
@@ -1740,7 +1761,7 @@ MYSQLND_METHOD(mysqlnd_stmt, server_status)(const MYSQLND_STMT * const s)
static unsigned int
MYSQLND_METHOD(mysqlnd_stmt, field_count)(const MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
return stmt? stmt->field_count : 0;
}
/* }}} */
@@ -1750,7 +1771,7 @@ MYSQLND_METHOD(mysqlnd_stmt, field_count)(const MYSQLND_STMT * const s)
static unsigned int
MYSQLND_METHOD(mysqlnd_stmt, param_count)(const MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
return stmt? stmt->param_count : 0;
}
/* }}} */
@@ -1760,7 +1781,7 @@ MYSQLND_METHOD(mysqlnd_stmt, param_count)(const MYSQLND_STMT * const s)
static unsigned int
MYSQLND_METHOD(mysqlnd_stmt, errno)(const MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
return stmt? stmt->error_info->error_no : 0;
}
/* }}} */
@@ -1770,7 +1791,7 @@ MYSQLND_METHOD(mysqlnd_stmt, errno)(const MYSQLND_STMT * const s)
static const char *
MYSQLND_METHOD(mysqlnd_stmt, error)(const MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
return stmt? stmt->error_info->error : 0;
}
/* }}} */
@@ -1780,7 +1801,7 @@ MYSQLND_METHOD(mysqlnd_stmt, error)(const MYSQLND_STMT * const s)
static const char *
MYSQLND_METHOD(mysqlnd_stmt, sqlstate)(const MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
return stmt && stmt->error_info->sqlstate[0] ? stmt->error_info->sqlstate:MYSQLND_SQLSTATE_NULL;
}
/* }}} */
@@ -1790,7 +1811,7 @@ MYSQLND_METHOD(mysqlnd_stmt, sqlstate)(const MYSQLND_STMT * const s)
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, data_seek)(const MYSQLND_STMT * const s, uint64_t row)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
return stmt && stmt->result? stmt->result->m.seek_data(stmt->result, row) : FAIL;
}
/* }}} */
@@ -1800,7 +1821,7 @@ MYSQLND_METHOD(mysqlnd_stmt, data_seek)(const MYSQLND_STMT * const s, uint64_t r
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, param_metadata)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
if (!stmt || !stmt->param_count) {
return NULL;
}
@@ -1813,57 +1834,57 @@ MYSQLND_METHOD(mysqlnd_stmt, param_metadata)(MYSQLND_STMT * const s)
static MYSQLND_RES *
MYSQLND_METHOD(mysqlnd_stmt, result_metadata)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND_RES *result;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
+ MYSQLND_RES * result_meta = NULL;
DBG_ENTER("mysqlnd_stmt::result_metadata");
- if (!stmt) {
+ if (!stmt || ! conn) {
DBG_RETURN(NULL);
}
DBG_INF_FMT("stmt=%u field_count=%u", stmt->stmt_id, stmt->field_count);
- if (!stmt->field_count || !stmt->conn || !stmt->result || !stmt->result->meta) {
+ if (!stmt->field_count || !stmt->result || !stmt->result->meta) {
DBG_INF("NULL");
DBG_RETURN(NULL);
}
if (stmt->update_max_length && stmt->result->stored_data) {
/* stored result, we have to update the max_length before we clone the meta data :( */
- stmt->result->stored_data->m.initialize_result_set_rest(stmt->result->stored_data, stmt->result->meta, stmt->conn->stats,
- stmt->conn->options->int_and_float_native);
+ stmt->result->stored_data->m.initialize_result_set_rest(stmt->result->stored_data,
+ stmt->result->meta,
+ conn->stats,
+ conn->options->int_and_float_native);
}
/*
TODO: This implementation is kind of a hack,
find a better way to do it. In different functions I have put
fuses to check for result->m.fetch_row() being NULL. This should
be handled in a better way.
-
- In the meantime we don't need a zval cache reference for this fake
- result set, so we don't get one.
*/
do {
- result = stmt->conn->m->result_init(stmt->field_count, stmt->persistent);
- if (!result) {
+ result_meta = conn->m->result_init(stmt->field_count, stmt->persistent);
+ if (!result_meta) {
break;
}
- result->type = MYSQLND_RES_NORMAL;
- result->unbuf = mysqlnd_result_unbuffered_init(stmt->field_count, TRUE, result->persistent);
- if (!result->unbuf) {
+ result_meta->type = MYSQLND_RES_NORMAL;
+ result_meta->unbuf = mysqlnd_result_unbuffered_init(stmt->field_count, TRUE, result_meta->persistent);
+ if (!result_meta->unbuf) {
break;
}
- result->unbuf->eof_reached = TRUE;
- result->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE);
- if (!result->meta) {
+ result_meta->unbuf->eof_reached = TRUE;
+ result_meta->meta = stmt->result->meta->m->clone_metadata(stmt->result->meta, FALSE);
+ if (!result_meta->meta) {
break;
}
- DBG_INF_FMT("result=%p", result);
- DBG_RETURN(result);
+ DBG_INF_FMT("result_meta=%p", result_meta);
+ DBG_RETURN(result_meta);
} while (0);
- SET_OOM_ERROR(*stmt->conn->error_info);
- if (result) {
- result->m.free_result(result, TRUE);
+ SET_OOM_ERROR(conn->error_info);
+ if (result_meta) {
+ result_meta->m.free_result(result_meta, TRUE);
}
DBG_RETURN(NULL);
}
@@ -1876,7 +1897,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const s,
enum mysqlnd_stmt_attr attr_type,
const void * const value)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
DBG_ENTER("mysqlnd_stmt::attr_set");
if (!stmt) {
DBG_RETURN(FAIL);
@@ -1896,7 +1917,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const s,
case STMT_ATTR_CURSOR_TYPE: {
unsigned int ival = *(unsigned int *) value;
if (ival > (zend_ulong) CURSOR_TYPE_READ_ONLY) {
- SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented");
+ SET_CLIENT_ERROR(stmt->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented");
DBG_INF("FAIL");
DBG_RETURN(FAIL);
}
@@ -1908,7 +1929,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const s,
if (ival == 0) {
ival = MYSQLND_DEFAULT_PREFETCH_ROWS;
} else if (ival > 1) {
- SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented");
+ SET_CLIENT_ERROR(stmt->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented");
DBG_INF("FAIL");
DBG_RETURN(FAIL);
}
@@ -1916,7 +1937,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_set)(MYSQLND_STMT * const s,
break;
}
default:
- SET_STMT_ERROR(stmt, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented");
+ SET_CLIENT_ERROR(stmt->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "Not implemented");
DBG_RETURN(FAIL);
}
DBG_INF("PASS");
@@ -1931,7 +1952,7 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_get)(const MYSQLND_STMT * const s,
enum mysqlnd_stmt_attr attr_type,
void * const value)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
DBG_ENTER("mysqlnd_stmt::attr_set");
if (!stmt) {
DBG_RETURN(FAIL);
@@ -1962,9 +1983,11 @@ MYSQLND_METHOD(mysqlnd_stmt, attr_get)(const MYSQLND_STMT * const s,
static enum_func_status
MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
+
DBG_ENTER("mysqlnd_stmt::free_result");
- if (!stmt || !stmt->conn) {
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
@@ -2005,7 +2028,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const s)
}
/* Line is free! */
- CONN_SET_STATE(stmt->conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
DBG_RETURN(PASS);
}
@@ -2016,7 +2039,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_result)(MYSQLND_STMT * const s)
static void
mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
unsigned int i;
DBG_ENTER("mysqlnd_stmt_separate_result_bind");
@@ -2037,8 +2060,7 @@ mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const s)
for (i = 0; i < stmt->field_count; i++) {
/* Let's try with no cache */
if (stmt->result_bind[i].bound == TRUE) {
- DBG_INF_FMT("%u has refcount=%u", i,
- Z_REFCOUNTED(stmt->result_bind[i].zv)? Z_REFCOUNT(stmt->result_bind[i].zv) : 0);
+ DBG_INF_FMT("%u has refcount=%u", i, Z_REFCOUNTED(stmt->result_bind[i].zv)? Z_REFCOUNT(stmt->result_bind[i].zv) : 0);
zval_ptr_dtor(&stmt->result_bind[i].zv);
}
}
@@ -2053,9 +2075,9 @@ mysqlnd_stmt_separate_result_bind(MYSQLND_STMT * const s)
/* {{{ mysqlnd_stmt_separate_one_result_bind */
static void
-mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param_no)
+mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, const unsigned int param_no)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
DBG_ENTER("mysqlnd_stmt_separate_one_result_bind");
if (!stmt) {
DBG_VOID_RETURN;
@@ -2073,9 +2095,7 @@ mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param
*/
/* Let's try with no cache */
if (stmt->result_bind[param_no].bound == TRUE) {
- DBG_INF_FMT("%u has refcount=%u", param_no,
- Z_REFCOUNTED(stmt->result_bind[param_no].zv)?
- Z_REFCOUNT(stmt->result_bind[param_no].zv) : 0);
+ DBG_INF_FMT("%u has refcount=%u", param_no, Z_REFCOUNTED(stmt->result_bind[param_no].zv)? Z_REFCOUNT(stmt->result_bind[param_no].zv) : 0);
zval_ptr_dtor(&stmt->result_bind[param_no].zv);
}
@@ -2088,7 +2108,7 @@ mysqlnd_stmt_separate_one_result_bind(MYSQLND_STMT * const s, unsigned int param
static void
MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
DBG_ENTER("mysqlnd_stmt::free_stmt_result");
if (!stmt) {
DBG_VOID_RETURN;
@@ -2119,7 +2139,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_result)(MYSQLND_STMT * const s)
static void
MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
DBG_ENTER("mysqlnd_stmt::free_stmt_content");
if (!stmt) {
DBG_VOID_RETURN;
@@ -2151,25 +2171,22 @@ MYSQLND_METHOD(mysqlnd_stmt, free_stmt_content)(MYSQLND_STMT * const s)
/* }}} */
-/* {{{ mysqlnd_stmt::net_close */
+/* {{{ mysqlnd_stmt::close_on_server */
static enum_func_status
-MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_bool implicit)
+MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, close_on_server)(MYSQLND_STMT * const s, zend_bool implicit)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
- MYSQLND_CONN_DATA * conn;
- zend_uchar cmd_buf[STMT_ID_LENGTH /* statement id */];
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
+ MYSQLND_CONN_DATA * conn = stmt? stmt->conn : NULL;
enum_mysqlnd_collected_stats statistic = STAT_LAST;
- DBG_ENTER("mysqlnd_stmt::net_close");
- if (!stmt || !stmt->conn) {
+ DBG_ENTER("mysqlnd_stmt::close_on_server");
+ if (!stmt || !conn) {
DBG_RETURN(FAIL);
}
DBG_INF_FMT("stmt=%lu", stmt->stmt_id);
- conn = stmt->conn;
-
- SET_EMPTY_ERROR(*stmt->error_info);
- SET_EMPTY_ERROR(*stmt->conn->error_info);
+ SET_EMPTY_ERROR(stmt->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
/*
If the user decided to close the statement right after execute()
@@ -2197,13 +2214,21 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_boo
MYSQLND_INC_GLOBAL_STATISTIC(implicit == TRUE? STAT_FREE_RESULT_IMPLICIT:
STAT_FREE_RESULT_EXPLICIT);
- int4store(cmd_buf, stmt->stmt_id);
- if (CONN_GET_STATE(conn) == CONN_READY &&
- FAIL == conn->m->simple_command(conn, COM_STMT_CLOSE, cmd_buf, sizeof(cmd_buf),
- PROT_LAST /* COM_STMT_CLOSE doesn't send an OK packet*/,
- FALSE, TRUE)) {
- COPY_CLIENT_ERROR(*stmt->error_info, *conn->error_info);
- DBG_RETURN(FAIL);
+ if (GET_CONNECTION_STATE(&conn->state) == CONN_READY) {
+ enum_func_status ret = FAIL;
+ size_t stmt_id = stmt->stmt_id;
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_STMT_CLOSE, conn, stmt_id);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
+
+ if (ret == FAIL) {
+ COPY_CLIENT_ERROR(stmt->error_info, *conn->error_info);
+ }
+ }
+ if (ret == FAIL) {
+ DBG_RETURN(FAIL);
+ }
}
}
switch (stmt->execute_count) {
@@ -2227,8 +2252,8 @@ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close)(MYSQLND_STMT * const s, zend_boo
s->m->free_stmt_content(s);
- if (stmt->conn) {
- stmt->conn->m->free_reference(stmt->conn);
+ if (conn) {
+ conn->m->free_reference(conn);
stmt->conn = NULL;
}
@@ -2251,7 +2276,7 @@ MYSQLND_METHOD(mysqlnd_stmt, dtor)(MYSQLND_STMT * const s, zend_bool implicit)
MYSQLND_INC_GLOBAL_STATISTIC(implicit == TRUE? STAT_STMT_CLOSE_IMPLICIT:
STAT_STMT_CLOSE_EXPLICIT);
- ret = s->m->net_close(s, implicit);
+ ret = s->m->close_on_server(s, implicit);
mnd_pefree(stmt, persistent);
}
mnd_pefree(s, persistent);
@@ -2266,7 +2291,7 @@ MYSQLND_METHOD(mysqlnd_stmt, dtor)(MYSQLND_STMT * const s, zend_bool implicit)
static MYSQLND_PARAM_BIND *
MYSQLND_METHOD(mysqlnd_stmt, alloc_param_bind)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
DBG_ENTER("mysqlnd_stmt::alloc_param_bind");
if (!stmt) {
DBG_RETURN(NULL);
@@ -2280,7 +2305,7 @@ MYSQLND_METHOD(mysqlnd_stmt, alloc_param_bind)(MYSQLND_STMT * const s)
static MYSQLND_RESULT_BIND *
MYSQLND_METHOD(mysqlnd_stmt, alloc_result_bind)(MYSQLND_STMT * const s)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
DBG_ENTER("mysqlnd_stmt::alloc_result_bind");
if (!stmt) {
DBG_RETURN(NULL);
@@ -2294,7 +2319,7 @@ MYSQLND_METHOD(mysqlnd_stmt, alloc_result_bind)(MYSQLND_STMT * const s)
PHPAPI void
MYSQLND_METHOD(mysqlnd_stmt, free_parameter_bind)(MYSQLND_STMT * const s, MYSQLND_PARAM_BIND * param_bind)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
if (stmt) {
mnd_pefree(param_bind, stmt->persistent);
}
@@ -2306,7 +2331,7 @@ MYSQLND_METHOD(mysqlnd_stmt, free_parameter_bind)(MYSQLND_STMT * const s, MYSQLN
PHPAPI void
MYSQLND_METHOD(mysqlnd_stmt, free_result_bind)(MYSQLND_STMT * const s, MYSQLND_RESULT_BIND * result_bind)
{
- MYSQLND_STMT_DATA * stmt = s? s->data:NULL;
+ MYSQLND_STMT_DATA * stmt = s? s->data : NULL;
if (stmt) {
mnd_pefree(result_bind, stmt->persistent);
}
@@ -2327,7 +2352,7 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_stmt)
MYSQLND_METHOD(mysqlnd_stmt, free_result),
MYSQLND_METHOD(mysqlnd_stmt, data_seek),
MYSQLND_METHOD(mysqlnd_stmt, reset),
- MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, net_close),
+ MYSQLND_METHOD_PRIVATE(mysqlnd_stmt, close_on_server),
MYSQLND_METHOD(mysqlnd_stmt, dtor),
MYSQLND_METHOD(mysqlnd_stmt, fetch),
@@ -2370,18 +2395,6 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_stmt)
MYSQLND_CLASS_METHODS_END;
-/* {{{ _mysqlnd_stmt_init */
-MYSQLND_STMT *
-_mysqlnd_stmt_init(MYSQLND_CONN_DATA * const conn)
-{
- MYSQLND_STMT * ret;
- DBG_ENTER("_mysqlnd_stmt_init");
- ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_prepared_statement(conn);
- DBG_RETURN(ret);
-}
-/* }}} */
-
-
/* {{{ _mysqlnd_init_ps_subsystem */
void _mysqlnd_init_ps_subsystem()
{
diff --git a/ext/mysqlnd/mysqlnd_ps.h b/ext/mysqlnd/mysqlnd_ps.h
new file mode 100644
index 0000000000..3a1092b977
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_ps.h
@@ -0,0 +1,54 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef MYSQLND_PS_H
+#define MYSQLND_PS_H
+
+/* PS stuff */
+typedef void (*ps_field_fetch_func)(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row);
+
+struct st_mysqlnd_perm_bind {
+ ps_field_fetch_func func;
+ /* should be signed int */
+ int pack_len;
+ unsigned int php_type;
+ zend_bool is_possibly_blob;
+ zend_bool can_ret_as_str_in_uni;
+};
+
+extern struct st_mysqlnd_perm_bind mysqlnd_ps_fetch_functions[MYSQL_TYPE_LAST + 1];
+
+enum_func_status mysqlnd_stmt_fetch_row_buffered(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything);
+enum_func_status mysqlnd_fetch_stmt_row_cursor(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything);
+
+void _mysqlnd_init_ps_subsystem();/* This one is private, mysqlnd_library_init() will call it */
+void _mysqlnd_init_ps_fetch_subsystem();
+
+void ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row, unsigned int byte_count);
+
+#endif /* MYSQLND_PS_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_ps_codec.c b/ext/mysqlnd/mysqlnd_ps_codec.c
index 55886d222b..11f00b1cca 100644
--- a/ext/mysqlnd/mysqlnd_ps_codec.c
+++ b/ext/mysqlnd/mysqlnd_ps_codec.c
@@ -22,11 +22,11 @@
#include "php.h"
#include "mysqlnd.h"
#include "mysqlnd_wireprotocol.h"
+#include "mysqlnd_connection.h"
+#include "mysqlnd_ps.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
-#include "ext/mysqlnd/mysql_float_to_double.h"
-
-#define MYSQLND_SILENT
+#include "mysql_float_to_double.h"
enum mysqlnd_timestamp_type
@@ -55,8 +55,8 @@ struct st_mysqlnd_perm_bind mysqlnd_ps_fetch_functions[MYSQL_TYPE_LAST + 1];
/* {{{ ps_fetch_from_1_to_8_bytes */
void
-ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len,
- zend_uchar ** row, unsigned int byte_count)
+ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len,
+ const zend_uchar ** row, unsigned int byte_count)
{
char tmp[22];
size_t tmp_len = 0;
@@ -128,7 +128,7 @@ ps_fetch_from_1_to_8_bytes(zval * zv, const MYSQLND_FIELD * const field, unsigne
/* {{{ ps_fetch_null */
static void
-ps_fetch_null(zval *zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_null(zval *zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
ZVAL_NULL(zv);
}
@@ -137,7 +137,7 @@ ps_fetch_null(zval *zv, const MYSQLND_FIELD * const field, unsigned int pack_len
/* {{{ ps_fetch_int8 */
static void
-ps_fetch_int8(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_int8(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 1);
}
@@ -146,7 +146,7 @@ ps_fetch_int8(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_le
/* {{{ ps_fetch_int16 */
static void
-ps_fetch_int16(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_int16(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 2);
}
@@ -155,7 +155,7 @@ ps_fetch_int16(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_l
/* {{{ ps_fetch_int32 */
static void
-ps_fetch_int32(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_int32(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 4);
}
@@ -164,7 +164,7 @@ ps_fetch_int32(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_l
/* {{{ ps_fetch_int64 */
static void
-ps_fetch_int64(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_int64(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, 8);
}
@@ -173,7 +173,7 @@ ps_fetch_int64(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_l
/* {{{ ps_fetch_float */
static void
-ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
float fval;
double dval;
@@ -196,7 +196,7 @@ ps_fetch_float(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_l
/* {{{ ps_fetch_double */
static void
-ps_fetch_double(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_double(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
double value;
DBG_ENTER("ps_fetch_double");
@@ -211,7 +211,7 @@ ps_fetch_double(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_
/* {{{ ps_fetch_time */
static void
-ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
struct st_mysqlnd_time t;
zend_ulong length; /* First byte encodes the length*/
@@ -219,7 +219,7 @@ ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_le
DBG_ENTER("ps_fetch_time");
if ((length = php_mysqlnd_net_field_length(row))) {
- zend_uchar * to= *row;
+ const zend_uchar * to = *row;
t.time_type = MYSQLND_TIMESTAMP_TIME;
t.neg = (zend_bool) to[0];
@@ -254,7 +254,7 @@ ps_fetch_time(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_le
/* {{{ ps_fetch_date */
static void
-ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
struct st_mysqlnd_time t = {0};
zend_ulong length; /* First byte encodes the length*/
@@ -262,10 +262,10 @@ ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_le
DBG_ENTER("ps_fetch_date");
if ((length = php_mysqlnd_net_field_length(row))) {
- zend_uchar *to= *row;
+ const zend_uchar * to = *row;
- t.time_type= MYSQLND_TIMESTAMP_DATE;
- t.neg= 0;
+ t.time_type = MYSQLND_TIMESTAMP_DATE;
+ t.neg = 0;
t.second_part = t.hour = t.minute = t.second = 0;
@@ -291,7 +291,7 @@ ps_fetch_date(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_le
/* {{{ ps_fetch_datetime */
static void
-ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
struct st_mysqlnd_time t;
zend_ulong length; /* First byte encodes the length*/
@@ -299,10 +299,10 @@ ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pac
DBG_ENTER("ps_fetch_datetime");
if ((length = php_mysqlnd_net_field_length(row))) {
- zend_uchar * to = *row;
+ const zend_uchar * to = *row;
t.time_type = MYSQLND_TIMESTAMP_DATETIME;
- t.neg = 0;
+ t.neg = 0;
t.year = (unsigned int) sint2korr(to);
t.month = (unsigned int) to[2];
@@ -335,7 +335,7 @@ ps_fetch_datetime(zval * zv, const MYSQLND_FIELD * const field, unsigned int pac
/* {{{ ps_fetch_string */
static void
-ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
/*
For now just copy, before we make it possible
@@ -355,9 +355,9 @@ ps_fetch_string(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_
/* {{{ ps_fetch_bit */
static void
-ps_fetch_bit(zval * zv, const MYSQLND_FIELD * const field, unsigned int pack_len, zend_uchar ** row)
+ps_fetch_bit(zval * zv, const MYSQLND_FIELD * const field, const unsigned int pack_len, const zend_uchar ** row)
{
- zend_ulong length = php_mysqlnd_net_field_length(row);
+ const zend_ulong length = php_mysqlnd_net_field_length(row);
ps_fetch_from_1_to_8_bytes(zv, field, pack_len, row, length);
}
/* }}} */
@@ -551,7 +551,7 @@ mysqlnd_stmt_execute_check_n_enlarge_buffer(zend_uchar **buf, zend_uchar **p, si
size_t left = (*buf_len - (*p - *buf));
if (left < (needed_bytes + overalloc)) {
- size_t offset = *p - *buf;
+ const size_t offset = *p - *buf;
zend_uchar *tmp_buf;
*buf_len = offset + needed_bytes + overalloc;
tmp_buf = mnd_emalloc(*buf_len);
@@ -578,7 +578,7 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie
unsigned int i;
DBG_ENTER("mysqlnd_stmt_execute_prepare_param_types");
for (i = 0; i < stmt->param_count; i++) {
- short current_type = stmt->param_bind[i].type;
+ const short current_type = stmt->param_bind[i].type;
zval *parameter = &stmt->param_bind[i].zv;
ZVAL_DEREF(parameter);
@@ -587,7 +587,7 @@ mysqlnd_stmt_execute_prepare_param_types(MYSQLND_STMT_DATA * stmt, zval ** copie
if (Z_TYPE_P(parameter) != IS_LONG &&
PASS != mysqlnd_stmt_copy_it(copies_param, parameter, stmt->param_count, i))
{
- SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(stmt->error_info);
goto end;
}
/*
@@ -695,7 +695,7 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval
/* Double binding of the same zval, make a copy */
if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i)) {
- SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(stmt->error_info);
goto end;
}
}
@@ -710,7 +710,7 @@ mysqlnd_stmt_execute_calculate_param_values_size(MYSQLND_STMT_DATA * stmt, zval
if (Z_TYPE_P(the_var) != IS_DOUBLE) {
if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i)) {
- SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(stmt->error_info);
goto end;
}
}
@@ -745,7 +745,7 @@ use_string:
if (Z_TYPE_P(the_var) != IS_STRING) {
if (!*copies_param || Z_ISUNDEF((*copies_param)[i])) {
if (PASS != mysqlnd_stmt_copy_it(copies_param, the_var, stmt->param_count, i)) {
- SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(stmt->error_info);
goto end;
}
}
@@ -810,7 +810,7 @@ mysqlnd_stmt_execute_store_param_values(MYSQLND_STMT_DATA * stmt, zval * copies,
case MYSQL_TYPE_VAR_STRING:
send_string:
{
- size_t len = Z_STRLEN_P(data);
+ const size_t len = Z_STRLEN_P(data);
/* to is after p. The latter hasn't been moved */
*p = php_mysqlnd_net_store_length(*p, len);
memcpy(*p, Z_STRVAL_P(data), len);
@@ -845,7 +845,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
{
unsigned int null_count = (stmt->param_count + 7) / 8;
if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, null_count)) {
- SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(stmt->error_info);
goto end;
}
/* put `null` bytes */
@@ -871,7 +871,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
if (stmt->send_types_to_server) {
if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, stmt->param_count * 2)) {
- SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(stmt->error_info);
goto end;
}
mysqlnd_stmt_execute_store_types(stmt, copies, p);
@@ -887,7 +887,7 @@ mysqlnd_stmt_execute_store_params(MYSQLND_STMT * s, zend_uchar **buf, zend_uchar
/* 2.2 Enlarge the buffer, if needed */
if (FAIL == mysqlnd_stmt_execute_check_n_enlarge_buffer(buf, p, buf_len, provided_buffer, data_size)) {
- SET_OOM_ERROR(*stmt->error_info);
+ SET_OOM_ERROR(stmt->error_info);
goto end;
}
diff --git a/ext/mysqlnd/mysqlnd_read_buffer.c b/ext/mysqlnd/mysqlnd_read_buffer.c
new file mode 100644
index 0000000000..99cb321f3f
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_read_buffer.c
@@ -0,0 +1,95 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_debug.h"
+#include "mysqlnd_read_buffer.h"
+
+
+/* {{{ mysqlnd_read_buffer_is_empty */
+static zend_bool
+mysqlnd_read_buffer_is_empty(const MYSQLND_READ_BUFFER * const buffer)
+{
+ return buffer->len? FALSE:TRUE;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_read_buffer_read */
+static void
+mysqlnd_read_buffer_read(MYSQLND_READ_BUFFER * buffer, const size_t count, zend_uchar * dest)
+{
+ if (buffer->len >= count) {
+ memcpy(dest, buffer->data + buffer->offset, count);
+ buffer->offset += count;
+ buffer->len -= count;
+ }
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_read_buffer_bytes_left */
+static size_t
+mysqlnd_read_buffer_bytes_left(const MYSQLND_READ_BUFFER * const buffer)
+{
+ return buffer->len;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_read_buffer_free */
+static void
+mysqlnd_read_buffer_free(MYSQLND_READ_BUFFER ** buffer)
+{
+ DBG_ENTER("mysqlnd_read_buffer_free");
+ if (*buffer) {
+ mnd_efree((*buffer)->data);
+ mnd_efree(*buffer);
+ *buffer = NULL;
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_create_read_buffer */
+PHPAPI MYSQLND_READ_BUFFER *
+mysqlnd_create_read_buffer(const size_t count)
+{
+ MYSQLND_READ_BUFFER * ret = mnd_emalloc(sizeof(MYSQLND_READ_BUFFER));
+ DBG_ENTER("mysqlnd_create_read_buffer");
+ ret->is_empty = mysqlnd_read_buffer_is_empty;
+ ret->read = mysqlnd_read_buffer_read;
+ ret->bytes_left = mysqlnd_read_buffer_bytes_left;
+ ret->free_buffer = mysqlnd_read_buffer_free;
+ ret->data = mnd_emalloc(count);
+ ret->size = ret->len = count;
+ ret->offset = 0;
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_read_buffer.h b/ext/mysqlnd/mysqlnd_read_buffer.h
new file mode 100644
index 0000000000..56286ae0fc
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_read_buffer.h
@@ -0,0 +1,25 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef MYSQLND_READ_BUFFER_H
+#define MYSQLND_READ_BUFFER_H
+
+PHPAPI MYSQLND_READ_BUFFER * mysqlnd_create_read_buffer(const size_t count);
+
+#endif /* MYSQLND_READ_BUFFER_H */
diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c
index 4208097cf7..29e0e253be 100644
--- a/ext/mysqlnd/mysqlnd_result.c
+++ b/ext/mysqlnd/mysqlnd_result.c
@@ -17,12 +17,11 @@
| Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id$ */
#include "php.h"
#include "mysqlnd.h"
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_block_alloc.h"
+#include "mysqlnd_connection.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_result.h"
#include "mysqlnd_result_meta.h"
@@ -30,18 +29,16 @@
#include "mysqlnd_debug.h"
#include "mysqlnd_ext_plugin.h"
-#define MYSQLND_SILENT
-
/* {{{ mysqlnd_result_buffered_zval::initialize_result_set_rest */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta,
- MYSQLND_STATS * stats, zend_bool int_and_float_native)
+MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result,
+ MYSQLND_RES_METADATA * const meta,
+ MYSQLND_STATS * stats,
+ zend_bool int_and_float_native)
{
- unsigned int i;
enum_func_status ret = PASS;
const unsigned int field_count = meta->field_count;
const uint64_t row_count = result->row_count;
- enum_func_status rc;
zval *data_begin = ((MYSQLND_RES_BUFFERED_ZVAL *) result)->data;
zval *data_cursor = data_begin;
@@ -53,25 +50,27 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND
}
while ((data_cursor - data_begin) < (int)(row_count * field_count)) {
if (Z_ISUNDEF(data_cursor[0])) {
- rc = result->m.row_decoder(result->row_buffers[(data_cursor - data_begin) / field_count],
- data_cursor,
- field_count,
- meta->fields,
- int_and_float_native,
- stats);
+ unsigned int i;
+ const size_t current_row_num = (data_cursor - data_begin) / field_count;
+ enum_func_status rc = result->m.row_decoder(result->row_buffers[current_row_num],
+ data_cursor,
+ field_count,
+ meta->fields,
+ int_and_float_native,
+ stats);
if (rc != PASS) {
ret = FAIL;
break;
}
- result->initialized_rows++;
- for (i = 0; i < field_count; i++) {
+ ++result->initialized_rows;
+ for (i = 0; i < field_count; ++i) {
/*
NULL fields are 0 length, 0 is not more than 0
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE(data_cursor[i]) == IS_STRING) {
- zend_ulong len = Z_STRLEN(data_cursor[i]);
+ const size_t len = Z_STRLEN(data_cursor[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
@@ -87,8 +86,10 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, initialize_result_set_rest)(MYSQLND
/* {{{ mysqlnd_result_buffered_c::initialize_result_set_rest */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta,
- MYSQLND_STATS * stats, zend_bool int_and_float_native)
+MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result,
+ MYSQLND_RES_METADATA * const meta,
+ MYSQLND_STATS * stats,
+ zend_bool int_and_float_native)
{
unsigned int i;
enum_func_status ret = PASS;
@@ -126,7 +127,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, initialize_result_set_rest)(MYSQLND_RE
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE(current_row[i]) == IS_STRING) {
- zend_ulong len = Z_STRLEN(current_row[i]);
+ const size_t len = Z_STRLEN(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
@@ -214,7 +215,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, free_result)(MYSQLND_RES_BUFFERED_Z
set->data = NULL; /* prevent double free if following loop is interrupted */
if (data) {
- unsigned int field_count = set->field_count;
+ const unsigned int field_count = set->field_count;
int64_t row;
for (row = set->row_count - 1; row >= 0; row--) {
@@ -282,7 +283,6 @@ MYSQLND_METHOD(mysqlnd_result_buffered, free_result)(MYSQLND_RES_BUFFERED * cons
set->result_set_memory_pool = NULL;
}
-
set->row_count = 0;
mnd_pefree(set, set->persistent);
@@ -307,7 +307,6 @@ MYSQLND_METHOD(mysqlnd_res, free_result_buffers)(MYSQLND_RES * result)
result->stored_data = NULL;
}
-
DBG_VOID_RETURN;
}
/* }}} */
@@ -371,7 +370,7 @@ MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND_
result->meta = result->m.result_meta_init(result->field_count, result->persistent);
if (!result->meta) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
DBG_RETURN(FAIL);
}
@@ -401,26 +400,27 @@ MYSQLND_METHOD(mysqlnd_res, read_result_metadata)(MYSQLND_RES * result, MYSQLND_
enum_func_status
mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
{
- MYSQLND_STMT_DATA * stmt = s ? s->data:NULL;
enum_func_status ret;
+ MYSQLND_STMT_DATA * stmt = s ? s->data : NULL;
MYSQLND_PACKET_RSET_HEADER * rset_header = NULL;
MYSQLND_PACKET_EOF * fields_eof = NULL;
+ const zend_bool persistent = conn->persistent;
DBG_ENTER("mysqlnd_query_read_result_set_header");
DBG_INF_FMT("stmt=%lu", stmt? stmt->stmt_id:0);
ret = FAIL;
do {
- rset_header = conn->protocol->m.get_rset_header_packet(conn->protocol, FALSE);
+ rset_header = conn->payload_decoder_factory->m.get_rset_header_packet(conn->payload_decoder_factory, FALSE);
if (!rset_header) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
ret = FAIL;
break;
}
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
- if (FAIL == (ret = PACKET_READ(rset_header, conn))) {
+ if (FAIL == (ret = PACKET_READ(rset_header))) {
php_error_docref(NULL, E_WARNING, "Error reading result set's header");
break;
}
@@ -435,16 +435,16 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
a multi-statement or a stored procedure, so it should be
safe to unconditionally turn off the flag here.
*/
- conn->upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
+ UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & ~SERVER_MORE_RESULTS_EXISTS);
/*
This will copy the error code and the messages, as they
are buffers in the struct
*/
- COPY_CLIENT_ERROR(*conn->error_info, rset_header->error_info);
+ COPY_CLIENT_ERROR(conn->error_info, rset_header->error_info);
ret = FAIL;
DBG_ERR_FMT("error=%s", rset_header->error_info.error);
/* Return back from CONN_QUERY_SENT */
- CONN_SET_STATE(conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
break;
}
conn->error_info->error_no = 0;
@@ -455,9 +455,9 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
DBG_INF("LOAD DATA");
conn->last_query_type = QUERY_LOAD_LOCAL;
conn->field_count = 0; /* overwrite previous value, or the last value could be used and lead to bug#53503 */
- CONN_SET_STATE(conn, CONN_SENDING_LOAD_DATA);
- ret = mysqlnd_handle_local_infile(conn, rset_header->info_or_local_file, &is_warning);
- CONN_SET_STATE(conn, (ret == PASS || is_warning == TRUE)? CONN_READY:CONN_QUIT_SENT);
+ SET_CONNECTION_STATE(&conn->state, CONN_SENDING_LOAD_DATA);
+ ret = mysqlnd_handle_local_infile(conn, rset_header->info_or_local_file.s, &is_warning);
+ SET_CONNECTION_STATE(&conn->state, (ret == PASS || is_warning == TRUE)? CONN_READY:CONN_QUIT_SENT);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_NON_RSET_QUERY);
break;
}
@@ -465,19 +465,19 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
DBG_INF("UPSERT");
conn->last_query_type = QUERY_UPSERT;
conn->field_count = rset_header->field_count;
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
- conn->upsert_status->warning_count = rset_header->warning_count;
- conn->upsert_status->server_status = rset_header->server_status;
- conn->upsert_status->affected_rows = rset_header->affected_rows;
- conn->upsert_status->last_insert_id = rset_header->last_insert_id;
- SET_NEW_MESSAGE(conn->last_message, conn->last_message_len,
- rset_header->info_or_local_file, rset_header->info_or_local_file_len,
- conn->persistent);
+ UPSERT_STATUS_RESET(conn->upsert_status);
+ UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, rset_header->warning_count);
+ UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, rset_header->server_status);
+ UPSERT_STATUS_SET_AFFECTED_ROWS(conn->upsert_status, rset_header->affected_rows);
+ UPSERT_STATUS_SET_LAST_INSERT_ID(conn->upsert_status, rset_header->last_insert_id);
+ SET_NEW_MESSAGE(conn->last_message.s, conn->last_message.l,
+ rset_header->info_or_local_file.s, rset_header->info_or_local_file.l,
+ persistent);
/* Result set can follow UPSERT statement, check server_status */
- if (conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
- CONN_SET_STATE(conn, CONN_NEXT_RESULT_PENDING);
+ if (UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_MORE_RESULTS_EXISTS) {
+ SET_CONNECTION_STATE(&conn->state, CONN_NEXT_RESULT_PENDING);
} else {
- CONN_SET_STATE(conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
}
ret = PASS;
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_NON_RSET_QUERY);
@@ -487,19 +487,19 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
enum_mysqlnd_collected_stats statistic = STAT_LAST;
DBG_INF("Result set pending");
- SET_EMPTY_MESSAGE(conn->last_message, conn->last_message_len, conn->persistent);
+ SET_EMPTY_MESSAGE(conn->last_message.s, conn->last_message.l, persistent);
MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_RSET_QUERY);
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
+ UPSERT_STATUS_RESET(conn->upsert_status);
/* restore after zeroing */
- SET_ERROR_AFF_ROWS(conn);
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(conn->upsert_status);
conn->last_query_type = QUERY_SELECT;
- CONN_SET_STATE(conn, CONN_FETCHING_DATA);
+ SET_CONNECTION_STATE(&conn->state, CONN_FETCHING_DATA);
/* PS has already allocated it */
conn->field_count = rset_header->field_count;
if (!stmt) {
- result = conn->current_result = conn->m->result_init(rset_header->field_count, conn->persistent);
+ result = conn->current_result = conn->m->result_init(rset_header->field_count, persistent);
} else {
if (!stmt->result) {
DBG_INF("This is 'SHOW'/'EXPLAIN'-like query.");
@@ -526,7 +526,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
result = stmt->result;
}
if (!result) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
ret = FAIL;
break;
}
@@ -542,13 +542,13 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
}
/* Check for SERVER_STATUS_MORE_RESULTS if needed */
- fields_eof = conn->protocol->m.get_eof_packet(conn->protocol, FALSE);
+ fields_eof = conn->payload_decoder_factory->m.get_eof_packet(conn->payload_decoder_factory, FALSE);
if (!fields_eof) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
ret = FAIL;
break;
}
- if (FAIL == (ret = PACKET_READ(fields_eof, conn))) {
+ if (FAIL == (ret = PACKET_READ(fields_eof))) {
DBG_ERR("Error occurred while reading the EOF packet");
result->m.free_result_contents(result);
mnd_efree(result);
@@ -556,12 +556,17 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
conn->current_result = NULL;
} else {
stmt->result = NULL;
+ /* XXX: This will crash, because we will null also the methods.
+ But seems it happens in extreme cases or doesn't. Should be fixed by exporting a function
+ (from mysqlnd_driver.c?) to do the reset.
+ This is done also in mysqlnd_ps.c
+ */
memset(stmt, 0, sizeof(*stmt));
stmt->state = MYSQLND_STMT_INITTED;
}
} else {
DBG_INF_FMT("warnings=%u server_status=%u", fields_eof->warning_count, fields_eof->server_status);
- conn->upsert_status->warning_count = fields_eof->warning_count;
+ UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, fields_eof->warning_count);
/*
If SERVER_MORE_RESULTS_EXISTS is set then this is either MULTI_QUERY or a CALL()
The first packet after sending the query/com_execute has the bit set only
@@ -569,7 +574,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
will include many result sets. What actually matters are the bits set at the end
of every result set (the EOF packet).
*/
- conn->upsert_status->server_status = fields_eof->server_status;
+ UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, fields_eof->server_status);
if (fields_eof->server_status & SERVER_QUERY_NO_GOOD_INDEX_USED) {
statistic = STAT_BAD_INDEX_USED;
} else if (fields_eof->server_status & SERVER_QUERY_NO_INDEX_USED) {
@@ -599,7 +604,7 @@ mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * s)
of PHP, to be called as separate function. But let's have it for
completeness.
*/
-static zend_ulong *
+static const size_t *
MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths)(MYSQLND_RES_BUFFERED * const result)
{
const MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result;
@@ -631,7 +636,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_lengths)(MYSQLND_RES_BUFFERED
of PHP, to be called as separate function. But let's have it for
completeness.
*/
-static zend_ulong *
+static const size_t *
MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths)(MYSQLND_RES_BUFFERED * const result)
{
const MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result;
@@ -648,7 +653,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_lengths)(MYSQLND_RES_BUFFERED *
/* {{{ mysqlnd_result_unbuffered::fetch_lengths */
-static zend_ulong *
+static const size_t *
MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths)(MYSQLND_RES_UNBUFFERED * const result)
{
/* simulate output of libmysql */
@@ -658,10 +663,10 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_lengths)(MYSQLND_RES_UNBUFFERED
/* {{{ mysqlnd_res::fetch_lengths */
-static zend_ulong *
+static const size_t *
MYSQLND_METHOD(mysqlnd_res, fetch_lengths)(MYSQLND_RES * const result)
{
- zend_ulong * ret;
+ const size_t * ret;
DBG_ENTER("mysqlnd_res::fetch_lengths");
ret = result->stored_data && result->stored_data->m.fetch_lengths ?
result->stored_data->m.fetch_lengths(result->stored_data) :
@@ -681,7 +686,8 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi
enum_func_status ret;
MYSQLND_ROW_C *row = (MYSQLND_ROW_C *) param;
MYSQLND_PACKET_ROW *row_packet = result->unbuf->row_packet;
- const MYSQLND_RES_METADATA * const meta = result->meta;
+ MYSQLND_RES_METADATA * const meta = result->meta;
+ MYSQLND_CONN_DATA * const conn = result->conn;
DBG_ENTER("mysqlnd_result_unbuffered::fetch_row_c");
@@ -690,8 +696,8 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi
/* No more rows obviously */
DBG_RETURN(PASS);
}
- if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ if (!conn || GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA) {
+ SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(FAIL);
}
if (!row_packet) {
@@ -705,15 +711,15 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi
If we skip rows (row == NULL) we have to
result->m.unbuffered_free_last_data() before it. The function returns always true.
*/
- if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
- result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL);
+ if (PASS == (ret = PACKET_READ(row_packet)) && !row_packet->eof) {
+ result->unbuf->m.free_last_data(result->unbuf, conn->stats);
result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
row_packet->fields = NULL;
row_packet->row_buffer = NULL;
- MYSQLND_INC_CONN_STATISTIC(result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF);
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF);
if (!row_packet->skip_extraction) {
unsigned int i, field_count = meta->field_count;
@@ -722,8 +728,8 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi
result->unbuf->last_row_data,
field_count,
row_packet->fields_metadata,
- result->conn->options->int_and_float_native,
- result->conn->stats);
+ conn->options->int_and_float_native,
+ conn->stats);
if (PASS != rc) {
DBG_RETURN(FAIL);
}
@@ -731,11 +737,11 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi
*row = mnd_malloc(field_count * sizeof(char *));
if (*row) {
MYSQLND_FIELD * field = meta->fields;
- zend_ulong * lengths = result->unbuf->lengths;
+ size_t * lengths = result->unbuf->lengths;
for (i = 0; i < field_count; i++, field++) {
zval * data = &result->unbuf->last_row_data[i];
- unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
+ const size_t len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
/* BEGIN difference between normal normal fetch and _c */
if (Z_TYPE_P(data) != IS_NULL) {
@@ -755,7 +761,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi
}
}
} else {
- SET_OOM_ERROR(*result->conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
}
}
}
@@ -763,28 +769,29 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row_c)(MYSQLND_RES * result, voi
*fetched_anything = TRUE;
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info);
+ COPY_CLIENT_ERROR(conn->error_info, row_packet->error_info);
DBG_ERR_FMT("errorno=%u error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
}
- CONN_SET_STATE(result->conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
} else if (row_packet->eof) {
/* Mark the connection as usable again */
DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
result->unbuf->eof_reached = TRUE;
- memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status));
- result->conn->upsert_status->warning_count = row_packet->warning_count;
- result->conn->upsert_status->server_status = row_packet->server_status;
+
+ UPSERT_STATUS_RESET(conn->upsert_status);
+ UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, row_packet->warning_count);
+ UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet->server_status);
/*
result->row_packet will be cleaned when
destroying the result object
*/
- if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
- CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING);
+ if (UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_MORE_RESULTS_EXISTS) {
+ SET_CONNECTION_STATE(&conn->state, CONN_NEXT_RESULT_PENDING);
} else {
- CONN_SET_STATE(result->conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
}
- result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL);
+ result->unbuf->m.free_last_data(result->unbuf, conn->stats);
}
DBG_INF_FMT("ret=%s fetched=%u", ret == PASS? "PASS":"FAIL", *fetched_anything);
@@ -801,6 +808,7 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
zval *row = (zval *) param;
MYSQLND_PACKET_ROW *row_packet = result->unbuf->row_packet;
const MYSQLND_RES_METADATA * const meta = result->meta;
+ MYSQLND_CONN_DATA * const conn = result->conn;
DBG_ENTER("mysqlnd_result_unbuffered::fetch_row");
@@ -809,8 +817,8 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
/* No more rows obviously */
DBG_RETURN(PASS);
}
- if (CONN_GET_STATE(result->conn) != CONN_FETCHING_DATA) {
- SET_CLIENT_ERROR(*result->conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ if (GET_CONNECTION_STATE(&conn->state) != CONN_FETCHING_DATA) {
+ SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(FAIL);
}
if (!row_packet) {
@@ -824,36 +832,36 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
If we skip rows (row == NULL) we have to
result->m.unbuffered_free_last_data() before it. The function returns always true.
*/
- if (PASS == (ret = PACKET_READ(row_packet, result->conn)) && !row_packet->eof) {
- result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL);
+ if (PASS == (ret = PACKET_READ(row_packet)) && !row_packet->eof) {
+ result->unbuf->m.free_last_data(result->unbuf, conn->stats);
result->unbuf->last_row_data = row_packet->fields;
result->unbuf->last_row_buffer = row_packet->row_buffer;
row_packet->fields = NULL;
row_packet->row_buffer = NULL;
- MYSQLND_INC_CONN_STATISTIC(result->conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF);
+ MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_UNBUF);
if (!row_packet->skip_extraction) {
unsigned int i, field_count = meta->field_count;
enum_func_status rc = result->unbuf->m.row_decoder(result->unbuf->last_row_buffer,
- result->unbuf->last_row_data,
- field_count,
- row_packet->fields_metadata,
- result->conn->options->int_and_float_native,
- result->conn->stats);
+ result->unbuf->last_row_data,
+ field_count,
+ row_packet->fields_metadata,
+ conn->options->int_and_float_native,
+ conn->stats);
if (PASS != rc) {
DBG_RETURN(FAIL);
}
{
HashTable * row_ht = Z_ARRVAL_P(row);
MYSQLND_FIELD * field = meta->fields;
- zend_ulong * lengths = result->unbuf->lengths;
+ size_t * lengths = result->unbuf->lengths;
for (i = 0; i < field_count; i++, field++) {
zval * data = &result->unbuf->last_row_data[i];
- unsigned int len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
+ const size_t len = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
if (flags & MYSQLND_FETCH_NUM) {
Z_TRY_ADDREF_P(data);
@@ -869,9 +877,9 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
*/
Z_TRY_ADDREF_P(data);
if (meta->zend_hash_keys[i].is_numeric == FALSE) {
- zend_hash_update(Z_ARRVAL_P(row), meta->fields[i].sname, data);
+ zend_hash_update(row_ht, meta->fields[i].sname, data);
} else {
- zend_hash_index_update(Z_ARRVAL_P(row), meta->zend_hash_keys[i].key, data);
+ zend_hash_index_update(row_ht, meta->zend_hash_keys[i].key, data);
}
}
@@ -889,28 +897,29 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
*fetched_anything = TRUE;
} else if (ret == FAIL) {
if (row_packet->error_info.error_no) {
- COPY_CLIENT_ERROR(*result->conn->error_info, row_packet->error_info);
+ COPY_CLIENT_ERROR(conn->error_info, row_packet->error_info);
DBG_ERR_FMT("errorno=%u error=%s", row_packet->error_info.error_no, row_packet->error_info.error);
}
- CONN_SET_STATE(result->conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
result->unbuf->eof_reached = TRUE; /* so next time we won't get an error */
} else if (row_packet->eof) {
/* Mark the connection as usable again */
DBG_INF_FMT("warnings=%u server_status=%u", row_packet->warning_count, row_packet->server_status);
result->unbuf->eof_reached = TRUE;
- memset(result->conn->upsert_status, 0, sizeof(*result->conn->upsert_status));
- result->conn->upsert_status->warning_count = row_packet->warning_count;
- result->conn->upsert_status->server_status = row_packet->server_status;
+
+ UPSERT_STATUS_RESET(conn->upsert_status);
+ UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, row_packet->warning_count);
+ UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet->server_status);
/*
result->row_packet will be cleaned when
destroying the result object
*/
- if (result->conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
- CONN_SET_STATE(result->conn, CONN_NEXT_RESULT_PENDING);
+ if (UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_MORE_RESULTS_EXISTS) {
+ SET_CONNECTION_STATE(&conn->state, CONN_NEXT_RESULT_PENDING);
} else {
- CONN_SET_STATE(result->conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
}
- result->unbuf->m.free_last_data(result->unbuf, result->conn? result->conn->stats : NULL);
+ result->unbuf->m.free_last_data(result->unbuf, conn->stats);
}
DBG_INF_FMT("ret=%s fetched=%u", ret == PASS? "PASS":"FAIL", *fetched_anything);
@@ -921,11 +930,12 @@ MYSQLND_METHOD(mysqlnd_result_unbuffered, fetch_row)(MYSQLND_RES * result, void
/* {{{ mysqlnd_res::use_result */
static MYSQLND_RES *
-MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps)
+MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, const zend_bool ps)
{
+ MYSQLND_CONN_DATA * const conn = result->conn;
DBG_ENTER("mysqlnd_res::use_result");
- SET_EMPTY_ERROR(*result->conn->error_info);
+ SET_EMPTY_ERROR(conn->error_info);
if (ps == FALSE) {
result->type = MYSQLND_RES_NORMAL;
@@ -944,20 +954,24 @@ MYSQLND_METHOD(mysqlnd_res, use_result)(MYSQLND_RES * const result, zend_bool ps
this to be not NULL.
*/
/* FALSE = non-persistent */
- result->unbuf->row_packet = result->conn->protocol->m.get_row_packet(result->conn->protocol, FALSE);
- if (!result->unbuf->row_packet) {
- goto oom;
+ {
+ struct st_mysqlnd_packet_row * row_packet = conn->payload_decoder_factory->m.get_row_packet(conn->payload_decoder_factory, FALSE);
+ if (!row_packet) {
+ goto oom;
+ }
+ row_packet->result_set_memory_pool = result->unbuf->result_set_memory_pool;
+ row_packet->field_count = result->field_count;
+ row_packet->binary_protocol = ps;
+ row_packet->fields_metadata = result->meta->fields;
+ row_packet->bit_fields_count = result->meta->bit_fields_count;
+ row_packet->bit_fields_total_len = result->meta->bit_fields_total_len;
+
+ result->unbuf->row_packet = row_packet;
}
- result->unbuf->row_packet->result_set_memory_pool = result->unbuf->result_set_memory_pool;
- result->unbuf->row_packet->field_count = result->field_count;
- result->unbuf->row_packet->binary_protocol = ps;
- result->unbuf->row_packet->fields_metadata = result->meta->fields;
- result->unbuf->row_packet->bit_fields_count = result->meta->bit_fields_count;
- result->unbuf->row_packet->bit_fields_total_len = result->meta->bit_fields_total_len;
DBG_RETURN(result);
oom:
- SET_OOM_ERROR(*result->conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
DBG_RETURN(NULL);
}
/* }}} */
@@ -967,10 +981,11 @@ oom:
static enum_func_status
MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void * param, unsigned int flags, zend_bool * fetched_anything)
{
+ enum_func_status ret = FAIL;
MYSQLND_ROW_C * row = (MYSQLND_ROW_C *) param;
const MYSQLND_RES_METADATA * const meta = result->meta;
unsigned int field_count = meta->field_count;
- enum_func_status ret = FAIL;
+ MYSQLND_CONN_DATA * const conn = result->conn;
DBG_ENTER("mysqlnd_result_buffered::fetch_row_c");
if (result->stored_data->type == MYSQLND_BUFFERED_TYPE_ZVAL) {
@@ -989,20 +1004,20 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void
current_row,
field_count,
meta->fields,
- result->conn->options->int_and_float_native,
- result->conn->stats);
+ conn->options->int_and_float_native,
+ conn->stats);
if (rc != PASS) {
DBG_RETURN(FAIL);
}
- set->initialized_rows++;
- for (i = 0; i < field_count; i++) {
+ ++set->initialized_rows;
+ for (i = 0; i < field_count; ++i) {
/*
NULL fields are 0 length, 0 is not more than 0
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE(current_row[i]) == IS_STRING) {
- zend_ulong len = Z_STRLEN(current_row[i]);
+ const size_t len = Z_STRLEN(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
@@ -1014,7 +1029,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void
/* there is no conn handle in this function thus we can't set OOM in error_info */
*row = mnd_malloc(field_count * sizeof(char *));
if (*row) {
- for (i = 0; i < field_count; i++) {
+ for (i = 0; i < field_count; ++i) {
zval * data = &current_row[i];
set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
@@ -1029,7 +1044,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void
set->data_cursor += field_count;
MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF);
} else {
- SET_OOM_ERROR(*result->conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
}
/* END difference between normal normal fetch and _c */
@@ -1059,41 +1074,40 @@ MYSQLND_METHOD(mysqlnd_result_buffered, fetch_row_c)(MYSQLND_RES * result, void
static enum_func_status
MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything)
{
+ enum_func_status ret = FAIL;
zval * row = (zval *) param;
const MYSQLND_RES_METADATA * const meta = result->meta;
- unsigned int field_count = meta->field_count;
- enum_func_status ret = FAIL;
+ const unsigned int field_count = meta->field_count;
MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data;
+ MYSQLND_CONN_DATA * const conn = result->conn;
DBG_ENTER("mysqlnd_result_buffered_zval::fetch_row");
/* If we haven't read everything */
- if (set->data_cursor &&
- (set->data_cursor - set->data) < (set->row_count * field_count))
- {
+ if (set->data_cursor && (set->data_cursor - set->data) < (set->row_count * field_count)) {
unsigned int i;
zval *current_row = set->data_cursor;
if (Z_ISUNDEF(current_row[0])) {
- uint64_t row_num = (set->data_cursor - set->data) / field_count;
+ const size_t row_num = (set->data_cursor - set->data) / field_count;
enum_func_status rc = set->m.row_decoder(set->row_buffers[row_num],
- current_row,
- field_count,
- meta->fields,
- result->conn->options->int_and_float_native,
- result->conn->stats);
+ current_row,
+ field_count,
+ meta->fields,
+ conn->options->int_and_float_native,
+ conn->stats);
if (rc != PASS) {
DBG_RETURN(FAIL);
}
- set->initialized_rows++;
- for (i = 0; i < field_count; i++) {
+ ++set->initialized_rows;
+ for (i = 0; i < field_count; ++i) {
/*
NULL fields are 0 length, 0 is not more than 0
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE(current_row[i]) == IS_STRING) {
- zend_ulong len = Z_STRLEN(current_row[i]);
+ const size_t len = Z_STRLEN(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
@@ -1101,7 +1115,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo
}
}
- for (i = 0; i < field_count; i++) {
+ for (i = 0; i < field_count; ++i) {
zval * data = &current_row[i];
set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
@@ -1146,10 +1160,11 @@ MYSQLND_METHOD(mysqlnd_result_buffered_zval, fetch_row)(MYSQLND_RES * result, vo
static enum_func_status
MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void * param, const unsigned int flags, zend_bool * fetched_anything)
{
+ enum_func_status ret = FAIL;
zval * row = (zval *) param;
const MYSQLND_RES_METADATA * const meta = result->meta;
- unsigned int field_count = meta->field_count;
- enum_func_status ret = FAIL;
+ const unsigned int field_count = meta->field_count;
+ MYSQLND_CONN_DATA * const conn = result->conn;
MYSQLND_RES_BUFFERED_C * set = (MYSQLND_RES_BUFFERED_C *) result->stored_data;
@@ -1157,38 +1172,38 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void
/* If we haven't read everything */
if (set->current_row < set->row_count) {
- zval *current_row;
enum_func_status rc;
+ zval * current_row;
unsigned int i;
current_row = mnd_emalloc(field_count * sizeof(zval));
if (!current_row) {
- SET_OOM_ERROR(*result->conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
DBG_RETURN(FAIL);
}
rc = result->stored_data->m.row_decoder(result->stored_data->row_buffers[set->current_row],
- current_row,
- field_count,
- meta->fields,
- result->conn->options->int_and_float_native,
- result->conn->stats);
+ current_row,
+ field_count,
+ meta->fields,
+ conn->options->int_and_float_native,
+ conn->stats);
if (rc != PASS) {
DBG_RETURN(FAIL);
}
if (!(set->initialized[set->current_row >> 3] & (1 << (set->current_row & 7)))) {
set->initialized[set->current_row >> 3] |= (1 << (set->current_row & 7)); /* mark initialized */
- set->initialized_rows++;
+ ++set->initialized_rows;
- for (i = 0; i < field_count; i++) {
+ for (i = 0; i < field_count; ++i) {
/*
NULL fields are 0 length, 0 is not more than 0
String of zero size, definitely can't be the next max_length.
Thus for NULL and zero-length we are quite efficient.
*/
if (Z_TYPE(current_row[i]) == IS_STRING) {
- zend_ulong len = Z_STRLEN(current_row[i]);
+ const size_t len = Z_STRLEN(current_row[i]);
if (meta->fields[i].max_length < len) {
meta->fields[i].max_length = len;
}
@@ -1196,7 +1211,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void
}
}
- for (i = 0; i < field_count; i++) {
+ for (i = 0; i < field_count; ++i) {
zval * data = &current_row[i];
set->lengths[i] = (Z_TYPE_P(data) == IS_STRING)? Z_STRLEN_P(data) : 0;
@@ -1229,7 +1244,7 @@ MYSQLND_METHOD(mysqlnd_result_buffered_c, fetch_row)(MYSQLND_RES * result, void
zval_ptr_dtor(data);
}
mnd_efree(current_row);
- set->current_row++;
+ ++set->current_row;
MYSQLND_INC_GLOBAL_STATISTIC(STAT_ROWS_FETCHED_FROM_CLIENT_NORMAL_BUF);
*fetched_anything = TRUE;
ret = PASS;
@@ -1272,14 +1287,11 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
zend_bool binary_protocol)
{
enum_func_status ret;
- MYSQLND_PACKET_ROW * row_packet = NULL;
unsigned int next_extend = STORE_RESULT_PREALLOCATED_SET_IF_NOT_EMPTY, free_rows = 1;
- MYSQLND_RES_BUFFERED *set;
+ MYSQLND_RES_BUFFERED * set = result->stored_data;
+ MYSQLND_PACKET_ROW * row_packet = NULL;
DBG_ENTER("mysqlnd_res::store_result_fetch_data");
-
- set = result->stored_data;
-
if (!set || !row_buffers) {
ret = FAIL;
goto end;
@@ -1287,20 +1299,20 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
if (free_rows) {
*row_buffers = mnd_pemalloc((size_t)(free_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0);
if (!*row_buffers) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
ret = FAIL;
goto end;
}
}
- set->references = 1;
-
/* non-persistent */
- row_packet = conn->protocol->m.get_row_packet(conn->protocol, FALSE);
+ row_packet = conn->payload_decoder_factory->m.get_row_packet(conn->payload_decoder_factory, FALSE);
if (!row_packet) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
ret = FAIL;
goto end;
}
+ set->references = 1;
+
row_packet->result_set_memory_pool = result->stored_data->result_set_memory_pool;
row_packet->field_count = meta->field_count;
row_packet->binary_protocol = binary_protocol;
@@ -1310,7 +1322,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
row_packet->skip_extraction = TRUE; /* let php_mysqlnd_rowp_read() not allocate row_packet->fields, we will do it */
- while (FAIL != (ret = PACKET_READ(row_packet, conn)) && !row_packet->eof) {
+ while (FAIL != (ret = PACKET_READ(row_packet)) && !row_packet->eof) {
if (!free_rows) {
uint64_t total_allocated_rows = free_rows = next_extend = next_extend * 11 / 10; /* extend with 10% */
MYSQLND_MEMORY_POOL_CHUNK ** new_row_buffers;
@@ -1318,13 +1330,13 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *) > SIZE_MAX) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
ret = FAIL;
goto end;
}
new_row_buffers = mnd_perealloc(*row_buffers, (size_t)(total_allocated_rows * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0);
if (!new_row_buffers) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
ret = FAIL;
goto end;
}
@@ -1354,35 +1366,38 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c
/* Finally clean */
if (row_packet->eof) {
- memset(conn->upsert_status, 0, sizeof(*conn->upsert_status));
- conn->upsert_status->warning_count = row_packet->warning_count;
- conn->upsert_status->server_status = row_packet->server_status;
+ UPSERT_STATUS_RESET(conn->upsert_status);
+ UPSERT_STATUS_SET_WARNINGS(conn->upsert_status, row_packet->warning_count);
+ UPSERT_STATUS_SET_SERVER_STATUS(conn->upsert_status, row_packet->server_status);
}
/* save some memory */
if (free_rows) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *) > SIZE_MAX) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
ret = FAIL;
goto end;
}
*row_buffers = mnd_perealloc(*row_buffers, (size_t) (set->row_count * sizeof(MYSQLND_MEMORY_POOL_CHUNK *)), 0);
}
- if (conn->upsert_status->server_status & SERVER_MORE_RESULTS_EXISTS) {
- CONN_SET_STATE(conn, CONN_NEXT_RESULT_PENDING);
+ if (UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status) & SERVER_MORE_RESULTS_EXISTS) {
+ SET_CONNECTION_STATE(&conn->state, CONN_NEXT_RESULT_PENDING);
} else {
- CONN_SET_STATE(conn, CONN_READY);
+ SET_CONNECTION_STATE(&conn->state, CONN_READY);
}
if (ret == FAIL) {
- COPY_CLIENT_ERROR(set->error_info, row_packet->error_info);
+ COPY_CLIENT_ERROR(&set->error_info, row_packet->error_info);
} else {
/* libmysql's documentation says it should be so for SELECT statements */
- conn->upsert_status->affected_rows = set->row_count;
+ UPSERT_STATUS_SET_AFFECTED_ROWS(conn->upsert_status, set->row_count);
}
DBG_INF_FMT("ret=%s row_count=%u warnings=%u server_status=%u",
- ret == PASS? "PASS":"FAIL", (uint) set->row_count, conn->upsert_status->warning_count, conn->upsert_status->server_status);
+ ret == PASS? "PASS":"FAIL",
+ (uint) set->row_count,
+ UPSERT_STATUS_GET_WARNINGS(conn->upsert_status),
+ UPSERT_STATUS_GET_SERVER_STATUS(conn->upsert_status));
end:
PACKET_FREE(row_packet);
DBG_INF_FMT("rows=%llu", (unsigned long long)result->stored_data->row_count);
@@ -1407,19 +1422,19 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
result->conn = conn->m->get_reference(conn);
result->type = MYSQLND_RES_NORMAL;
- CONN_SET_STATE(conn, CONN_FETCHING_DATA);
+ SET_CONNECTION_STATE(&conn->state, CONN_FETCHING_DATA);
if (flags & MYSQLND_STORE_NO_COPY) {
result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_zval_init(result->field_count, flags & MYSQLND_STORE_PS, result->persistent);
if (!result->stored_data) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
DBG_RETURN(NULL);
}
row_buffers = &result->stored_data->row_buffers;
} else if (flags & MYSQLND_STORE_COPY) {
result->stored_data = (MYSQLND_RES_BUFFERED *) mysqlnd_result_buffered_c_init(result->field_count, flags & MYSQLND_STORE_PS, result->persistent);
if (!result->stored_data) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
DBG_RETURN(NULL);
}
row_buffers = &result->stored_data->row_buffers;
@@ -1428,26 +1443,26 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
if (FAIL == ret) {
if (result->stored_data) {
- COPY_CLIENT_ERROR(*conn->error_info, result->stored_data->error_info);
+ COPY_CLIENT_ERROR(conn->error_info, result->stored_data->error_info);
} else {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
}
DBG_RETURN(NULL);
} else {
- /* Overflow ? */
if (flags & MYSQLND_STORE_NO_COPY) {
- MYSQLND_RES_METADATA * meta = result->meta;
+ const MYSQLND_RES_METADATA * const meta = result->meta;
MYSQLND_RES_BUFFERED_ZVAL * set = (MYSQLND_RES_BUFFERED_ZVAL *) result->stored_data;
+
if (set->row_count) {
/* don't try to allocate more than possible - mnd_XXalloc expects size_t, and it can have narrower range than uint64_t */
if (set->row_count * meta->field_count * sizeof(zval *) > SIZE_MAX) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
DBG_RETURN(NULL);
}
/* if pecalloc is used valgrind barks gcc version 4.3.1 20080507 (prerelease) [gcc-4_3-branch revision 135036] (SUSE Linux) */
set->data = mnd_emalloc((size_t)(set->row_count * meta->field_count * sizeof(zval)));
if (!set->data) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
DBG_RETURN(NULL);
}
memset(set->data, 0, (size_t)(set->row_count * meta->field_count * sizeof(zval)));
@@ -1462,7 +1477,7 @@ MYSQLND_METHOD(mysqlnd_res, store_result)(MYSQLND_RES * result,
}
/* libmysql's documentation says it should be so for SELECT statements */
- conn->upsert_status->affected_rows = result->stored_data->row_count;
+ UPSERT_STATUS_SET_AFFECTED_ROWS(conn->upsert_status, result->stored_data->row_count);
DBG_RETURN(result);
}
@@ -1482,9 +1497,10 @@ MYSQLND_METHOD(mysqlnd_res, skip_result)(MYSQLND_RES * const result)
fetch_row function isn't actually set (NULL), thus we have to skip these.
*/
if (result->unbuf && !result->unbuf->eof_reached) {
+ MYSQLND_CONN_DATA * const conn = result->conn;
DBG_INF("skipping result");
/* We have to fetch all data to clean the line */
- MYSQLND_INC_CONN_STATISTIC(result->conn->stats,
+ MYSQLND_INC_CONN_STATISTIC(conn->stats,
result->type == MYSQLND_RES_NORMAL? STAT_FLUSHED_NORMAL_SETS:
STAT_FLUSHED_PS_SETS);
@@ -1499,7 +1515,7 @@ MYSQLND_METHOD(mysqlnd_res, skip_result)(MYSQLND_RES * const result)
/* {{{ mysqlnd_res::free_result */
static enum_func_status
-MYSQLND_METHOD(mysqlnd_res, free_result)(MYSQLND_RES * result, zend_bool implicit)
+MYSQLND_METHOD(mysqlnd_res, free_result)(MYSQLND_RES * result, const zend_bool implicit)
{
DBG_ENTER("mysqlnd_res::free_result");
@@ -1566,7 +1582,7 @@ static uint64_t
MYSQLND_METHOD(mysqlnd_result_unbuffered, num_rows)(const MYSQLND_RES_UNBUFFERED * const result)
{
/* Be compatible with libmysql. We count row_count, but will return 0 */
- return result->eof_reached? result->row_count:0;
+ return result->eof_reached? result->row_count : 0;
}
/* }}} */
@@ -1618,10 +1634,13 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field)(MYSQLND_RES * const result)
not during mysqli_fetch_field() time.
*/
if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
+ const MYSQLND_CONN_DATA * const conn = result->conn;
DBG_INF_FMT("We have decode the whole result set to be able to satisfy this meta request");
/* we have to initialize the rest to get the updated max length */
- if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data, result->meta, result->conn->stats,
- result->conn->options->int_and_float_native))
+ if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data,
+ result->meta,
+ conn->stats,
+ conn->options->int_and_float_native))
{
break;
}
@@ -1652,10 +1671,13 @@ MYSQLND_METHOD(mysqlnd_res, fetch_field_direct)(MYSQLND_RES * const result, cons
not during mysqli_fetch_field_direct() time.
*/
if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
+ const MYSQLND_CONN_DATA * const conn = result->conn;
DBG_INF_FMT("We have decode the whole result set to be able to satisfy this meta request");
/* we have to initialized the rest to get the updated max length */
- if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data, result->meta, result->conn->stats,
- result->conn->options->int_and_float_native))
+ if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data,
+ result->meta,
+ conn->stats,
+ conn->options->int_and_float_native))
{
break;
}
@@ -1677,9 +1699,12 @@ MYSQLND_METHOD(mysqlnd_res, fetch_fields)(MYSQLND_RES * const result)
do {
if (result->meta) {
if (result->stored_data && (result->stored_data->initialized_rows < result->stored_data->row_count)) {
+ const MYSQLND_CONN_DATA * const conn = result->conn;
/* we have to initialize the rest to get the updated max length */
- if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data, result->meta, result->conn->stats,
- result->conn->options->int_and_float_native))
+ if (PASS != result->stored_data->m.initialize_result_set_rest(result->stored_data,
+ result->meta,
+ conn->stats,
+ conn->options->int_and_float_native))
{
break;
}
@@ -1784,7 +1809,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_all)(MYSQLND_RES * result, const unsigned int
if ((!result->unbuf && !set)) {
php_error_docref(NULL, E_WARNING, "fetch_all can be used only with buffered sets");
if (result->conn) {
- SET_CLIENT_ERROR(*result->conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "fetch_all can be used only with buffered sets");
+ SET_CLIENT_ERROR(result->conn->error_info, CR_NOT_IMPLEMENTED, UNKNOWN_SQLSTATE, "fetch_all can be used only with buffered sets");
}
RETVAL_NULL();
DBG_VOID_RETURN;
@@ -1894,9 +1919,9 @@ MYSQLND_CLASS_METHODS_END;
/* {{{ mysqlnd_result_init */
PHPAPI MYSQLND_RES *
-mysqlnd_result_init(unsigned int field_count, zend_bool persistent)
+mysqlnd_result_init(const unsigned int field_count, const zend_bool persistent)
{
- size_t alloc_size = sizeof(MYSQLND_RES) + mysqlnd_plugin_count() * sizeof(void *);
+ const size_t alloc_size = sizeof(MYSQLND_RES) + mysqlnd_plugin_count() * sizeof(void *);
MYSQLND_RES * ret = mnd_pecalloc(1, alloc_size, persistent);
DBG_ENTER("mysqlnd_result_init");
@@ -1916,9 +1941,9 @@ mysqlnd_result_init(unsigned int field_count, zend_bool persistent)
/* {{{ mysqlnd_result_unbuffered_init */
PHPAPI MYSQLND_RES_UNBUFFERED *
-mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent)
+mysqlnd_result_unbuffered_init(const unsigned int field_count, const zend_bool ps, const zend_bool persistent)
{
- size_t alloc_size = sizeof(MYSQLND_RES_UNBUFFERED) + mysqlnd_plugin_count() * sizeof(void *);
+ const size_t alloc_size = sizeof(MYSQLND_RES_UNBUFFERED) + mysqlnd_plugin_count() * sizeof(void *);
MYSQLND_RES_UNBUFFERED * ret = mnd_pecalloc(1, alloc_size, persistent);
DBG_ENTER("mysqlnd_result_unbuffered_init");
@@ -1927,7 +1952,7 @@ mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool
DBG_RETURN(NULL);
}
- if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(zend_ulong), persistent))) {
+ if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(size_t), persistent))) {
mnd_pefree(ret, persistent);
DBG_RETURN(NULL);
}
@@ -1957,9 +1982,9 @@ mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool
/* {{{ mysqlnd_result_buffered_zval_init */
PHPAPI MYSQLND_RES_BUFFERED_ZVAL *
-mysqlnd_result_buffered_zval_init(unsigned int field_count, zend_bool ps, zend_bool persistent)
+mysqlnd_result_buffered_zval_init(const unsigned int field_count, const zend_bool ps, const zend_bool persistent)
{
- size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_ZVAL) + mysqlnd_plugin_count() * sizeof(void *);
+ const size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_ZVAL) + mysqlnd_plugin_count() * sizeof(void *);
MYSQLND_RES_BUFFERED_ZVAL * ret = mnd_pecalloc(1, alloc_size, persistent);
DBG_ENTER("mysqlnd_result_buffered_zval_init");
@@ -1967,7 +1992,7 @@ mysqlnd_result_buffered_zval_init(unsigned int field_count, zend_bool ps, zend_b
if (!ret) {
DBG_RETURN(NULL);
}
- if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(zend_ulong), persistent))) {
+ if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(size_t), persistent))) {
mnd_pefree(ret, persistent);
DBG_RETURN(NULL);
}
@@ -2000,9 +2025,9 @@ mysqlnd_result_buffered_zval_init(unsigned int field_count, zend_bool ps, zend_b
/* {{{ mysqlnd_result_buffered_c_init */
PHPAPI MYSQLND_RES_BUFFERED_C *
-mysqlnd_result_buffered_c_init(unsigned int field_count, zend_bool ps, zend_bool persistent)
+mysqlnd_result_buffered_c_init(const unsigned int field_count, const zend_bool ps, const zend_bool persistent)
{
- size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_C) + mysqlnd_plugin_count() * sizeof(void *);
+ const size_t alloc_size = sizeof(MYSQLND_RES_BUFFERED_C) + mysqlnd_plugin_count() * sizeof(void *);
MYSQLND_RES_BUFFERED_C * ret = mnd_pecalloc(1, alloc_size, persistent);
DBG_ENTER("mysqlnd_result_buffered_c_init");
@@ -2010,7 +2035,7 @@ mysqlnd_result_buffered_c_init(unsigned int field_count, zend_bool ps, zend_bool
if (!ret) {
DBG_RETURN(NULL);
}
- if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(zend_ulong), persistent))) {
+ if (!(ret->lengths = mnd_pecalloc(field_count, sizeof(size_t), persistent))) {
mnd_pefree(ret, persistent);
DBG_RETURN(NULL);
}
diff --git a/ext/mysqlnd/mysqlnd_result.h b/ext/mysqlnd/mysqlnd_result.h
index fffae33e4c..27547de283 100644
--- a/ext/mysqlnd/mysqlnd_result.h
+++ b/ext/mysqlnd/mysqlnd_result.h
@@ -17,16 +17,13 @@
| Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id$ */
-
#ifndef MYSQLND_RESULT_H
#define MYSQLND_RESULT_H
-PHPAPI MYSQLND_RES * mysqlnd_result_init(unsigned int field_count, zend_bool persistent);
-PHPAPI MYSQLND_RES_UNBUFFERED * mysqlnd_result_unbuffered_init(unsigned int field_count, zend_bool ps, zend_bool persistent);
-PHPAPI MYSQLND_RES_BUFFERED_ZVAL * mysqlnd_result_buffered_zval_init(unsigned int field_count, zend_bool ps, zend_bool persistent);
-PHPAPI MYSQLND_RES_BUFFERED_C * mysqlnd_result_buffered_c_init(unsigned int field_count, zend_bool ps, zend_bool persistent);
+PHPAPI MYSQLND_RES * mysqlnd_result_init(const unsigned int field_count, const zend_bool persistent);
+PHPAPI MYSQLND_RES_UNBUFFERED * mysqlnd_result_unbuffered_init(const unsigned int field_count, const zend_bool ps, const zend_bool persistent);
+PHPAPI MYSQLND_RES_BUFFERED_ZVAL * mysqlnd_result_buffered_zval_init(const unsigned int field_count, const zend_bool ps, const zend_bool persistent);
+PHPAPI MYSQLND_RES_BUFFERED_C * mysqlnd_result_buffered_c_init(const unsigned int field_count, const zend_bool ps, const zend_bool persistent);
enum_func_status mysqlnd_query_read_result_set_header(MYSQLND_CONN_DATA * conn, MYSQLND_STMT * stmt);
diff --git a/ext/mysqlnd/mysqlnd_result_meta.c b/ext/mysqlnd/mysqlnd_result_meta.c
index 154d05357f..7da6756432 100644
--- a/ext/mysqlnd/mysqlnd_result_meta.c
+++ b/ext/mysqlnd/mysqlnd_result_meta.c
@@ -17,10 +17,10 @@
| Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id$ */
#include "php.h"
#include "mysqlnd.h"
+#include "mysqlnd_connection.h"
+#include "mysqlnd_ps.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_result.h"
#include "mysqlnd_wireprotocol.h"
@@ -57,9 +57,9 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met
DBG_ENTER("mysqlnd_res_meta::read_metadata");
- field_packet = conn->protocol->m.get_result_field_packet(conn->protocol, FALSE);
+ field_packet = conn->payload_decoder_factory->m.get_result_field_packet(conn->payload_decoder_factory, FALSE);
if (!field_packet) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(conn->error_info);
DBG_RETURN(FAIL);
}
field_packet->persistent_alloc = meta->persistent;
@@ -73,29 +73,20 @@ MYSQLND_METHOD(mysqlnd_res_meta, read_metadata)(MYSQLND_RES_METADATA * const met
}
field_packet->metadata = &(meta->fields[i]);
- if (FAIL == PACKET_READ(field_packet, conn)) {
+ if (FAIL == PACKET_READ(field_packet)) {
PACKET_FREE(field_packet);
DBG_RETURN(FAIL);
}
if (field_packet->error_info.error_no) {
- COPY_CLIENT_ERROR(*conn->error_info, field_packet->error_info);
+ COPY_CLIENT_ERROR(conn->error_info, field_packet->error_info);
/* Return back from CONN_QUERY_SENT */
PACKET_FREE(field_packet);
DBG_RETURN(FAIL);
}
- if (field_packet->stupid_list_fields_eof == TRUE) {
- meta->field_count = i;
- break;
- }
-
if (mysqlnd_ps_fetch_functions[meta->fields[i].type].func == NULL) {
- DBG_ERR_FMT("Unknown type %u sent by the server. Please send a report to the developers",
- meta->fields[i].type);
- php_error_docref(NULL, E_WARNING,
- "Unknown type %u sent by the server. "
- "Please send a report to the developers",
- meta->fields[i].type);
+ DBG_ERR_FMT("Unknown type %u sent by the server. Please send a report to the developers", meta->fields[i].type);
+ php_error_docref(NULL, E_WARNING, "Unknown type %u sent by the server. Please send a report to the developers", meta->fields[i].type);
PACKET_FREE(field_packet);
DBG_RETURN(FAIL);
}
@@ -180,7 +171,7 @@ MYSQLND_METHOD(mysqlnd_res_meta, free)(MYSQLND_RES_METADATA * meta)
/* {{{ mysqlnd_res::clone_metadata */
static MYSQLND_RES_METADATA *
-MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * const meta, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_res_meta, clone_metadata)(const MYSQLND_RES_METADATA * const meta, const zend_bool persistent)
{
unsigned int i;
/* +1 is to have empty marker at the end */
diff --git a/ext/mysqlnd/mysqlnd_statistics.c b/ext/mysqlnd/mysqlnd_statistics.c
index 6050e38e86..247e627ef2 100644
--- a/ext/mysqlnd/mysqlnd_statistics.c
+++ b/ext/mysqlnd/mysqlnd_statistics.c
@@ -12,13 +12,10 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id$ */
#include "php.h"
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
@@ -26,9 +23,7 @@
#include "mysqlnd_debug.h"
-/* {{{ mysqlnd_stats_values_names
- */
-
+/* {{{ mysqlnd_stats_values_names */
const MYSQLND_STRING mysqlnd_stats_values_names[STAT_LAST] =
{
{ MYSQLND_STR_W_LEN("bytes_sent") },
@@ -213,25 +208,9 @@ mysqlnd_fill_stats_hash(const MYSQLND_STATS * const stats, const MYSQLND_STRING
/* }}} */
-/* {{{ _mysqlnd_get_client_stats */
-PHPAPI void
-_mysqlnd_get_client_stats(zval *return_value ZEND_FILE_LINE_DC)
-{
- MYSQLND_STATS stats, *stats_ptr = mysqlnd_global_stats;
- DBG_ENTER("_mysqlnd_get_client_stats");
- if (!stats_ptr) {
- memset(&stats, 0, sizeof(stats));
- stats_ptr = &stats;
- }
- mysqlnd_fill_stats_hash(stats_ptr, mysqlnd_stats_values_names, return_value ZEND_FILE_LINE_CC);
- DBG_VOID_RETURN;
-}
-/* }}} */
-
-
/* {{{ mysqlnd_stats_init */
PHPAPI void
-mysqlnd_stats_init(MYSQLND_STATS ** stats, size_t statistic_count, int persistent)
+mysqlnd_stats_init(MYSQLND_STATS ** stats, const size_t statistic_count, const zend_bool persistent)
{
*stats = pecalloc(1, sizeof(MYSQLND_STATS), persistent);
if (*stats == NULL) {
@@ -250,7 +229,7 @@ mysqlnd_stats_init(MYSQLND_STATS ** stats, size_t statistic_count, int persisten
/* {{{ mysqlnd_stats_end */
PHPAPI void
-mysqlnd_stats_end(MYSQLND_STATS * stats, int persistent)
+mysqlnd_stats_end(MYSQLND_STATS * stats, const zend_bool persistent)
{
#ifdef ZTS
tsrm_mutex_free(stats->LOCK_access);
@@ -296,6 +275,25 @@ mysqlnd_stats_reset_triggers(MYSQLND_STATS * const stats)
/* }}} */
+/************ MYSQLND specific code **********/
+
+/* {{{ _mysqlnd_get_client_stats */
+PHPAPI void
+_mysqlnd_get_client_stats(MYSQLND_STATS * stats_ptr, zval *return_value ZEND_FILE_LINE_DC)
+{
+ MYSQLND_STATS stats;
+ DBG_ENTER("_mysqlnd_get_client_stats");
+ if (!stats_ptr) {
+ memset(&stats, 0, sizeof(stats));
+ stats_ptr = &stats;
+ }
+ mysqlnd_fill_stats_hash(stats_ptr, mysqlnd_stats_values_names, return_value ZEND_FILE_LINE_CC);
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+
/*
* Local variables:
* tab-width: 4
diff --git a/ext/mysqlnd/mysqlnd_statistics.h b/ext/mysqlnd/mysqlnd_statistics.h
index 19aedf37a2..ca8ca8d9ee 100644
--- a/ext/mysqlnd/mysqlnd_statistics.h
+++ b/ext/mysqlnd/mysqlnd_statistics.h
@@ -12,22 +12,13 @@
| obtain it through the world-wide-web, please send a note to |
| license@php.net so we can mail you a copy immediately. |
+----------------------------------------------------------------------+
- | Authors: Georg Richter <georg@mysql.com> |
- | Andrey Hristov <andrey@mysql.com> |
+ | Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id$ */
-
#ifndef MYSQLND_STATISTICS_H
#define MYSQLND_STATISTICS_H
-
-PHPAPI extern MYSQLND_STATS * mysqlnd_global_stats;
-
-extern const MYSQLND_STRING mysqlnd_stats_values_names[];
-
#ifdef ZTS
#define MYSQLND_STATS_LOCK(stats) tsrm_mutex_lock((stats)->LOCK_access)
#define MYSQLND_STATS_UNLOCK(stats) tsrm_mutex_unlock((stats)->LOCK_access)
@@ -118,50 +109,11 @@ extern const MYSQLND_STRING mysqlnd_stats_values_names[];
-#ifndef MYSQLND_CORE_STATISTICS_DISABLED
-
-#define MYSQLND_INC_GLOBAL_STATISTIC(statistic) \
- MYSQLND_INC_STATISTIC(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic))
-
-#define MYSQLND_DEC_CONN_STATISTIC(conn_stats, statistic) \
- MYSQLND_DEC_STATISTIC(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic))
-
-#define MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(statistic1, value1, statistic2, value2) \
- MYSQLND_INC_STATISTIC_W_VALUE2(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic1), (value1), (statistic2), (value2))
-
-#define MYSQLND_INC_CONN_STATISTIC(conn_stats, statistic) \
- MYSQLND_INC_STATISTIC(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic)); \
- MYSQLND_INC_STATISTIC(MYSQLND_G(collect_statistics), (conn_stats), (statistic));
-
-#define MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn_stats, statistic, value) \
- MYSQLND_INC_STATISTIC_W_VALUE(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic), (value)); \
- MYSQLND_INC_STATISTIC_W_VALUE(MYSQLND_G(collect_statistics), (conn_stats), (statistic), (value));
-
-#define MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn_stats, statistic1, value1, statistic2, value2) \
- MYSQLND_INC_STATISTIC_W_VALUE2(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic1), (value1), (statistic2), (value2)); \
- MYSQLND_INC_STATISTIC_W_VALUE2(MYSQLND_G(collect_statistics), (conn_stats), (statistic1), (value1), (statistic2), (value2));
-
-#define MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats, statistic1, value1, statistic2, value2, statistic3, value3) \
- MYSQLND_INC_STATISTIC_W_VALUE3(MYSQLND_G(collect_statistics), mysqlnd_global_stats, (statistic1), (value1), (statistic2), (value2), (statistic3), (value3)); \
- MYSQLND_INC_STATISTIC_W_VALUE3(MYSQLND_G(collect_statistics), (conn_stats), (statistic1), (value1), (statistic2), (value2), (statistic3), (value3));
-
-#else
-
-#define MYSQLND_INC_GLOBAL_STATISTIC(statistic)
-#define MYSQLND_DEC_CONN_STATISTIC(conn_stats, statistic)
-#define MYSQLND_INC_GLOBAL_STATISTIC_W_VALUE2(statistic1, value1, statistic2, value2)
-#define MYSQLND_INC_CONN_STATISTIC(conn_stats, statistic)
-#define MYSQLND_INC_CONN_STATISTIC_W_VALUE(conn_stats, statistic, value)
-#define MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn_stats, statistic1, value1, statistic2, value2)
-#define MYSQLND_INC_CONN_STATISTIC_W_VALUE3(conn_stats, statistic1, value1, statistic2, value2, statistic3, value3)
-
-#endif /* MYSQLND_CORE_STATISTICS_DISABLED */
+PHPAPI void mysqlnd_stats_init(MYSQLND_STATS ** stats, const size_t statistic_count, const zend_bool persistent);
+PHPAPI void mysqlnd_stats_end(MYSQLND_STATS * stats, const zend_bool persistent);
PHPAPI void mysqlnd_fill_stats_hash(const MYSQLND_STATS * const stats, const MYSQLND_STRING * names, zval *return_value ZEND_FILE_LINE_DC);
-PHPAPI void mysqlnd_stats_init(MYSQLND_STATS ** stats, size_t statistic_count, int persistent);
-PHPAPI void mysqlnd_stats_end(MYSQLND_STATS * stats, int persistent);
-
PHPAPI mysqlnd_stat_trigger mysqlnd_stats_set_trigger(MYSQLND_STATS * const stats, enum_mysqlnd_collected_stats stat, mysqlnd_stat_trigger trigger);
PHPAPI mysqlnd_stat_trigger mysqlnd_stats_reset_triggers(MYSQLND_STATS * const stats);
diff --git a/ext/mysqlnd/mysqlnd_structs.h b/ext/mysqlnd/mysqlnd_structs.h
index c01f5f9034..bdcf29f7aa 100644
--- a/ext/mysqlnd/mysqlnd_structs.h
+++ b/ext/mysqlnd/mysqlnd_structs.h
@@ -18,8 +18,6 @@
+----------------------------------------------------------------------+
*/
-/* $Id$ */
-
#ifndef MYSQLND_STRUCTS_H
#define MYSQLND_STRUCTS_H
@@ -28,12 +26,26 @@
#define MYSQLND_TYPEDEFED_METHODS
#define MYSQLND_CLASS_METHOD_TABLE_NAME(class) mysqlnd_##class##_methods
-#define MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) struct st_##class##_methods MYSQLND_CLASS_METHOD_TABLE_NAME(class)
+#define MYSQLND_CLASS_METHODS_TYPE(class) struct st_##class##_methods
+#define MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) MYSQLND_CLASS_METHODS_TYPE(class) MYSQLND_CLASS_METHOD_TABLE_NAME(class)
#define MYSQLND_CLASS_METHODS_START(class) MYSQLND_CLASS_METHOD_TABLE_NAME_FORWARD(class) = {
#define MYSQLND_CLASS_METHODS_END }
+typedef struct st_mysqlnd_string
+{
+ char *s;
+ size_t l;
+} MYSQLND_STRING;
+
+typedef struct st_mysqlnd_const_string
+{
+ const char *s;
+ size_t l;
+} MYSQLND_CSTRING;
+
+
typedef struct st_mysqlnd_memory_pool MYSQLND_MEMORY_POOL;
typedef struct st_mysqlnd_memory_pool_chunk MYSQLND_MEMORY_POOL_CHUNK;
typedef struct st_mysqlnd_memory_pool_chunk_llist MYSQLND_MEMORY_POOL_CHUNK_LLIST;
@@ -79,7 +91,7 @@ typedef struct st_mysqlnd_field
const char *org_table; /* Org table name, if table was an alias */
const char *db; /* Database for table */
const char *catalog; /* Catalog for table */
- char *def; /* Default value (set by mysql_list_fields) */
+ char *def; /* Default value */
zend_ulong length; /* Width of column (create length) */
zend_ulong max_length; /* Max width for selected set */
unsigned int name_length;
@@ -98,22 +110,52 @@ typedef struct st_mysqlnd_field
} MYSQLND_FIELD;
-typedef struct st_mysqlnd_upsert_result
+typedef struct st_mysqlnd_upsert_status MYSQLND_UPSERT_STATUS;
+typedef void (*func_mysqlnd_upsert_status__reset)(MYSQLND_UPSERT_STATUS * const upsert_status);
+typedef void (*func_mysqlnd_upsert_status__set_affected_rows_to_error)(MYSQLND_UPSERT_STATUS * const upsert_status);
+
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_upsert_status)
+{
+ func_mysqlnd_upsert_status__reset reset;
+ func_mysqlnd_upsert_status__set_affected_rows_to_error set_affected_rows_to_error;
+};
+
+struct st_mysqlnd_upsert_status
{
unsigned int warning_count;
unsigned int server_status;
uint64_t affected_rows;
uint64_t last_insert_id;
-} MYSQLND_UPSERT_STATUS;
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_upsert_status) *m;
+};
+
+#define SET_EMPTY_ERROR(info) (info)->m->reset((info))
+#define SET_CLIENT_ERROR(info, err_no, sqlstate, error) (err_no)? (info)->m->set_client_error((info), (err_no), (sqlstate), (error)) : (info)->m->reset((info))
+#define SET_OOM_ERROR(info) SET_CLIENT_ERROR((info), CR_OUT_OF_MEMORY, UNKNOWN_SQLSTATE, mysqlnd_out_of_memory)
+#define COPY_CLIENT_ERROR(dest, source) SET_CLIENT_ERROR((dest), (source).error_no, (source).sqlstate, (source).error)
+
+
+typedef struct st_mysqlnd_error_info MYSQLND_ERROR_INFO;
+typedef void (*func_mysqlnd_error_info__reset)(MYSQLND_ERROR_INFO * const info);
+typedef void (*func_mysqlnd_error_info__set_client_error)(MYSQLND_ERROR_INFO * const info, const unsigned int err_no, const char * const sqlstate, const char * const error);
+
+
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_error_info)
+{
+ func_mysqlnd_error_info__reset reset;
+ func_mysqlnd_error_info__set_client_error set_client_error;
+};
-typedef struct st_mysqlnd_error_info
+struct st_mysqlnd_error_info
{
char error[MYSQLND_ERRMSG_SIZE+1];
char sqlstate[MYSQLND_SQLSTATE_LENGTH + 1];
unsigned int error_no;
zend_llist * error_list;
-} MYSQLND_ERROR_INFO;
+
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_error_info) *m;
+};
typedef struct st_mysqlnd_error_list_element
@@ -156,7 +198,7 @@ typedef struct st_mysqlnd_infile
void (*local_infile_end)(void *ptr);
} MYSQLND_INFILE;
-typedef struct st_mysqlnd_options
+typedef struct st_mysqlnd_session_options
{
ulong flags;
@@ -175,11 +217,11 @@ typedef struct st_mysqlnd_options
in the memory which can crash external code. Feel free to reuse these.
*/
HashTable * connect_attr;
+ char * unused1;
+ char * unused2;
char * unused3;
- char * unused4;
- char * unused5;
- enum_mysqlnd_protocol_type protocol;
+ enum_mysqlnd_session_protocol_type protocol;
char *charset_name;
/* maximum allowed packet size for communication */
@@ -188,9 +230,10 @@ typedef struct st_mysqlnd_options
#ifdef MYSQLND_STRING_TO_INT_CONVERSION
zend_bool int_and_float_native;
#endif
-} MYSQLND_OPTIONS;
+} MYSQLND_SESSION_OPTIONS;
-typedef struct st_mysqlnd_net_options
+
+typedef struct st_mysqlnd_vio_options
{
/* timeouts */
unsigned int timeout_connect;
@@ -213,23 +256,17 @@ typedef struct st_mysqlnd_net_options
#define MYSQLND_SSL_PEER_DEFAULT_ACTION MYSQLND_SSL_PEER_VERIFY
} ssl_verify_peer;
- uint64_t flags;
-
- char * sha256_server_public_key;
-
- char * unused1;
- char * unused2;
- char * unused3;
- char * unused4;
-} MYSQLND_NET_OPTIONS;
+} MYSQLND_VIO_OPTIONS;
typedef struct st_mysqlnd_connection MYSQLND;
typedef struct st_mysqlnd_connection_data MYSQLND_CONN_DATA;
-typedef struct st_mysqlnd_net MYSQLND_NET;
-typedef struct st_mysqlnd_net_data MYSQLND_NET_DATA;
-typedef struct st_mysqlnd_protocol MYSQLND_PROTOCOL;
+typedef struct st_mysqlnd_protocol_frame_codec MYSQLND_PFC;
+typedef struct st_mysqlnd_protocol_frame_codec_data MYSQLND_PFC_DATA;
+typedef struct st_mysqlnd_vio MYSQLND_VIO;
+typedef struct st_mysqlnd_vio_data MYSQLND_VIO_DATA;
+typedef struct st_mysqlnd_protocol_payload_decoder_factory MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY;
typedef struct st_mysqlnd_res MYSQLND_RES;
typedef char** MYSQLND_ROW_C; /* return data as array of strings */
typedef struct st_mysqlnd_stmt_data MYSQLND_STMT_DATA;
@@ -273,158 +310,85 @@ struct st_mysqlnd_stats
};
-typedef struct st_mysqlnd_read_buffer {
- zend_uchar * data;
- size_t offset;
- size_t size;
- size_t len;
- zend_bool (*is_empty)(struct st_mysqlnd_read_buffer *);
- void (*read)(struct st_mysqlnd_read_buffer *, size_t count, zend_uchar * dest);
- size_t (*bytes_left)(struct st_mysqlnd_read_buffer *);
- void (*free_buffer)(struct st_mysqlnd_read_buffer **);
-} MYSQLND_READ_BUFFER;
+typedef enum_func_status (*func_mysqlnd_vio__init)(MYSQLND_VIO * const vio, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info);
+typedef void (*func_mysqlnd_vio__dtor)(MYSQLND_VIO * const vio, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
+typedef enum_func_status (*func_mysqlnd_vio__connect)(MYSQLND_VIO * const vio, const MYSQLND_CSTRING scheme, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
+typedef void (*func_mysqlnd_vio__close_stream)(MYSQLND_VIO * const vio, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
+typedef php_stream * (*func_mysqlnd_vio__open_stream)(MYSQLND_VIO * const vio, const MYSQLND_CSTRING scheme, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
+typedef php_stream * (*func_mysqlnd_vio__get_stream)(const MYSQLND_VIO * const vio);
+typedef php_stream * (*func_mysqlnd_vio__set_stream)(MYSQLND_VIO * const vio, php_stream * vio_stream);
+typedef func_mysqlnd_vio__open_stream (*func_mysqlnd_vio__get_open_stream)(MYSQLND_VIO * const vio, const MYSQLND_CSTRING scheme, MYSQLND_ERROR_INFO * const error_info);
-typedef enum_func_status (*func_mysqlnd_net__set_client_option)(MYSQLND_NET * const net, enum_mysqlnd_option option, const char * const value);
-typedef enum_func_status (*func_mysqlnd_net__decode)(zend_uchar * uncompressed_data, const size_t uncompressed_data_len, const zend_uchar * const compressed_data, const size_t compressed_data_len);
-typedef enum_func_status (*func_mysqlnd_net__encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len, const zend_uchar * const uncompressed_data, const size_t uncompressed_data_len);
-typedef size_t (*func_mysqlnd_net__consume_uneaten_data)(MYSQLND_NET * const net, enum php_mysqlnd_server_command cmd);
-typedef void (*func_mysqlnd_net__free_contents)(MYSQLND_NET * net);
-typedef enum_func_status (*func_mysqlnd_net__enable_ssl)(MYSQLND_NET * const net);
-typedef enum_func_status (*func_mysqlnd_net__disable_ssl)(MYSQLND_NET * const net);
-typedef enum_func_status (*func_mysqlnd_net__network_read_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info);
-typedef size_t (*func_mysqlnd_net__network_write_ex)(MYSQLND_NET * const net, const zend_uchar * const buf, const size_t count, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info);
-typedef size_t (*func_mysqlnd_net__send_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
-typedef enum_func_status (*func_mysqlnd_net__receive_ex)(MYSQLND_NET * const net, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
-typedef enum_func_status (*func_mysqlnd_net__init)(MYSQLND_NET * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info);
-typedef void (*func_mysqlnd_net__dtor)(MYSQLND_NET * const net, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
-typedef enum_func_status (*func_mysqlnd_net__connect_ex)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
-typedef void (*func_mysqlnd_net__close_stream)(MYSQLND_NET * const net, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
-typedef php_stream * (*func_mysqlnd_net__open_stream)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, const zend_bool persistent, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
-typedef php_stream * (*func_mysqlnd_net__get_stream)(const MYSQLND_NET * const net);
-typedef php_stream * (*func_mysqlnd_net__set_stream)(MYSQLND_NET * const net, php_stream * net_stream);
-typedef func_mysqlnd_net__open_stream (*func_mysqlnd_net__get_open_stream)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, MYSQLND_ERROR_INFO * const error_info);
-typedef void (*func_mysqlnd_net__post_connect_set_opt)(MYSQLND_NET * const net, const char * const scheme, const size_t scheme_len, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
-typedef enum_func_status (*func_mysqlnd_net__read_compressed_packet_from_stream_and_fill_read_buffer)(MYSQLND_NET * net, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info);
-
-struct st_mysqlnd_net_methods
-{
- func_mysqlnd_net__init init;
- func_mysqlnd_net__dtor dtor;
- func_mysqlnd_net__connect_ex connect_ex;
- func_mysqlnd_net__close_stream close_stream;
- func_mysqlnd_net__open_stream open_pipe;
- func_mysqlnd_net__open_stream open_tcp_or_unix;
-
- func_mysqlnd_net__get_stream get_stream;
- func_mysqlnd_net__set_stream set_stream;
- func_mysqlnd_net__get_open_stream get_open_stream;
-
- func_mysqlnd_net__post_connect_set_opt post_connect_set_opt;
-
- func_mysqlnd_net__set_client_option set_client_option;
- func_mysqlnd_net__decode decode;
- func_mysqlnd_net__encode encode;
- func_mysqlnd_net__consume_uneaten_data consume_uneaten_data;
- func_mysqlnd_net__free_contents free_contents;
- func_mysqlnd_net__enable_ssl enable_ssl;
- func_mysqlnd_net__disable_ssl disable_ssl;
-
- func_mysqlnd_net__network_read_ex network_read_ex;
- func_mysqlnd_net__network_write_ex network_write_ex;
- func_mysqlnd_net__send_ex send_ex;
- func_mysqlnd_net__receive_ex receive_ex;
-
- func_mysqlnd_net__read_compressed_packet_from_stream_and_fill_read_buffer read_compressed_packet_from_stream_and_fill_read_buffer;
+typedef enum_func_status (*func_mysqlnd_vio__set_client_option)(MYSQLND_VIO * const vio, enum_mysqlnd_client_option option, const char * const value);
+typedef void (*func_mysqlnd_vio__post_connect_set_opt)(MYSQLND_VIO * const vio, const MYSQLND_CSTRING scheme, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
- void * unused1;
- void * unused2;
- void * unused3;
- void * unused4;
- void * unused5;
-};
+typedef enum_func_status (*func_mysqlnd_vio__enable_ssl)(MYSQLND_VIO * const vio);
+typedef enum_func_status (*func_mysqlnd_vio__disable_ssl)(MYSQLND_VIO * const vio);
+typedef enum_func_status (*func_mysqlnd_vio__network_read)(MYSQLND_VIO * const vio, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info);
+typedef size_t (*func_mysqlnd_vio__network_write)(MYSQLND_VIO * const vio, const zend_uchar * const buf, const size_t count, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info);
+typedef size_t (*func_mysqlnd_vio__consume_uneaten_data)(MYSQLND_VIO * const vio, enum php_mysqlnd_server_command cmd);
-struct st_mysqlnd_packet_greet;
-struct st_mysqlnd_packet_greet;
-struct st_mysqlnd_packet_auth;
-struct st_mysqlnd_packet_ok;
-struct st_mysqlnd_packet_command;
-struct st_mysqlnd_packet_eof;
-struct st_mysqlnd_packet_rset_header;
-struct st_mysqlnd_packet_res_field;
-struct st_mysqlnd_packet_row;
-struct st_mysqlnd_packet_stats;
-struct st_mysqlnd_packet_prepare_response;
-struct st_mysqlnd_packet_chg_user_resp;
-struct st_mysqlnd_packet_auth_pam;
-struct st_mysqlnd_packet_sha256_pk_request;
-struct st_mysqlnd_packet_sha256_pk_request_response;
+typedef void (*func_mysqlnd_vio__free_contents)(MYSQLND_VIO * vio);
-typedef struct st_mysqlnd_packet_greet * (*func_mysqlnd_protocol__get_greet_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_auth * (*func_mysqlnd_protocol__get_auth_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_auth_response *(*func_mysqlnd_protocol__get_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_change_auth_response * (*func_mysqlnd_protocol__get_change_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_ok * (*func_mysqlnd_protocol__get_ok_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_command * (*func_mysqlnd_protocol__get_command_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_eof * (*func_mysqlnd_protocol__get_eof_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_rset_header * (*func_mysqlnd_protocol__get_rset_header_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_res_field * (*func_mysqlnd_protocol__get_result_field_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_row * (*func_mysqlnd_protocol__get_row_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_stats * (*func_mysqlnd_protocol__get_stats_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_prepare_response *(*func_mysqlnd_protocol__get_prepare_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_chg_user_resp*(*func_mysqlnd_protocol__get_change_user_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_sha256_pk_request *(*func_mysqlnd_protocol__get_sha256_pk_request_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-typedef struct st_mysqlnd_packet_sha256_pk_request_response *(*func_mysqlnd_protocol__get_sha256_pk_request_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent);
-
-struct st_mysqlnd_protocol_methods
+
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_vio)
{
- func_mysqlnd_protocol__get_greet_packet get_greet_packet;
- func_mysqlnd_protocol__get_auth_packet get_auth_packet;
- func_mysqlnd_protocol__get_auth_response_packet get_auth_response_packet;
- func_mysqlnd_protocol__get_change_auth_response_packet get_change_auth_response_packet;
- func_mysqlnd_protocol__get_ok_packet get_ok_packet;
- func_mysqlnd_protocol__get_command_packet get_command_packet;
- func_mysqlnd_protocol__get_eof_packet get_eof_packet;
- func_mysqlnd_protocol__get_rset_header_packet get_rset_header_packet;
- func_mysqlnd_protocol__get_result_field_packet get_result_field_packet;
- func_mysqlnd_protocol__get_row_packet get_row_packet;
- func_mysqlnd_protocol__get_stats_packet get_stats_packet;
- func_mysqlnd_protocol__get_prepare_response_packet get_prepare_response_packet;
- func_mysqlnd_protocol__get_change_user_response_packet get_change_user_response_packet;
- func_mysqlnd_protocol__get_sha256_pk_request_packet get_sha256_pk_request_packet;
- func_mysqlnd_protocol__get_sha256_pk_request_response_packet get_sha256_pk_request_response_packet;
+ func_mysqlnd_vio__init init;
+ func_mysqlnd_vio__dtor dtor;
+ func_mysqlnd_vio__connect connect;
- void * unused1;
- void * unused2;
- void * unused3;
+ func_mysqlnd_vio__close_stream close_stream;
+ func_mysqlnd_vio__open_stream open_pipe;
+ func_mysqlnd_vio__open_stream open_tcp_or_unix;
+
+ func_mysqlnd_vio__get_stream get_stream;
+ func_mysqlnd_vio__set_stream set_stream;
+ func_mysqlnd_vio__get_open_stream get_open_stream;
+
+ func_mysqlnd_vio__set_client_option set_client_option;
+ func_mysqlnd_vio__post_connect_set_opt post_connect_set_opt;
+
+ func_mysqlnd_vio__enable_ssl enable_ssl;
+ func_mysqlnd_vio__disable_ssl disable_ssl;
+
+ func_mysqlnd_vio__network_read network_read;
+ func_mysqlnd_vio__network_write network_write;
+
+ func_mysqlnd_vio__consume_uneaten_data consume_uneaten_data;
+
+ func_mysqlnd_vio__free_contents free_contents;
};
-typedef MYSQLND * (*func_mysqlnd_object_factory__get_connection)(zend_bool persistent);
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory);
+
+typedef MYSQLND * (*func_mysqlnd_object_factory__get_connection)(MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) * factory, const zend_bool persistent);
typedef MYSQLND * (*func_mysqlnd_object_factory__clone_connection_object)(MYSQLND * conn);
-typedef MYSQLND_STMT * (*func_mysqlnd_object_factory__get_prepared_statement)(MYSQLND_CONN_DATA * conn);
-typedef MYSQLND_NET * (*func_mysqlnd_object_factory__get_io_channel)(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info);
-typedef MYSQLND_PROTOCOL * (*func_mysqlnd_object_factory__get_protocol_decoder)(zend_bool persistent);
+typedef MYSQLND_STMT * (*func_mysqlnd_object_factory__get_prepared_statement)(MYSQLND_CONN_DATA * conn, const zend_bool persistent);
+typedef MYSQLND_PFC * (*func_mysqlnd_object_factory__get_pfc)(const zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info);
+typedef MYSQLND_VIO * (*func_mysqlnd_object_factory__get_vio)(const zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info);
+typedef MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * (*func_mysqlnd_object_factory__get_protocol_payload_decoder_factory)(MYSQLND_CONN_DATA * conn, const zend_bool persistent);
-struct st_mysqlnd_object_factory_methods
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory)
{
func_mysqlnd_object_factory__get_connection get_connection;
func_mysqlnd_object_factory__clone_connection_object clone_connection_object;
func_mysqlnd_object_factory__get_prepared_statement get_prepared_statement;
- func_mysqlnd_object_factory__get_io_channel get_io_channel;
- func_mysqlnd_object_factory__get_protocol_decoder get_protocol_decoder;
+ func_mysqlnd_object_factory__get_pfc get_protocol_frame_codec;
+ func_mysqlnd_object_factory__get_vio get_vio;
+ func_mysqlnd_object_factory__get_protocol_payload_decoder_factory get_protocol_payload_decoder_factory;
};
-typedef enum_func_status (*func_mysqlnd_conn_data__init)(MYSQLND_CONN_DATA * conn);
-typedef enum_func_status (*func_mysqlnd_conn_data__connect)(MYSQLND_CONN_DATA * conn, const char * host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket_or_pipe, unsigned int mysql_flags);
-typedef zend_ulong (*func_mysqlnd_conn_data__escape_string)(MYSQLND_CONN_DATA * const conn, char *newstr, const char *escapestr, size_t escapestr_len);
+typedef enum_func_status (*func_mysqlnd_conn_data__connect)(MYSQLND_CONN_DATA * conn, MYSQLND_CSTRING hostname, MYSQLND_CSTRING username, MYSQLND_CSTRING password, MYSQLND_CSTRING database, unsigned int port, MYSQLND_CSTRING socket_or_pipe, unsigned int mysql_flags);
+typedef zend_ulong (*func_mysqlnd_conn_data__escape_string)(MYSQLND_CONN_DATA * const conn, char *newstr, const char *escapestr, size_t escapestr_len);
typedef enum_func_status (*func_mysqlnd_conn_data__set_charset)(MYSQLND_CONN_DATA * const conn, const char * const charset);
-typedef enum_func_status (*func_mysqlnd_conn_data__query)(MYSQLND_CONN_DATA * conn, const char * query, unsigned int query_len);
-typedef enum_func_status (*func_mysqlnd_conn_data__send_query)(MYSQLND_CONN_DATA * conn, const char *query, unsigned int query_len, enum_mysqlnd_send_query_type type, zval *read_cb, zval *err_cb);
+typedef enum_func_status (*func_mysqlnd_conn_data__query)(MYSQLND_CONN_DATA * conn, const char * const query, const size_t query_len);
+typedef enum_func_status (*func_mysqlnd_conn_data__send_query)(MYSQLND_CONN_DATA * conn, const char * const query, const size_t query_len, enum_mysqlnd_send_query_type type, zval *read_cb, zval *err_cb);
typedef enum_func_status (*func_mysqlnd_conn_data__reap_query)(MYSQLND_CONN_DATA * conn, enum_mysqlnd_reap_result_type type);
typedef MYSQLND_RES * (*func_mysqlnd_conn_data__use_result)(MYSQLND_CONN_DATA * const conn, const unsigned int flags);
typedef MYSQLND_RES * (*func_mysqlnd_conn_data__store_result)(MYSQLND_CONN_DATA * const conn, const unsigned int flags);
@@ -438,7 +402,7 @@ typedef enum_func_status (*func_mysqlnd_conn_data__refresh_server)(MYSQLND_CONN_
typedef enum_func_status (*func_mysqlnd_conn_data__ping)(MYSQLND_CONN_DATA * const conn);
typedef enum_func_status (*func_mysqlnd_conn_data__kill_connection)(MYSQLND_CONN_DATA * conn, unsigned int pid);
-typedef enum_func_status (*func_mysqlnd_conn_data__select_db)(MYSQLND_CONN_DATA * const conn, const char * const db, unsigned int db_len);
+typedef enum_func_status (*func_mysqlnd_conn_data__select_db)(MYSQLND_CONN_DATA * const conn, const char * const db, const size_t db_len);
typedef enum_func_status (*func_mysqlnd_conn_data__server_dump_debug_information)(MYSQLND_CONN_DATA * const conn);
typedef enum_func_status (*func_mysqlnd_conn_data__change_user)(MYSQLND_CONN_DATA * const conn, const char * user, const char * passwd, const char * db, zend_bool silent, size_t passwd_len);
@@ -448,15 +412,14 @@ typedef const char * (*func_mysqlnd_conn_data__get_sqlstate)(const MYSQLND_CONN
typedef uint64_t (*func_mysqlnd_conn_data__get_thread_id)(const MYSQLND_CONN_DATA * const conn);
typedef void (*func_mysqlnd_conn_data__get_statistics)(const MYSQLND_CONN_DATA * const conn, zval *return_value ZEND_FILE_LINE_DC);
-typedef zend_ulong (*func_mysqlnd_conn_data__get_server_version)(const MYSQLND_CONN_DATA * const conn);
+typedef zend_ulong (*func_mysqlnd_conn_data__get_server_version)(const MYSQLND_CONN_DATA * const conn);
typedef const char * (*func_mysqlnd_conn_data__get_server_information)(const MYSQLND_CONN_DATA * const conn);
typedef enum_func_status (*func_mysqlnd_conn_data__get_server_statistics)(MYSQLND_CONN_DATA * conn, zend_string **message);
typedef const char * (*func_mysqlnd_conn_data__get_host_information)(const MYSQLND_CONN_DATA * const conn);
typedef unsigned int (*func_mysqlnd_conn_data__get_protocol_information)(const MYSQLND_CONN_DATA * const conn);
typedef const char * (*func_mysqlnd_conn_data__get_last_message)(const MYSQLND_CONN_DATA * const conn);
typedef const char * (*func_mysqlnd_conn_data__charset_name)(const MYSQLND_CONN_DATA * const conn);
-typedef MYSQLND_RES * (*func_mysqlnd_conn_data__list_fields)(MYSQLND_CONN_DATA * conn, const char * table, const char * achtung_wild);
-typedef MYSQLND_RES * (*func_mysqlnd_conn_data__list_method)(MYSQLND_CONN_DATA * conn, const char * query, const char * achtung_wild, char *par1);
+typedef MYSQLND_RES * (*func_mysqlnd_conn_data__list_method)(MYSQLND_CONN_DATA * conn, const char * const query, const char * const achtung_wild, const char * const par1);
typedef uint64_t (*func_mysqlnd_conn_data__get_last_insert_id)(const MYSQLND_CONN_DATA * const conn);
typedef uint64_t (*func_mysqlnd_conn_data__get_affected_rows)(const MYSQLND_CONN_DATA * const conn);
@@ -466,7 +429,7 @@ typedef unsigned int (*func_mysqlnd_conn_data__get_field_count)(const MYSQLND_C
typedef unsigned int (*func_mysqlnd_conn_data__get_server_status)(const MYSQLND_CONN_DATA * const conn);
typedef enum_func_status (*func_mysqlnd_conn_data__set_server_option)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_server_option option);
-typedef enum_func_status (*func_mysqlnd_conn_data__set_client_option)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_option option, const char * const value);
+typedef enum_func_status (*func_mysqlnd_conn_data__set_client_option)(MYSQLND_CONN_DATA * const conn, enum_mysqlnd_client_option option, const char * const value);
typedef void (*func_mysqlnd_conn_data__free_contents)(MYSQLND_CONN_DATA * conn);/* private */
typedef void (*func_mysqlnd_conn_data__free_options)(MYSQLND_CONN_DATA * conn); /* private */
typedef void (*func_mysqlnd_conn_data__dtor)(MYSQLND_CONN_DATA * conn); /* private */
@@ -475,11 +438,9 @@ typedef enum_func_status (*func_mysqlnd_conn_data__query_read_result_set_header)
typedef MYSQLND_CONN_DATA * (*func_mysqlnd_conn_data__get_reference)(MYSQLND_CONN_DATA * const conn);
typedef enum_func_status (*func_mysqlnd_conn_data__free_reference)(MYSQLND_CONN_DATA * const conn);
-typedef enum mysqlnd_connection_state (*func_mysqlnd_conn_data__get_state)(const MYSQLND_CONN_DATA * const conn);
-typedef void (*func_mysqlnd_conn_data__set_state)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_connection_state new_state);
-typedef enum_func_status (*func_mysqlnd_conn_data__simple_command)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, size_t arg_len, enum mysqlnd_packet_type ok_packet, zend_bool silent, zend_bool ignore_upsert_status);
-typedef enum_func_status (*func_mysqlnd_conn_data__simple_command_handle_response)(MYSQLND_CONN_DATA * conn, enum mysqlnd_packet_type ok_packet, zend_bool silent, enum php_mysqlnd_server_command command, zend_bool ignore_upsert_status);
+typedef enum_func_status (*func_mysqlnd_conn_data__send_command_do_request)(MYSQLND_CONN_DATA * const conn, const enum php_mysqlnd_server_command command, const zend_uchar * const arg, const size_t arg_len, const zend_bool silent, const zend_bool ignore_upsert_status);
+typedef enum_func_status (*func_mysqlnd_conn_data__send_command_handle_response)(MYSQLND_CONN_DATA * const conn, const enum mysqlnd_packet_type ok_packet, const zend_bool silent, const enum php_mysqlnd_server_command command, const zend_bool ignore_upsert_status);
typedef enum_func_status (*func_mysqlnd_conn_data__restart_psession)(MYSQLND_CONN_DATA * conn);
typedef enum_func_status (*func_mysqlnd_conn_data__end_psession)(MYSQLND_CONN_DATA * conn);
@@ -498,24 +459,25 @@ typedef void (*func_mysqlnd_conn_data__tx_cor_options_to_string)(const MYSQLN
typedef enum_func_status (*func_mysqlnd_conn_data__tx_savepoint)(MYSQLND_CONN_DATA * conn, const char * const name);
typedef enum_func_status (*func_mysqlnd_conn_data__tx_savepoint_release)(MYSQLND_CONN_DATA * conn, const char * const name);
-typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_start)(MYSQLND_CONN_DATA * conn, size_t this_func);
-typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_end)(MYSQLND_CONN_DATA * conn, size_t this_func, enum_func_status status);
+typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_start)(MYSQLND_CONN_DATA * conn, const size_t this_func);
+typedef enum_func_status (*func_mysqlnd_conn_data__local_tx_end)(MYSQLND_CONN_DATA * conn, const size_t this_func, const enum_func_status status);
typedef enum_func_status (*func_mysqlnd_conn_data__execute_init_commands)(MYSQLND_CONN_DATA * conn);
typedef unsigned int (*func_mysqlnd_conn_data__get_updated_connect_flags)(MYSQLND_CONN_DATA * conn, unsigned int mysql_flags);
-typedef enum_func_status (*func_mysqlnd_conn_data__connect_handshake)(MYSQLND_CONN_DATA * conn, const char * const host, const char * const user, const char * const passwd, const unsigned int passwd_len, const char * const db, const unsigned int db_len, const unsigned int mysql_flags);
-typedef enum_func_status (*func_mysqlnd_conn_data__simple_command_send_request)(MYSQLND_CONN_DATA * conn, enum php_mysqlnd_server_command command, const zend_uchar * const arg, size_t arg_len, zend_bool silent, zend_bool ignore_upsert_status);
+typedef enum_func_status (*func_mysqlnd_conn_data__connect_handshake)(MYSQLND_CONN_DATA * conn, const MYSQLND_CSTRING * const scheme, const MYSQLND_CSTRING * const username, const MYSQLND_CSTRING * const password, const MYSQLND_CSTRING * const database, const unsigned int mysql_flags);
typedef struct st_mysqlnd_authentication_plugin * (*func_mysqlnd_conn_data__fetch_auth_plugin_by_name)(const char * const requested_protocol);
-typedef enum_func_status (*func_mysqlnd_conn_data__set_client_option_2d)(MYSQLND_CONN_DATA * const conn, enum mysqlnd_option option, const char * const key, const char * const value);
+typedef enum_func_status (*func_mysqlnd_conn_data__set_client_option_2d)(MYSQLND_CONN_DATA * const conn, const enum_mysqlnd_client_option option, const char * const key, const char * const value);
-typedef unsigned int (*func_mysqlnd_conn_data__negotiate_client_api_capabilities)(MYSQLND_CONN_DATA * const conn, const unsigned int flags);
-typedef unsigned int (*func_mysqlnd_conn_data__get_client_api_capabilities)(const MYSQLND_CONN_DATA * const conn);
+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);
-struct st_mysqlnd_conn_data_methods
+
+
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data)
{
- func_mysqlnd_conn_data__init init;
func_mysqlnd_conn_data__connect connect;
func_mysqlnd_conn_data__escape_string escape_string;
func_mysqlnd_conn_data__set_charset set_charset;
@@ -551,7 +513,6 @@ struct st_mysqlnd_conn_data_methods
func_mysqlnd_conn_data__get_protocol_information get_protocol_information;
func_mysqlnd_conn_data__get_last_message get_last_message;
func_mysqlnd_conn_data__charset_name charset_name;
- func_mysqlnd_conn_data__list_fields list_fields;
func_mysqlnd_conn_data__list_method list_method;
func_mysqlnd_conn_data__get_last_insert_id get_last_insert_id;
@@ -572,11 +533,6 @@ struct st_mysqlnd_conn_data_methods
func_mysqlnd_conn_data__get_reference get_reference;
func_mysqlnd_conn_data__free_reference free_reference;
- func_mysqlnd_conn_data__get_state get_state;
- func_mysqlnd_conn_data__set_state set_state;
-
- func_mysqlnd_conn_data__simple_command simple_command;
- func_mysqlnd_conn_data__simple_command_handle_response simple_command_handle_response;
func_mysqlnd_conn_data__restart_psession restart_psession;
func_mysqlnd_conn_data__end_psession end_psession;
@@ -600,22 +556,23 @@ struct st_mysqlnd_conn_data_methods
func_mysqlnd_conn_data__execute_init_commands execute_init_commands;
func_mysqlnd_conn_data__get_updated_connect_flags get_updated_connect_flags;
func_mysqlnd_conn_data__connect_handshake connect_handshake;
- func_mysqlnd_conn_data__simple_command_send_request simple_command_send_request;
func_mysqlnd_conn_data__fetch_auth_plugin_by_name fetch_auth_plugin_by_name;
func_mysqlnd_conn_data__set_client_option_2d set_client_option_2d;
func_mysqlnd_conn_data__negotiate_client_api_capabilities negotiate_client_api_capabilities;
func_mysqlnd_conn_data__get_client_api_capabilities get_client_api_capabilities;
+
+ func_mysqlnd_conn_data__get_scheme get_scheme;
};
-typedef enum_func_status (*func_mysqlnd_data__connect)(MYSQLND * conn, const char * host, const char * user, const char * passwd, unsigned int passwd_len, const char * db, unsigned int db_len, unsigned int port, const char * socket_or_pipe, unsigned int mysql_flags);
+typedef enum_func_status (*func_mysqlnd_data__connect)(MYSQLND * conn, const MYSQLND_CSTRING hostname, const MYSQLND_CSTRING username, const MYSQLND_CSTRING password, const MYSQLND_CSTRING database, unsigned int port, const MYSQLND_CSTRING socket_or_pipe, unsigned int mysql_flags);
typedef MYSQLND * (*func_mysqlnd_conn__clone_object)(MYSQLND * const conn);
typedef void (*func_mysqlnd_conn__dtor)(MYSQLND * conn);
-typedef enum_func_status (*func_mysqlnd_conn__close)(MYSQLND * conn, enum_connection_close_type close_type);
+typedef enum_func_status (*func_mysqlnd_conn__close)(MYSQLND * conn, const enum_connection_close_type close_type);
-struct st_mysqlnd_conn_methods
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn)
{
func_mysqlnd_data__connect connect;
func_mysqlnd_conn__clone_object clone_object;
@@ -623,13 +580,14 @@ struct st_mysqlnd_conn_methods
func_mysqlnd_conn__close close;
};
+
/* for decoding - binary or text protocol */
typedef enum_func_status (*func_mysqlnd_res__row_decoder)(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zval * fields,
unsigned int field_count, const MYSQLND_FIELD * fields_metadata,
zend_bool as_int_or_float, MYSQLND_STATS * stats);
-typedef MYSQLND_RES * (*func_mysqlnd_res__use_result)(MYSQLND_RES * const result, zend_bool ps_protocol);
+typedef MYSQLND_RES * (*func_mysqlnd_res__use_result)(MYSQLND_RES * const result, const zend_bool ps_protocol);
typedef MYSQLND_RES * (*func_mysqlnd_res__store_result)(MYSQLND_RES * result, MYSQLND_CONN_DATA * const conn, const unsigned int flags);
typedef void (*func_mysqlnd_res__fetch_into)(MYSQLND_RES *result, const unsigned int flags, zval *return_value, enum_mysqlnd_extension ext ZEND_FILE_LINE_DC);
typedef MYSQLND_ROW_C (*func_mysqlnd_res__fetch_row_c)(MYSQLND_RES *result);
@@ -646,11 +604,11 @@ typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_field_direct)(MYSQLND_RES
typedef const MYSQLND_FIELD *(*func_mysqlnd_res__fetch_fields)(MYSQLND_RES * const result);
typedef enum_func_status (*func_mysqlnd_res__read_result_metadata)(MYSQLND_RES * result, MYSQLND_CONN_DATA * conn);
-typedef zend_ulong * (*func_mysqlnd_res__fetch_lengths)(MYSQLND_RES * const result);
+typedef const size_t * (*func_mysqlnd_res__fetch_lengths)(MYSQLND_RES * const result);
typedef enum_func_status (*func_mysqlnd_res__store_result_fetch_data)(MYSQLND_CONN_DATA * const conn, MYSQLND_RES * result, MYSQLND_RES_METADATA * meta, MYSQLND_MEMORY_POOL_CHUNK *** row_buffers, zend_bool binary_protocol);
typedef void (*func_mysqlnd_res__free_result_buffers)(MYSQLND_RES * result); /* private */
-typedef enum_func_status (*func_mysqlnd_res__free_result)(MYSQLND_RES * result, zend_bool implicit);
+typedef enum_func_status (*func_mysqlnd_res__free_result)(MYSQLND_RES * result, const zend_bool implicit);
typedef void (*func_mysqlnd_res__free_result_internal)(MYSQLND_RES *result);
typedef void (*func_mysqlnd_res__free_result_contents)(MYSQLND_RES *result);
typedef void (*func_mysqlnd_res__free_buffered_data)(MYSQLND_RES *result);
@@ -659,7 +617,7 @@ typedef void (*func_mysqlnd_res__unbuffered_free_last_data)(MYSQLND_RES *resu
typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res__result_meta_init)(unsigned int field_count, zend_bool persistent);
-struct st_mysqlnd_res_methods
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_res)
{
mysqlnd_fetch_row_func fetch_row;
@@ -696,12 +654,12 @@ struct st_mysqlnd_res_methods
};
-typedef uint64_t (*func_mysqlnd_result_unbuffered__num_rows)(const MYSQLND_RES_UNBUFFERED * const result);
-typedef zend_ulong * (*func_mysqlnd_result_unbuffered__fetch_lengths)(MYSQLND_RES_UNBUFFERED * const result);
-typedef void (*func_mysqlnd_result_unbuffered__free_last_data)(MYSQLND_RES_UNBUFFERED * result, MYSQLND_STATS * const global_stats);
-typedef void (*func_mysqlnd_result_unbuffered__free_result)(MYSQLND_RES_UNBUFFERED * const result, MYSQLND_STATS * const global_stats);
+typedef uint64_t (*func_mysqlnd_result_unbuffered__num_rows)(const MYSQLND_RES_UNBUFFERED * const result);
+typedef const size_t * (*func_mysqlnd_result_unbuffered__fetch_lengths)(MYSQLND_RES_UNBUFFERED * const result);
+typedef void (*func_mysqlnd_result_unbuffered__free_last_data)(MYSQLND_RES_UNBUFFERED * result, MYSQLND_STATS * const global_stats);
+typedef void (*func_mysqlnd_result_unbuffered__free_result)(MYSQLND_RES_UNBUFFERED * const result, MYSQLND_STATS * const global_stats);
-struct st_mysqlnd_result_unbuffered_methods
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_unbuffered)
{
mysqlnd_fetch_row_func fetch_row;
func_mysqlnd_res__row_decoder row_decoder;
@@ -714,11 +672,11 @@ struct st_mysqlnd_result_unbuffered_methods
typedef uint64_t (*func_mysqlnd_result_buffered__num_rows)(const MYSQLND_RES_BUFFERED * const result);
typedef enum_func_status (*func_mysqlnd_result_buffered__initialize_result_set_rest)(MYSQLND_RES_BUFFERED * const result, MYSQLND_RES_METADATA * const meta,
MYSQLND_STATS * stats, zend_bool int_and_float_native);
-typedef zend_ulong * (*func_mysqlnd_result_buffered__fetch_lengths)(MYSQLND_RES_BUFFERED * const result);
+typedef const size_t * (*func_mysqlnd_result_buffered__fetch_lengths)(MYSQLND_RES_BUFFERED * const result);
typedef enum_func_status (*func_mysqlnd_result_buffered__data_seek)(MYSQLND_RES_BUFFERED * const result, const uint64_t row);
typedef void (*func_mysqlnd_result_buffered__free_result)(MYSQLND_RES_BUFFERED * const result);
-struct st_mysqlnd_result_buffered_methods
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_buffered)
{
mysqlnd_fetch_row_func fetch_row;
func_mysqlnd_res__row_decoder row_decoder;
@@ -736,10 +694,10 @@ typedef const MYSQLND_FIELD * (*func_mysqlnd_res_meta__fetch_fields)(MYSQLND_RES
typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res_meta__field_tell)(const MYSQLND_RES_METADATA * const meta);
typedef MYSQLND_FIELD_OFFSET (*func_mysqlnd_res_meta__field_seek)(MYSQLND_RES_METADATA * const meta, const MYSQLND_FIELD_OFFSET field_offset);
typedef enum_func_status (*func_mysqlnd_res_meta__read_metadata)(MYSQLND_RES_METADATA * const meta, MYSQLND_CONN_DATA * conn);
-typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res_meta__clone_metadata)(const MYSQLND_RES_METADATA * const meta, zend_bool persistent);
+typedef MYSQLND_RES_METADATA * (*func_mysqlnd_res_meta__clone_metadata)(const MYSQLND_RES_METADATA * const meta, const zend_bool persistent);
typedef void (*func_mysqlnd_res_meta__free_metadata)(MYSQLND_RES_METADATA * meta);
-struct st_mysqlnd_res_meta_methods
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_res_meta)
{
func_mysqlnd_res_meta__fetch_field fetch_field;
func_mysqlnd_res_meta__fetch_field_direct fetch_field_direct;
@@ -752,8 +710,8 @@ struct st_mysqlnd_res_meta_methods
};
-typedef enum_func_status (*func_mysqlnd_stmt__prepare)(MYSQLND_STMT * const stmt, const char * const query, unsigned int query_len);
-typedef enum_func_status (*func_mysqlnd_stmt__send_execute)(MYSQLND_STMT * const s, enum_mysqlnd_send_execute_type type, zval * read_cb, zval * err_cb);
+typedef enum_func_status (*func_mysqlnd_stmt__prepare)(MYSQLND_STMT * const stmt, const char * const query, const size_t query_len);
+typedef enum_func_status (*func_mysqlnd_stmt__send_execute)(MYSQLND_STMT * const s, const enum_mysqlnd_send_execute_type type, zval * read_cb, zval * err_cb);
typedef enum_func_status (*func_mysqlnd_stmt__execute)(MYSQLND_STMT * const stmt);
typedef MYSQLND_RES * (*func_mysqlnd_stmt__use_result)(MYSQLND_STMT * const stmt);
typedef MYSQLND_RES * (*func_mysqlnd_stmt__store_result)(MYSQLND_STMT * const stmt);
@@ -763,7 +721,7 @@ typedef enum_func_status (*func_mysqlnd_stmt__next_result)(MYSQLND_STMT * const
typedef enum_func_status (*func_mysqlnd_stmt__free_result)(MYSQLND_STMT * const stmt);
typedef enum_func_status (*func_mysqlnd_stmt__seek_data)(const MYSQLND_STMT * const stmt, uint64_t row);
typedef enum_func_status (*func_mysqlnd_stmt__reset)(MYSQLND_STMT * const stmt);
-typedef enum_func_status (*func_mysqlnd_stmt__net_close)(MYSQLND_STMT * const stmt, zend_bool implicit); /* private */
+typedef enum_func_status (*func_mysqlnd_stmt__close_on_server)(MYSQLND_STMT * const stmt, zend_bool implicit); /* private */
typedef enum_func_status (*func_mysqlnd_stmt__dtor)(MYSQLND_STMT * const stmt, zend_bool implicit); /* use this for mysqlnd_stmt_close */
typedef enum_func_status (*func_mysqlnd_stmt__fetch)(MYSQLND_STMT * const stmt, zend_bool * const fetched_anything);
typedef enum_func_status (*func_mysqlnd_stmt__bind_parameters)(MYSQLND_STMT * const stmt, MYSQLND_PARAM_BIND * const param_bind);
@@ -796,7 +754,7 @@ typedef void (*func_mysqlnd_stmt__free_stmt_content)(MYSQLND_STMT * const s)
typedef enum_func_status (*func_mysqlnd_stmt__flush)(MYSQLND_STMT * const stmt);
typedef void (*func_mysqlnd_stmt__free_stmt_result)(MYSQLND_STMT * const s);
-struct st_mysqlnd_stmt_methods
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_stmt)
{
func_mysqlnd_stmt__prepare prepare;
func_mysqlnd_stmt__send_execute send_execute;
@@ -809,7 +767,7 @@ struct st_mysqlnd_stmt_methods
func_mysqlnd_stmt__free_result free_result;
func_mysqlnd_stmt__seek_data seek_data;
func_mysqlnd_stmt__reset reset;
- func_mysqlnd_stmt__net_close net_close;
+ func_mysqlnd_stmt__close_on_server close_on_server;
func_mysqlnd_stmt__dtor dtor;
func_mysqlnd_stmt__fetch fetch;
@@ -856,103 +814,96 @@ struct st_mysqlnd_stmt_methods
};
-struct st_mysqlnd_net_data
+struct st_mysqlnd_vio_data
{
php_stream *stream;
- zend_bool compressed;
zend_bool ssl;
+ MYSQLND_VIO_OPTIONS options;
#ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
zend_uchar last_command;
#else
zend_uchar unused_pad1;
#endif
- MYSQLND_NET_OPTIONS options;
-
- unsigned int refcount;
zend_bool persistent;
- struct st_mysqlnd_net_methods m;
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_vio) m;
};
-struct st_mysqlnd_net
+struct st_mysqlnd_vio
{
- /* cmd buffer */
- MYSQLND_CMD_BUFFER cmd_buffer;
+ struct st_mysqlnd_vio_data * data;
- struct st_mysqlnd_net_data * data;
+ zend_bool persistent;
+};
-#ifdef MYSQLND_COMPRESSION_ENABLED
- MYSQLND_READ_BUFFER * uncompressed_data;
-#else
- void * unused_pad1;
-#endif
- zend_bool persistent;
- /* sequence for simple checking of correct packets */
- zend_uchar packet_no;
- zend_uchar compressed_envelope_packet_no;
+struct st_mysqlnd_protocol_command
+{
+ enum_func_status (*run)(void *cmd);
+ void (*free_command)(void * cmd);
};
+typedef struct st_mysqlnd_protocol_command * (*func_mysqlnd__command_factory)(enum php_mysqlnd_server_command command, ...);
+
-struct st_mysqlnd_protocol
+
+typedef struct st_mysqlnd_connection_state MYSQLND_CONNECTION_STATE;
+typedef enum mysqlnd_connection_state (*func_mysqlnd_connection_state__get)(const MYSQLND_CONNECTION_STATE * const state_struct);
+typedef void (*func_mysqlnd_connection_state__set)(MYSQLND_CONNECTION_STATE * const state_struct, const enum mysqlnd_connection_state state);
+
+
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_connection_state)
{
- zend_bool persistent;
- struct st_mysqlnd_protocol_methods m;
+ func_mysqlnd_connection_state__get get;
+ func_mysqlnd_connection_state__set set;
};
+struct st_mysqlnd_connection_state
+{
+ enum mysqlnd_connection_state state;
+
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_connection_state) *m;
+};
struct st_mysqlnd_connection_data
{
/* Operation related */
- MYSQLND_NET * net;
- MYSQLND_PROTOCOL * protocol;
+ MYSQLND_PFC * protocol_frame_codec;
+ MYSQLND_VIO * vio;
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * payload_decoder_factory;
/* Information related */
- char *host;
- unsigned int host_len;
- char *unix_socket;
- unsigned int unix_socket_len;
- char *user;
- unsigned int user_len;
- char *passwd;
- unsigned int passwd_len;
- char *scheme;
- unsigned int scheme_len;
+ MYSQLND_STRING hostname;
+ MYSQLND_STRING unix_socket;
+ MYSQLND_STRING username;
+ MYSQLND_STRING password;
+ MYSQLND_STRING scheme;
uint64_t thread_id;
char *server_version;
char *host_info;
- zend_uchar *auth_plugin_data;
- size_t auth_plugin_data_len;
+ MYSQLND_STRING authentication_plugin_data;
const MYSQLND_CHARSET *charset;
const MYSQLND_CHARSET *greet_charset;
- char *connect_or_select_db;
- unsigned int connect_or_select_db_len;
+ MYSQLND_STRING connect_or_select_db;
MYSQLND_INFILE infile;
unsigned int protocol_version;
- zend_ulong max_packet_size;
unsigned int port;
- zend_ulong client_flag;
- zend_ulong server_capabilities;
+ zend_ulong server_capabilities;
/* For UPSERT queries */
MYSQLND_UPSERT_STATUS * upsert_status;
MYSQLND_UPSERT_STATUS upsert_status_impl;
- char *last_message;
- unsigned int last_message_len;
+ MYSQLND_STRING last_message;
/* If error packet, we use these */
MYSQLND_ERROR_INFO * error_info;
MYSQLND_ERROR_INFO error_info_impl;
- /*
- To prevent queries during unbuffered fetches. Also to
- mark the connection as destroyed for garbage collection.
- */
- enum mysqlnd_connection_state state;
- enum_mysqlnd_query_type last_query_type;
+ MYSQLND_CONNECTION_STATE state;
+ enum_mysqlnd_query_type last_query_type;
/* Temporary storage between query and (use|store)_result() call */
MYSQLND_RES *current_result;
@@ -969,20 +920,23 @@ struct st_mysqlnd_connection_data
unsigned int field_count;
/* options */
- MYSQLND_OPTIONS * options;
- MYSQLND_OPTIONS options_impl;
+ MYSQLND_SESSION_OPTIONS * options;
+ MYSQLND_SESSION_OPTIONS options_impl;
/* stats */
MYSQLND_STATS * stats;
- unsigned int client_api_capabilities;
+ size_t client_api_capabilities;
zval async_read_cb;
zval async_err_cb;
zend_bool in_async_read_cb;
zend_bool in_async_err_cb;
- struct st_mysqlnd_conn_data_methods * m;
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_object_factory) object_factory;
+ func_mysqlnd__command_factory command_factory;
+
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn_data) * m;
/* persistent connection */
zend_bool persistent;
@@ -993,10 +947,192 @@ struct st_mysqlnd_connection
{
MYSQLND_CONN_DATA * data;
zend_bool persistent;
- struct st_mysqlnd_conn_methods * m;
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_conn) * m;
+};
+
+
+
+struct st_mysqlnd_packet_greet;
+struct st_mysqlnd_packet_greet;
+struct st_mysqlnd_packet_auth;
+struct st_mysqlnd_packet_ok;
+struct st_mysqlnd_packet_command;
+struct st_mysqlnd_packet_eof;
+struct st_mysqlnd_packet_rset_header;
+struct st_mysqlnd_packet_res_field;
+struct st_mysqlnd_packet_row;
+struct st_mysqlnd_packet_stats;
+struct st_mysqlnd_packet_prepare_response;
+struct st_mysqlnd_packet_chg_user_resp;
+struct st_mysqlnd_packet_auth_pam;
+struct st_mysqlnd_packet_sha256_pk_request;
+struct st_mysqlnd_packet_sha256_pk_request_response;
+
+typedef struct st_mysqlnd_packet_greet * (*func_mysqlnd_protocol_payload_decoder_factory__get_greet_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_auth * (*func_mysqlnd_protocol_payload_decoder_factory__get_auth_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_auth_response *(*func_mysqlnd_protocol_payload_decoder_factory__get_auth_response_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_change_auth_response * (*func_mysqlnd_protocol_payload_decoder_factory__get_change_auth_response_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_ok * (*func_mysqlnd_protocol_payload_decoder_factory__get_ok_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_command * (*func_mysqlnd_protocol_payload_decoder_factory__get_command_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_eof * (*func_mysqlnd_protocol_payload_decoder_factory__get_eof_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_rset_header * (*func_mysqlnd_protocol_payload_decoder_factory__get_rset_header_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_res_field * (*func_mysqlnd_protocol_payload_decoder_factory__get_result_field_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_row * (*func_mysqlnd_protocol_payload_decoder_factory__get_row_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_stats * (*func_mysqlnd_protocol_payload_decoder_factory__get_stats_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_prepare_response *(*func_mysqlnd_protocol_payload_decoder_factory__get_prepare_response_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_chg_user_resp*(*func_mysqlnd_protocol_payload_decoder_factory__get_change_user_response_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_sha256_pk_request *(*func_mysqlnd_protocol_payload_decoder_factory__get_sha256_pk_request_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+typedef struct st_mysqlnd_packet_sha256_pk_request_response *(*func_mysqlnd_protocol_payload_decoder_factory__get_sha256_pk_request_response_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent);
+
+typedef enum_func_status (*func_mysqlnd_protocol_payload_decoder_factory__send_command)(
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * payload_decoder_factory,
+ const enum php_mysqlnd_server_command command,
+ const zend_uchar * const arg, const size_t arg_len,
+ const zend_bool silent,
+
+ MYSQLND_CONNECTION_STATE * connection_state,
+ MYSQLND_ERROR_INFO * error_info,
+ MYSQLND_UPSERT_STATUS * upsert_status,
+ MYSQLND_STATS * stats,
+ func_mysqlnd_conn_data__send_close send_close,
+ void * send_close_ctx);
+
+typedef enum_func_status (*func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_OK)(
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const payload_decoder_factory,
+ MYSQLND_ERROR_INFO * const error_info,
+ MYSQLND_UPSERT_STATUS * const upsert_status,
+ const zend_bool ignore_upsert_status, /* actually used only by LOAD DATA. COM_QUERY and COM_EXECUTE handle the responses themselves */
+ MYSQLND_STRING * const last_message,
+ const zend_bool last_message_persistent);
+
+typedef enum_func_status (*func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_EOF)(
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const payload_decoder_factory,
+ MYSQLND_ERROR_INFO * const error_info,
+ MYSQLND_UPSERT_STATUS * const upsert_status);
+
+typedef enum_func_status (*func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response)(
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * payload_decoder_factory,
+ const enum mysqlnd_packet_type ok_packet,
+ const zend_bool silent,
+ const enum php_mysqlnd_server_command command,
+ const zend_bool ignore_upsert_status, /* actually used only by LOAD DATA. COM_QUERY and COM_EXECUTE handle the responses themselves */
+
+ MYSQLND_ERROR_INFO * error_info,
+ MYSQLND_UPSERT_STATUS * upsert_status,
+ MYSQLND_STRING * last_message,
+ zend_bool last_message_persistent);
+
+
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_payload_decoder_factory)
+{
+ func_mysqlnd_protocol_payload_decoder_factory__get_greet_packet get_greet_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_auth_packet get_auth_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_auth_response_packet get_auth_response_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_change_auth_response_packet get_change_auth_response_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_ok_packet get_ok_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_command_packet get_command_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_eof_packet get_eof_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_rset_header_packet get_rset_header_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_result_field_packet get_result_field_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_row_packet get_row_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_stats_packet get_stats_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_prepare_response_packet get_prepare_response_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_change_user_response_packet get_change_user_response_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_sha256_pk_request_packet get_sha256_pk_request_packet;
+ func_mysqlnd_protocol_payload_decoder_factory__get_sha256_pk_request_response_packet get_sha256_pk_request_response_packet;
+
+ func_mysqlnd_protocol_payload_decoder_factory__send_command send_command;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_response send_command_handle_response;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_OK send_command_handle_OK;
+ func_mysqlnd_protocol_payload_decoder_factory__send_command_handle_EOF send_command_handle_EOF;
+};
+
+struct st_mysqlnd_protocol_payload_decoder_factory
+{
+ MYSQLND_CONN_DATA * conn;
+ zend_bool persistent;
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_payload_decoder_factory) m;
};
+typedef struct st_mysqlnd_read_buffer {
+ zend_uchar * data;
+ size_t offset;
+ size_t size;
+ size_t len;
+ zend_bool (*is_empty)(const struct st_mysqlnd_read_buffer *);
+ void (*read)(struct st_mysqlnd_read_buffer *, size_t count, zend_uchar * dest);
+ size_t (*bytes_left)(const struct st_mysqlnd_read_buffer *);
+ void (*free_buffer)(struct st_mysqlnd_read_buffer **);
+} MYSQLND_READ_BUFFER;
+
+
+
+typedef enum_func_status (*func_mysqlnd_pfc__init)(MYSQLND_PFC * const pfc, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info);
+typedef void (*func_mysqlnd_pfc__dtor)(MYSQLND_PFC * const pfc, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
+typedef enum_func_status (*func_mysqlnd_pfc__reset)(MYSQLND_PFC * const pfc, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
+typedef enum_func_status (*func_mysqlnd_pfc__set_client_option)(MYSQLND_PFC * const pfc, enum_mysqlnd_client_option option, const char * const value);
+typedef enum_func_status (*func_mysqlnd_pfc__decode)(zend_uchar * uncompressed_data, const size_t uncompressed_data_len, const zend_uchar * const compressed_data, const size_t compressed_data_len);
+typedef enum_func_status (*func_mysqlnd_pfc__encode)(zend_uchar * compress_buffer, size_t * compress_buffer_len, const zend_uchar * const uncompressed_data, const size_t uncompressed_data_len);
+typedef size_t (*func_mysqlnd_pfc__send)(MYSQLND_PFC * const pfc, MYSQLND_VIO * const vio, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
+typedef enum_func_status (*func_mysqlnd_pfc__receive)(MYSQLND_PFC * const pfc, MYSQLND_VIO * const vio, zend_uchar * const buffer, const size_t count, MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info);
+typedef enum_func_status (*func_mysqlnd_pfc__read_compressed_packet_from_stream_and_fill_read_buffer)(MYSQLND_PFC * pfc, MYSQLND_VIO * const vio, size_t net_payload_size, MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info);
+typedef void (*func_mysqlnd_pfc__free_contents)(MYSQLND_PFC * pfc);
+
+MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_packet_frame_codec)
+{
+ func_mysqlnd_pfc__init init;
+ func_mysqlnd_pfc__dtor dtor;
+ func_mysqlnd_pfc__reset reset;
+ func_mysqlnd_pfc__set_client_option set_client_option;
+
+ func_mysqlnd_pfc__decode decode;
+ func_mysqlnd_pfc__encode encode;
+
+ func_mysqlnd_pfc__send send;
+ func_mysqlnd_pfc__receive receive;
+
+ func_mysqlnd_pfc__read_compressed_packet_from_stream_and_fill_read_buffer read_compressed_packet_from_stream_and_fill_read_buffer;
+
+ func_mysqlnd_pfc__free_contents free_contents;
+};
+
+
+struct st_mysqlnd_protocol_frame_codec_data
+{
+ php_stream *stream;
+ zend_bool compressed;
+ zend_bool ssl;
+ uint64_t flags;
+ char * sha256_server_public_key;
+
+#ifdef MYSQLND_COMPRESSION_ENABLED
+ MYSQLND_READ_BUFFER * uncompressed_data;
+#else
+ void * unused_pad1;
+#endif
+
+ /* sequence for simple checking of correct packets */
+ zend_uchar packet_no;
+ zend_uchar compressed_envelope_packet_no;
+
+ zend_bool persistent;
+
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_protocol_packet_frame_codec) m;
+};
+
+
+struct st_mysqlnd_protocol_frame_codec
+{
+ MYSQLND_CMD_BUFFER cmd_buffer;
+
+ struct st_mysqlnd_protocol_frame_codec_data * data;
+
+ zend_bool persistent;
+};
+
+
+
struct mysqlnd_field_hash_key
{
zend_bool is_numeric;
@@ -1009,7 +1145,7 @@ struct st_mysqlnd_result_metadata
MYSQLND_FIELD *fields;
struct mysqlnd_field_hash_key *zend_hash_keys;
- struct st_mysqlnd_res_meta_methods * m;
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_res_meta) * m;
size_t bit_fields_total_len; /* trailing \0 not counted */
/* We need this to make fast allocs in rowp_read */
@@ -1028,7 +1164,7 @@ struct st_mysqlnd_result_metadata
uint64_t initialized_rows; \
\
/* Column lengths of current row - both buffered and unbuffered. For buffered results it duplicates the data found in **data */ \
- zend_ulong *lengths; \
+ size_t *lengths; \
\
MYSQLND_MEMORY_POOL *result_set_memory_pool; \
\
@@ -1039,7 +1175,7 @@ struct st_mysqlnd_result_metadata
unsigned int field_count; \
zend_bool ps; \
zend_bool persistent; \
- struct st_mysqlnd_result_buffered_methods m; \
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_buffered) m; \
enum mysqlnd_buffered_type type; \
void * unused1; \
void * unused2; \
@@ -1072,7 +1208,7 @@ struct st_mysqlnd_buffered_result_c
struct st_mysqlnd_unbuffered_result
{
- struct st_mysqlnd_result_unbuffered_methods m;
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_result_unbuffered) m;
uint64_t row_count;
/* For unbuffered (both normal and PS) */
@@ -1083,7 +1219,7 @@ struct st_mysqlnd_unbuffered_result
Column lengths of current row - both buffered and unbuffered.
For buffered results it duplicates the data found in **data
*/
- zend_ulong *lengths;
+ size_t *lengths;
MYSQLND_MEMORY_POOL *result_set_memory_pool;
@@ -1113,8 +1249,7 @@ struct st_mysqlnd_res
MYSQLND_RES_UNBUFFERED *unbuf;
zend_bool persistent;
-
- struct st_mysqlnd_res_methods m;
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_res) m;
};
@@ -1138,7 +1273,6 @@ struct st_mysqlnd_stmt_data
zend_ulong stmt_id;
zend_ulong flags;/* cursor is set here */
enum_mysqlnd_stmt_state state;
- unsigned int warning_count;
MYSQLND_RES *result;
unsigned int field_count;
unsigned int param_count;
@@ -1173,18 +1307,11 @@ struct st_mysqlnd_stmt_data
struct st_mysqlnd_stmt
{
MYSQLND_STMT_DATA * data;
- struct st_mysqlnd_stmt_methods *m;
+ MYSQLND_CLASS_METHODS_TYPE(mysqlnd_stmt) * m;
zend_bool persistent;
};
-typedef struct st_mysqlnd_string
-{
- char *s;
- size_t l;
-} MYSQLND_STRING;
-
-
struct st_mysqlnd_plugin_header
{
unsigned int plugin_api_version;
@@ -1225,8 +1352,8 @@ typedef zend_uchar * (*func_auth_plugin__get_auth_data)(struct st_mysqlnd_authen
size_t * auth_data_len,
MYSQLND_CONN_DATA * conn, const char * const user, const char * const passwd,
const size_t passwd_len, zend_uchar * auth_plugin_data, size_t auth_plugin_data_len,
- const MYSQLND_OPTIONS * const options,
- const MYSQLND_NET_OPTIONS * const net_options, zend_ulong mysql_flags
+ const MYSQLND_SESSION_OPTIONS * const session_options,
+ const MYSQLND_PFC_DATA * const pfc_data, zend_ulong mysql_flags
);
struct st_mysqlnd_authentication_plugin
@@ -1237,5 +1364,4 @@ struct st_mysqlnd_authentication_plugin
} methods;
};
-
#endif /* MYSQLND_STRUCTS_H */
diff --git a/ext/mysqlnd/mysqlnd_vio.c b/ext/mysqlnd/mysqlnd_vio.c
new file mode 100644
index 0000000000..1d9b00c337
--- /dev/null
+++ b/ext/mysqlnd/mysqlnd_vio.c
@@ -0,0 +1,809 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 2006-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Andrey Hristov <andrey@mysql.com> |
+ | Ulf Wendel <uwendel@mysql.com> |
+ +----------------------------------------------------------------------+
+*/
+#include "php.h"
+#include "mysqlnd.h"
+#include "mysqlnd_priv.h"
+#include "mysqlnd_statistics.h"
+#include "mysqlnd_debug.h"
+#include "mysqlnd_ext_plugin.h"
+#include "php_network.h"
+
+#ifndef PHP_WIN32
+#include <netinet/tcp.h>
+#else
+#include <winsock.h>
+#endif
+
+
+/* {{{ mysqlnd_set_sock_no_delay */
+static int
+mysqlnd_set_sock_no_delay(php_stream * stream)
+{
+ int socketd = ((php_netstream_data_t*)stream->abstract)->socket;
+ int ret = SUCCESS;
+ int flag = 1;
+ int result = setsockopt(socketd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int));
+
+ DBG_ENTER("mysqlnd_set_sock_no_delay");
+
+ if (result == -1) {
+ ret = FAILURE;
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_set_sock_keepalive */
+static int
+mysqlnd_set_sock_keepalive(php_stream * stream)
+{
+ int socketd = ((php_netstream_data_t*)stream->abstract)->socket;
+ int ret = SUCCESS;
+ int flag = 1;
+ int result = setsockopt(socketd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int));
+
+ DBG_ENTER("mysqlnd_set_sock_keepalive");
+
+ if (result == -1) {
+ ret = FAILURE;
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::network_read */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_vio, network_read)(MYSQLND_VIO * const vio, zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ enum_func_status return_value = PASS;
+ php_stream * net_stream = vio->data->m.get_stream(vio);
+ size_t old_chunk_size = net_stream->chunk_size;
+ size_t to_read = count, ret;
+ zend_uchar * p = buffer;
+
+ DBG_ENTER("mysqlnd_vio::network_read");
+ DBG_INF_FMT("count="MYSQLND_SZ_T_SPEC, count);
+
+ net_stream->chunk_size = MIN(to_read, vio->data->options.net_read_buffer_size);
+ while (to_read) {
+ if (!(ret = php_stream_read(net_stream, (char *) p, to_read))) {
+ DBG_ERR_FMT("Error while reading header from socket");
+ return_value = FAIL;
+ break;
+ }
+ p += ret;
+ to_read -= ret;
+ }
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE(stats, STAT_BYTES_RECEIVED, count - to_read);
+ net_stream->chunk_size = old_chunk_size;
+ DBG_RETURN(return_value);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::network_write */
+static size_t
+MYSQLND_METHOD(mysqlnd_vio, network_write)(MYSQLND_VIO * const vio, const zend_uchar * const buffer, const size_t count,
+ MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ size_t ret;
+ DBG_ENTER("mysqlnd_vio::network_write");
+ DBG_INF_FMT("sending %u bytes", count);
+ ret = php_stream_write(vio->data->m.get_stream(vio), (char *)buffer, count);
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::open_pipe */
+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;
+
+ DBG_ENTER("mysqlnd_vio::open_pipe");
+ if (persistent) {
+ streams_options |= STREAM_OPEN_PERSISTENT;
+ }
+ streams_options |= IGNORE_URL;
+ net_stream = php_stream_open_wrapper(scheme.s + sizeof("pipe://") - 1, "r+", streams_options, NULL);
+ if (!net_stream) {
+ SET_CLIENT_ERROR(error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "Unknown errror while connecting");
+ DBG_RETURN(NULL);
+ }
+ /*
+ Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
+ be registered as resource (in EG(regular_list). So far, so good. However, it won't be
+ unregistered until the script ends. So, we need to take care of that.
+ */
+ origin_dtor = EG(regular_list).pDestructor;
+ EG(regular_list).pDestructor = NULL;
+ zend_hash_index_del(&EG(regular_list), net_stream->res->handle); /* ToDO: should it be res->handle, do streams register with addref ?*/
+ EG(regular_list).pDestructor = origin_dtor;
+ net_stream->res = NULL;
+
+ DBG_RETURN(net_stream);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::open_tcp_or_unix */
+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;
+ zend_string *errstr = NULL;
+ int errcode = 0;
+ struct timeval tv;
+ dtor_func_t origin_dtor;
+ php_stream * net_stream = NULL;
+
+ DBG_ENTER("mysqlnd_vio::open_tcp_or_unix");
+
+ vio->data->stream = NULL;
+
+ if (persistent) {
+ hashed_details_len = mnd_sprintf(&hashed_details, 0, "%p", vio);
+ DBG_INF_FMT("hashed_details=%s", hashed_details);
+ }
+
+ if (vio->data->options.timeout_connect) {
+ tv.tv_sec = vio->data->options.timeout_connect;
+ tv.tv_usec = 0;
+ }
+
+ DBG_INF_FMT("calling php_stream_xport_create");
+ net_stream = php_stream_xport_create(scheme.s, scheme.l, streams_options, streams_flags,
+ hashed_details, (vio->data->options.timeout_connect) ? &tv : NULL,
+ NULL /*ctx*/, &errstr, &errcode);
+ if (errstr || !net_stream) {
+ DBG_ERR("Error");
+ if (hashed_details) {
+ mnd_sprintf_free(hashed_details);
+ }
+ errcode = CR_CONNECTION_ERROR;
+ SET_CLIENT_ERROR(error_info,
+ CR_CONNECTION_ERROR,
+ UNKNOWN_SQLSTATE,
+ errstr? ZSTR_VAL(errstr):"Unknown error while connecting");
+ if (errstr) {
+ zend_string_release(errstr);
+ }
+ DBG_RETURN(NULL);
+ }
+ if (hashed_details) {
+ /*
+ If persistent, the streams register it in EG(persistent_list).
+ This is unwanted. ext/mysql or ext/mysqli are responsible to clean,
+ whatever they have to.
+ */
+ zend_resource *le;
+
+ if ((le = zend_hash_str_find_ptr(&EG(persistent_list), hashed_details, hashed_details_len))) {
+ origin_dtor = EG(persistent_list).pDestructor;
+ /*
+ in_free will let streams code skip destructing - big HACK,
+ but STREAMS suck big time regarding persistent streams.
+ Just not compatible for extensions that need persistency.
+ */
+ EG(persistent_list).pDestructor = NULL;
+ zend_hash_str_del(&EG(persistent_list), hashed_details, hashed_details_len);
+ EG(persistent_list).pDestructor = origin_dtor;
+ pefree(le, 1);
+ }
+#if ZEND_DEBUG
+ /* Shut-up the streams, they don't know what they are doing */
+ net_stream->__exposed = 1;
+#endif
+ mnd_sprintf_free(hashed_details);
+ }
+
+ /*
+ Streams are not meant for C extensions! Thus we need a hack. Every connected stream will
+ be registered as resource (in EG(regular_list). So far, so good. However, it won't be
+ unregistered until the script ends. So, we need to take care of that.
+ */
+ origin_dtor = EG(regular_list).pDestructor;
+ EG(regular_list).pDestructor = NULL;
+ zend_hash_index_del(&EG(regular_list), net_stream->res->handle); /* ToDO: should it be res->handle, do streams register with addref ?*/
+ efree(net_stream->res);
+ net_stream->res = NULL;
+ EG(regular_list).pDestructor = origin_dtor;
+ DBG_RETURN(net_stream);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::post_connect_set_opt */
+static void
+MYSQLND_METHOD(mysqlnd_vio, post_connect_set_opt)(MYSQLND_VIO * const vio, const MYSQLND_CSTRING scheme,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ php_stream * net_stream = vio->data->m.get_stream(vio);
+ DBG_ENTER("mysqlnd_vio::post_connect_set_opt");
+ if (net_stream) {
+ if (vio->data->options.timeout_read) {
+ struct timeval tv;
+ DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", vio->data->options.timeout_read);
+ tv.tv_sec = vio->data->options.timeout_read;
+ tv.tv_usec = 0;
+ php_stream_set_option(net_stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv);
+ }
+
+ if (!memcmp(scheme.s, "tcp://", sizeof("tcp://") - 1)) {
+ /* TCP -> Set TCP_NODELAY */
+ mysqlnd_set_sock_no_delay(net_stream);
+ /* TCP -> Set SO_KEEPALIVE */
+ mysqlnd_set_sock_keepalive(net_stream);
+ }
+ }
+
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::get_open_stream */
+static func_mysqlnd_vio__open_stream
+MYSQLND_METHOD(mysqlnd_vio, get_open_stream)(MYSQLND_VIO * const vio, const MYSQLND_CSTRING scheme,
+ MYSQLND_ERROR_INFO * const error_info)
+{
+ func_mysqlnd_vio__open_stream ret = NULL;
+ DBG_ENTER("mysqlnd_vio::get_open_stream");
+ if (scheme.l > (sizeof("pipe://") - 1) && !memcmp(scheme.s, "pipe://", sizeof("pipe://") - 1)) {
+ ret = vio->data->m.open_pipe;
+ } else if ((scheme.l > (sizeof("tcp://") - 1) && !memcmp(scheme.s, "tcp://", sizeof("tcp://") - 1))
+ ||
+ (scheme.l > (sizeof("unix://") - 1) && !memcmp(scheme.s, "unix://", sizeof("unix://") - 1)))
+ {
+ ret = vio->data->m.open_tcp_or_unix;
+ }
+
+ if (!ret) {
+ SET_CLIENT_ERROR(error_info, CR_CONNECTION_ERROR, UNKNOWN_SQLSTATE, "No handler for this scheme");
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::connect */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_vio, connect)(MYSQLND_VIO * const vio, const MYSQLND_CSTRING scheme, const zend_bool persistent,
+ MYSQLND_STATS * const conn_stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ enum_func_status ret = FAIL;
+ func_mysqlnd_vio__open_stream open_stream = NULL;
+ DBG_ENTER("mysqlnd_vio::connect");
+
+ vio->data->m.close_stream(vio, conn_stats, error_info);
+
+ open_stream = vio->data->m.get_open_stream(vio, scheme, error_info);
+ if (open_stream) {
+ php_stream * net_stream = open_stream(vio, scheme, persistent, conn_stats, error_info);
+ if (net_stream) {
+ (void) vio->data->m.set_stream(vio, net_stream);
+ vio->data->m.post_connect_set_opt(vio, scheme, conn_stats, error_info);
+ ret = PASS;
+ }
+ }
+
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::set_client_option */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_vio, set_client_option)(MYSQLND_VIO * const net, enum_mysqlnd_client_option option, const char * const value)
+{
+ DBG_ENTER("mysqlnd_vio::set_client_option");
+ DBG_INF_FMT("option=%u", option);
+ switch (option) {
+ case MYSQLND_OPT_NET_READ_BUFFER_SIZE:
+ DBG_INF("MYSQLND_OPT_NET_READ_BUFFER_SIZE");
+ net->data->options.net_read_buffer_size = *(unsigned int*) value;
+ DBG_INF_FMT("new_length="MYSQLND_SZ_T_SPEC, net->data->options.net_read_buffer_size);
+ break;
+ case MYSQL_OPT_CONNECT_TIMEOUT:
+ DBG_INF("MYSQL_OPT_CONNECT_TIMEOUT");
+ net->data->options.timeout_connect = *(unsigned int*) value;
+ break;
+ case MYSQLND_OPT_SSL_KEY:
+ {
+ zend_bool pers = net->persistent;
+ if (net->data->options.ssl_key) {
+ mnd_pefree(net->data->options.ssl_key, pers);
+ }
+ net->data->options.ssl_key = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQLND_OPT_SSL_CERT:
+ {
+ zend_bool pers = net->persistent;
+ if (net->data->options.ssl_cert) {
+ mnd_pefree(net->data->options.ssl_cert, pers);
+ }
+ net->data->options.ssl_cert = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQLND_OPT_SSL_CA:
+ {
+ zend_bool pers = net->persistent;
+ if (net->data->options.ssl_ca) {
+ mnd_pefree(net->data->options.ssl_ca, pers);
+ }
+ net->data->options.ssl_ca = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQLND_OPT_SSL_CAPATH:
+ {
+ zend_bool pers = net->persistent;
+ if (net->data->options.ssl_capath) {
+ mnd_pefree(net->data->options.ssl_capath, pers);
+ }
+ net->data->options.ssl_capath = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQLND_OPT_SSL_CIPHER:
+ {
+ zend_bool pers = net->persistent;
+ if (net->data->options.ssl_cipher) {
+ mnd_pefree(net->data->options.ssl_cipher, pers);
+ }
+ net->data->options.ssl_cipher = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQLND_OPT_SSL_PASSPHRASE:
+ {
+ zend_bool pers = net->persistent;
+ if (net->data->options.ssl_passphrase) {
+ mnd_pefree(net->data->options.ssl_passphrase, pers);
+ }
+ net->data->options.ssl_passphrase = value? mnd_pestrdup(value, pers) : NULL;
+ break;
+ }
+ case MYSQL_OPT_SSL_VERIFY_SERVER_CERT:
+ {
+ enum mysqlnd_ssl_peer val = *((enum mysqlnd_ssl_peer *)value);
+ switch (val) {
+ case MYSQLND_SSL_PEER_VERIFY:
+ DBG_INF("MYSQLND_SSL_PEER_VERIFY");
+ break;
+ case MYSQLND_SSL_PEER_DONT_VERIFY:
+ DBG_INF("MYSQLND_SSL_PEER_DONT_VERIFY");
+ break;
+ case MYSQLND_SSL_PEER_DEFAULT:
+ DBG_INF("MYSQLND_SSL_PEER_DEFAULT");
+ val = MYSQLND_SSL_PEER_DEFAULT;
+ break;
+ default:
+ DBG_INF("default = MYSQLND_SSL_PEER_DEFAULT_ACTION");
+ val = MYSQLND_SSL_PEER_DEFAULT;
+ break;
+ }
+ net->data->options.ssl_verify_peer = val;
+ break;
+ }
+ case MYSQL_OPT_READ_TIMEOUT:
+ net->data->options.timeout_read = *(unsigned int*) value;
+ break;
+#ifdef WHEN_SUPPORTED_BY_MYSQLI
+ case MYSQL_OPT_WRITE_TIMEOUT:
+ net->data->options.timeout_write = *(unsigned int*) value;
+ break;
+#endif
+ default:
+ DBG_RETURN(FAIL);
+ }
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::consume_uneaten_data */
+size_t
+MYSQLND_METHOD(mysqlnd_vio, consume_uneaten_data)(MYSQLND_VIO * const net, enum php_mysqlnd_server_command cmd)
+{
+#ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
+ /*
+ Switch to non-blocking mode and try to consume something from
+ the line, if possible, then continue. This saves us from looking for
+ the actual place where out-of-order packets have been sent.
+ If someone is completely sure that everything is fine, he can switch it
+ off.
+ */
+ char tmp_buf[256];
+ size_t skipped_bytes = 0;
+ int opt = PHP_STREAM_OPTION_BLOCKING;
+ php_stream * net_stream = net->data->get_stream(net);
+ int was_blocked = net_stream->ops->set_option(net_stream, opt, 0, NULL);
+
+ DBG_ENTER("mysqlnd_vio::consume_uneaten_data");
+
+ if (PHP_STREAM_OPTION_RETURN_ERR != was_blocked) {
+ /* Do a read of 1 byte */
+ int bytes_consumed;
+
+ do {
+ skipped_bytes += (bytes_consumed = php_stream_read(net_stream, tmp_buf, sizeof(tmp_buf)));
+ } while (bytes_consumed == sizeof(tmp_buf));
+
+ if (was_blocked) {
+ net_stream->ops->set_option(net_stream, opt, 1, NULL);
+ }
+
+ if (bytes_consumed) {
+ DBG_ERR_FMT("Skipped %u bytes. Last command hasn't consumed all the output from the server",
+ bytes_consumed, mysqlnd_command_to_text[net->last_command]);
+ php_error_docref(NULL, E_WARNING, "Skipped %u bytes. Last command %s hasn't "
+ "consumed all the output from the server",
+ bytes_consumed, mysqlnd_command_to_text[net->last_command]);
+ }
+ }
+ net->last_command = cmd;
+
+ DBG_RETURN(skipped_bytes);
+#else
+ return 0;
+#endif
+}
+/* }}} */
+
+/*
+ in libmyusql, if cert and !key then key=cert
+*/
+/* {{{ mysqlnd_vio::enable_ssl */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_vio, enable_ssl)(MYSQLND_VIO * const net)
+{
+#ifdef MYSQLND_SSL_SUPPORTED
+ php_stream_context * context = php_stream_context_alloc();
+ php_stream * net_stream = net->data->m.get_stream(net);
+ zend_bool any_flag = FALSE;
+
+ DBG_ENTER("mysqlnd_vio::enable_ssl");
+ if (!context) {
+ DBG_RETURN(FAIL);
+ }
+
+ if (net->data->options.ssl_key) {
+ zval key_zval;
+ ZVAL_STRING(&key_zval, net->data->options.ssl_key);
+ php_stream_context_set_option(context, "ssl", "local_pk", &key_zval);
+ zval_ptr_dtor(&key_zval);
+ any_flag = TRUE;
+ }
+ if (net->data->options.ssl_cert) {
+ zval cert_zval;
+ ZVAL_STRING(&cert_zval, net->data->options.ssl_cert);
+ php_stream_context_set_option(context, "ssl", "local_cert", &cert_zval);
+ if (!net->data->options.ssl_key) {
+ php_stream_context_set_option(context, "ssl", "local_pk", &cert_zval);
+ }
+ zval_ptr_dtor(&cert_zval);
+ any_flag = TRUE;
+ }
+ if (net->data->options.ssl_ca) {
+ zval cafile_zval;
+ ZVAL_STRING(&cafile_zval, net->data->options.ssl_ca);
+ php_stream_context_set_option(context, "ssl", "cafile", &cafile_zval);
+ any_flag = TRUE;
+ }
+ if (net->data->options.ssl_capath) {
+ zval capath_zval;
+ ZVAL_STRING(&capath_zval, net->data->options.ssl_capath);
+ php_stream_context_set_option(context, "ssl", "capath", &capath_zval);
+ zval_ptr_dtor(&capath_zval);
+ any_flag = TRUE;
+ }
+ if (net->data->options.ssl_passphrase) {
+ zval passphrase_zval;
+ ZVAL_STRING(&passphrase_zval, net->data->options.ssl_passphrase);
+ php_stream_context_set_option(context, "ssl", "passphrase", &passphrase_zval);
+ zval_ptr_dtor(&passphrase_zval);
+ any_flag = TRUE;
+ }
+ if (net->data->options.ssl_cipher) {
+ zval cipher_zval;
+ ZVAL_STRING(&cipher_zval, net->data->options.ssl_cipher);
+ php_stream_context_set_option(context, "ssl", "ciphers", &cipher_zval);
+ zval_ptr_dtor(&cipher_zval);
+ any_flag = TRUE;
+ }
+ {
+ zval verify_peer_zval;
+ zend_bool verify;
+
+ if (net->data->options.ssl_verify_peer == MYSQLND_SSL_PEER_DEFAULT) {
+ net->data->options.ssl_verify_peer = any_flag? MYSQLND_SSL_PEER_DEFAULT_ACTION:MYSQLND_SSL_PEER_DONT_VERIFY;
+ }
+
+ verify = net->data->options.ssl_verify_peer == MYSQLND_SSL_PEER_VERIFY? TRUE:FALSE;
+
+ DBG_INF_FMT("VERIFY=%d", verify);
+ ZVAL_BOOL(&verify_peer_zval, verify);
+ php_stream_context_set_option(context, "ssl", "verify_peer", &verify_peer_zval);
+ php_stream_context_set_option(context, "ssl", "verify_peer_name", &verify_peer_zval);
+ if (net->data->options.ssl_verify_peer == MYSQLND_SSL_PEER_DONT_VERIFY) {
+ ZVAL_TRUE(&verify_peer_zval);
+ 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)
+ {
+ DBG_ERR("Cannot connect to MySQL by using SSL");
+ php_error_docref(NULL, E_WARNING, "Cannot connect to MySQL by using SSL");
+ DBG_RETURN(FAIL);
+ }
+ net->data->ssl = TRUE;
+ /*
+ get rid of the context. we are persistent and if this is a real pconn used by mysql/mysqli,
+ then the context would not survive cleaning of EG(regular_list), where it is registered, as a
+ resource. What happens is that after this destruction any use of the network will mean usage
+ 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;
+ DBG_INF_FMT("setting %u as PHP_STREAM_OPTION_READ_TIMEOUT", net->data->options.timeout_read);
+ tv.tv_sec = net->data->options.timeout_read;
+ tv.tv_usec = 0;
+ php_stream_set_option(net_stream, PHP_STREAM_OPTION_READ_TIMEOUT, 0, &tv);
+ }
+
+ DBG_RETURN(PASS);
+#else
+ DBG_ENTER("mysqlnd_vio::enable_ssl");
+ DBG_INF("MYSQLND_SSL_SUPPORTED is not defined");
+ DBG_RETURN(PASS);
+#endif
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::disable_ssl */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_vio, disable_ssl)(MYSQLND_VIO * const vio)
+{
+ DBG_ENTER("mysqlnd_vio::disable_ssl");
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::free_contents */
+static void
+MYSQLND_METHOD(mysqlnd_vio, free_contents)(MYSQLND_VIO * net)
+{
+ zend_bool pers = net->persistent;
+ DBG_ENTER("mysqlnd_vio::free_contents");
+
+ if (net->data->options.ssl_key) {
+ mnd_pefree(net->data->options.ssl_key, pers);
+ net->data->options.ssl_key = NULL;
+ }
+ if (net->data->options.ssl_cert) {
+ mnd_pefree(net->data->options.ssl_cert, pers);
+ net->data->options.ssl_cert = NULL;
+ }
+ if (net->data->options.ssl_ca) {
+ mnd_pefree(net->data->options.ssl_ca, pers);
+ net->data->options.ssl_ca = NULL;
+ }
+ if (net->data->options.ssl_capath) {
+ mnd_pefree(net->data->options.ssl_capath, pers);
+ net->data->options.ssl_capath = NULL;
+ }
+ if (net->data->options.ssl_cipher) {
+ mnd_pefree(net->data->options.ssl_cipher, pers);
+ net->data->options.ssl_cipher = NULL;
+ }
+
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::close_stream */
+static void
+MYSQLND_METHOD(mysqlnd_vio, close_stream)(MYSQLND_VIO * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ php_stream * net_stream;
+ DBG_ENTER("mysqlnd_vio::close_stream");
+ if (net && (net_stream = net->data->m.get_stream(net))) {
+ zend_bool pers = net->persistent;
+ DBG_INF_FMT("Freeing stream. abstract=%p", net_stream->abstract);
+ if (pers) {
+ if (EG(active)) {
+ php_stream_free(net_stream, PHP_STREAM_FREE_CLOSE_PERSISTENT | PHP_STREAM_FREE_RSRC_DTOR);
+ } else {
+ /*
+ otherwise we will crash because the EG(persistent_list) has been freed already,
+ before the modules are shut down
+ */
+ php_stream_free(net_stream, PHP_STREAM_FREE_CLOSE | PHP_STREAM_FREE_RSRC_DTOR);
+ }
+ } else {
+ php_stream_free(net_stream, PHP_STREAM_FREE_CLOSE);
+ }
+ (void) net->data->m.set_stream(net, NULL);
+ }
+
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::init */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_vio, init)(MYSQLND_VIO * const net, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ unsigned int buf_size;
+ DBG_ENTER("mysqlnd_vio::init");
+
+ buf_size = MYSQLND_G(net_read_buffer_size); /* this is long, cast to unsigned int*/
+ net->data->m.set_client_option(net, MYSQLND_OPT_NET_READ_BUFFER_SIZE, (char *)&buf_size);
+
+ buf_size = MYSQLND_G(net_read_timeout); /* this is long, cast to unsigned int*/
+ net->data->m.set_client_option(net, MYSQL_OPT_READ_TIMEOUT, (char *)&buf_size);
+
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::dtor */
+static void
+MYSQLND_METHOD(mysqlnd_vio, dtor)(MYSQLND_VIO * const vio, MYSQLND_STATS * const stats, MYSQLND_ERROR_INFO * const error_info)
+{
+ DBG_ENTER("mysqlnd_vio::dtor");
+ if (vio) {
+ vio->data->m.free_contents(vio);
+ vio->data->m.close_stream(vio, stats, error_info);
+
+ mnd_pefree(vio->data, vio->data->persistent);
+ mnd_pefree(vio, vio->persistent);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::get_stream */
+static php_stream *
+MYSQLND_METHOD(mysqlnd_vio, get_stream)(const MYSQLND_VIO * const net)
+{
+ DBG_ENTER("mysqlnd_vio::get_stream");
+ DBG_INF_FMT("%p", net? net->data->stream:NULL);
+ DBG_RETURN(net? net->data->stream:NULL);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio::set_stream */
+static php_stream *
+MYSQLND_METHOD(mysqlnd_vio, set_stream)(MYSQLND_VIO * const net, php_stream * net_stream)
+{
+ php_stream * ret = NULL;
+ DBG_ENTER("mysqlnd_vio::set_stream");
+ if (net) {
+ net->data->stream = net_stream;
+ ret = net->data->stream;
+ }
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+MYSQLND_CLASS_METHODS_START(mysqlnd_vio)
+ MYSQLND_METHOD(mysqlnd_vio, init),
+ MYSQLND_METHOD(mysqlnd_vio, dtor),
+
+ MYSQLND_METHOD(mysqlnd_vio, connect),
+
+ MYSQLND_METHOD(mysqlnd_vio, close_stream),
+ MYSQLND_METHOD(mysqlnd_vio, open_pipe),
+ MYSQLND_METHOD(mysqlnd_vio, open_tcp_or_unix),
+
+ MYSQLND_METHOD(mysqlnd_vio, get_stream),
+ MYSQLND_METHOD(mysqlnd_vio, set_stream),
+ MYSQLND_METHOD(mysqlnd_vio, get_open_stream),
+
+ MYSQLND_METHOD(mysqlnd_vio, set_client_option),
+ MYSQLND_METHOD(mysqlnd_vio, post_connect_set_opt),
+
+ MYSQLND_METHOD(mysqlnd_vio, enable_ssl),
+ MYSQLND_METHOD(mysqlnd_vio, disable_ssl),
+
+ MYSQLND_METHOD(mysqlnd_vio, network_read),
+ MYSQLND_METHOD(mysqlnd_vio, network_write),
+
+ MYSQLND_METHOD(mysqlnd_vio, consume_uneaten_data),
+
+ MYSQLND_METHOD(mysqlnd_vio, free_contents),
+MYSQLND_CLASS_METHODS_END;
+
+
+/* {{{ mysqlnd_vio_init */
+PHPAPI MYSQLND_VIO *
+mysqlnd_vio_init(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info)
+{
+ MYSQLND_VIO * vio;
+ DBG_ENTER("mysqlnd_vio_init");
+ vio = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_vio(persistent, stats, error_info);
+ DBG_RETURN(vio);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_vio_free */
+PHPAPI void
+mysqlnd_vio_free(MYSQLND_VIO * const vio, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info)
+{
+ DBG_ENTER("mysqlnd_vio_free");
+ if (vio) {
+ vio->data->m.dtor(vio, stats, error_info);
+ }
+ DBG_VOID_RETURN;
+}
+/* }}} */
+
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: noet sw=4 ts=4 fdm=marker
+ * vim<600: noet sw=4 ts=4
+ */
diff --git a/ext/mysqlnd/mysqlnd_net.h b/ext/mysqlnd/mysqlnd_vio.h
index d863753a86..4e8333c497 100644
--- a/ext/mysqlnd/mysqlnd_net.h
+++ b/ext/mysqlnd/mysqlnd_vio.h
@@ -14,19 +14,15 @@
+----------------------------------------------------------------------+
| Authors: Andrey Hristov <andrey@mysql.com> |
| Ulf Wendel <uwendel@mysql.com> |
- | Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
+#ifndef MYSQLND_VIO_H
+#define MYSQLND_VIO_H
-/* $Id: mysqlnd_wireprotocol.h 291983 2009-12-11 11:58:57Z andrey $ */
+PHPAPI MYSQLND_VIO * mysqlnd_vio_init(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info);
+PHPAPI void mysqlnd_vio_free(MYSQLND_VIO * const vio, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info);
-#ifndef MYSQLND_NET_H
-#define MYSQLND_NET_H
-
-PHPAPI MYSQLND_NET * mysqlnd_net_init(zend_bool persistent, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info);
-PHPAPI void mysqlnd_net_free(MYSQLND_NET * const net, MYSQLND_STATS * stats, MYSQLND_ERROR_INFO * error_info);
-
-#endif /* MYSQLND_NET_H */
+#endif /* MYSQLND_VIO_H */
/*
* Local variables:
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c
index b464aab821..63b12c677b 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.c
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.c
@@ -17,49 +17,14 @@
| Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id$ */
#include "php.h"
-#include "php_globals.h"
#include "mysqlnd.h"
+#include "mysqlnd_connection.h"
+#include "mysqlnd_ps.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_wireprotocol.h"
#include "mysqlnd_statistics.h"
#include "mysqlnd_debug.h"
-#include "zend_ini.h"
-
-#define MYSQLND_SILENT 1
-
-#define MYSQLND_DUMP_HEADER_N_BODY
-
-#define PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_size, packet_type_as_text, packet_type) \
- { \
- DBG_INF_FMT("buf=%p size=%u", (buf), (buf_size)); \
- if (FAIL == mysqlnd_read_header((conn)->net, &((packet)->header), (conn)->stats, ((conn)->error_info))) {\
- CONN_SET_STATE(conn, CONN_QUIT_SENT); \
- SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
- php_error_docref(NULL, E_WARNING, "%s", mysqlnd_server_gone); \
- DBG_ERR_FMT("Can't read %s's header", (packet_type_as_text)); \
- DBG_RETURN(FAIL);\
- }\
- if ((buf_size) < (packet)->header.size) { \
- DBG_ERR_FMT("Packet buffer %u wasn't big enough %u, %u bytes will be unread", \
- (buf_size), (packet)->header.size, (packet)->header.size - (buf_size)); \
- DBG_RETURN(FAIL); \
- }\
- if (FAIL == conn->net->data->m.receive_ex((conn)->net, (buf), (packet)->header.size, (conn)->stats, ((conn)->error_info))) { \
- CONN_SET_STATE(conn, CONN_QUIT_SENT); \
- SET_CLIENT_ERROR(*conn->error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);\
- php_error_docref(NULL, E_WARNING, "%s", mysqlnd_server_gone); \
- DBG_ERR_FMT("Empty '%s' packet body", (packet_type_as_text)); \
- DBG_RETURN(FAIL);\
- } \
- MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, packet_type_to_statistic_byte_count[packet_type], \
- MYSQLND_HEADER_SIZE + (packet)->header.size, \
- packet_type_to_statistic_packet_count[packet_type], \
- 1); \
- }
-
#define BAIL_IF_NO_MORE_DATA \
if ((size_t)(p - begin) > packet->header.size) { \
@@ -127,9 +92,9 @@ static enum_mysqlnd_collected_stats packet_type_to_statistic_packet_count[PROT_L
/* {{{ php_mysqlnd_net_field_length
Get next field's length */
zend_ulong
-php_mysqlnd_net_field_length(zend_uchar **packet)
+php_mysqlnd_net_field_length(const zend_uchar **packet)
{
- register zend_uchar *p= (zend_uchar *)*packet;
+ register const zend_uchar *p= (const zend_uchar *)*packet;
if (*p < 251) {
(*packet)++;
@@ -157,9 +122,9 @@ php_mysqlnd_net_field_length(zend_uchar **packet)
/* {{{ php_mysqlnd_net_field_length_ll
Get next field's length */
uint64_t
-php_mysqlnd_net_field_length_ll(zend_uchar **packet)
+php_mysqlnd_net_field_length_ll(const zend_uchar **packet)
{
- register zend_uchar *p = (zend_uchar *)*packet;
+ register const zend_uchar *p = (zend_uchar *)*packet;
if (*p < 251) {
(*packet)++;
@@ -186,7 +151,7 @@ php_mysqlnd_net_field_length_ll(zend_uchar **packet)
/* {{{ php_mysqlnd_net_store_length */
zend_uchar *
-php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t length)
+php_mysqlnd_net_store_length(zend_uchar *packet, const uint64_t length)
{
if (length < (uint64_t) L64(251)) {
*packet = (zend_uchar) length;
@@ -231,12 +196,12 @@ php_mysqlnd_net_store_length_size(uint64_t length)
/* {{{ php_mysqlnd_read_error_from_line */
static enum_func_status
-php_mysqlnd_read_error_from_line(zend_uchar *buf, size_t buf_len,
- char *error, int error_buf_len,
- unsigned int *error_no, char *sqlstate)
+php_mysqlnd_read_error_from_line(const zend_uchar * const buf, const size_t buf_len,
+ char *error, const size_t error_buf_len,
+ unsigned int *error_no, char *sqlstate)
{
- zend_uchar *p = buf;
- int error_msg_len= 0;
+ const zend_uchar *p = buf;
+ size_t error_msg_len = 0;
DBG_ENTER("php_mysqlnd_read_error_from_line");
@@ -275,64 +240,110 @@ end:
/* {{{ mysqlnd_read_header */
static enum_func_status
-mysqlnd_read_header(MYSQLND_NET * net, MYSQLND_PACKET_HEADER * header,
+mysqlnd_read_header(MYSQLND_PFC * pfc, MYSQLND_VIO * vio, MYSQLND_PACKET_HEADER * header,
MYSQLND_STATS * conn_stats, MYSQLND_ERROR_INFO * error_info)
{
zend_uchar buffer[MYSQLND_HEADER_SIZE];
DBG_ENTER(mysqlnd_read_header_name);
- DBG_INF_FMT("compressed=%u", net->data->compressed);
- if (FAIL == net->data->m.receive_ex(net, buffer, MYSQLND_HEADER_SIZE, conn_stats, error_info)) {
+ DBG_INF_FMT("compressed=%u", pfc->data->compressed);
+ if (FAIL == pfc->data->m.receive(pfc, vio, buffer, MYSQLND_HEADER_SIZE, conn_stats, error_info)) {
DBG_RETURN(FAIL);
}
header->size = uint3korr(buffer);
header->packet_no = uint1korr(buffer + 3);
-#ifdef MYSQLND_DUMP_HEADER_N_BODY
DBG_INF_FMT("HEADER: prot_packet_no=%u size=%3u", header->packet_no, header->size);
-#endif
MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn_stats,
STAT_PROTOCOL_OVERHEAD_IN, MYSQLND_HEADER_SIZE,
STAT_PACKETS_RECEIVED, 1);
- if (net->data->compressed || net->packet_no == header->packet_no) {
+ if (pfc->data->compressed || pfc->data->packet_no == header->packet_no) {
/*
Have to increase the number, so we can send correct number back. It will
round at 255 as this is unsigned char. The server needs this for simple
flow control checking.
*/
- net->packet_no++;
+ pfc->data->packet_no++;
DBG_RETURN(PASS);
}
DBG_ERR_FMT("Logical link: packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
- net->packet_no, header->packet_no, header->size);
+ pfc->data->packet_no, header->packet_no, header->size);
php_error(E_WARNING, "Packets out of order. Expected %u received %u. Packet size="MYSQLND_SZ_T_SPEC,
- net->packet_no, header->packet_no, header->size);
+ pfc->data->packet_no, header->packet_no, header->size);
DBG_RETURN(FAIL);
}
/* }}} */
+/* {{{ mysqlnd_read_packet_header_and_body */
+static enum_func_status
+mysqlnd_read_packet_header_and_body(MYSQLND_PACKET_HEADER * packet_header,
+ MYSQLND_PFC * pfc,
+ MYSQLND_VIO * vio,
+ MYSQLND_STATS * stats,
+ MYSQLND_ERROR_INFO * error_info,
+ MYSQLND_CONNECTION_STATE * connection_state,
+ zend_uchar * buf, size_t buf_size, const char * const packet_type_as_text,
+ enum mysqlnd_packet_type packet_type)
+{
+ DBG_ENTER("mysqlnd_read_packet_header_and_body");
+ DBG_INF_FMT("buf=%p size=%u", buf, buf_size);
+ if (FAIL == mysqlnd_read_header(pfc, vio, packet_header, stats, error_info)) {
+ SET_CONNECTION_STATE(connection_state, CONN_QUIT_SENT);
+ SET_CLIENT_ERROR(error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ php_error_docref(NULL, E_WARNING, "%s", mysqlnd_server_gone);
+ DBG_ERR_FMT("Can't read %s's header", packet_type_as_text);
+ DBG_RETURN(FAIL);
+ }
+ if (buf_size < packet_header->size) {
+ DBG_ERR_FMT("Packet buffer %u wasn't big enough %u, %u bytes will be unread",
+ buf_size, packet_header->size, packet_header->size - buf_size);
+ DBG_RETURN(FAIL);
+ }
+ if (FAIL == pfc->data->m.receive(pfc, vio, buf, packet_header->size, stats, error_info)) {
+ SET_CONNECTION_STATE(connection_state, CONN_QUIT_SENT);
+ SET_CLIENT_ERROR(error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ php_error_docref(NULL, E_WARNING, "%s", mysqlnd_server_gone);
+ DBG_ERR_FMT("Empty '%s' packet body", packet_type_as_text);
+ DBG_RETURN(FAIL);
+ }
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE2(stats, packet_type_to_statistic_byte_count[packet_type],
+ MYSQLND_HEADER_SIZE + packet_header->size,
+ packet_type_to_statistic_packet_count[packet_type],
+ 1);
+ DBG_RETURN(PASS);
+}
+/* }}} */
+
+
/* {{{ php_mysqlnd_greet_read */
static enum_func_status
-php_mysqlnd_greet_read(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_greet_read(void * _packet)
{
zend_uchar buf[2048];
- zend_uchar *p = buf;
- zend_uchar *begin = buf;
- zend_uchar *pad_start = NULL;
+ const zend_uchar * p = buf;
+ const zend_uchar * const begin = buf;
+ const zend_uchar * pad_start = NULL;
MYSQLND_PACKET_GREET *packet= (MYSQLND_PACKET_GREET *) _packet;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
DBG_ENTER("php_mysqlnd_greet_read");
- PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "greeting", PROT_GREET_PACKET);
+ if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, sizeof(buf), "greeting", PROT_GREET_PACKET)) {
+ DBG_RETURN(FAIL);
+ }
BAIL_IF_NO_MORE_DATA;
- packet->auth_plugin_data = packet->intern_auth_plugin_data;
- packet->auth_plugin_data_len = sizeof(packet->intern_auth_plugin_data);
+ packet->authentication_plugin_data.s = packet->intern_auth_plugin_data;
+ packet->authentication_plugin_data.l = sizeof(packet->intern_auth_plugin_data);
if (packet->header.size < sizeof(buf)) {
/*
@@ -370,7 +381,7 @@ php_mysqlnd_greet_read(void * _packet, MYSQLND_CONN_DATA * conn)
p+=4;
BAIL_IF_NO_MORE_DATA;
- memcpy(packet->auth_plugin_data, p, SCRAMBLE_LENGTH_323);
+ memcpy(packet->authentication_plugin_data.s, p, SCRAMBLE_LENGTH_323);
p+= SCRAMBLE_LENGTH_323;
BAIL_IF_NO_MORE_DATA;
@@ -397,7 +408,7 @@ php_mysqlnd_greet_read(void * _packet, MYSQLND_CONN_DATA * conn)
if ((size_t) (p - buf) < packet->header.size) {
/* auth_plugin_data is split into two parts */
- memcpy(packet->auth_plugin_data + SCRAMBLE_LENGTH_323, p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
+ memcpy(packet->authentication_plugin_data.s + SCRAMBLE_LENGTH_323, p, SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323);
p+= SCRAMBLE_LENGTH - SCRAMBLE_LENGTH_323;
p++; /* 0x0 at the end of the scramble and thus last byte in the packet in 5.1 and previous */
} else {
@@ -412,19 +423,19 @@ php_mysqlnd_greet_read(void * _packet, MYSQLND_CONN_DATA * conn)
/* Additional 16 bits for server capabilities */
packet->server_capabilities |= uint2korr(pad_start) << 16;
/* And a length of the server scramble in one byte */
- packet->auth_plugin_data_len = uint1korr(pad_start + 2);
- if (packet->auth_plugin_data_len > SCRAMBLE_LENGTH) {
+ packet->authentication_plugin_data.l = uint1korr(pad_start + 2);
+ if (packet->authentication_plugin_data.l > SCRAMBLE_LENGTH) {
/* more data*/
- zend_uchar * new_auth_plugin_data = emalloc(packet->auth_plugin_data_len);
+ char * new_auth_plugin_data = emalloc(packet->authentication_plugin_data.l);
if (!new_auth_plugin_data) {
goto premature_end;
}
/* copy what we already have */
- memcpy(new_auth_plugin_data, packet->auth_plugin_data, SCRAMBLE_LENGTH);
+ memcpy(new_auth_plugin_data, packet->authentication_plugin_data.s, SCRAMBLE_LENGTH);
/* add additional scramble data 5.5+ sent us */
- memcpy(new_auth_plugin_data + SCRAMBLE_LENGTH, p, packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
- p+= (packet->auth_plugin_data_len - SCRAMBLE_LENGTH);
- packet->auth_plugin_data = new_auth_plugin_data;
+ memcpy(new_auth_plugin_data + SCRAMBLE_LENGTH, p, packet->authentication_plugin_data.l - SCRAMBLE_LENGTH);
+ p+= (packet->authentication_plugin_data.l - SCRAMBLE_LENGTH);
+ packet->authentication_plugin_data.s = new_auth_plugin_data;
}
}
@@ -440,7 +451,7 @@ php_mysqlnd_greet_read(void * _packet, MYSQLND_CONN_DATA * conn)
DBG_INF_FMT("server_capabilities=%u charset_no=%u server_status=%i auth_protocol=%s scramble_length=%u",
packet->server_capabilities, packet->charset_no, packet->server_status,
- packet->auth_protocol? packet->auth_protocol:"n/a", packet->auth_plugin_data_len);
+ packet->auth_protocol? packet->auth_protocol:"n/a", packet->authentication_plugin_data.l);
DBG_RETURN(PASS);
premature_end:
@@ -461,9 +472,9 @@ void php_mysqlnd_greet_free_mem(void * _packet, zend_bool stack_allocation)
efree(p->server_version);
p->server_version = NULL;
}
- if (p->auth_plugin_data && p->auth_plugin_data != p->intern_auth_plugin_data) {
- efree(p->auth_plugin_data);
- p->auth_plugin_data = NULL;
+ if (p->authentication_plugin_data.s && p->authentication_plugin_data.s != p->intern_auth_plugin_data) {
+ efree(p->authentication_plugin_data.s);
+ p->authentication_plugin_data.s = NULL;
}
if (p->auth_protocol) {
efree(p->auth_protocol);
@@ -480,12 +491,18 @@ void php_mysqlnd_greet_free_mem(void * _packet, zend_bool stack_allocation)
/* {{{ php_mysqlnd_auth_write */
static
-size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn)
+size_t php_mysqlnd_auth_write(void * _packet)
{
zend_uchar buffer[AUTH_WRITE_BUFFER_LEN];
zend_uchar *p = buffer + MYSQLND_HEADER_SIZE; /* start after the header */
- int len;
+ size_t len;
MYSQLND_PACKET_AUTH * packet= (MYSQLND_PACKET_AUTH *) _packet;
+ MYSQLND_CONN_DATA * conn = packet->header.conn;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
DBG_ENTER("php_mysqlnd_auth_write");
@@ -516,7 +533,7 @@ size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn)
if (packet->auth_data_len > 0xFF) {
const char * const msg = "Authentication data too long. "
"Won't fit into the buffer and will be truncated. Authentication will thus fail";
- SET_CLIENT_ERROR(*conn->error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, msg);
+ SET_CLIENT_ERROR(error_info, CR_UNKNOWN_ERROR, UNKNOWN_SQLSTATE, msg);
php_error_docref(NULL, E_WARNING, "%s", msg);
DBG_RETURN(0);
}
@@ -552,7 +569,7 @@ size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn)
}
if (packet->auth_plugin_name) {
- size_t len = MIN(strlen(packet->auth_plugin_name), sizeof(buffer) - (p - buffer) - 1);
+ len = MIN(strlen(packet->auth_plugin_name), sizeof(buffer) - (p - buffer) - 1);
memcpy(p, packet->auth_plugin_name, len);
p+= len;
*p++= '\0';
@@ -560,25 +577,6 @@ size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn)
if (packet->connect_attr && zend_hash_num_elements(packet->connect_attr)) {
size_t ca_payload_len = 0;
-#ifdef OLD_CODE
- HashPosition pos_value;
- const char ** entry_value;
- zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
- while (SUCCESS == zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, &pos_value)) {
- char *s_key;
- unsigned int s_len;
- zend_ulong num_key;
- size_t value_len = strlen(*entry_value);
-
- if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(packet->connect_attr, &s_key, &s_len, &num_key, &pos_value)) {
- ca_payload_len += php_mysqlnd_net_store_length_size(s_len);
- ca_payload_len += s_len;
- ca_payload_len += php_mysqlnd_net_store_length_size(value_len);
- ca_payload_len += value_len;
- }
- zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
- }
-#else
{
zend_string * key;
@@ -594,30 +592,10 @@ size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn)
}
} ZEND_HASH_FOREACH_END();
}
-#endif
+
if (sizeof(buffer) >= (ca_payload_len + php_mysqlnd_net_store_length_size(ca_payload_len) + (p - buffer))) {
p = php_mysqlnd_net_store_length(p, ca_payload_len);
-#ifdef OLD_CODE
- zend_hash_internal_pointer_reset_ex(packet->connect_attr, &pos_value);
- while (SUCCESS == zend_hash_get_current_data_ex(packet->connect_attr, (void **)&entry_value, &pos_value)) {
- char *s_key;
- unsigned int s_len;
- zend_ulong num_key;
- size_t value_len = strlen(*entry_value);
- if (HASH_KEY_IS_STRING == zend_hash_get_current_key_ex(packet->connect_attr, &s_key, &s_len, &num_key, &pos_value)) {
- /* copy key */
- p = php_mysqlnd_net_store_length(p, s_len);
- memcpy(p, s_key, s_len);
- p+= s_len;
- /* copy value */
- p = php_mysqlnd_net_store_length(p, value_len);
- memcpy(p, *entry_value, value_len);
- p+= value_len;
- }
- zend_hash_move_forward_ex(conn->options->connect_attr, &pos_value);
- }
-#else
{
zend_string * key;
zval * entry_value;
@@ -636,23 +614,26 @@ size_t php_mysqlnd_auth_write(void * _packet, MYSQLND_CONN_DATA * conn)
}
} ZEND_HASH_FOREACH_END();
}
-#endif
} else {
/* cannot put the data - skip */
}
}
}
if (packet->is_change_user_packet) {
- if (PASS != conn->m->simple_command(conn, COM_CHANGE_USER, buffer + MYSQLND_HEADER_SIZE, p - buffer - MYSQLND_HEADER_SIZE,
- PROT_LAST /* the caller will handle the OK packet */,
- packet->silent, TRUE)) {
- DBG_RETURN(0);
+ enum_func_status ret = FAIL;
+ const MYSQLND_CSTRING payload = {(char*) buffer + MYSQLND_HEADER_SIZE, p - (buffer + MYSQLND_HEADER_SIZE)};
+ const unsigned int silent = packet->silent;
+ struct st_mysqlnd_protocol_command * command = conn->command_factory(COM_CHANGE_USER, conn, payload, silent);
+ if (command) {
+ ret = command->run(command);
+ command->free_command(command);
}
- DBG_RETURN(p - buffer - MYSQLND_HEADER_SIZE);
+
+ DBG_RETURN(ret == PASS? (p - buffer - MYSQLND_HEADER_SIZE) : 0);
} else {
- size_t sent = conn->net->data->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info);
+ size_t sent = pfc->data->m.send(pfc, vio, buffer, p - buffer - MYSQLND_HEADER_SIZE, stats, error_info);
if (!sent) {
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CONNECTION_STATE(connection_state, CONN_QUIT_SENT);
}
DBG_RETURN(sent);
}
@@ -676,21 +657,27 @@ void php_mysqlnd_auth_free_mem(void * _packet, zend_bool stack_allocation)
/* {{{ php_mysqlnd_auth_response_read */
static enum_func_status
-php_mysqlnd_auth_response_read(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_auth_response_read(void * _packet)
{
- zend_uchar local_buf[AUTH_RESP_BUFFER_SIZE];
- size_t buf_len = conn->net->cmd_buffer.buffer? conn->net->cmd_buffer.length: AUTH_RESP_BUFFER_SIZE;
- zend_uchar *buf = conn->net->cmd_buffer.buffer? (zend_uchar *) conn->net->cmd_buffer.buffer : local_buf;
- zend_uchar *p = buf;
- zend_uchar *begin = buf;
- zend_ulong i;
register MYSQLND_PACKET_AUTH_RESPONSE * packet= (MYSQLND_PACKET_AUTH_RESPONSE *) _packet;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
+ zend_uchar local_buf[AUTH_RESP_BUFFER_SIZE];
+ size_t buf_len = pfc->cmd_buffer.buffer? pfc->cmd_buffer.length: AUTH_RESP_BUFFER_SIZE;
+ zend_uchar *buf = pfc->cmd_buffer.buffer? (zend_uchar *) pfc->cmd_buffer.buffer : local_buf;
+ const zend_uchar * p = buf;
+ const zend_uchar * const begin = buf;
DBG_ENTER("php_mysqlnd_auth_response_read");
/* leave space for terminating safety \0 */
buf_len--;
- PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "OK", PROT_OK_PACKET);
+ if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, buf_len, "OK", PROT_OK_PACKET)) {
+ DBG_RETURN(FAIL);
+ }
BAIL_IF_NO_MORE_DATA;
/*
@@ -727,6 +714,7 @@ php_mysqlnd_auth_response_read(void * _packet, MYSQLND_CONN_DATA * conn)
DBG_INF_FMT("Server salt : [%d][%.*s]", packet->new_auth_protocol_data_len, packet->new_auth_protocol_data_len, packet->new_auth_protocol_data);
}
} else {
+ zend_ulong net_len;
/* Everything was fine! */
packet->affected_rows = php_mysqlnd_net_field_length_ll(&p);
BAIL_IF_NO_MORE_DATA;
@@ -743,8 +731,8 @@ php_mysqlnd_auth_response_read(void * _packet, MYSQLND_CONN_DATA * conn)
BAIL_IF_NO_MORE_DATA;
/* There is a message */
- if (packet->header.size > (size_t) (p - buf) && (i = php_mysqlnd_net_field_length(&p))) {
- packet->message_len = MIN(i, buf_len - (p - begin));
+ if (packet->header.size > (size_t) (p - buf) && (net_len = php_mysqlnd_net_field_length(&p))) {
+ packet->message_len = MIN(net_len, buf_len - (p - begin));
packet->message = mnd_pestrndup((char *)p, packet->message_len, FALSE);
} else {
packet->message = NULL;
@@ -796,11 +784,16 @@ php_mysqlnd_auth_response_free_mem(void * _packet, zend_bool stack_allocation)
/* {{{ php_mysqlnd_change_auth_response_write */
static size_t
-php_mysqlnd_change_auth_response_write(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_change_auth_response_write(void * _packet)
{
MYSQLND_PACKET_CHANGE_AUTH_RESPONSE *packet= (MYSQLND_PACKET_CHANGE_AUTH_RESPONSE *) _packet;
- zend_uchar * buffer = conn->net->cmd_buffer.length >= packet->auth_data_len? conn->net->cmd_buffer.buffer : mnd_emalloc(packet->auth_data_len);
- zend_uchar *p = buffer + MYSQLND_HEADER_SIZE; /* start after the header */
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
+ zend_uchar * buffer = pfc->cmd_buffer.length >= packet->auth_data_len? pfc->cmd_buffer.buffer : mnd_emalloc(packet->auth_data_len);
+ zend_uchar * p = buffer + MYSQLND_HEADER_SIZE; /* start after the header */
DBG_ENTER("php_mysqlnd_change_auth_response_write");
@@ -810,12 +803,12 @@ php_mysqlnd_change_auth_response_write(void * _packet, MYSQLND_CONN_DATA * conn)
}
{
- size_t sent = conn->net->data->m.send_ex(conn->net, buffer, p - buffer - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info);
- if (buffer != conn->net->cmd_buffer.buffer) {
+ size_t sent = pfc->data->m.send(pfc, vio, buffer, p - buffer - MYSQLND_HEADER_SIZE, stats, error_info);
+ if (buffer != pfc->cmd_buffer.buffer) {
mnd_efree(buffer);
}
if (!sent) {
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CONNECTION_STATE(connection_state, CONN_QUIT_SENT);
}
DBG_RETURN(sent);
}
@@ -839,19 +832,26 @@ php_mysqlnd_change_auth_response_free_mem(void * _packet, zend_bool stack_alloca
/* {{{ php_mysqlnd_ok_read */
static enum_func_status
-php_mysqlnd_ok_read(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_ok_read(void * _packet)
{
- zend_uchar local_buf[OK_BUFFER_SIZE];
- size_t buf_len = conn->net->cmd_buffer.buffer? conn->net->cmd_buffer.length : OK_BUFFER_SIZE;
- zend_uchar *buf = conn->net->cmd_buffer.buffer? (zend_uchar *) conn->net->cmd_buffer.buffer : local_buf;
- zend_uchar *p = buf;
- zend_uchar *begin = buf;
- zend_ulong i;
register MYSQLND_PACKET_OK *packet= (MYSQLND_PACKET_OK *) _packet;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
+ zend_uchar local_buf[OK_BUFFER_SIZE];
+ size_t buf_len = pfc->cmd_buffer.buffer? pfc->cmd_buffer.length : OK_BUFFER_SIZE;
+ zend_uchar * buf = pfc->cmd_buffer.buffer? (zend_uchar *) pfc->cmd_buffer.buffer : local_buf;
+ const zend_uchar * p = buf;
+ const zend_uchar * const begin = buf;
+ zend_ulong net_len;
DBG_ENTER("php_mysqlnd_ok_read");
- PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "OK", PROT_OK_PACKET);
+ if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, buf_len, "OK", PROT_OK_PACKET)) {
+ DBG_RETURN(FAIL);
+ }
BAIL_IF_NO_MORE_DATA;
/* Should be always 0x0 or ERROR_MARKER for error */
@@ -864,7 +864,6 @@ php_mysqlnd_ok_read(void * _packet, MYSQLND_CONN_DATA * conn)
packet->error, sizeof(packet->error),
&packet->error_no, packet->sqlstate
);
- DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status);
DBG_RETURN(PASS);
}
/* Everything was fine! */
@@ -883,8 +882,8 @@ php_mysqlnd_ok_read(void * _packet, MYSQLND_CONN_DATA * conn)
BAIL_IF_NO_MORE_DATA;
/* There is a message */
- if (packet->header.size > (size_t) (p - buf) && (i = php_mysqlnd_net_field_length(&p))) {
- packet->message_len = MIN(i, buf_len - (p - begin));
+ if (packet->header.size > (size_t) (p - buf) && (net_len = php_mysqlnd_net_field_length(&p))) {
+ packet->message_len = MIN(net_len, buf_len - (p - begin));
packet->message = mnd_pestrndup((char *)p, packet->message_len, FALSE);
} else {
packet->message = NULL;
@@ -925,7 +924,7 @@ php_mysqlnd_ok_free_mem(void * _packet, zend_bool stack_allocation)
/* {{{ php_mysqlnd_eof_read */
static enum_func_status
-php_mysqlnd_eof_read(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_eof_read(void * _packet)
{
/*
EOF packet is since 4.1 five bytes long,
@@ -934,14 +933,21 @@ php_mysqlnd_eof_read(void * _packet, MYSQLND_CONN_DATA * conn)
Error : error_code + '#' + sqlstate + MYSQLND_ERRMSG_SIZE
*/
MYSQLND_PACKET_EOF *packet= (MYSQLND_PACKET_EOF *) _packet;
- size_t buf_len = conn->net->cmd_buffer.length;
- zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
- zend_uchar *p = buf;
- zend_uchar *begin = buf;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
+ size_t buf_len = pfc->cmd_buffer.length;
+ zend_uchar * buf = (zend_uchar *) pfc->cmd_buffer.buffer;
+ const zend_uchar * p = buf;
+ const zend_uchar * const begin = buf;
DBG_ENTER("php_mysqlnd_eof_read");
- PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "EOF", PROT_EOF_PACKET);
+ if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, buf_len, "EOF", PROT_EOF_PACKET)) {
+ DBG_RETURN(FAIL);
+ }
BAIL_IF_NO_MORE_DATA;
/* Should be always EODATA_MARKER */
@@ -1002,11 +1008,15 @@ void php_mysqlnd_eof_free_mem(void * _packet, zend_bool stack_allocation)
/* {{{ php_mysqlnd_cmd_write */
-size_t php_mysqlnd_cmd_write(void * _packet, MYSQLND_CONN_DATA * conn)
+size_t php_mysqlnd_cmd_write(void * _packet)
{
/* Let's have some space, which we can use, if not enough, we will allocate new buffer */
MYSQLND_PACKET_COMMAND * packet= (MYSQLND_PACKET_COMMAND *) _packet;
- MYSQLND_NET * net = conn->net;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
unsigned int error_reporting = EG(error_reporting);
size_t sent = 0;
@@ -1015,28 +1025,27 @@ size_t php_mysqlnd_cmd_write(void * _packet, MYSQLND_CONN_DATA * conn)
Reset packet_no, or we will get bad handshake!
Every command starts a new TX and packet numbers are reset to 0.
*/
- net->packet_no = 0;
- net->compressed_envelope_packet_no = 0; /* this is for the response */
+ pfc->data->m.reset(pfc, stats, error_info);
if (error_reporting) {
EG(error_reporting) = 0;
}
- MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_PACKETS_SENT_CMD);
+ MYSQLND_INC_CONN_STATISTIC(stats, STAT_PACKETS_SENT_CMD);
#ifdef MYSQLND_DO_WIRE_CHECK_BEFORE_COMMAND
- net->data->m.consume_uneaten_data(net, packet->command);
+ vio->data->m.consume_uneaten_data(vio, packet->command);
#endif
- if (!packet->argument || !packet->arg_len) {
+ if (!packet->argument.s || !packet->argument.l) {
zend_uchar buffer[MYSQLND_HEADER_SIZE + 1];
int1store(buffer + MYSQLND_HEADER_SIZE, packet->command);
- sent = net->data->m.send_ex(net, buffer, 1, conn->stats, conn->error_info);
+ sent = pfc->data->m.send(pfc, vio, buffer, 1, stats, error_info);
} else {
- size_t tmp_len = packet->arg_len + 1 + MYSQLND_HEADER_SIZE;
+ size_t tmp_len = packet->argument.l + 1 + MYSQLND_HEADER_SIZE;
zend_uchar *tmp, *p;
- tmp = (tmp_len > net->cmd_buffer.length)? mnd_emalloc(tmp_len):net->cmd_buffer.buffer;
+ tmp = (tmp_len > pfc->cmd_buffer.length)? mnd_emalloc(tmp_len):pfc->cmd_buffer.buffer;
if (!tmp) {
goto end;
}
@@ -1045,11 +1054,11 @@ size_t php_mysqlnd_cmd_write(void * _packet, MYSQLND_CONN_DATA * conn)
int1store(p, packet->command);
p++;
- memcpy(p, packet->argument, packet->arg_len);
+ memcpy(p, packet->argument.s, packet->argument.l);
- sent = net->data->m.send_ex(net, tmp, tmp_len - MYSQLND_HEADER_SIZE, conn->stats, conn->error_info);
- if (tmp != net->cmd_buffer.buffer) {
- MYSQLND_INC_CONN_STATISTIC(conn->stats, STAT_CMD_BUFFER_TOO_SMALL);
+ sent = pfc->data->m.send(pfc, vio, tmp, tmp_len - MYSQLND_HEADER_SIZE, stats, error_info);
+ if (tmp != pfc->cmd_buffer.buffer) {
+ MYSQLND_INC_CONN_STATISTIC(stats, STAT_CMD_BUFFER_TOO_SMALL);
mnd_efree(tmp);
}
}
@@ -1059,7 +1068,7 @@ end:
EG(error_reporting) = error_reporting;
}
if (!sent) {
- CONN_SET_STATE(conn, CONN_QUIT_SENT);
+ SET_CONNECTION_STATE(connection_state, CONN_QUIT_SENT);
}
DBG_RETURN(sent);
}
@@ -1080,19 +1089,26 @@ void php_mysqlnd_cmd_free_mem(void * _packet, zend_bool stack_allocation)
/* {{{ php_mysqlnd_rset_header_read */
static enum_func_status
-php_mysqlnd_rset_header_read(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_rset_header_read(void * _packet)
{
+ MYSQLND_PACKET_RSET_HEADER * packet= (MYSQLND_PACKET_RSET_HEADER *) _packet;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
enum_func_status ret = PASS;
- size_t buf_len = conn->net->cmd_buffer.length;
- zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
- zend_uchar *p = buf;
- zend_uchar *begin = buf;
+ size_t buf_len = pfc->cmd_buffer.length;
+ zend_uchar * buf = (zend_uchar *) pfc->cmd_buffer.buffer;
+ const zend_uchar * p = buf;
+ const zend_uchar * const begin = buf;
size_t len;
- MYSQLND_PACKET_RSET_HEADER *packet= (MYSQLND_PACKET_RSET_HEADER *) _packet;
DBG_ENTER("php_mysqlnd_rset_header_read");
- PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "resultset header", PROT_RSET_HEADER_PACKET);
+ if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, buf_len, "resultset header", PROT_RSET_HEADER_PACKET)) {
+ DBG_RETURN(FAIL);
+ }
BAIL_IF_NO_MORE_DATA;
/*
@@ -1107,7 +1123,6 @@ php_mysqlnd_rset_header_read(void * _packet, MYSQLND_CONN_DATA * conn)
packet->error_info.error, sizeof(packet->error_info.error),
&packet->error_info.error_no, packet->error_info.sqlstate
);
- DBG_INF_FMT("conn->server_status=%u", conn->upsert_status->server_status);
DBG_RETURN(PASS);
}
@@ -1125,13 +1140,13 @@ php_mysqlnd_rset_header_read(void * _packet, MYSQLND_CONN_DATA * conn)
would lead to 0 byte allocation but 2^32 or 2^64 bytes copied.
*/
len = packet->header.size - 1;
- packet->info_or_local_file = mnd_emalloc(len + 1);
- if (packet->info_or_local_file) {
- memcpy(packet->info_or_local_file, p, len);
- packet->info_or_local_file[len] = '\0';
- packet->info_or_local_file_len = len;
+ packet->info_or_local_file.s = mnd_emalloc(len + 1);
+ if (packet->info_or_local_file.s) {
+ memcpy(packet->info_or_local_file.s, p, len);
+ packet->info_or_local_file.s[len] = '\0';
+ packet->info_or_local_file.l = len;
} else {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(error_info);
ret = FAIL;
}
break;
@@ -1152,13 +1167,13 @@ php_mysqlnd_rset_header_read(void * _packet, MYSQLND_CONN_DATA * conn)
BAIL_IF_NO_MORE_DATA;
/* Check for additional textual data */
if (packet->header.size > (size_t) (p - buf) && (len = php_mysqlnd_net_field_length(&p))) {
- packet->info_or_local_file = mnd_emalloc(len + 1);
- if (packet->info_or_local_file) {
- memcpy(packet->info_or_local_file, p, len);
- packet->info_or_local_file[len] = '\0';
- packet->info_or_local_file_len = len;
+ packet->info_or_local_file.s = mnd_emalloc(len + 1);
+ if (packet->info_or_local_file.s) {
+ memcpy(packet->info_or_local_file.s, p, len);
+ packet->info_or_local_file.s[len] = '\0';
+ packet->info_or_local_file.l = len;
} else {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(error_info);
ret = FAIL;
}
}
@@ -1189,9 +1204,9 @@ void php_mysqlnd_rset_header_free_mem(void * _packet, zend_bool stack_allocation
{
MYSQLND_PACKET_RSET_HEADER *p= (MYSQLND_PACKET_RSET_HEADER *) _packet;
DBG_ENTER("php_mysqlnd_rset_header_free_mem");
- if (p->info_or_local_file) {
- mnd_efree(p->info_or_local_file);
- p->info_or_local_file = NULL;
+ if (p->info_or_local_file.s) {
+ mnd_efree(p->info_or_local_file.s);
+ p->info_or_local_file.s = NULL;
}
if (!stack_allocation) {
mnd_pefree(p, p->header.persistent);
@@ -1219,14 +1234,19 @@ static size_t rset_field_offsets[] =
/* {{{ php_mysqlnd_rset_field_read */
static enum_func_status
-php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_rset_field_read(void * _packet)
{
/* Should be enough for the metadata of a single row */
MYSQLND_PACKET_RES_FIELD *packet = (MYSQLND_PACKET_RES_FIELD *) _packet;
- size_t buf_len = conn->net->cmd_buffer.length, total_len = 0;
- zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
- zend_uchar *p = buf;
- zend_uchar *begin = buf;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
+ size_t buf_len = pfc->cmd_buffer.length, total_len = 0;
+ zend_uchar * buf = (zend_uchar *) pfc->cmd_buffer.buffer;
+ const zend_uchar * p = buf;
+ const zend_uchar * const begin = buf;
char *root_ptr;
zend_ulong len;
MYSQLND_FIELD *meta;
@@ -1234,7 +1254,9 @@ php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn)
DBG_ENTER("php_mysqlnd_rset_field_read");
- PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "field", PROT_RSET_FLD_PACKET);
+ if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, buf_len, "field", PROT_RSET_FLD_PACKET)) {
+ DBG_RETURN(FAIL);
+ }
if (packet->skip_parsing) {
DBG_RETURN(PASS);
@@ -1252,9 +1274,8 @@ php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn)
DBG_ERR_FMT("Server error : (%u) %s", packet->error_info.error_no, packet->error_info.error);
DBG_RETURN(PASS);
} else if (EODATA_MARKER == *p && packet->header.size < 8) {
- /* Premature EOF. That should be COM_FIELD_LIST */
+ /* Premature EOF. That should be COM_FIELD_LIST. But we don't support COM_FIELD_LIST anymore, thus this should not happen */
DBG_INF("Premature EOF. That should be COM_FIELD_LIST");
- packet->stupid_list_fields_eof = TRUE;
DBG_RETURN(PASS);
}
@@ -1336,7 +1357,7 @@ php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn)
DBG_INF_FMT("Def found, length %lu, persistent=%u", len, packet->persistent_alloc);
meta->def = mnd_pemalloc(len + 1, packet->persistent_alloc);
if (!meta->def) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(error_info);
DBG_RETURN(FAIL);
}
memcpy(meta->def, p, len);
@@ -1347,7 +1368,7 @@ php_mysqlnd_rset_field_read(void * _packet, MYSQLND_CONN_DATA * conn)
root_ptr = meta->root = mnd_pemalloc(total_len, packet->persistent_alloc);
if (!root_ptr) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(error_info);
DBG_RETURN(FAIL);
}
@@ -1433,7 +1454,11 @@ void php_mysqlnd_rset_field_free_mem(void * _packet, zend_bool stack_allocation)
/* {{{ php_mysqlnd_read_row_ex */
static enum_func_status
-php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_set_memory_pool,
+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_CHUNK ** buffer,
size_t * data_size, zend_bool persistent_alloc,
unsigned int prealloc_more_bytes)
@@ -1455,7 +1480,7 @@ php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_s
*data_size = prealloc_more_bytes;
while (1) {
- if (FAIL == mysqlnd_read_header(conn->net, &header, conn->stats, conn->error_info)) {
+ if (FAIL == mysqlnd_read_header(pfc, vio, &header, stats, error_info)) {
ret = FAIL;
break;
}
@@ -1480,7 +1505,7 @@ php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_s
We have to realloc the buffer.
*/
if (FAIL == (*buffer)->resize_chunk((*buffer), *data_size)) {
- SET_OOM_ERROR(*conn->error_info);
+ SET_OOM_ERROR(error_info);
ret = FAIL;
break;
}
@@ -1488,7 +1513,7 @@ php_mysqlnd_read_row_ex(MYSQLND_CONN_DATA * conn, MYSQLND_MEMORY_POOL * result_s
p = (*buffer)->ptr + (*data_size - header.size);
}
- if (PASS != (ret = conn->net->data->m.receive_ex(conn->net, p, header.size, conn->stats, conn->error_info))) {
+ if (PASS != (ret = pfc->data->m.receive(pfc, vio, p, header.size, stats, error_info))) {
DBG_ERR("Empty row packet body");
php_error(E_WARNING, "Empty row packet body");
break;
@@ -1515,8 +1540,9 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
zend_bool as_int_or_float, MYSQLND_STATS * stats)
{
unsigned int i;
- zend_uchar *p = row_buffer->ptr;
- zend_uchar *null_ptr, bit;
+ const zend_uchar * p = row_buffer->ptr;
+ const zend_uchar * null_ptr;
+ zend_uchar bit;
zval *current_field, *end_field, *start_field;
DBG_ENTER("php_mysqlnd_rowp_read_binary_protocol");
@@ -1535,7 +1561,7 @@ php_mysqlnd_rowp_read_binary_protocol(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
for (i = 0, current_field = start_field; current_field < end_field; current_field++, i++) {
enum_mysqlnd_collected_stats statistic;
- zend_uchar * orig_p = p;
+ const zend_uchar * orig_p = p;
DBG_INF_FMT("Into zval=%p decoding column %u [%s.%s.%s] type=%u field->flags&unsigned=%u flags=%u is_bit=%u",
current_field, i,
@@ -1620,7 +1646,7 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer,
for (i = 0, current_field = start_field; current_field < end_field; current_field++, i++) {
/* php_mysqlnd_net_field_length() call should be after *this_field_len_pos = p; */
- zend_ulong len = php_mysqlnd_net_field_length(&p);
+ const zend_ulong len = php_mysqlnd_net_field_length((const zend_uchar **) &p);
/* NULL or NOT NULL, this is the question! */
if (len == MYSQLND_NULL_LENGTH) {
@@ -1723,7 +1749,7 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_MEMORY_POOL_CHUNK * row_buffer,
Definitely not nice, _hackish_ :(, but works.
*/
zend_uchar *start = bit_area;
- ps_fetch_from_1_to_8_bytes(current_field, &(fields_metadata[i]), 0, &p, len);
+ ps_fetch_from_1_to_8_bytes(current_field, &(fields_metadata[i]), 0, (const zend_uchar **) &p, len);
/*
We have advanced in ps_fetch_from_1_to_8_bytes. We should go back because
later in this function there will be an advancement.
@@ -1785,11 +1811,15 @@ php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK * row_buffer, zv
if PS => packet->fields is passed from outside
*/
static enum_func_status
-php_mysqlnd_rowp_read(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_rowp_read(void * _packet)
{
+ MYSQLND_PACKET_ROW *packet= (MYSQLND_PACKET_ROW *) _packet;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
zend_uchar *p;
enum_func_status ret = PASS;
- MYSQLND_PACKET_ROW *packet= (MYSQLND_PACKET_ROW *) _packet;
size_t post_alloc_for_bit_fields = 0;
size_t data_size = 0;
@@ -1800,13 +1830,14 @@ php_mysqlnd_rowp_read(void * _packet, MYSQLND_CONN_DATA * conn)
post_alloc_for_bit_fields = packet->bit_fields_total_len + packet->bit_fields_count;
}
- ret = php_mysqlnd_read_row_ex(conn, packet->result_set_memory_pool, &packet->row_buffer, &data_size,
+ ret = php_mysqlnd_read_row_ex(pfc, vio, stats, error_info,
+ packet->result_set_memory_pool, &packet->row_buffer, &data_size,
packet->persistent_alloc, post_alloc_for_bit_fields
);
if (FAIL == ret) {
goto end;
}
- MYSQLND_INC_CONN_STATISTIC_W_VALUE2(conn->stats, packet_type_to_statistic_byte_count[PROT_ROW_PACKET],
+ MYSQLND_INC_CONN_STATISTIC_W_VALUE2(stats, packet_type_to_statistic_byte_count[PROT_ROW_PACKET],
MYSQLND_HEADER_SIZE + packet->header.size,
packet_type_to_statistic_packet_count[PROT_ROW_PACKET],
1);
@@ -1839,7 +1870,7 @@ php_mysqlnd_rowp_read(void * _packet, MYSQLND_CONN_DATA * conn)
DBG_INF_FMT("server_status=%u warning_count=%u", packet->server_status, packet->warning_count);
}
} else {
- MYSQLND_INC_CONN_STATISTIC(conn->stats,
+ MYSQLND_INC_CONN_STATISTIC(stats,
packet->binary_protocol? STAT_ROWS_FETCHED_FROM_SERVER_PS:
STAT_ROWS_FETCHED_FROM_SERVER_NORMAL);
@@ -1863,7 +1894,7 @@ php_mysqlnd_rowp_read(void * _packet, MYSQLND_CONN_DATA * conn)
packet->persistent_alloc);
}
} else {
- MYSQLND_INC_CONN_STATISTIC(conn->stats,
+ MYSQLND_INC_CONN_STATISTIC(stats,
packet->binary_protocol? STAT_ROWS_SKIPPED_PS:
STAT_ROWS_SKIPPED_NORMAL);
}
@@ -1905,20 +1936,27 @@ php_mysqlnd_rowp_free_mem(void * _packet, zend_bool stack_allocation)
/* {{{ php_mysqlnd_stats_read */
static enum_func_status
-php_mysqlnd_stats_read(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_stats_read(void * _packet)
{
MYSQLND_PACKET_STATS *packet= (MYSQLND_PACKET_STATS *) _packet;
- size_t buf_len = conn->net->cmd_buffer.length;
- zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
+ size_t buf_len = pfc->cmd_buffer.length;
+ zend_uchar *buf = (zend_uchar *) pfc->cmd_buffer.buffer;
DBG_ENTER("php_mysqlnd_stats_read");
- PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "statistics", PROT_STATS_PACKET);
+ if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, buf_len, "statistics", PROT_STATS_PACKET)) {
+ DBG_RETURN(FAIL);
+ }
- packet->message = mnd_emalloc(packet->header.size + 1);
- memcpy(packet->message, buf, packet->header.size);
- packet->message[packet->header.size] = '\0';
- packet->message_len = packet->header.size;
+ packet->message.s = mnd_emalloc(packet->header.size + 1);
+ memcpy(packet->message.s, buf, packet->header.size);
+ packet->message.s[packet->header.size] = '\0';
+ packet->message.l = packet->header.size;
DBG_RETURN(PASS);
}
@@ -1930,9 +1968,9 @@ static
void php_mysqlnd_stats_free_mem(void * _packet, zend_bool stack_allocation)
{
MYSQLND_PACKET_STATS *p= (MYSQLND_PACKET_STATS *) _packet;
- if (p->message) {
- mnd_efree(p->message);
- p->message = NULL;
+ if (p->message.s) {
+ mnd_efree(p->message.s);
+ p->message.s = NULL;
}
if (!stack_allocation) {
mnd_pefree(p, p->header.persistent);
@@ -1947,19 +1985,26 @@ void php_mysqlnd_stats_free_mem(void * _packet, zend_bool stack_allocation)
/* {{{ php_mysqlnd_prepare_read */
static enum_func_status
-php_mysqlnd_prepare_read(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_prepare_read(void * _packet)
{
+ MYSQLND_PACKET_PREPARE_RESPONSE *packet= (MYSQLND_PACKET_PREPARE_RESPONSE *) _packet;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
/* In case of an error, we should have place to put it */
- size_t buf_len = conn->net->cmd_buffer.length;
- zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
+ size_t buf_len = pfc->cmd_buffer.length;
+ zend_uchar *buf = (zend_uchar *) pfc->cmd_buffer.buffer;
zend_uchar *p = buf;
- zend_uchar *begin = buf;
+ const zend_uchar * const begin = buf;
unsigned int data_size;
- MYSQLND_PACKET_PREPARE_RESPONSE *packet= (MYSQLND_PACKET_PREPARE_RESPONSE *) _packet;
DBG_ENTER("php_mysqlnd_prepare_read");
- PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "prepare", PROT_PREPARE_RESP_PACKET);
+ if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, buf_len, "prepare", PROT_PREPARE_RESP_PACKET)) {
+ DBG_RETURN(FAIL);
+ }
BAIL_IF_NO_MORE_DATA;
data_size = packet->header.size;
@@ -2035,18 +2080,25 @@ php_mysqlnd_prepare_free_mem(void * _packet, zend_bool stack_allocation)
/* {{{ php_mysqlnd_chg_user_read */
static enum_func_status
-php_mysqlnd_chg_user_read(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_chg_user_read(void * _packet)
{
+ MYSQLND_PACKET_CHG_USER_RESPONSE *packet= (MYSQLND_PACKET_CHG_USER_RESPONSE *) _packet;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
/* There could be an error message */
- size_t buf_len = conn->net->cmd_buffer.length;
- zend_uchar *buf = (zend_uchar *) conn->net->cmd_buffer.buffer;
+ size_t buf_len = pfc->cmd_buffer.length;
+ zend_uchar *buf = (zend_uchar *) pfc->cmd_buffer.buffer;
zend_uchar *p = buf;
- zend_uchar *begin = buf;
- MYSQLND_PACKET_CHG_USER_RESPONSE *packet= (MYSQLND_PACKET_CHG_USER_RESPONSE *) _packet;
+ const zend_uchar * const begin = buf;
DBG_ENTER("php_mysqlnd_chg_user_read");
- PACKET_READ_HEADER_AND_BODY(packet, conn, buf, buf_len, "change user response", PROT_CHG_USER_RESP_PACKET);
+ if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, buf_len, "change user response", PROT_CHG_USER_RESP_PACKET)) {
+ DBG_RETURN(FAIL);
+ }
BAIL_IF_NO_MORE_DATA;
/*
@@ -2123,15 +2175,20 @@ php_mysqlnd_chg_user_free_mem(void * _packet, zend_bool stack_allocation)
/* {{{ php_mysqlnd_sha256_pk_request_write */
static
-size_t php_mysqlnd_sha256_pk_request_write(void * _packet, MYSQLND_CONN_DATA * conn)
+size_t php_mysqlnd_sha256_pk_request_write(void * _packet)
{
+ MYSQLND_PACKET_SHA256_PK_REQUEST * packet = (MYSQLND_PACKET_SHA256_PK_REQUEST *) _packet;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
zend_uchar buffer[MYSQLND_HEADER_SIZE + 1];
size_t sent;
DBG_ENTER("php_mysqlnd_sha256_pk_request_write");
int1store(buffer + MYSQLND_HEADER_SIZE, '\1');
- sent = conn->net->data->m.send_ex(conn->net, buffer, 1, conn->stats, conn->error_info);
+ sent = pfc->data->m.send(pfc, vio, buffer, 1, stats, error_info);
DBG_RETURN(sent);
}
@@ -2154,17 +2211,24 @@ void php_mysqlnd_sha256_pk_request_free_mem(void * _packet, zend_bool stack_allo
/* {{{ php_mysqlnd_sha256_pk_request_response_read */
static enum_func_status
-php_mysqlnd_sha256_pk_request_response_read(void * _packet, MYSQLND_CONN_DATA * conn)
+php_mysqlnd_sha256_pk_request_response_read(void * _packet)
{
+ MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE * packet= (MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE *) _packet;
+ MYSQLND_ERROR_INFO * error_info = packet->header.error_info;
+ MYSQLND_PFC * pfc = packet->header.protocol_frame_codec;
+ MYSQLND_VIO * vio = packet->header.vio;
+ MYSQLND_STATS * stats = packet->header.stats;
+ MYSQLND_CONNECTION_STATE * connection_state = packet->header.connection_state;
zend_uchar buf[SHA256_PK_REQUEST_RESP_BUFFER_SIZE];
zend_uchar *p = buf;
- zend_uchar *begin = buf;
- MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE * packet= (MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE *) _packet;
+ const zend_uchar * const begin = buf;
DBG_ENTER("php_mysqlnd_sha256_pk_request_response_read");
/* leave space for terminating safety \0 */
- PACKET_READ_HEADER_AND_BODY(packet, conn, buf, sizeof(buf), "SHA256_PK_REQUEST_RESPONSE", PROT_SHA256_PK_REQUEST_RESPONSE_PACKET);
+ if (FAIL == mysqlnd_read_packet_header_and_body(&(packet->header), pfc, vio, stats, error_info, connection_state, buf, sizeof(buf), "SHA256_PK_REQUEST_RESPONSE", PROT_SHA256_PK_REQUEST_RESPONSE_PACKET)) {
+ DBG_RETURN(FAIL);
+ }
BAIL_IF_NO_MORE_DATA;
p++;
@@ -2304,12 +2368,20 @@ mysqlnd_packet_methods packet_methods[PROT_LAST] =
/* {{{ mysqlnd_protocol::get_greet_packet */
static struct st_mysqlnd_packet_greet *
-MYSQLND_METHOD(mysqlnd_protocol, get_greet_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_greet_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_greet * packet = mnd_pecalloc(1, packet_methods[PROT_GREET_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_greet_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_GREET_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2319,12 +2391,21 @@ MYSQLND_METHOD(mysqlnd_protocol, get_greet_packet)(MYSQLND_PROTOCOL * const prot
/* {{{ mysqlnd_protocol::get_auth_packet */
static struct st_mysqlnd_packet_auth *
-MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_auth * packet = mnd_pecalloc(1, packet_methods[PROT_AUTH_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_auth_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_AUTH_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.conn = factory->conn;
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2334,12 +2415,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet)(MYSQLND_PROTOCOL * const proto
/* {{{ mysqlnd_protocol::get_auth_response_packet */
static struct st_mysqlnd_packet_auth_response *
-MYSQLND_METHOD(mysqlnd_protocol, get_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_auth_response_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_auth_response * packet = mnd_pecalloc(1, packet_methods[PROT_AUTH_RESP_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_auth_response_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_AUTH_RESP_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2349,12 +2438,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_auth_response_packet)(MYSQLND_PROTOCOL * co
/* {{{ mysqlnd_protocol::get_change_auth_response_packet */
static struct st_mysqlnd_packet_change_auth_response *
-MYSQLND_METHOD(mysqlnd_protocol, get_change_auth_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_change_auth_response_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_change_auth_response * packet = mnd_pecalloc(1, packet_methods[PROT_CHANGE_AUTH_RESP_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_change_auth_response_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_CHANGE_AUTH_RESP_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2364,12 +2461,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_change_auth_response_packet)(MYSQLND_PROTOC
/* {{{ mysqlnd_protocol::get_ok_packet */
static struct st_mysqlnd_packet_ok *
-MYSQLND_METHOD(mysqlnd_protocol, get_ok_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_ok_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_ok * packet = mnd_pecalloc(1, packet_methods[PROT_OK_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_ok_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_OK_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2379,12 +2484,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_ok_packet)(MYSQLND_PROTOCOL * const protoco
/* {{{ mysqlnd_protocol::get_eof_packet */
static struct st_mysqlnd_packet_eof *
-MYSQLND_METHOD(mysqlnd_protocol, get_eof_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_eof_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_eof * packet = mnd_pecalloc(1, packet_methods[PROT_EOF_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_eof_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_EOF_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2394,12 +2507,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_eof_packet)(MYSQLND_PROTOCOL * const protoc
/* {{{ mysqlnd_protocol::get_command_packet */
static struct st_mysqlnd_packet_command *
-MYSQLND_METHOD(mysqlnd_protocol, get_command_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_command_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_command * packet = mnd_pecalloc(1, packet_methods[PROT_CMD_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_command_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_CMD_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2409,12 +2530,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_command_packet)(MYSQLND_PROTOCOL * const pr
/* {{{ mysqlnd_protocol::get_rset_packet */
static struct st_mysqlnd_packet_rset_header *
-MYSQLND_METHOD(mysqlnd_protocol, get_rset_header_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_rset_header_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_rset_header * packet = mnd_pecalloc(1, packet_methods[PROT_RSET_HEADER_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_rset_header_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_RSET_HEADER_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2424,12 +2553,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_rset_header_packet)(MYSQLND_PROTOCOL * cons
/* {{{ mysqlnd_protocol::get_result_field_packet */
static struct st_mysqlnd_packet_res_field *
-MYSQLND_METHOD(mysqlnd_protocol, get_result_field_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_result_field_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_res_field * packet = mnd_pecalloc(1, packet_methods[PROT_RSET_FLD_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_result_field_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_RSET_FLD_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2439,12 +2576,21 @@ MYSQLND_METHOD(mysqlnd_protocol, get_result_field_packet)(MYSQLND_PROTOCOL * con
/* {{{ mysqlnd_protocol::get_row_packet */
static struct st_mysqlnd_packet_row *
-MYSQLND_METHOD(mysqlnd_protocol, get_row_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_row_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_row * packet = mnd_pecalloc(1, packet_methods[PROT_ROW_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_row_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_ROW_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.conn = factory->conn;
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2454,12 +2600,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_row_packet)(MYSQLND_PROTOCOL * const protoc
/* {{{ mysqlnd_protocol::get_stats_packet */
static struct st_mysqlnd_packet_stats *
-MYSQLND_METHOD(mysqlnd_protocol, get_stats_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_stats_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_stats * packet = mnd_pecalloc(1, packet_methods[PROT_STATS_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_stats_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_STATS_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2469,12 +2623,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_stats_packet)(MYSQLND_PROTOCOL * const prot
/* {{{ mysqlnd_protocol::get_prepare_response_packet */
static struct st_mysqlnd_packet_prepare_response *
-MYSQLND_METHOD(mysqlnd_protocol, get_prepare_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_prepare_response_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_prepare_response * packet = mnd_pecalloc(1, packet_methods[PROT_PREPARE_RESP_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_prepare_response_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_PREPARE_RESP_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2484,12 +2646,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_prepare_response_packet)(MYSQLND_PROTOCOL *
/* {{{ mysqlnd_protocol::get_change_user_response_packet */
static struct st_mysqlnd_packet_chg_user_resp*
-MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_chg_user_resp * packet = mnd_pecalloc(1, packet_methods[PROT_CHG_USER_RESP_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_change_user_response_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_CHG_USER_RESP_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2499,12 +2669,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet)(MYSQLND_PROTOC
/* {{{ mysqlnd_protocol::get_sha256_pk_request_packet */
static struct st_mysqlnd_packet_sha256_pk_request *
-MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_sha256_pk_request * packet = mnd_pecalloc(1, packet_methods[PROT_SHA256_PK_REQUEST_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_sha256_pk_request_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_SHA256_PK_REQUEST_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2514,12 +2692,20 @@ MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_packet)(MYSQLND_PROTOCOL
/* {{{ mysqlnd_protocol::get_sha256_pk_request_response_packet */
static struct st_mysqlnd_packet_sha256_pk_request_response *
-MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_response_packet)(MYSQLND_PROTOCOL * const protocol, zend_bool persistent)
+MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_response_packet)(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory, const zend_bool persistent)
{
struct st_mysqlnd_packet_sha256_pk_request_response * packet = mnd_pecalloc(1, packet_methods[PROT_SHA256_PK_REQUEST_RESPONSE_PACKET].struct_size, persistent);
DBG_ENTER("mysqlnd_protocol::get_sha256_pk_request_response_packet");
if (packet) {
packet->header.m = &packet_methods[PROT_SHA256_PK_REQUEST_RESPONSE_PACKET];
+ packet->header.factory = factory;
+
+ packet->header.protocol_frame_codec = factory->conn->protocol_frame_codec;
+ packet->header.vio = factory->conn->vio;
+ packet->header.stats = factory->conn->stats;
+ packet->header.error_info = factory->conn->error_info;
+ packet->header.connection_state = &factory->conn->state;
+
packet->header.persistent = persistent;
}
DBG_RETURN(packet);
@@ -2527,8 +2713,219 @@ MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_response_packet)(MYSQLND_
/* }}} */
+/* {{{ mysqlnd_protocol::send_command */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_protocol, send_command)(
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * payload_decoder_factory,
+ const enum php_mysqlnd_server_command command,
+ const zend_uchar * const arg, const size_t arg_len,
+ const zend_bool silent,
+
+ struct st_mysqlnd_connection_state * connection_state,
+ MYSQLND_ERROR_INFO * error_info,
+ MYSQLND_UPSERT_STATUS * upsert_status,
+ MYSQLND_STATS * stats,
+ func_mysqlnd_conn_data__send_close send_close,
+ void * send_close_ctx)
+{
+ enum_func_status ret = PASS;
+ MYSQLND_PACKET_COMMAND * cmd_packet = NULL;
+ DBG_ENTER("mysqlnd_protocol::send_command");
+ DBG_INF_FMT("command=%s silent=%u", mysqlnd_command_to_text[command], silent);
+ DBG_INF_FMT("server_status=%u", UPSERT_STATUS_GET_SERVER_STATUS(upsert_status));
+ DBG_INF_FMT("sending %u bytes", arg_len + 1); /* + 1 is for the command */
+ enum mysqlnd_connection_state state = connection_state->m->get(connection_state);
+
+ switch (state) {
+ case CONN_READY:
+ break;
+ case CONN_QUIT_SENT:
+ SET_CLIENT_ERROR(error_info, CR_SERVER_GONE_ERROR, UNKNOWN_SQLSTATE, mysqlnd_server_gone);
+ DBG_ERR("Server is gone");
+ DBG_RETURN(FAIL);
+ default:
+ SET_CLIENT_ERROR(error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
+ DBG_ERR_FMT("Command out of sync. State=%u", state);
+ DBG_RETURN(FAIL);
+ }
+
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(upsert_status);
+ SET_EMPTY_ERROR(error_info);
-MYSQLND_CLASS_METHODS_START(mysqlnd_protocol)
+ cmd_packet = payload_decoder_factory->m.get_command_packet(payload_decoder_factory, FALSE);
+ if (!cmd_packet) {
+ SET_OOM_ERROR(error_info);
+ DBG_RETURN(FAIL);
+ }
+
+ cmd_packet->command = command;
+ if (arg && arg_len) {
+ cmd_packet->argument.s = (char *) arg;
+ cmd_packet->argument.l = arg_len;
+ }
+
+ MYSQLND_INC_CONN_STATISTIC(stats, STAT_COM_QUIT + command - 1 /* because of COM_SLEEP */ );
+
+ if (! PACKET_WRITE(cmd_packet)) {
+ if (!silent) {
+ DBG_ERR_FMT("Error while sending %s packet", mysqlnd_command_to_text[command]);
+ php_error(E_WARNING, "Error while sending %s packet. PID=%d", mysqlnd_command_to_text[command], getpid());
+ }
+ connection_state->m->set(connection_state, CONN_QUIT_SENT);
+ send_close(send_close_ctx);
+ DBG_ERR("Server is gone");
+ ret = FAIL;
+ }
+ PACKET_FREE(cmd_packet);
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_protocol::send_command_handle_OK */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_protocol, send_command_handle_OK)(
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const payload_decoder_factory,
+ MYSQLND_ERROR_INFO * const error_info,
+ MYSQLND_UPSERT_STATUS * const upsert_status,
+ const zend_bool ignore_upsert_status, /* actually used only by LOAD DATA. COM_QUERY and COM_EXECUTE handle the responses themselves */
+ MYSQLND_STRING * const last_message,
+ const zend_bool last_message_persistent)
+{
+ enum_func_status ret = FAIL;
+ MYSQLND_PACKET_OK * ok_response = payload_decoder_factory->m.get_ok_packet(payload_decoder_factory, FALSE);
+
+ DBG_ENTER("mysqlnd_protocol::send_command_handle_OK");
+ if (!ok_response) {
+ SET_OOM_ERROR(error_info);
+ DBG_RETURN(FAIL);
+ }
+ if (FAIL == (ret = PACKET_READ(ok_response))) {
+ DBG_INF("Error while reading OK packet");
+ SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
+ goto end;
+ }
+ DBG_INF_FMT("OK from server");
+ if (0xFF == ok_response->field_count) {
+ /* The server signalled error. Set the error */
+ SET_CLIENT_ERROR(error_info, ok_response->error_no, ok_response->sqlstate, ok_response->error);
+ ret = FAIL;
+ /*
+ Cover a protocol design error: error packet does not
+ contain the server status. Therefore, the client has no way
+ to find out whether there are more result sets of
+ a multiple-result-set statement pending. Luckily, in 5.0 an
+ error always aborts execution of a statement, wherever it is
+ a multi-statement or a stored procedure, so it should be
+ safe to unconditionally turn off the flag here.
+ */
+ upsert_status->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(upsert_status);
+ } else {
+ SET_NEW_MESSAGE(last_message->s, last_message->l,
+ ok_response->message, ok_response->message_len,
+ last_message_persistent);
+ if (!ignore_upsert_status) {
+ UPSERT_STATUS_RESET(upsert_status);
+ UPSERT_STATUS_SET_WARNINGS(upsert_status, ok_response->warning_count);
+ UPSERT_STATUS_SET_SERVER_STATUS(upsert_status, ok_response->server_status);
+ UPSERT_STATUS_SET_AFFECTED_ROWS(upsert_status, ok_response->affected_rows);
+ UPSERT_STATUS_SET_LAST_INSERT_ID(upsert_status, ok_response->last_insert_id);
+ } else {
+ /* LOAD DATA */
+ }
+ }
+end:
+ PACKET_FREE(ok_response);
+ DBG_INF(ret == PASS ? "PASS":"FAIL");
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ mysqlnd_protocol::send_command_handle_EOF */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_protocol, send_command_handle_EOF)(
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const payload_decoder_factory,
+ MYSQLND_ERROR_INFO * const error_info,
+ MYSQLND_UPSERT_STATUS * const upsert_status)
+{
+ enum_func_status ret = FAIL;
+ MYSQLND_PACKET_EOF * response = payload_decoder_factory->m.get_eof_packet(payload_decoder_factory, FALSE);
+
+ DBG_ENTER("mysqlnd_protocol::send_command_handle_EOF");
+
+ if (!response) {
+ SET_OOM_ERROR(error_info);
+ DBG_RETURN(FAIL);
+ }
+ if (FAIL == (ret = PACKET_READ(response))) {
+ DBG_INF("Error while reading EOF packet");
+ SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
+ } else if (0xFF == response->field_count) {
+ /* The server signalled error. Set the error */
+ DBG_INF_FMT("Error_no=%d SQLstate=%s Error=%s", response->error_no, response->sqlstate, response->error);
+
+ SET_CLIENT_ERROR(error_info, response->error_no, response->sqlstate, response->error);
+
+ UPSERT_STATUS_SET_AFFECTED_ROWS_TO_ERROR(upsert_status);
+ } else if (0xFE != response->field_count) {
+ SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
+ DBG_ERR_FMT("EOF packet expected, field count wasn't 0xFE but 0x%2X", response->field_count);
+ php_error_docref(NULL, E_WARNING, "EOF packet expected, field count wasn't 0xFE but 0x%2X", response->field_count);
+ } else {
+ DBG_INF_FMT("EOF from server");
+ }
+ PACKET_FREE(response);
+
+ DBG_INF(ret == PASS ? "PASS":"FAIL");
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+/* {{{ send_command_handle_response */
+static enum_func_status
+MYSQLND_METHOD(mysqlnd_protocol, send_command_handle_response)(
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * payload_decoder_factory,
+ const enum mysqlnd_packet_type ok_packet,
+ const zend_bool silent,
+ const enum php_mysqlnd_server_command command,
+ const zend_bool ignore_upsert_status, /* actually used only by LOAD DATA. COM_QUERY and COM_EXECUTE handle the responses themselves */
+
+ MYSQLND_ERROR_INFO * error_info,
+ MYSQLND_UPSERT_STATUS * upsert_status,
+ MYSQLND_STRING * last_message,
+ zend_bool last_message_persistent
+ )
+{
+ enum_func_status ret = FAIL;
+
+ DBG_ENTER("mysqlnd_protocol::send_command_handle_response");
+ DBG_INF_FMT("silent=%u packet=%u command=%s", silent, ok_packet, mysqlnd_command_to_text[command]);
+
+ switch (ok_packet) {
+ case PROT_OK_PACKET:
+ ret = payload_decoder_factory->m.send_command_handle_OK(payload_decoder_factory, error_info, upsert_status, ignore_upsert_status, last_message, last_message_persistent);
+ break;
+ case PROT_EOF_PACKET:
+ ret = payload_decoder_factory->m.send_command_handle_EOF(payload_decoder_factory, error_info, upsert_status);
+ break;
+ default:
+ SET_CLIENT_ERROR(error_info, CR_MALFORMED_PACKET, UNKNOWN_SQLSTATE, "Malformed packet");
+ php_error_docref(NULL, E_ERROR, "Wrong response packet %u passed to the function", ok_packet);
+ break;
+ }
+ if (!silent && error_info->error_no == CR_MALFORMED_PACKET) {
+ php_error_docref(NULL, E_WARNING, "Error while reading %s's response packet. PID=%d", mysqlnd_command_to_text[command], getpid());
+ }
+ DBG_INF(ret == PASS ? "PASS":"FAIL");
+ DBG_RETURN(ret);
+}
+/* }}} */
+
+
+MYSQLND_CLASS_METHODS_START(mysqlnd_protocol_payload_decoder_factory)
MYSQLND_METHOD(mysqlnd_protocol, get_greet_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_auth_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_auth_response_packet),
@@ -2543,31 +2940,36 @@ MYSQLND_CLASS_METHODS_START(mysqlnd_protocol)
MYSQLND_METHOD(mysqlnd_protocol, get_prepare_response_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_change_user_response_packet),
MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_packet),
- MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_response_packet)
+ MYSQLND_METHOD(mysqlnd_protocol, get_sha256_pk_request_response_packet),
+
+ MYSQLND_METHOD(mysqlnd_protocol, send_command),
+ MYSQLND_METHOD(mysqlnd_protocol, send_command_handle_response),
+ MYSQLND_METHOD(mysqlnd_protocol, send_command_handle_OK),
+ MYSQLND_METHOD(mysqlnd_protocol, send_command_handle_EOF),
MYSQLND_CLASS_METHODS_END;
-/* {{{ mysqlnd_protocol_init */
-PHPAPI MYSQLND_PROTOCOL *
-mysqlnd_protocol_init(zend_bool persistent)
+/* {{{ mysqlnd_protocol_payload_decoder_factory_init */
+PHPAPI MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY *
+mysqlnd_protocol_payload_decoder_factory_init(MYSQLND_CONN_DATA * conn, const zend_bool persistent)
{
- MYSQLND_PROTOCOL * ret;
- DBG_ENTER("mysqlnd_protocol_init");
- ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_protocol_decoder(persistent);
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * ret;
+ DBG_ENTER("mysqlnd_protocol_payload_decoder_factory_init");
+ ret = MYSQLND_CLASS_METHOD_TABLE_NAME(mysqlnd_object_factory).get_protocol_payload_decoder_factory(conn, persistent);
DBG_RETURN(ret);
}
/* }}} */
-/* {{{ mysqlnd_protocol_free */
+/* {{{ mysqlnd_protocol_payload_decoder_factory_free */
PHPAPI void
-mysqlnd_protocol_free(MYSQLND_PROTOCOL * const protocol)
+mysqlnd_protocol_payload_decoder_factory_free(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const factory)
{
- DBG_ENTER("mysqlnd_protocol_free");
+ DBG_ENTER("mysqlnd_protocol_payload_decoder_factory_free");
- if (protocol) {
- zend_bool pers = protocol->persistent;
- mnd_pefree(protocol, pers);
+ if (factory) {
+ zend_bool pers = factory->persistent;
+ mnd_pefree(factory, pers);
}
DBG_VOID_RETURN;
}
diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.h b/ext/mysqlnd/mysqlnd_wireprotocol.h
index 26b90c6750..ce44c8016f 100644
--- a/ext/mysqlnd/mysqlnd_wireprotocol.h
+++ b/ext/mysqlnd/mysqlnd_wireprotocol.h
@@ -17,14 +17,9 @@
| Georg Richter <georg@mysql.com> |
+----------------------------------------------------------------------+
*/
-
-/* $Id$ */
-
#ifndef MYSQLND_WIREPROTOCOL_H
#define MYSQLND_WIREPROTOCOL_H
-#include "mysqlnd_net.h"
-
#define MYSQLND_HEADER_SIZE 4
#define COMPRESSED_HEADER_SIZE 3
@@ -36,8 +31,8 @@ PHPAPI extern const char mysqlnd_read_body_name[];
/* Packet handling */
-#define PACKET_WRITE(packet, conn) ((packet)->header.m->write_to_net((packet), (conn)))
-#define PACKET_READ(packet, conn) ((packet)->header.m->read_from_net((packet), (conn)))
+#define PACKET_WRITE(packet) ((packet)->header.m->write_to_net((packet)))
+#define PACKET_READ(packet) ((packet)->header.m->read_from_net((packet)))
#define PACKET_FREE(packet) \
do { \
DBG_INF_FMT("PACKET_FREE(%p)", packet); \
@@ -51,17 +46,26 @@ PHPAPI extern const char * const mysqlnd_command_to_text[COM_END];
/* Low-level extraction functionality */
typedef struct st_mysqlnd_packet_methods {
size_t struct_size;
- enum_func_status (*read_from_net)(void * packet, MYSQLND_CONN_DATA * conn);
- size_t (*write_to_net)(void * packet, MYSQLND_CONN_DATA * conn);
+ enum_func_status (*read_from_net)(void * packet);
+ size_t (*write_to_net)(void * packet);
void (*free_mem)(void *packet, zend_bool stack_allocation);
} mysqlnd_packet_methods;
typedef struct st_mysqlnd_packet_header {
size_t size;
- mysqlnd_packet_methods *m;
zend_uchar packet_no;
zend_bool persistent;
+
+ mysqlnd_packet_methods *m;
+
+ MYSQLND_CONN_DATA * conn;
+ MYSQLND_PFC * protocol_frame_codec;
+ MYSQLND_VIO * vio;
+ MYSQLND_ERROR_INFO * error_info;
+ MYSQLND_STATS * stats;
+ MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * factory;
+ MYSQLND_CONNECTION_STATE * connection_state;
} MYSQLND_PACKET_HEADER;
/* Server greets the client */
@@ -70,9 +74,8 @@ typedef struct st_mysqlnd_packet_greet {
uint8_t protocol_version;
char *server_version;
uint32_t thread_id;
- zend_uchar intern_auth_plugin_data[SCRAMBLE_LENGTH];
- zend_uchar * auth_plugin_data;
- size_t auth_plugin_data_len;
+ char intern_auth_plugin_data[SCRAMBLE_LENGTH];
+ MYSQLND_STRING authentication_plugin_data;
/* 1 byte pad */
uint32_t server_capabilities;
uint8_t charset_no;
@@ -157,8 +160,7 @@ typedef struct st_mysqlnd_packet_ok {
typedef struct st_mysqlnd_packet_command {
MYSQLND_PACKET_HEADER header;
enum php_mysqlnd_server_command command;
- const zend_uchar *argument;
- size_t arg_len;
+ MYSQLND_CSTRING argument;
} MYSQLND_PACKET_COMMAND;
@@ -178,7 +180,7 @@ typedef struct st_mysqlnd_packet_eof {
/* Result Set header*/
typedef struct st_mysqlnd_packet_rset_header {
- MYSQLND_PACKET_HEADER header;
+ MYSQLND_PACKET_HEADER header;
/*
0x00 => ok
~0 => LOAD DATA LOCAL
@@ -195,8 +197,7 @@ typedef struct st_mysqlnd_packet_rset_header {
uint64_t affected_rows;
uint64_t last_insert_id;
/* This is for both LOAD DATA or info, when no result set */
- char *info_or_local_file;
- size_t info_or_local_file_len;
+ MYSQLND_STRING info_or_local_file;
/* If error packet, we use these */
MYSQLND_ERROR_INFO error_info;
} MYSQLND_PACKET_RSET_HEADER;
@@ -208,7 +209,6 @@ typedef struct st_mysqlnd_packet_res_field {
MYSQLND_FIELD *metadata;
/* For table definitions, empty for result sets */
zend_bool skip_parsing;
- zend_bool stupid_list_fields_eof;
zend_bool persistent_alloc;
MYSQLND_ERROR_INFO error_info;
@@ -247,9 +247,7 @@ typedef struct st_mysqlnd_packet_row {
/* Statistics packet */
typedef struct st_mysqlnd_packet_stats {
MYSQLND_PACKET_HEADER header;
- char *message;
- /* message_len is not part of the packet*/
- size_t message_len;
+ MYSQLND_STRING message;
} MYSQLND_PACKET_STATS;
@@ -298,9 +296,7 @@ typedef struct st_mysqlnd_packet_sha256_pk_request_response {
} MYSQLND_PACKET_SHA256_PK_REQUEST_RESPONSE;
-PHPAPI void php_mysqlnd_scramble(zend_uchar * const buffer, const zend_uchar * const scramble, const zend_uchar * const pass, size_t pass_len);
-
-zend_ulong php_mysqlnd_net_field_length(zend_uchar **packet);
+zend_ulong php_mysqlnd_net_field_length(const zend_uchar **packet);
zend_uchar * php_mysqlnd_net_store_length(zend_uchar *packet, uint64_t length);
size_t php_mysqlnd_net_store_length_size(uint64_t length);
@@ -320,8 +316,8 @@ enum_func_status php_mysqlnd_rowp_read_text_protocol_c(MYSQLND_MEMORY_POOL_CHUNK
zend_bool as_int_or_float, MYSQLND_STATS * stats);
-PHPAPI MYSQLND_PROTOCOL * mysqlnd_protocol_init(zend_bool persistent);
-PHPAPI void mysqlnd_protocol_free(MYSQLND_PROTOCOL * const protocol);
+PHPAPI MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * mysqlnd_protocol_payload_decoder_factory_init(MYSQLND_CONN_DATA * conn, const zend_bool persistent);
+PHPAPI void mysqlnd_protocol_payload_decoder_factory_free(MYSQLND_PROTOCOL_PAYLOAD_DECODER_FACTORY * const payload_decoder_factory);
#endif /* MYSQLND_WIREPROTOCOL_H */
diff --git a/ext/mysqlnd/php_mysqlnd.c b/ext/mysqlnd/php_mysqlnd.c
index 5f1bf05217..b4cba4c5dc 100644
--- a/ext/mysqlnd/php_mysqlnd.c
+++ b/ext/mysqlnd/php_mysqlnd.c
@@ -20,7 +20,6 @@
/* $Id$ */
#include "php.h"
-#include "php_ini.h"
#include "mysqlnd.h"
#include "mysqlnd_priv.h"
#include "mysqlnd_debug.h"
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c
index 210078e7a9..9a100e15f9 100644
--- a/ext/opcache/Optimizer/block_pass.c
+++ b/ext/opcache/Optimizer/block_pass.c
@@ -27,6 +27,8 @@
#include "zend_execute.h"
#include "zend_vm.h"
#include "zend_bitset.h"
+#include "zend_cfg.h"
+#include "zend_dump.h"
#define DEBUG_BLOCKPASS 0
@@ -39,7 +41,7 @@ int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int
ALLOCA_FLAG(use_heap);
if ((c = zend_hash_find_ptr(EG(zend_constants), name)) == NULL) {
- lookup_name = DO_ALLOCA(ZSTR_LEN(name) + 1);
+ lookup_name = do_alloca(ZSTR_LEN(name) + 1, use_heap);
memcpy(lookup_name, ZSTR_VAL(name), ZSTR_LEN(name) + 1);
zend_str_tolower(lookup_name, ZSTR_LEN(name));
@@ -50,7 +52,7 @@ int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int
} else {
retval = 0;
}
- FREE_ALLOCA(lookup_name);
+ free_alloca(lookup_name, use_heap);
}
if (retval) {
@@ -67,483 +69,10 @@ int zend_optimizer_get_persistent_constant(zend_string *name, zval *result, int
return retval;
}
-#if DEBUG_BLOCKPASS
-# define BLOCK_REF(b) b?op_array->opcodes-b->start_opline:-1
-
-static inline void print_block(zend_code_block *block, zend_op *opcodes, char *txt)
-{
- fprintf(stderr, "%sBlock: %d-%d (%d)", txt, block->start_opline - opcodes, block->start_opline - opcodes + block->len - 1, block->len);
- if (!block->access) {
- fprintf(stderr, " unused");
- }
- if (block->op1_to) {
- fprintf(stderr, " 1: %d", block->op1_to->start_opline - opcodes);
- }
- if (block->op2_to) {
- fprintf(stderr, " 2: %d", block->op2_to->start_opline - opcodes);
- }
- if (block->ext_to) {
- fprintf(stderr, " e: %d", block->ext_to->start_opline - opcodes);
- }
- if (block->follow_to) {
- fprintf(stderr, " f: %d", block->follow_to->start_opline - opcodes);
- }
-
- if (block->sources) {
- zend_block_source *bs = block->sources;
- fprintf(stderr, " s:");
- while (bs) {
- fprintf(stderr, " %d", bs->from->start_opline - opcodes);
- bs = bs->next;
- }
- }
-
- fprintf(stderr, "\n");
- fflush(stderr);
-}
-#else
-#define print_block(a,b,c)
-#endif
-
-#define START_BLOCK_OP(opno) blocks[opno].start_opline = &op_array->opcodes[opno]; blocks[opno].start_opline_no = opno; blocks[opno].access = 1
-
-/* find code blocks in op_array
- code block is a set of opcodes with single flow of control, i.e. without jmps,
- branches, etc. */
-static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimizer_ctx *ctx)
-{
- zend_op *opline;
- zend_op *end = op_array->opcodes + op_array->last;
- zend_code_block *blocks, *cur_block;
- uint32_t opno = 0;
-
- memset(cfg, 0, sizeof(zend_cfg));
- blocks = cfg->blocks = zend_arena_calloc(&ctx->arena, op_array->last + 2, sizeof(zend_code_block));
- opline = op_array->opcodes;
- blocks[0].start_opline = opline;
- blocks[0].start_opline_no = 0;
- while (opline < end) {
- switch((unsigned)opline->opcode) {
- case ZEND_FAST_CALL:
- START_BLOCK_OP(ZEND_OP1(opline).opline_num);
- if (opline->extended_value) {
- START_BLOCK_OP(ZEND_OP2(opline).opline_num);
- }
- START_BLOCK_OP(opno + 1);
- break;
- case ZEND_FAST_RET:
- if (opline->extended_value) {
- START_BLOCK_OP(ZEND_OP2(opline).opline_num);
- }
- START_BLOCK_OP(opno + 1);
- break;
- case ZEND_JMP:
- case ZEND_DECLARE_ANON_CLASS:
- case ZEND_DECLARE_ANON_INHERITED_CLASS:
- START_BLOCK_OP(ZEND_OP1(opline).opline_num);
- /* break missing intentionally */
- case ZEND_RETURN:
- case ZEND_RETURN_BY_REF:
- case ZEND_GENERATOR_RETURN:
- case ZEND_EXIT:
- case ZEND_THROW:
- /* start new block from this+1 */
- START_BLOCK_OP(opno + 1);
- break;
- /* TODO: if conditional jmp depends on constant,
- don't start block that won't be executed */
- case ZEND_CATCH:
- START_BLOCK_OP(opline->extended_value);
- START_BLOCK_OP(opno + 1);
- break;
- case ZEND_JMPZNZ:
- START_BLOCK_OP(opline->extended_value);
- case ZEND_JMPZ:
- case ZEND_JMPNZ:
- case ZEND_JMPZ_EX:
- case ZEND_JMPNZ_EX:
- case ZEND_FE_RESET_R:
- case ZEND_FE_RESET_RW:
- case ZEND_NEW:
- case ZEND_JMP_SET:
- case ZEND_COALESCE:
- case ZEND_ASSERT_CHECK:
- START_BLOCK_OP(ZEND_OP2(opline).opline_num);
- START_BLOCK_OP(opno + 1);
- break;
- case ZEND_FE_FETCH_R:
- case ZEND_FE_FETCH_RW:
- START_BLOCK_OP(opline->extended_value);
- START_BLOCK_OP(opno + 1);
- break;
- }
- opno++;
- opline++;
- }
-
- /* first find block start points */
- if (op_array->last_try_catch) {
- int i;
- cfg->try = zend_arena_calloc(&ctx->arena, op_array->last_try_catch, sizeof(zend_code_block *));
- cfg->catch = zend_arena_calloc(&ctx->arena, op_array->last_try_catch, sizeof(zend_code_block *));
- for (i = 0; i< op_array->last_try_catch; i++) {
- cfg->try[i] = &blocks[op_array->try_catch_array[i].try_op];
- cfg->catch[i] = &blocks[op_array->try_catch_array[i].catch_op];
- START_BLOCK_OP(op_array->try_catch_array[i].try_op);
- START_BLOCK_OP(op_array->try_catch_array[i].catch_op);
- blocks[op_array->try_catch_array[i].try_op].protected = 1;
- }
- }
- /* Currently, we don't optimize op_arrays with BRK/CONT/GOTO opcodes,
- * but, we have to keep brk_cont_array to avoid memory leaks during
- * exception handling */
- if (op_array->last_brk_cont) {
- int i, j;
-
- j = 0;
- for (i = 0; i< op_array->last_brk_cont; i++) {
- if (op_array->brk_cont_array[i].start >= 0 &&
- (op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE ||
- op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE ||
- op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_ROPE_END ||
- op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) {
- int parent = op_array->brk_cont_array[i].parent;
-
- while (parent >= 0 &&
- op_array->brk_cont_array[parent].start < 0 &&
- (op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FREE ||
- op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_FE_FREE ||
- op_array->opcodes[op_array->brk_cont_array[i].brk].opcode != ZEND_ROPE_END ||
- op_array->opcodes[op_array->brk_cont_array[parent].brk].opcode != ZEND_END_SILENCE)) {
- parent = op_array->brk_cont_array[parent].parent;
- }
- op_array->brk_cont_array[i].parent = parent;
- j++;
- }
- }
- if (j) {
- cfg->loop_start = zend_arena_calloc(&ctx->arena, op_array->last_brk_cont, sizeof(zend_code_block *));
- cfg->loop_cont = zend_arena_calloc(&ctx->arena, op_array->last_brk_cont, sizeof(zend_code_block *));
- cfg->loop_brk = zend_arena_calloc(&ctx->arena, op_array->last_brk_cont, sizeof(zend_code_block *));
- j = 0;
- for (i = 0; i< op_array->last_brk_cont; i++) {
- if (op_array->brk_cont_array[i].start >= 0 &&
- (op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FREE ||
- op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_FE_FREE ||
- op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_ROPE_END ||
- op_array->opcodes[op_array->brk_cont_array[i].brk].opcode == ZEND_END_SILENCE)) {
- if (i != j) {
- op_array->brk_cont_array[j] = op_array->brk_cont_array[i];
- }
- cfg->loop_start[j] = &blocks[op_array->brk_cont_array[j].start];
- cfg->loop_cont[j] = &blocks[op_array->brk_cont_array[j].cont];
- cfg->loop_brk[j] = &blocks[op_array->brk_cont_array[j].brk];
- START_BLOCK_OP(op_array->brk_cont_array[j].start);
- START_BLOCK_OP(op_array->brk_cont_array[j].cont);
- START_BLOCK_OP(op_array->brk_cont_array[j].brk);
- blocks[op_array->brk_cont_array[j].start].protected = 1;
- blocks[op_array->brk_cont_array[j].brk].protected = 1;
- j++;
- }
- }
- op_array->last_brk_cont = j;
- } else {
- efree(op_array->brk_cont_array);
- op_array->brk_cont_array = NULL;
- op_array->last_brk_cont = 0;
- }
- }
-
- /* Build CFG (Control Flow Graph) */
- cur_block = blocks;
- for (opno = 1; opno < op_array->last; opno++) {
- if (blocks[opno].start_opline) {
- /* found new block start */
- cur_block->len = blocks[opno].start_opline - cur_block->start_opline;
- cur_block->next = &blocks[opno];
- /* what is the last OP of previous block? */
- opline = blocks[opno].start_opline - 1;
- if (opline->opcode == ZEND_OP_DATA) {
- opline--;
- }
- switch((unsigned)opline->opcode) {
- case ZEND_RETURN:
- case ZEND_RETURN_BY_REF:
- case ZEND_GENERATOR_RETURN:
- case ZEND_EXIT:
- case ZEND_THROW:
- break;
- case ZEND_FAST_CALL:
- if (opline->extended_value) {
- cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num];
- }
- cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num];
- break;
- case ZEND_FAST_RET:
- if (opline->extended_value) {
- cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num];
- }
- break;
- case ZEND_JMP:
- cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num];
- break;
- case ZEND_DECLARE_ANON_CLASS:
- case ZEND_DECLARE_ANON_INHERITED_CLASS:
- cur_block->op1_to = &blocks[ZEND_OP1(opline).opline_num];
- cur_block->follow_to = &blocks[opno];
- break;
- case ZEND_JMPZNZ:
- cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num];
- cur_block->ext_to = &blocks[opline->extended_value];
- break;
- case ZEND_CATCH:
- cur_block->ext_to = &blocks[opline->extended_value];
- cur_block->follow_to = &blocks[opno];
- break;
- case ZEND_FE_FETCH_R:
- case ZEND_FE_FETCH_RW:
- cur_block->ext_to = &blocks[opline->extended_value];
- cur_block->follow_to = &blocks[opno];
- break;
- case ZEND_JMPZ:
- case ZEND_JMPNZ:
- case ZEND_JMPZ_EX:
- case ZEND_JMPNZ_EX:
- case ZEND_FE_RESET_R:
- case ZEND_FE_RESET_RW:
- case ZEND_NEW:
- case ZEND_JMP_SET:
- case ZEND_COALESCE:
- case ZEND_ASSERT_CHECK:
- cur_block->op2_to = &blocks[ZEND_OP2(opline).opline_num];
- /* break missing intentionally */
- default:
- /* next block follows this */
- cur_block->follow_to = &blocks[opno];
- break;
- }
- print_block(cur_block, op_array->opcodes, "");
- cur_block = cur_block->next;
- }
- }
- cur_block->len = end - cur_block->start_opline;
- cur_block->next = &blocks[op_array->last + 1];
- print_block(cur_block, op_array->opcodes, "");
-
- return 1;
-}
-
/* CFG back references management */
-#define ADD_SOURCE(fromb, tob) { \
- zend_block_source *__s = tob->sources; \
- while (__s && __s->from != fromb) __s = __s->next; \
- if (__s == NULL) { \
- zend_block_source *__t = zend_arena_alloc(&ctx->arena, sizeof(zend_block_source)); \
- __t->next = tob->sources; \
- tob->sources = __t; \
- __t->from = fromb; \
- } \
-}
-
-#define DEL_SOURCE(cs) do { \
- *(cs) = (*(cs))->next; \
- } while (0)
-
-
-static inline void replace_source(zend_block_source *list, zend_code_block *old, zend_code_block *new)
-{
- /* replace all references to 'old' in 'list' with 'new' */
- zend_block_source **cs;
- int found = 0;
-
- for (cs = &list; *cs; cs = &((*cs)->next)) {
- if ((*cs)->from == new) {
- if (found) {
- DEL_SOURCE(cs);
- } else {
- found = 1;
- }
- }
-
- if ((*cs)->from == old) {
- if (found) {
- DEL_SOURCE(cs);
- } else {
- (*cs)->from = new;
- found = 1;
- }
- }
- }
-}
-
-static inline void del_source(zend_code_block *from, zend_code_block *to)
-{
- /* delete source 'from' from 'to'-s sources list */
- zend_block_source **cs = &to->sources;
-
- if (to->sources == NULL) {
- to->access = 0;
- return;
- }
-
- if (from == to) {
- return;
- }
-
- while (*cs) {
- if ((*cs)->from == from) {
- DEL_SOURCE(cs);
- break;
- }
- cs = &((*cs)->next);
- }
-
- if (to->sources == NULL) {
- /* 'to' has no more sources - it's unused, will be stripped */
- to->access = 0;
- return;
- }
-
- if (!to->protected && to->sources->next == NULL) {
- /* source to only one block */
- zend_code_block *from_block = to->sources->from;
-
- if (from_block->access && from_block->follow_to == to &&
- from_block->op1_to == NULL &&
- from_block->op2_to == NULL &&
- from_block->ext_to == NULL) {
- /* this block follows it's only predecessor - we can join them */
- zend_op *new_to = from_block->start_opline + from_block->len;
- if (new_to != to->start_opline) {
- /* move block to new location */
- memmove(new_to, to->start_opline, sizeof(zend_op)*to->len);
- }
- /* join blocks' lengths */
- from_block->len += to->len;
- /* move 'to'`s references to 'from' */
- to->start_opline = NULL;
- to->access = 0;
- to->sources = NULL;
- from_block->follow_to = to->follow_to;
- if (to->op1_to) {
- from_block->op1_to = to->op1_to;
- replace_source(to->op1_to->sources, to, from_block);
- }
- if (to->op2_to) {
- from_block->op2_to = to->op2_to;
- replace_source(to->op2_to->sources, to, from_block);
- }
- if (to->ext_to) {
- from_block->ext_to = to->ext_to;
- replace_source(to->ext_to->sources, to, from_block);
- }
- if (to->follow_to) {
- replace_source(to->follow_to->sources, to, from_block);
- }
- /* remove "to" from list */
- }
- }
-}
-
-static void delete_code_block(zend_code_block *block, zend_optimizer_ctx *ctx)
-{
- if (block->protected) {
- return;
- }
- if (block->follow_to) {
- zend_block_source *bs = block->sources;
- while (bs) {
- zend_code_block *from_block = bs->from;
- zend_code_block *to = block->follow_to;
- if (from_block->op1_to == block) {
- from_block->op1_to = to;
- ADD_SOURCE(from_block, to);
- }
- if (from_block->op2_to == block) {
- from_block->op2_to = to;
- ADD_SOURCE(from_block, to);
- }
- if (from_block->ext_to == block) {
- from_block->ext_to = to;
- ADD_SOURCE(from_block, to);
- }
- if (from_block->follow_to == block) {
- from_block->follow_to = to;
- ADD_SOURCE(from_block, to);
- }
- bs = bs->next;
- }
- }
- block->access = 0;
-}
-
-static void zend_access_path(zend_code_block *block, zend_optimizer_ctx *ctx)
-{
- if (block->access) {
- return;
- }
-
- block->access = 1;
- if (block->op1_to) {
- zend_access_path(block->op1_to, ctx);
- ADD_SOURCE(block, block->op1_to);
- }
- if (block->op2_to) {
- zend_access_path(block->op2_to, ctx);
- ADD_SOURCE(block, block->op2_to);
- }
- if (block->ext_to) {
- zend_access_path(block->ext_to, ctx);
- ADD_SOURCE(block, block->ext_to);
- }
- if (block->follow_to) {
- zend_access_path(block->follow_to, ctx);
- ADD_SOURCE(block, block->follow_to);
- }
-}
-
-/* Traverse CFG, mark reachable basic blocks and build back references */
-static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int find_start, zend_optimizer_ctx *ctx)
-{
- zend_code_block *blocks = cfg->blocks;
- zend_code_block *start = find_start? NULL : blocks;
- zend_code_block *b;
-
- /* Mark all blocks as unaccessible and destroy back references */
- b = blocks;
- while (b != NULL) {
- if (!start && b->access) {
- start = b;
- }
- b->access = 0;
- b->sources = NULL;
- b = b->next;
- }
-
- /* Walk thorough all paths */
- zend_access_path(start, ctx);
-
- /* Add brk/cont paths */
- if (op_array->last_brk_cont) {
- int i;
- for (i=0; i< op_array->last_brk_cont; i++) {
- zend_access_path(cfg->loop_start[i], ctx);
- zend_access_path(cfg->loop_cont[i], ctx);
- zend_access_path(cfg->loop_brk[i], ctx);
- }
- }
-
- /* Add exception paths */
- if (op_array->last_try_catch) {
- int i;
- for (i=0; i< op_array->last_try_catch; i++) {
- if (!cfg->catch[i]->access) {
- zend_access_path(cfg->catch[i], ctx);
- }
- }
- }
-}
+#define DEL_SOURCE(from, to)
+#define ADD_SOURCE(from, to)
/* Data dependencies macros */
@@ -552,8 +81,6 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int
#define VAR_SOURCE(op) Tsource[VAR_NUM(op.var)]
#define SET_VAR_SOURCE(opline) Tsource[VAR_NUM(opline->result.var)] = opline
-#define VAR_UNSET(op) do { if (op ## _type & (IS_TMP_VAR|IS_VAR)) {VAR_SOURCE(op) = NULL;}} while (0)
-
#define convert_to_string_safe(v) \
if (Z_TYPE_P((v)) == IS_NULL) { \
ZVAL_STRINGL((v), "", 0); \
@@ -561,140 +88,181 @@ static void zend_rebuild_access_path(zend_cfg *cfg, zend_op_array *op_array, int
convert_to_string((v)); \
}
-static void strip_nop(zend_code_block *block, zend_optimizer_ctx *ctx)
+static void strip_leading_nops(zend_op_array *op_array, zend_basic_block *b)
{
- zend_op *opline = block->start_opline;
- zend_op *end, *new_end;
+ zend_op *opcodes = op_array->opcodes;
- /* remove leading NOPs */
- while (block->len > 0 && block->start_opline->opcode == ZEND_NOP) {
- if (block->len == 1) {
- /* this block is all NOPs, join with following block */
- if (block->follow_to) {
- delete_code_block(block, ctx);
- }
- return;
- }
- block->start_opline++;
- block->start_opline_no++;
- block->len--;
+ while (opcodes[b->start].opcode == ZEND_NOP && b->start < b->end) {
+ b->start++;
}
+}
- /* strip the inside NOPs */
- opline = new_end = block->start_opline;
- end = opline + block->len;
-
- while (opline < end) {
- zend_op *src;
- int len = 0;
+static void strip_nops(zend_op_array *op_array, zend_basic_block *b)
+{
+ uint32_t i, j;
- while (opline < end && opline->opcode == ZEND_NOP) {
- opline++;
- }
- src = opline;
+ strip_leading_nops(op_array, b);
- while (opline < end && opline->opcode != ZEND_NOP) {
- opline++;
+ /* strip the inside NOPs */
+ i = j = b->start + 1;
+ while (i <= b->end) {
+ if (op_array->opcodes[i].opcode != ZEND_NOP) {
+ if (i != j) {
+ op_array->opcodes[j] = op_array->opcodes[i];
+ }
+ j++;
}
- len = opline - src;
-
- /* move up non-NOP opcodes */
- memmove(new_end, src, len*sizeof(zend_op));
-
- new_end += len;
+ i++;
+ }
+ b->end = j - 1;
+ while (j < i) {
+ MAKE_NOP(op_array->opcodes + j);
+ j++;
}
- block->len = new_end - block->start_opline;
}
-static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array, zend_bitset used_ext, zend_cfg *cfg, zend_optimizer_ctx *ctx)
+static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array, zend_bitset used_ext, zend_cfg *cfg, zend_op **Tsource)
{
- zend_op *opline = block->start_opline;
+ zend_op *opline, *src;
zend_op *end, *last_op = NULL;
- zend_op **Tsource = cfg->Tsource;
-
- print_block(block, op_array->opcodes, "Opt ");
/* remove leading NOPs */
- while (block->len > 0 && block->start_opline->opcode == ZEND_NOP) {
- if (block->len == 1) {
- /* this block is all NOPs, join with following block */
- if (block->follow_to) {
- delete_code_block(block, ctx);
- }
- return;
- }
- block->start_opline++;
- block->start_opline_no++;
- block->len--;
- }
+ strip_leading_nops(op_array, block);
/* we track data dependencies only insight a single basic block */
memset(Tsource, 0, (op_array->last_var + op_array->T) * sizeof(zend_op *));
- opline = block->start_opline;
- end = opline + block->len;
- while ((op_array->T) && (opline < end)) {
- /* strip X = QM_ASSIGN(const) */
- if ((ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
- VAR_SOURCE(opline->op1) &&
- VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN &&
- ZEND_OP1_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST &&
- opline->opcode != ZEND_CASE && /* CASE _always_ expects variable */
- opline->opcode != ZEND_FETCH_LIST &&
- (opline->opcode != ZEND_FE_RESET_R || opline->opcode != ZEND_FE_RESET_RW) &&
- opline->opcode != ZEND_FREE
- ) {
- znode_op op1 = opline->op1;
- zend_op *src = VAR_SOURCE(op1);
- zval c = ZEND_OP1_LITERAL(src);
- zval_copy_ctor(&c);
- if (zend_optimizer_update_op1_const(op_array, opline, &c)) {
- VAR_SOURCE(op1) = NULL;
- literal_dtor(&ZEND_OP1_LITERAL(src));
- MAKE_NOP(src);
+ opline = op_array->opcodes + block->start;
+ end = op_array->opcodes + block->end + 1;
+ while (opline < end) {
+
+ /* Constant Propagation: strip X = QM_ASSIGN(const) */
+ if ((opline->op1_type & (IS_TMP_VAR|IS_VAR)) &&
+ opline->opcode != ZEND_FREE) {
+ src = VAR_SOURCE(opline->op1);
+ if (src &&
+ src->opcode == ZEND_QM_ASSIGN &&
+ src->op1_type == IS_CONST) {
+
+ znode_op op1 = opline->op1;
+ zval c = ZEND_OP1_LITERAL(src);
+
+ zval_copy_ctor(&c);
+ if (zend_optimizer_update_op1_const(op_array, opline, &c)) {
+ zend_optimizer_remove_live_range(op_array, op1.var);
+ VAR_SOURCE(op1) = NULL;
+ literal_dtor(&ZEND_OP1_LITERAL(src));
+ MAKE_NOP(src);
+ }
}
}
- /* T = QM_ASSIGN(C), F(T) => NOP, F(C) */
- if ((ZEND_OP2_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
- VAR_SOURCE(opline->op2) &&
- VAR_SOURCE(opline->op2)->opcode == ZEND_QM_ASSIGN &&
- ZEND_OP1_TYPE(VAR_SOURCE(opline->op2)) == IS_CONST) {
- znode_op op2 = opline->op2;
- zend_op *src = VAR_SOURCE(op2);
- zval c = ZEND_OP1_LITERAL(src);
- zval_copy_ctor(&c);
- if (zend_optimizer_update_op2_const(op_array, opline, &c)) {
- VAR_SOURCE(op2) = NULL;
- literal_dtor(&ZEND_OP1_LITERAL(src));
- MAKE_NOP(src);
+ /* Constant Propagation: strip X = QM_ASSIGN(const) */
+ if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
+ src = VAR_SOURCE(opline->op2);
+ if (src &&
+ src->opcode == ZEND_QM_ASSIGN &&
+ src->op1_type == IS_CONST) {
+
+ znode_op op2 = opline->op2;
+ zval c = ZEND_OP1_LITERAL(src);
+
+ zval_copy_ctor(&c);
+ if (zend_optimizer_update_op2_const(op_array, opline, &c)) {
+ zend_optimizer_remove_live_range(op_array, op2.var);
+ VAR_SOURCE(op2) = NULL;
+ literal_dtor(&ZEND_OP1_LITERAL(src));
+ MAKE_NOP(src);
+ }
}
}
- /* T = CAST(X, String), ECHO(T) => NOP, ECHO(X) */
- if (opline->opcode == ZEND_ECHO &&
- ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR) &&
- VAR_SOURCE(opline->op1) &&
- VAR_SOURCE(opline->op1)->opcode == ZEND_CAST &&
- VAR_SOURCE(opline->op1)->extended_value == IS_STRING) {
- zend_op *src = VAR_SOURCE(opline->op1);
- COPY_NODE(opline->op1, src->op1);
- MAKE_NOP(src);
- }
+ if (opline->opcode == ZEND_ECHO) {
+ if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
+ src = VAR_SOURCE(opline->op1);
+ if (src &&
+ src->opcode == ZEND_CAST &&
+ src->extended_value == IS_STRING) {
+ /* T = CAST(X, String), ECHO(T) => NOP, ECHO(X) */
+ VAR_SOURCE(opline->op1) = NULL;
+ COPY_NODE(opline->op1, src->op1);
+ MAKE_NOP(src);
+ }
+ }
- /* T = BOOL(X), FREE(T) => NOP */
- if (opline->opcode == ZEND_FREE &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
- VAR_SOURCE(opline->op1)) {
- zend_op *src = VAR_SOURCE(opline->op1);
- if (src->opcode == ZEND_BOOL) {
- if (ZEND_OP1_TYPE(src) == IS_CONST) {
- literal_dtor(&ZEND_OP1_LITERAL(src));
+ if (opline->op1_type == IS_CONST) {
+ if (last_op && last_op->opcode == ZEND_ECHO &&
+ last_op->op1_type == IS_CONST &&
+ Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_DOUBLE &&
+ Z_TYPE(ZEND_OP1_LITERAL(last_op)) != IS_DOUBLE) {
+ /* compress consecutive ECHO's.
+ * Float to string conversion may be affected by current
+ * locale setting.
+ */
+ int l, old_len;
+
+ if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_STRING) {
+ convert_to_string_safe(&ZEND_OP1_LITERAL(opline));
+ }
+ if (Z_TYPE(ZEND_OP1_LITERAL(last_op)) != IS_STRING) {
+ convert_to_string_safe(&ZEND_OP1_LITERAL(last_op));
+ }
+ old_len = Z_STRLEN(ZEND_OP1_LITERAL(last_op));
+ 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);
+ 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);
+ }
+ Z_TYPE_INFO(ZEND_OP1_LITERAL(last_op)) = IS_STRING_EX;
+ 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_NULL(&ZEND_OP1_LITERAL(last_op));
+ MAKE_NOP(last_op);
}
- MAKE_NOP(src);
- MAKE_NOP(opline);
+ last_op = opline;
+ } else {
+ last_op = NULL;
}
+ } else {
+ last_op = NULL;
}
+ switch (opline->opcode) {
+
+ case ZEND_FREE:
+ if (opline->op1_type == IS_TMP_VAR) {
+ src = VAR_SOURCE(opline->op1);
+ if (src &&
+ (src->opcode == ZEND_BOOL || src->opcode == ZEND_BOOL_NOT)) {
+ /* T = BOOL(X), FREE(T) => NOP */
+ if (ZEND_OP1_TYPE(src) == IS_CONST) {
+ literal_dtor(&ZEND_OP1_LITERAL(src));
+ }
+ VAR_SOURCE(opline->op1) = NULL;
+ MAKE_NOP(src);
+ MAKE_NOP(opline);
+ }
+ } else if (opline->op1_type == IS_VAR) {
+ src = VAR_SOURCE(opline->op1);
+ /* V = OP, FREE(V) => OP. NOP */
+ if (src &&
+ src->opcode != ZEND_FETCH_R &&
+ src->opcode != ZEND_FETCH_STATIC_PROP_R &&
+ src->opcode != ZEND_FETCH_DIM_R &&
+ src->opcode != ZEND_FETCH_OBJ_R) {
+ ZEND_RESULT_TYPE(src) |= EXT_TYPE_UNUSED;
+ MAKE_NOP(opline);
+ }
+ }
+ break;
+
#if 0
/* pre-evaluate functions:
constant(x)
@@ -758,481 +326,618 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
}
#endif
- /* IS_EQ(TRUE, X) => BOOL(X)
- * IS_EQ(FALSE, X) => BOOL_NOT(X)
- * IS_NOT_EQ(TRUE, X) => BOOL_NOT(X)
- * IS_NOT_EQ(FALSE, X) => BOOL(X)
- * CASE(TRUE, X) => BOOL(X)
- * CASE(FALSE, X) => BOOL_NOT(X)
- */
- if (opline->opcode == ZEND_IS_EQUAL ||
- opline->opcode == ZEND_IS_NOT_EQUAL ||
- /* CASE variable will be deleted later by FREE, so we can't optimize it */
- (opline->opcode == ZEND_CASE && (ZEND_OP1_TYPE(opline) & (IS_CONST|IS_CV)))) {
- if (ZEND_OP1_TYPE(opline) == IS_CONST &&
- (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_FALSE ||
- Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_TRUE)) {
- /* T = IS_EQUAL(TRUE, X) => T = BOOL(X) */
- /* T = IS_EQUAL(FALSE, X) => T = BOOL_NOT(X) */
- /* T = IS_NOT_EQUAL(TRUE, X) => T = BOOL_NOT(X) */
- /* T = IS_NOT_EQUAL(FALSE, X) => T = BOOL(X) */
- /* Optimization of comparison with "null" is not safe,
- * because ("0" == null) is not equal to !("0")
- */
- opline->opcode =
- ((opline->opcode != ZEND_IS_NOT_EQUAL) == ((Z_TYPE(ZEND_OP1_LITERAL(opline))) == IS_TRUE)) ?
- ZEND_BOOL : ZEND_BOOL_NOT;
- COPY_NODE(opline->op1, opline->op2);
- SET_UNUSED(opline->op2);
- } else if (ZEND_OP2_TYPE(opline) == IS_CONST &&
- (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_FALSE ||
- Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_TRUE)) {
- /* T = IS_EQUAL(X, TRUE) => T = BOOL(X) */
- /* T = IS_EQUAL(X, FALSE) => T = BOOL_NOT(X) */
- /* T = IS_NOT_EQUAL(X, TRUE) => T = BOOL_NOT(X) */
- /* T = IS_NOT_EQUAL(X, FALSE) => T = BOOL(X) */
- /* Optimization of comparison with "null" is not safe,
- * because ("0" == null) is not equal to !("0")
- */
- opline->opcode =
- ((opline->opcode != ZEND_IS_NOT_EQUAL) == ((Z_TYPE(ZEND_OP2_LITERAL(opline))) == IS_TRUE)) ?
- ZEND_BOOL : ZEND_BOOL_NOT;
- SET_UNUSED(opline->op2);
- }
- }
-
- if ((opline->opcode == ZEND_BOOL ||
- opline->opcode == ZEND_BOOL_NOT ||
- opline->opcode == ZEND_JMPZ ||
- opline->opcode == ZEND_JMPNZ ||
- opline->opcode == ZEND_JMPZNZ) &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
- VAR_SOURCE(opline->op1) != NULL &&
- !zend_bitset_in(used_ext, VAR_NUM(ZEND_OP1(opline).var)) &&
- VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL_NOT) {
- /* T = BOOL_NOT(X) + JMPZ(T) -> NOP, JMPNZ(X) */
- zend_op *src = VAR_SOURCE(opline->op1);
-
- COPY_NODE(opline->op1, src->op1);
-
- switch (opline->opcode) {
- case ZEND_BOOL:
- /* T = BOOL_NOT(X) + BOOL(T) -> NOP, BOOL_NOT(X) */
- opline->opcode = ZEND_BOOL_NOT;
- break;
- case ZEND_BOOL_NOT:
- /* T = BOOL_NOT(X) + BOOL_BOOL(T) -> NOP, BOOL(X) */
- opline->opcode = ZEND_BOOL;
+ case ZEND_CASE:
+ if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
+ /* CASE variable will be deleted later by FREE, so we can't optimize it */
break;
- case ZEND_JMPZ:
- /* T = BOOL_NOT(X) + JMPZ(T,L) -> NOP, JMPNZ(X,L) */
- opline->opcode = ZEND_JMPNZ;
- break;
- case ZEND_JMPNZ:
- /* T = BOOL_NOT(X) + JMPNZ(T,L) -> NOP, JMPZ(X,L) */
- opline->opcode = ZEND_JMPZ;
+ }
+ if (opline->op1_type == IS_CONST &&
+ opline->op2_type == IS_CONST) {
break;
- case ZEND_JMPZNZ:
- {
- /* T = BOOL_NOT(X) + JMPZNZ(T,L1,L2) -> NOP, JMPZNZ(X,L2,L1) */
- int op_t;
- zend_code_block *op_b;
-
- op_t = opline->extended_value;
- opline->extended_value = ZEND_OP2(opline).opline_num;
- ZEND_OP2(opline).opline_num = op_t;
-
- op_b = block->ext_to;
- block->ext_to = block->op2_to;
- block->op2_to = op_b;
+ }
+ /* break missing intentionally */
+
+ case ZEND_IS_EQUAL:
+ case ZEND_IS_NOT_EQUAL:
+ if (opline->op1_type == IS_CONST &&
+ opline->op2_type == IS_CONST) {
+ goto optimize_constant_binary_op;
+ }
+ /* IS_EQ(TRUE, X) => BOOL(X)
+ * IS_EQ(FALSE, X) => BOOL_NOT(X)
+ * IS_NOT_EQ(TRUE, X) => BOOL_NOT(X)
+ * IS_NOT_EQ(FALSE, X) => BOOL(X)
+ * CASE(TRUE, X) => BOOL(X)
+ * CASE(FALSE, X) => BOOL_NOT(X)
+ */
+ if (opline->op1_type == IS_CONST &&
+ (Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_FALSE ||
+ Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_TRUE)) {
+ /* Optimization of comparison with "null" is not safe,
+ * because ("0" == null) is not equal to !("0")
+ */
+ opline->opcode =
+ ((opline->opcode != ZEND_IS_NOT_EQUAL) == ((Z_TYPE(ZEND_OP1_LITERAL(opline))) == IS_TRUE)) ?
+ ZEND_BOOL : ZEND_BOOL_NOT;
+ COPY_NODE(opline->op1, opline->op2);
+ SET_UNUSED(opline->op2);
+ goto optimize_bool;
+ } else if (opline->op2_type == IS_CONST &&
+ (Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_FALSE ||
+ Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_TRUE)) {
+ /* Optimization of comparison with "null" is not safe,
+ * because ("0" == null) is not equal to !("0")
+ */
+ opline->opcode =
+ ((opline->opcode != ZEND_IS_NOT_EQUAL) == ((Z_TYPE(ZEND_OP2_LITERAL(opline))) == IS_TRUE)) ?
+ ZEND_BOOL : ZEND_BOOL_NOT;
+ SET_UNUSED(opline->op2);
+ goto optimize_bool;
}
break;
- }
- VAR_UNSET(opline->op1);
- MAKE_NOP(src);
- continue;
- } else
+ case ZEND_BOOL:
+ case ZEND_BOOL_NOT:
+ optimize_bool:
+ if (opline->op1_type == IS_CONST) {
+ goto optimize_const_unary_op;
+ }
+ if (opline->op1_type == IS_TMP_VAR &&
+ !zend_bitset_in(used_ext, VAR_NUM(opline->op1.var))) {
+ src = VAR_SOURCE(opline->op1);
+ if (src) {
+ switch (src->opcode) {
+ case ZEND_BOOL_NOT:
+ /* T = BOOL_NOT(X) + BOOL(T) -> NOP, BOOL_NOT(X) */
+ VAR_SOURCE(opline->op1) = NULL;
+ COPY_NODE(opline->op1, src->op1);
+ opline->opcode = (opline->opcode == ZEND_BOOL) ? ZEND_BOOL_NOT : ZEND_BOOL;
+ MAKE_NOP(src);
+ goto optimize_bool;
+ case ZEND_BOOL:
+ /* T = BOOL(X) + BOOL(T) -> NOP, BOOL(X) */
+ VAR_SOURCE(opline->op1) = NULL;
+ COPY_NODE(opline->op1, src->op1);
+ MAKE_NOP(src);
+ goto optimize_bool;
+ case ZEND_IS_EQUAL:
+ if (opline->opcode == ZEND_BOOL_NOT) {
+ src->opcode = ZEND_IS_NOT_EQUAL;
+ }
+ COPY_NODE(src->result, opline->result);
+ SET_VAR_SOURCE(src);
+ MAKE_NOP(opline);
+ break;
+ case ZEND_IS_NOT_EQUAL:
+ if (opline->opcode == ZEND_BOOL_NOT) {
+ src->opcode = ZEND_IS_EQUAL;
+ }
+ COPY_NODE(src->result, opline->result);
+ SET_VAR_SOURCE(src);
+ MAKE_NOP(opline);
+ break;
+ case ZEND_IS_IDENTICAL:
+ if (opline->opcode == ZEND_BOOL_NOT) {
+ src->opcode = ZEND_IS_NOT_IDENTICAL;
+ }
+ COPY_NODE(src->result, opline->result);
+ SET_VAR_SOURCE(src);
+ MAKE_NOP(opline);
+ break;
+ case ZEND_IS_NOT_IDENTICAL:
+ if (opline->opcode == ZEND_BOOL_NOT) {
+ src->opcode = ZEND_IS_IDENTICAL;
+ }
+ COPY_NODE(src->result, opline->result);
+ SET_VAR_SOURCE(src);
+ MAKE_NOP(opline);
+ break;
+ case ZEND_IS_SMALLER:
+ if (opline->opcode == ZEND_BOOL_NOT) {
+ zend_uchar tmp_type;
+ uint32_t tmp;
+
+ src->opcode = ZEND_IS_SMALLER_OR_EQUAL;
+ tmp_type = src->op1_type;
+ src->op1_type = src->op2_type;
+ src->op2_type = tmp_type;
+ tmp = src->op1.num;
+ src->op1.num = src->op2.num;
+ src->op2.num = tmp;
+ }
+ COPY_NODE(src->result, opline->result);
+ SET_VAR_SOURCE(src);
+ MAKE_NOP(opline);
+ break;
+ case ZEND_IS_SMALLER_OR_EQUAL:
+ if (opline->opcode == ZEND_BOOL_NOT) {
+ zend_uchar tmp_type;
+ uint32_t tmp;
+
+ src->opcode = ZEND_IS_SMALLER;
+ tmp_type = src->op1_type;
+ src->op1_type = src->op2_type;
+ src->op2_type = tmp_type;
+ tmp = src->op1.num;
+ src->op1.num = src->op2.num;
+ src->op2.num = tmp;
+ }
+ COPY_NODE(src->result, opline->result);
+ SET_VAR_SOURCE(src);
+ MAKE_NOP(opline);
+ break;
+ case ZEND_ISSET_ISEMPTY_VAR:
+ case ZEND_ISSET_ISEMPTY_DIM_OBJ:
+ case ZEND_ISSET_ISEMPTY_PROP_OBJ:
+ case ZEND_ISSET_ISEMPTY_STATIC_PROP:
+ case ZEND_INSTANCEOF:
+ case ZEND_TYPE_CHECK:
+ case ZEND_DEFINED:
+ if (opline->opcode == ZEND_BOOL_NOT) {
+ break;
+ }
+ COPY_NODE(src->result, opline->result);
+ SET_VAR_SOURCE(src);
+ MAKE_NOP(opline);
+ break;
+ }
+ }
+ }
+ break;
+
+ case ZEND_JMPZ:
+ case ZEND_JMPNZ:
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+ case ZEND_JMPZNZ:
+ optimize_jmpznz:
+ if (opline->op1_type == IS_TMP_VAR &&
+ (!zend_bitset_in(used_ext, VAR_NUM(opline->op1.var)) ||
+ (opline->result_type == opline->op1_type &&
+ opline->result.var == opline->op1.var))) {
+ src = VAR_SOURCE(opline->op1);
+ if (src) {
+ if (src->opcode == ZEND_BOOL_NOT &&
+ opline->opcode != ZEND_JMPZ_EX &&
+ opline->opcode != ZEND_JMPNZ_EX) {
+ VAR_SOURCE(opline->op1) = NULL;
+ COPY_NODE(opline->op1, src->op1);
+ if (opline->opcode == ZEND_JMPZ) {
+ /* T = BOOL_NOT(X) + JMPZ(T) -> NOP, JMPNZ(X) */
+ opline->opcode = ZEND_JMPNZ;
+ } else if (opline->opcode == ZEND_JMPNZ) {
+ /* T = BOOL_NOT(X) + JMPNZ(T) -> NOP, JMPZ(X) */
+ opline->opcode = ZEND_JMPZ;
#if 0
- /* T = BOOL_NOT(X) + T = JMPZ_EX(T, X) -> T = BOOL_NOT(X), JMPNZ(X) */
- if(0 && (opline->opcode == ZEND_JMPZ_EX ||
- opline->opcode == ZEND_JMPNZ_EX) &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
- VAR_SOURCE(opline->op1) != NULL &&
- VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL_NOT &&
- ZEND_OP1(opline).var == ZEND_RESULT(opline).var
- ) {
- zend_op *src = VAR_SOURCE(opline->op1);
- if(opline->opcode == ZEND_JMPZ_EX) {
- opline->opcode = ZEND_JMPNZ;
- } else {
- opline->opcode = ZEND_JMPZ;
- }
- COPY_NODE(opline->op1, src->op1);
- SET_UNUSED(opline->result);
- continue;
- } else
+ } else if (opline->opcode == ZEND_JMPZ_EX) {
+ /* T = BOOL_NOT(X) + JMPZ_EX(T) -> NOP, JMPNZ_EX(X) */
+ opline->opcode = ZEND_JMPNZ_EX;
+ } else if (opline->opcode == ZEND_JMPNZ_EX) {
+ /* T = BOOL_NOT(X) + JMPNZ_EX(T) -> NOP, JMPZ_EX(X) */
+ opline->opcode = ZEND_JMPZ;
#endif
- /* T = BOOL(X) + JMPZ(T) -> NOP, JMPZ(X) */
- if ((opline->opcode == ZEND_BOOL ||
- opline->opcode == ZEND_BOOL_NOT ||
- opline->opcode == ZEND_JMPZ ||
- opline->opcode == ZEND_JMPZ_EX ||
- opline->opcode == ZEND_JMPNZ_EX ||
- opline->opcode == ZEND_JMPNZ ||
- opline->opcode == ZEND_JMPZNZ) &&
- (ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
- VAR_SOURCE(opline->op1) != NULL &&
- (!zend_bitset_in(used_ext, VAR_NUM(ZEND_OP1(opline).var)) ||
- ((ZEND_RESULT_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
- ZEND_RESULT(opline).var == ZEND_OP1(opline).var)) &&
- (VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN)) {
- zend_op *src = VAR_SOURCE(opline->op1);
- COPY_NODE(opline->op1, src->op1);
-
- VAR_UNSET(opline->op1);
- MAKE_NOP(src);
- continue;
- } else if (last_op && opline->opcode == ZEND_ECHO &&
- last_op->opcode == ZEND_ECHO &&
- ZEND_OP1_TYPE(opline) == IS_CONST &&
- Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_DOUBLE &&
- ZEND_OP1_TYPE(last_op) == IS_CONST &&
- Z_TYPE(ZEND_OP1_LITERAL(last_op)) != IS_DOUBLE) {
- /* compress consecutive ECHO's.
- * Float to string conversion may be affected by current
- * locale setting.
- */
- int l, old_len;
-
- if (Z_TYPE(ZEND_OP1_LITERAL(opline)) != IS_STRING) {
- convert_to_string_safe(&ZEND_OP1_LITERAL(opline));
- }
- if (Z_TYPE(ZEND_OP1_LITERAL(last_op)) != IS_STRING) {
- convert_to_string_safe(&ZEND_OP1_LITERAL(last_op));
- }
- old_len = Z_STRLEN(ZEND_OP1_LITERAL(last_op));
- 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);
- 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);
- }
- Z_TYPE_INFO(ZEND_OP1_LITERAL(last_op)) = IS_STRING_EX;
- 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_NULL(&ZEND_OP1_LITERAL(last_op));
- MAKE_NOP(last_op);
- } else if ((opline->opcode == ZEND_CONCAT) &&
- ZEND_OP2_TYPE(opline) == IS_CONST &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
- VAR_SOURCE(opline->op1) &&
- (VAR_SOURCE(opline->op1)->opcode == ZEND_CONCAT ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_FAST_CONCAT) &&
- ZEND_OP2_TYPE(VAR_SOURCE(opline->op1)) == IS_CONST &&
- ZEND_RESULT(VAR_SOURCE(opline->op1)).var == ZEND_OP1(opline).var) {
- /* compress consecutive CONCAT/ADD_STRING/ADD_CHARs */
- zend_op *src = VAR_SOURCE(opline->op1);
- int l, old_len;
-
- if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
- convert_to_string_safe(&ZEND_OP2_LITERAL(opline));
- }
- if (Z_TYPE(ZEND_OP2_LITERAL(src)) != IS_STRING) {
- convert_to_string_safe(&ZEND_OP2_LITERAL(src));
- }
+ } else {
+ /* T = BOOL_NOT(X) + JMPZNZ(T,L1,L2) -> NOP, JMPZNZ(X,L2,L1) */
+ uint32_t tmp;
+
+ ZEND_ASSERT(opline->opcode == ZEND_JMPZNZ);
+ tmp = block->successors[0];
+ block->successors[0] = block->successors[1];
+ block->successors[1] = tmp;
+ }
+ MAKE_NOP(src);
+ goto optimize_jmpznz;
+ } else if (src->opcode == ZEND_BOOL ||
+ src->opcode == ZEND_QM_ASSIGN) {
+ VAR_SOURCE(opline->op1) = NULL;
+ COPY_NODE(opline->op1, src->op1);
+ MAKE_NOP(src);
+ goto optimize_jmpznz;
+ }
+ }
+ }
+ break;
- VAR_UNSET(opline->op1);
- COPY_NODE(opline->op1, src->op1);
- old_len = Z_STRLEN(ZEND_OP2_LITERAL(src));
- l = old_len + Z_STRLEN(ZEND_OP2_LITERAL(opline));
- if (!Z_REFCOUNTED(ZEND_OP2_LITERAL(src))) {
- zend_string *tmp = zend_string_alloc(l, 0);
- memcpy(ZSTR_VAL(tmp), Z_STRVAL(ZEND_OP2_LITERAL(src)), old_len);
- Z_STR(ZEND_OP2_LITERAL(last_op)) = tmp;
- } else {
- Z_STR(ZEND_OP2_LITERAL(src)) = zend_string_extend(Z_STR(ZEND_OP2_LITERAL(src)), l, 0);
- }
- Z_TYPE_INFO(ZEND_OP2_LITERAL(last_op)) = IS_STRING_EX;
- 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_NULL(&ZEND_OP2_LITERAL(src));
- MAKE_NOP(src);
- } else if ((opline->opcode == ZEND_ADD ||
- opline->opcode == ZEND_SUB ||
- opline->opcode == ZEND_MUL ||
- opline->opcode == ZEND_DIV ||
- opline->opcode == ZEND_MOD ||
- opline->opcode == ZEND_SL ||
- opline->opcode == ZEND_SR ||
- opline->opcode == ZEND_CONCAT ||
- opline->opcode == ZEND_FAST_CONCAT ||
- opline->opcode == ZEND_IS_EQUAL ||
- opline->opcode == ZEND_IS_NOT_EQUAL ||
- opline->opcode == ZEND_IS_SMALLER ||
- opline->opcode == ZEND_IS_SMALLER_OR_EQUAL ||
- opline->opcode == ZEND_IS_IDENTICAL ||
- opline->opcode == ZEND_IS_NOT_IDENTICAL ||
- opline->opcode == ZEND_BOOL_XOR ||
- opline->opcode == ZEND_BW_OR ||
- opline->opcode == ZEND_BW_AND ||
- opline->opcode == ZEND_BW_XOR) &&
- ZEND_OP1_TYPE(opline)==IS_CONST &&
- ZEND_OP2_TYPE(opline)==IS_CONST) {
- /* evaluate constant expressions */
- binary_op_type binary_op = get_binary_op(opline->opcode);
- zval result;
- int er;
-
- if ((opline->opcode == ZEND_DIV || opline->opcode == ZEND_MOD) &&
- zval_get_long(&ZEND_OP2_LITERAL(opline)) == 0) {
- if (RESULT_USED(opline)) {
- SET_VAR_SOURCE(opline);
+ case ZEND_CONCAT:
+ case ZEND_FAST_CONCAT:
+ if (opline->op1_type == IS_CONST &&
+ opline->op2_type == IS_CONST) {
+ goto optimize_constant_binary_op;
+ }
+
+ if (opline->op2_type == IS_CONST &&
+ opline->op1_type == IS_TMP_VAR) {
+
+ src = VAR_SOURCE(opline->op1);
+ if (src &&
+ (src->opcode == ZEND_CONCAT ||
+ src->opcode == ZEND_FAST_CONCAT) &&
+ src->op2_type == IS_CONST) {
+ /* compress consecutive CONCATs */
+ int l, old_len;
+
+ if (Z_TYPE(ZEND_OP2_LITERAL(opline)) != IS_STRING) {
+ convert_to_string_safe(&ZEND_OP2_LITERAL(opline));
+ }
+ if (Z_TYPE(ZEND_OP2_LITERAL(src)) != IS_STRING) {
+ convert_to_string_safe(&ZEND_OP2_LITERAL(src));
+ }
+
+ VAR_SOURCE(opline->op1) = NULL;
+ COPY_NODE(opline->op1, src->op1);
+ old_len = Z_STRLEN(ZEND_OP2_LITERAL(src));
+ l = old_len + Z_STRLEN(ZEND_OP2_LITERAL(opline));
+ if (!Z_REFCOUNTED(ZEND_OP2_LITERAL(src))) {
+ zend_string *tmp = zend_string_alloc(l, 0);
+ memcpy(ZSTR_VAL(tmp), Z_STRVAL(ZEND_OP2_LITERAL(src)), old_len);
+ Z_STR(ZEND_OP2_LITERAL(src)) = tmp;
+ } else {
+ Z_STR(ZEND_OP2_LITERAL(src)) = zend_string_extend(Z_STR(ZEND_OP2_LITERAL(src)), l, 0);
+ }
+ Z_TYPE_INFO(ZEND_OP2_LITERAL(src)) = IS_STRING_EX;
+ 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_NULL(&ZEND_OP2_LITERAL(src));
+ MAKE_NOP(src);
+ }
}
- opline++;
- continue;
- } else if ((opline->opcode == ZEND_SL || opline->opcode == ZEND_SR) &&
- zval_get_long(&ZEND_OP2_LITERAL(opline)) < 0) {
- if (RESULT_USED(opline)) {
- SET_VAR_SOURCE(opline);
+
+ if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
+ src = VAR_SOURCE(opline->op1);
+ if (src &&
+ src->opcode == ZEND_CAST &&
+ src->extended_value == IS_STRING) {
+ /* convert T1 = CAST(STRING, X), T2 = CONCAT(T1, Y) to T2 = CONCAT(X,Y) */
+ VAR_SOURCE(opline->op1) = NULL;
+ COPY_NODE(opline->op1, src->op1);
+ MAKE_NOP(src);
+ }
+ }
+ if (opline->op2_type & (IS_TMP_VAR|IS_VAR)) {
+ src = VAR_SOURCE(opline->op2);
+ if (src &&
+ src->opcode == ZEND_CAST &&
+ src->extended_value == IS_STRING) {
+ /* convert T1 = CAST(STRING, X), T2 = CONCAT(Y, T1) to T2 = CONCAT(Y,X) */
+ zend_op *src = VAR_SOURCE(opline->op2);
+ VAR_SOURCE(opline->op2) = NULL;
+ COPY_NODE(opline->op2, src->op1);
+ MAKE_NOP(src);
+ }
}
- opline++;
- continue;
- }
- er = EG(error_reporting);
- EG(error_reporting) = 0;
- if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) == SUCCESS) {
- literal_dtor(&ZEND_OP1_LITERAL(opline));
- literal_dtor(&ZEND_OP2_LITERAL(opline));
- opline->opcode = ZEND_QM_ASSIGN;
- SET_UNUSED(opline->op2);
- zend_optimizer_update_op1_const(op_array, opline, &result);
- }
- EG(error_reporting) = er;
- } else if ((opline->opcode == ZEND_BOOL ||
- opline->opcode == ZEND_BOOL_NOT ||
- opline->opcode == ZEND_BW_NOT) && ZEND_OP1_TYPE(opline) == IS_CONST) {
- /* evaluate constant unary ops */
- unary_op_type unary_op = get_unary_op(opline->opcode);
- zval result;
-
- if (unary_op) {
- unary_op(&result, &ZEND_OP1_LITERAL(opline));
- literal_dtor(&ZEND_OP1_LITERAL(opline));
- } else {
- /* BOOL */
- result = ZEND_OP1_LITERAL(opline);
- convert_to_boolean(&result);
- ZVAL_NULL(&ZEND_OP1_LITERAL(opline));
- }
- opline->opcode = ZEND_QM_ASSIGN;
- zend_optimizer_update_op1_const(op_array, opline, &result);
- } else if ((opline->opcode == ZEND_RETURN || opline->opcode == ZEND_EXIT) &&
- (ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
- VAR_SOURCE(opline->op1) &&
- VAR_SOURCE(opline->op1)->opcode == ZEND_QM_ASSIGN) {
- /* T = QM_ASSIGN(X), RETURN(T) to RETURN(X) */
- zend_op *src = VAR_SOURCE(opline->op1);
- VAR_UNSET(opline->op1);
- COPY_NODE(opline->op1, src->op1);
- MAKE_NOP(src);
- } else if (opline->opcode == ZEND_CONCAT || opline->opcode == ZEND_FAST_CONCAT) {
- if ((ZEND_OP1_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
- VAR_SOURCE(opline->op1) &&
- VAR_SOURCE(opline->op1)->opcode == ZEND_CAST &&
- VAR_SOURCE(opline->op1)->extended_value == IS_STRING) {
- /* convert T1 = CAST(STRING, X), T2 = CONCAT(T1, Y) to T2 = CONCAT(X,Y) */
- zend_op *src = VAR_SOURCE(opline->op1);
- VAR_UNSET(opline->op1);
- COPY_NODE(opline->op1, src->op1);
- MAKE_NOP(src);
- }
- if ((ZEND_OP2_TYPE(opline) & (IS_TMP_VAR|IS_VAR)) &&
- VAR_SOURCE(opline->op2) &&
- VAR_SOURCE(opline->op2)->opcode == ZEND_CAST &&
- VAR_SOURCE(opline->op2)->extended_value == IS_STRING) {
- /* convert T1 = CAST(STRING, X), T2 = CONCAT(Y, T1) to T2 = CONCAT(Y,X) */
- zend_op *src = VAR_SOURCE(opline->op2);
- VAR_UNSET(opline->op2);
- COPY_NODE(opline->op2, src->op1);
- MAKE_NOP(src);
- }
- if (ZEND_OP1_TYPE(opline) == IS_CONST &&
- Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
- Z_STRLEN(ZEND_OP1_LITERAL(opline)) == 0) {
- /* convert CONCAT('', X) => CAST(STRING, X) */
- literal_dtor(&ZEND_OP1_LITERAL(opline));
- opline->opcode = ZEND_CAST;
- opline->extended_value = IS_STRING;
- COPY_NODE(opline->op1, opline->op2);
- opline->op2_type = IS_UNUSED;
- opline->op2.var = 0;
- } else if (ZEND_OP2_TYPE(opline) == IS_CONST &&
+ if (opline->op1_type == IS_CONST &&
+ Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
+ Z_STRLEN(ZEND_OP1_LITERAL(opline)) == 0) {
+ /* convert CONCAT('', X) => CAST(STRING, X) */
+ literal_dtor(&ZEND_OP1_LITERAL(opline));
+ opline->opcode = ZEND_CAST;
+ opline->extended_value = IS_STRING;
+ COPY_NODE(opline->op1, opline->op2);
+ opline->op2_type = IS_UNUSED;
+ opline->op2.var = 0;
+ } else if (opline->op2_type == IS_CONST &&
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
Z_STRLEN(ZEND_OP2_LITERAL(opline)) == 0) {
- /* convert CONCAT(X, '') => CAST(STRING, X) */
- literal_dtor(&ZEND_OP2_LITERAL(opline));
- opline->opcode = ZEND_CAST;
- opline->extended_value = IS_STRING;
- opline->op2_type = IS_UNUSED;
- opline->op2.var = 0;
- } else if (opline->opcode == ZEND_CONCAT &&
- (opline->op1_type == IS_CONST ||
- (opline->op1_type == IS_TMP_VAR &&
- VAR_SOURCE(opline->op1) &&
- (VAR_SOURCE(opline->op1)->opcode == ZEND_FAST_CONCAT ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_ROPE_END ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_FETCH_CONSTANT))) &&
- (opline->op2_type == IS_CONST ||
- (opline->op2_type == IS_TMP_VAR &&
- VAR_SOURCE(opline->op2) &&
- (VAR_SOURCE(opline->op2)->opcode == ZEND_FAST_CONCAT ||
- VAR_SOURCE(opline->op2)->opcode == ZEND_ROPE_END ||
- VAR_SOURCE(opline->op2)->opcode == ZEND_FETCH_CONSTANT)))) {
- opline->opcode = ZEND_FAST_CONCAT;
- }
- } else if (opline->opcode == ZEND_QM_ASSIGN &&
- ZEND_OP1_TYPE(opline) == ZEND_RESULT_TYPE(opline) &&
- ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
- /* strip T = QM_ASSIGN(T) */
- MAKE_NOP(opline);
- } else if (opline->opcode == ZEND_BOOL &&
- ZEND_OP1_TYPE(opline) == IS_TMP_VAR &&
- VAR_SOURCE(opline->op1) &&
- (VAR_SOURCE(opline->op1)->opcode == ZEND_IS_EQUAL ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_IS_NOT_EQUAL ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_IS_SMALLER ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_IS_SMALLER_OR_EQUAL ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_BOOL ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_IS_IDENTICAL ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_IS_NOT_IDENTICAL ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_ISSET_ISEMPTY_VAR ||
- VAR_SOURCE(opline->op1)->opcode == ZEND_ISSET_ISEMPTY_DIM_OBJ) &&
- !zend_bitset_in(used_ext, VAR_NUM(ZEND_OP1(opline).var))) {
- /* T = IS_SMALLER(X, Y), T1 = BOOL(T) => T = IS_SMALLER(X, Y), T1 = QM_ASSIGN(T) */
- zend_op *src = VAR_SOURCE(opline->op1);
- COPY_NODE(src->result, opline->result);
- SET_VAR_SOURCE(src);
- MAKE_NOP(opline);
+ /* convert CONCAT(X, '') => CAST(STRING, X) */
+ literal_dtor(&ZEND_OP2_LITERAL(opline));
+ opline->opcode = ZEND_CAST;
+ opline->extended_value = IS_STRING;
+ opline->op2_type = IS_UNUSED;
+ opline->op2.var = 0;
+ } else if (opline->opcode == ZEND_CONCAT &&
+ (opline->op1_type == IS_CONST ||
+ (opline->op1_type == IS_TMP_VAR &&
+ VAR_SOURCE(opline->op1) &&
+ (VAR_SOURCE(opline->op1)->opcode == ZEND_FAST_CONCAT ||
+ VAR_SOURCE(opline->op1)->opcode == ZEND_ROPE_END ||
+ VAR_SOURCE(opline->op1)->opcode == ZEND_FETCH_CONSTANT ||
+ VAR_SOURCE(opline->op1)->opcode == ZEND_FETCH_CLASS_CONSTANT))) &&
+ (opline->op2_type == IS_CONST ||
+ (opline->op2_type == IS_TMP_VAR &&
+ VAR_SOURCE(opline->op2) &&
+ (VAR_SOURCE(opline->op2)->opcode == ZEND_FAST_CONCAT ||
+ VAR_SOURCE(opline->op2)->opcode == ZEND_ROPE_END ||
+ VAR_SOURCE(opline->op2)->opcode == ZEND_FETCH_CONSTANT ||
+ VAR_SOURCE(opline->op2)->opcode == ZEND_FETCH_CLASS_CONSTANT)))) {
+ opline->opcode = ZEND_FAST_CONCAT;
+ }
+ break;
+
+ case ZEND_ADD:
+ case ZEND_SUB:
+ case ZEND_MUL:
+ case ZEND_DIV:
+ case ZEND_MOD:
+ case ZEND_SL:
+ case ZEND_SR:
+ case ZEND_IS_SMALLER:
+ case ZEND_IS_SMALLER_OR_EQUAL:
+ case ZEND_IS_IDENTICAL:
+ case ZEND_IS_NOT_IDENTICAL:
+ case ZEND_BOOL_XOR:
+ case ZEND_BW_OR:
+ case ZEND_BW_AND:
+ case ZEND_BW_XOR:
+ if (opline->op1_type == IS_CONST &&
+ opline->op2_type == IS_CONST) {
+ /* evaluate constant expressions */
+ binary_op_type binary_op;
+ zval result;
+ int er;
+
+optimize_constant_binary_op:
+ binary_op = get_binary_op(opline->opcode);
+ if ((opline->opcode == ZEND_DIV || opline->opcode == ZEND_MOD) &&
+ zval_get_long(&ZEND_OP2_LITERAL(opline)) == 0) {
+ SET_VAR_SOURCE(opline);
+ opline++;
+ continue;
+ } else if ((opline->opcode == ZEND_SL || opline->opcode == ZEND_SR) &&
+ zval_get_long(&ZEND_OP2_LITERAL(opline)) < 0) {
+ SET_VAR_SOURCE(opline);
+ opline++;
+ continue;
+ }
+ er = EG(error_reporting);
+ EG(error_reporting) = 0;
+ if (binary_op(&result, &ZEND_OP1_LITERAL(opline), &ZEND_OP2_LITERAL(opline)) == SUCCESS) {
+ literal_dtor(&ZEND_OP1_LITERAL(opline));
+ literal_dtor(&ZEND_OP2_LITERAL(opline));
+ opline->opcode = ZEND_QM_ASSIGN;
+ SET_UNUSED(opline->op2);
+ zend_optimizer_update_op1_const(op_array, opline, &result);
+ }
+ EG(error_reporting) = er;
+ }
+ break;
+
+ case ZEND_BW_NOT:
+ if (opline->op1_type == IS_CONST) {
+ /* evaluate constant unary ops */
+ unary_op_type unary_op;
+ zval result;
+
+optimize_const_unary_op:
+ unary_op = get_unary_op(opline->opcode);
+ if (unary_op) {
+ unary_op(&result, &ZEND_OP1_LITERAL(opline));
+ literal_dtor(&ZEND_OP1_LITERAL(opline));
+ } else {
+ /* BOOL */
+ result = ZEND_OP1_LITERAL(opline);
+ convert_to_boolean(&result);
+ ZVAL_NULL(&ZEND_OP1_LITERAL(opline));
+ }
+ opline->opcode = ZEND_QM_ASSIGN;
+ zend_optimizer_update_op1_const(op_array, opline, &result);
+ }
+ break;
+
+ case ZEND_RETURN:
+ case ZEND_EXIT:
+ if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) {
+ src = VAR_SOURCE(opline->op1);
+ if (src && src->opcode == ZEND_QM_ASSIGN) {
+ /* T = QM_ASSIGN(X), RETURN(T) to NOP, RETURN(X) */
+ VAR_SOURCE(opline->op1) = NULL;
+ COPY_NODE(opline->op1, src->op1);
+ MAKE_NOP(src);
+ }
+ }
+ break;
+
+ case ZEND_QM_ASSIGN:
+ if (opline->op1_type == opline->result_type &&
+ opline->op1.var == opline->result.var) {
+ /* strip T = QM_ASSIGN(T) */
+ MAKE_NOP(opline);
+ }
+ break;
}
+
/* get variable source */
- if (RESULT_USED(opline)) {
+ if (opline->result_type == IS_VAR || opline->result_type == IS_TMP_VAR) {
SET_VAR_SOURCE(opline);
}
- if (opline->opcode != ZEND_NOP) {
- last_op = opline;
- }
opline++;
}
- strip_nop(block, ctx);
+ strip_nops(op_array, block);
}
/* Rebuild plain (optimized) op_array from CFG */
static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
{
- zend_code_block *blocks = cfg->blocks;
- zend_op *new_opcodes = emalloc(op_array->last * sizeof(zend_op));
- zend_op *opline = new_opcodes;
- zend_code_block *cur_block = blocks;
+ zend_basic_block *blocks = cfg->blocks;
+ zend_basic_block *end = blocks + cfg->blocks_count;
+ zend_basic_block *b;
+ zend_op *new_opcodes;
+ zend_op *opline;
+ uint32_t len = 0;
- /* Copy code of reachable blocks into a single buffer */
- while (cur_block) {
- if (cur_block->access) {
- memcpy(opline, cur_block->start_opline, cur_block->len * sizeof(zend_op));
- cur_block->start_opline = opline;
- opline += cur_block->len;
- if ((opline - 1)->opcode == ZEND_JMP) {
- zend_code_block *next;
- next = cur_block->next;
- while (next && !next->access) {
- next = next->next;
+ for (b = blocks; b < end; b++) {
+ if (b->flags & ZEND_BB_REACHABLE) {
+ ZEND_ASSERT(b->start <= b->end);
+ opline = op_array->opcodes + b->end;
+ if (opline->opcode == ZEND_JMP) {
+ zend_basic_block *next = b + 1;
+
+ while (next < end && (!(next->flags & ZEND_BB_REACHABLE) || next->start > next->end)) {
+ next++;
}
- if (next && next == cur_block->op1_to) {
+ if (next < end && next == blocks + b->successors[0]) {
/* JMP to the next block - strip it */
- cur_block->follow_to = cur_block->op1_to;
- cur_block->op1_to = NULL;
- MAKE_NOP((opline - 1));
- opline--;
- cur_block->len--;
+ MAKE_NOP(opline);
+ b->end--;
}
}
- } else {
+ len += b->end - b->start + 1;
+ } else if (b->start <= b->end) {
/* this block will not be used, delete all constants there */
- zend_op *_opl;
- zend_op *end = cur_block->start_opline + cur_block->len;
- for (_opl = cur_block->start_opline; _opl && _opl < end; _opl++) {
- if (ZEND_OP1_TYPE(_opl) == IS_CONST) {
- literal_dtor(&ZEND_OP1_LITERAL(_opl));
+ zend_op *op;
+ zend_op *end = op_array->opcodes + b->end ;
+ for (op = op_array->opcodes + b->start; op <= end; op++) {
+ if (ZEND_OP1_TYPE(op) == IS_CONST) {
+ literal_dtor(&ZEND_OP1_LITERAL(op));
}
- if (ZEND_OP2_TYPE(_opl) == IS_CONST) {
- literal_dtor(&ZEND_OP2_LITERAL(_opl));
+ if (ZEND_OP2_TYPE(op) == IS_CONST) {
+ literal_dtor(&ZEND_OP2_LITERAL(op));
}
}
}
- cur_block = cur_block->next;
}
- op_array->last = opline-new_opcodes;
+ new_opcodes = emalloc(len * sizeof(zend_op));
+ opline = new_opcodes;
+
+ /* Copy code of reachable blocks into a single buffer */
+ for (b = blocks; b < end; b++) {
+ if (b->flags & ZEND_BB_REACHABLE) {
+ uint32_t n;
+
+ ZEND_ASSERT(b->start <= b->end);
+ n = b->end - b->start + 1;
+ memcpy(opline, op_array->opcodes + b->start, n * sizeof(zend_op));
+ b->start = opline - new_opcodes;
+ b->end = opline - new_opcodes + n - 1;
+ opline += n;
+ }
+ }
+
+ /* adjust jump targets */
+ efree(op_array->opcodes);
+ op_array->opcodes = new_opcodes;
+ op_array->last = len;
+
+ for (b = blocks; b < end; b++) {
+ if (!(b->flags & ZEND_BB_REACHABLE)) {
+ continue;
+ }
+ opline = op_array->opcodes + b->end;
+ switch (opline->opcode) {
+ case ZEND_FAST_CALL:
+ case ZEND_JMP:
+ case ZEND_DECLARE_ANON_CLASS:
+ case ZEND_DECLARE_ANON_INHERITED_CLASS:
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op1, new_opcodes + blocks[b->successors[0]].start);
+ break;
+ case ZEND_JMPZNZ:
+ opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, new_opcodes + blocks[b->successors[1]].start);
+ /* break missing intentionally */
+ case ZEND_JMPZ:
+ case ZEND_JMPNZ:
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+ case ZEND_FE_RESET_R:
+ case ZEND_FE_RESET_RW:
+ case ZEND_NEW:
+ case ZEND_JMP_SET:
+ case ZEND_COALESCE:
+ case ZEND_ASSERT_CHECK:
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_opcodes + blocks[b->successors[0]].start);
+ break;
+ case ZEND_CATCH:
+ if (!opline->result.var) {
+ opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, new_opcodes + blocks[b->successors[0]].start);
+ }
+ break;
+ case ZEND_FE_FETCH_R:
+ case ZEND_FE_FETCH_RW:
+ opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, new_opcodes + blocks[b->successors[0]].start);
+ break;
+ }
+ }
- /* adjust exception jump targets */
+ /* adjust exception jump targets & remove unused try_catch_array entries */
if (op_array->last_try_catch) {
int i, j;
+ uint32_t *map;
+ ALLOCA_FLAG(use_heap);
+
+ map = (uint32_t *)do_alloca(sizeof(uint32_t) * op_array->last_try_catch, use_heap);
for (i = 0, j = 0; i< op_array->last_try_catch; i++) {
- if (cfg->try[i]->access) {
- op_array->try_catch_array[j].try_op = cfg->try[i]->start_opline - new_opcodes;
- op_array->try_catch_array[j].catch_op = cfg->catch[i]->start_opline - new_opcodes;
+ if (blocks[cfg->map[op_array->try_catch_array[i].try_op]].flags & ZEND_BB_REACHABLE) {
+ map[i] = j;
+ op_array->try_catch_array[j].try_op = blocks[cfg->map[op_array->try_catch_array[i].try_op]].start;
+ if (op_array->try_catch_array[i].catch_op) {
+ op_array->try_catch_array[j].catch_op = blocks[cfg->map[op_array->try_catch_array[i].catch_op]].start;
+ } else {
+ op_array->try_catch_array[j].catch_op = 0;
+ }
+ if (op_array->try_catch_array[i].finally_op) {
+ op_array->try_catch_array[j].finally_op = blocks[cfg->map[op_array->try_catch_array[i].finally_op]].start;
+ } else {
+ op_array->try_catch_array[j].finally_op = 0;
+ }
+ if (!op_array->try_catch_array[i].finally_end) {
+ op_array->try_catch_array[j].finally_end = 0;
+ } else {
+ op_array->try_catch_array[j].finally_end = blocks[cfg->map[op_array->try_catch_array[i].finally_end]].start;
+ }
j++;
}
}
- op_array->last_try_catch = j;
- }
-
- /* adjust loop jump targets */
- if (op_array->last_brk_cont) {
- int i;
- for (i = 0; i< op_array->last_brk_cont; i++) {
- op_array->brk_cont_array[i].start = cfg->loop_start[i]->start_opline - new_opcodes;
- op_array->brk_cont_array[i].cont = cfg->loop_cont[i]->start_opline - new_opcodes;
- op_array->brk_cont_array[i].brk = cfg->loop_brk[i]->start_opline - new_opcodes;
+ if (i != j) {
+ op_array->last_try_catch = j;
+ if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
+ zend_op *opline = new_opcodes;
+ zend_op *end = opline + len;
+ while (opline < end) {
+ if ((opline->opcode == ZEND_FAST_CALL ||
+ opline->opcode == ZEND_FAST_RET) &&
+ opline->extended_value &&
+ opline->op2.num < (uint32_t)j) {
+ opline->op2.num = map[opline->op2.num];
+ }
+ opline++;
+ }
+ }
}
+ free_alloca(map, use_heap);
}
- /* adjust jump targets */
- for (cur_block = blocks; cur_block; cur_block = cur_block->next) {
- if (!cur_block->access) {
- continue;
- }
- opline = cur_block->start_opline + cur_block->len - 1;
- if (opline->opcode == ZEND_OP_DATA) {
- opline--;
- }
- if (cur_block->op1_to) {
- ZEND_OP1(opline).opline_num = cur_block->op1_to->start_opline - new_opcodes;
- }
- if (cur_block->op2_to) {
- ZEND_OP2(opline).opline_num = cur_block->op2_to->start_opline - new_opcodes;
+ /* adjust loop jump targets & remove unused live range entries */
+ if (op_array->last_live_range) {
+ int i, j;
+ uint32_t *map;
+ ALLOCA_FLAG(use_heap);
+
+ map = (uint32_t *)do_alloca(sizeof(uint32_t) * op_array->last_live_range, use_heap);
+
+ for (i = 0, j = 0; i < op_array->last_live_range; i++) {
+ if (!(blocks[cfg->map[op_array->live_range[i].start]].flags & ZEND_BB_REACHABLE)) {
+ ZEND_ASSERT(!(blocks[cfg->map[op_array->live_range[i].end]].flags & ZEND_BB_REACHABLE));
+ } else {
+ op_array->live_range[i].start = blocks[cfg->map[op_array->live_range[i].start]].start;
+ op_array->live_range[i].end = blocks[cfg->map[op_array->live_range[i].end]].start;
+ map[i] = j;
+ if (i != j) {
+ op_array->live_range[j] = op_array->live_range[i];
+ }
+ j++;
+ }
}
- if (cur_block->ext_to) {
- opline->extended_value = cur_block->ext_to->start_opline - new_opcodes;
+
+ 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 &&
+ opline->op2.num < (uint32_t)j) {
+ opline->op2.num = map[opline->op2.num];
+ }
+ opline++;
+ }
}
- print_block(cur_block, new_opcodes, "Out ");
}
- efree(op_array->opcodes);
- op_array->opcodes = erealloc(new_opcodes, op_array->last * sizeof(zend_op));
/* adjust early binding list */
if (op_array->early_binding != (uint32_t)-1) {
@@ -1250,45 +955,57 @@ static void assemble_code_blocks(zend_cfg *cfg, zend_op_array *op_array)
}
*opline_num = -1;
}
+
+#if DEBUG_BLOCKPASS
+ /* rebild map (judt for printing) */
+ memset(cfg->map, -1, sizeof(int) * op_array->last);
+ for (n = 0; n < cfg->blocks_count; n++) {
+ if (cfg->blocks[n].flags & ZEND_BB_REACHABLE) {
+ cfg->map[cfg->blocks[n].start] = n;
+ }
+ }
+#endif
}
-static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_array, zend_code_block *blocks, zend_cfg *cfg, zend_optimizer_ctx *ctx)
+static void zend_jmp_optimization(zend_basic_block *block, zend_op_array *op_array, zend_cfg *cfg, zend_uchar *same_t)
{
/* last_op is the last opcode of the current block */
- zend_op *last_op = (block->start_opline + block->len - 1);
+ zend_basic_block *blocks = cfg->blocks;
+ zend_op *last_op;
- if (!block->len) {
- return;
- }
+ ZEND_ASSERT(block->start <= block->end);
+ last_op = op_array->opcodes + block->end;
switch (last_op->opcode) {
case ZEND_JMP:
{
- zend_op *target = block->op1_to->start_opline;
- zend_code_block *next = block->next;
+ zend_basic_block *target_block = blocks + block->successors[0];
+ zend_op *target = op_array->opcodes + target_block->start;
+ int next = (block - blocks) + 1;
- while (next && !next->access) {
+ while (next < cfg->blocks_count && !(blocks[next].flags & ZEND_BB_REACHABLE)) {
/* find used one */
- next = next->next;
+ next++;
}
/* JMP(next) -> NOP */
- if (block->op1_to == next) {
- block->follow_to = block->op1_to;
- block->op1_to = NULL;
+ if (block->successors[0] == next) {
MAKE_NOP(last_op);
- block->len--;
- if (block->len == 0) {
- /* this block is nothing but NOP now */
- delete_code_block(block, ctx);
+ if (block->start != block->end) {
+ block->end--;
}
break;
}
- if (((target->opcode == ZEND_JMP &&
- block->op1_to != block->op1_to->op1_to) ||
- target->opcode == ZEND_JMPZNZ) &&
- !block->op1_to->protected) {
+ if (target->opcode == ZEND_JMP &&
+ block->successors[0] != target_block->successors[0] &&
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* JMP L, L: JMP L1 -> JMP L1 */
+ *last_op = *target;
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[0];
+ ADD_SOURCE(block, block->successors[0]);
+ } else if (target->opcode == ZEND_JMPZNZ &&
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* JMP L, L: JMPZNZ L1,L2 -> JMPZNZ L1,L2 */
*last_op = *target;
if (ZEND_OP1_TYPE(last_op) == IS_CONST) {
@@ -1296,25 +1013,15 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
zval_copy_ctor(&zv);
last_op->op1.constant = zend_optimizer_add_literal(op_array, &zv);
}
- del_source(block, block->op1_to);
- if (block->op1_to->op2_to) {
- block->op2_to = block->op1_to->op2_to;
- ADD_SOURCE(block, block->op2_to);
- }
- if (block->op1_to->ext_to) {
- block->ext_to = block->op1_to->ext_to;
- ADD_SOURCE(block, block->ext_to);
- }
- if (block->op1_to->op1_to) {
- block->op1_to = block->op1_to->op1_to;
- ADD_SOURCE(block, block->op1_to);
- } else {
- block->op1_to = NULL;
- }
- } else if (target->opcode == ZEND_RETURN ||
- target->opcode == ZEND_RETURN_BY_REF ||
- target->opcode == ZEND_FAST_RET ||
- target->opcode == ZEND_EXIT) {
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[0];
+ block->successors[1] = target_block->successors[1];
+ ADD_SOURCE(block, block->successors[0]);
+ ADD_SOURCE(block, block->successors[1]);
+ } else if ((target->opcode == ZEND_RETURN ||
+ target->opcode == ZEND_RETURN_BY_REF ||
+ target->opcode == ZEND_EXIT) &&
+ !(op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK)) {
/* JMP L, L: RETURN to immediate RETURN */
*last_op = *target;
if (ZEND_OP1_TYPE(last_op) == IS_CONST) {
@@ -1322,8 +1029,8 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
zval_copy_ctor(&zv);
last_op->op1.constant = zend_optimizer_add_literal(op_array, &zv);
}
- del_source(block, block->op1_to);
- block->op1_to = NULL;
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = -1;
#if 0
/* Temporarily disabled - see bug #0025274 */
} else if (0&& block->op1_to != block &&
@@ -1356,7 +1063,7 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
next = next->follow_to;
}
if (can_reorder) {
- zend_code_block *prev = blocks;
+ zend_basic_block *prev = blocks;
while (prev->next != block->op1_to) {
prev = prev->next;
@@ -1395,159 +1102,135 @@ static void zend_jmp_optimization(zend_code_block *block, zend_op_array *op_arra
if (should_jmp) {
/* JMPNZ(true) -> JMP */
last_op->opcode = ZEND_JMP;
- COPY_NODE(last_op->op1, last_op->op2);
- block->op1_to = block->op2_to;
- del_source(block, block->follow_to);
- block->op2_to = NULL;
- block->follow_to = NULL;
+ DEL_SOURCE(block, block->successors[1]);
+ block->successors[1] = -1;
} else {
/* JMPNZ(false) -> NOP */
MAKE_NOP(last_op);
- del_source(block, block->op2_to);
- block->op2_to = NULL;
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = block->successors[1];
+ block->successors[1] = -1;
}
break;
}
- if (block->op2_to == block->follow_to) {
- /* L: JMPZ(X, L+1) -> NOP or FREE(X) */
-
- if (last_op->op1_type == IS_VAR) {
- zend_op **Tsource = cfg->Tsource;
- zend_op *src = VAR_SOURCE(last_op->op1);
+ if (block->successors[0] == block->successors[1]) {
+ /* L: JMP[N]Z(X, L+1) -> NOP or FREE(X) */
- if (src &&
- src->opcode != ZEND_FETCH_R &&
- src->opcode != ZEND_FETCH_DIM_R &&
- src->opcode != ZEND_FETCH_OBJ_R) {
- ZEND_RESULT_TYPE(src) |= EXT_TYPE_UNUSED;
- MAKE_NOP(last_op);
- block->op2_to = NULL;
- break;
- }
- }
if (last_op->op1_type & (IS_VAR|IS_TMP_VAR)) {
last_op->opcode = ZEND_FREE;
last_op->op2.num = 0;
- block->op2_to = NULL;
} else {
MAKE_NOP(last_op);
- block->op2_to = NULL;
}
+ block->successors[1] = -1;
break;
}
- if (block->op2_to) {
+ if (1) {
zend_uchar same_type = ZEND_OP1_TYPE(last_op);
uint32_t same_var = VAR_NUM_EX(last_op->op1);
zend_op *target;
zend_op *target_end;
- zend_code_block *target_block = block->op2_to;;
+ zend_basic_block *target_block = blocks + block->successors[0];
next_target:
- target = target_block->start_opline;
- target_end = target_block->start_opline + target_block->len;
+ target = op_array->opcodes + target_block->start;
+ target_end = op_array->opcodes + target_block->end + 1;
while (target < target_end && target->opcode == ZEND_NOP) {
target++;
}
/* next block is only NOP's */
if (target == target_end) {
- target_block = target_block->follow_to;
+ target_block = blocks + target_block->successors[0];
goto next_target;
} else if (target->opcode == INV_COND(last_op->opcode) &&
/* JMPZ(X, L), L: JMPNZ(X, L2) -> JMPZ(X, L+1) */
(ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
same_type == ZEND_OP1_TYPE(target) &&
same_var == VAR_NUM_EX(target->op1) &&
- target_block->follow_to &&
- !target_block->protected
+ !(target_block->flags & ZEND_BB_PROTECTED)
) {
- del_source(block, block->op2_to);
- block->op2_to = target_block->follow_to;
- ADD_SOURCE(block, block->op2_to);
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[1];
+ ADD_SOURCE(block, block->successors[0]);
} else if (target->opcode == INV_COND_EX(last_op->opcode) &&
(ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
same_type == ZEND_OP1_TYPE(target) &&
same_var == VAR_NUM_EX(target->op1) &&
- target_block->follow_to &&
- !target_block->protected) {
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* JMPZ(X, L), L: X = JMPNZ_EX(X, L2) -> JMPZ(X, L+1) */
last_op->opcode += 3;
last_op->result = target->result;
- del_source(block, block->op2_to);
- block->op2_to = target_block->follow_to;
- ADD_SOURCE(block, block->op2_to);
- } else if (target_block->op2_to &&
- target->opcode == last_op->opcode &&
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[1];
+ ADD_SOURCE(block, block->successors[0]);
+ } else if (target->opcode == last_op->opcode &&
(ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
same_type == ZEND_OP1_TYPE(target) &&
same_var == VAR_NUM_EX(target->op1) &&
- !target_block->protected) {
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* JMPZ(X, L), L: JMPZ(X, L2) -> JMPZ(X, L2) */
- del_source(block, block->op2_to);
- block->op2_to = target_block->op2_to;
- ADD_SOURCE(block, block->op2_to);
- } else if (target_block->op1_to &&
- target->opcode == ZEND_JMP &&
- !target_block->protected) {
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[0];
+ ADD_SOURCE(block, block->successors[0]);
+ } else if (target->opcode == ZEND_JMP &&
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* JMPZ(X, L), L: JMP(L2) -> JMPZ(X, L2) */
- del_source(block, block->op2_to);
- block->op2_to = target_block->op1_to;
- ADD_SOURCE(block, block->op2_to);
- } else if (target_block->op2_to &&
- target_block->ext_to &&
- target->opcode == ZEND_JMPZNZ &&
- (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
- same_type == ZEND_OP1_TYPE(target) &&
- same_var == VAR_NUM_EX(target->op1) &&
- !target_block->protected) {
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[0];
+ ADD_SOURCE(block, block->successors[0]);
+ } else if (target->opcode == ZEND_JMPZNZ &&
+ (ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
+ same_type == ZEND_OP1_TYPE(target) &&
+ same_var == VAR_NUM_EX(target->op1) &&
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* JMPZ(X, L), L: JMPZNZ(X, L2, L3) -> JMPZ(X, L2) */
- del_source(block, block->op2_to);
+ DEL_SOURCE(block, block->successors[0]);
if (last_op->opcode == ZEND_JMPZ) {
- block->op2_to = target_block->op2_to;
+ block->successors[0] = target_block->successors[0];
} else {
- block->op2_to = target_block->ext_to;
+ block->successors[0] = target_block->successors[1];
}
- ADD_SOURCE(block, block->op2_to);
+ ADD_SOURCE(block, block->successors[0]);
}
}
- if (block->follow_to &&
- (last_op->opcode == ZEND_JMPZ || last_op->opcode == ZEND_JMPNZ)) {
+ if (last_op->opcode == ZEND_JMPZ || last_op->opcode == ZEND_JMPNZ) {
zend_op *target;
zend_op *target_end;
+ zend_basic_block *target_block;
while (1) {
- target = block->follow_to->start_opline;
- target_end = block->follow_to->start_opline + block->follow_to->len;
+ target_block = blocks + block->successors[1];
+ target = op_array->opcodes + target_block->start;
+ target_end = op_array->opcodes + target_block->start + 1;
while (target < target_end && target->opcode == ZEND_NOP) {
target++;
}
/* next block is only NOP's */
- if (target == target_end && ! block->follow_to->protected) {
- del_source(block, block->follow_to);
- block->follow_to = block->follow_to->follow_to;
- ADD_SOURCE(block, block->follow_to);
+ if (target == target_end && !(target_block->flags & ZEND_BB_PROTECTED)) {
+ DEL_SOURCE(block, block->successors[1]);
+ block->successors[1] = target_block->successors[0];
+ ADD_SOURCE(block, block->successors[1]);
} else {
break;
}
}
/* JMPZ(X,L1), JMP(L2) -> JMPZNZ(X,L1,L2) */
if (target->opcode == ZEND_JMP &&
- block->follow_to->op1_to &&
- !block->follow_to->protected) {
- del_source(block, block->follow_to);
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
+ DEL_SOURCE(block, block->successors[1]);
if (last_op->opcode == ZEND_JMPZ) {
- block->ext_to = block->follow_to->op1_to;
- ADD_SOURCE(block, block->ext_to);
+ block->successors[1] = target_block->successors[0];
+ ADD_SOURCE(block, block->successors[1]);
} else {
- block->ext_to = block->op2_to;
- block->op2_to = block->follow_to->op1_to;
- ADD_SOURCE(block, block->op2_to);
+ block->successors[1] = block->successors[0];
+ block->successors[0] = target_block->successors[0];
+ ADD_SOURCE(block, block->successors[0]);
}
- block->follow_to = NULL;
last_op->opcode = ZEND_JMPZNZ;
}
}
@@ -1568,207 +1251,182 @@ next_target:
*/
last_op->opcode = ZEND_QM_ASSIGN;
SET_UNUSED(last_op->op2);
- del_source(block, block->op2_to);
- block->op2_to = NULL;
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = block->successors[1];
+ block->successors[1] = -1;
}
break;
}
- if (block->op2_to) {
+ if (1) {
zend_op *target, *target_end;
- char *same_t=NULL;
- zend_code_block *target_block;
+ zend_basic_block *target_block;
int var_num = op_array->last_var + op_array->T;
if (var_num <= 0) {
return;
}
- same_t = cfg->same_t;
memset(same_t, 0, var_num);
same_t[VAR_NUM_EX(last_op->op1)] |= ZEND_OP1_TYPE(last_op);
same_t[VAR_NUM_EX(last_op->result)] |= ZEND_RESULT_TYPE(last_op);
- target_block = block->op2_to;
+ target_block = blocks + block->successors[0];
next_target_ex:
- target = target_block->start_opline;
- target_end = target_block->start_opline + target_block->len;
+ target = op_array->opcodes + target_block->start;
+ target_end = op_array->opcodes + target_block->end + 1;
while (target < target_end && target->opcode == ZEND_NOP) {
target++;
}
/* next block is only NOP's */
if (target == target_end) {
- target_block = target_block->follow_to;
+ target_block = blocks + target_block->successors[0];
goto next_target_ex;
- } else if (target_block->op2_to &&
- target->opcode == last_op->opcode-3 &&
+ } else if (target->opcode == last_op->opcode-3 &&
(ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
(same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 &&
- !target_block->protected) {
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* T = JMPZ_EX(X, L1), L1: JMPZ({X|T}, L2) -> T = JMPZ_EX(X, L2) */
- del_source(block, block->op2_to);
- block->op2_to = target_block->op2_to;
- ADD_SOURCE(block, block->op2_to);
- } else if (target_block->op2_to &&
- target->opcode == INV_EX_COND(last_op->opcode) &&
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[0];
+ ADD_SOURCE(block, block->successors[0]);
+ } else if (target->opcode == INV_EX_COND(last_op->opcode) &&
(ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
(same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 &&
- !target_block->protected) {
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* T = JMPZ_EX(X, L1), L1: JMPNZ({X|T1}, L2) -> T = JMPZ_EX(X, L1+1) */
- del_source(block, block->op2_to);
- block->op2_to = target_block->follow_to;
- ADD_SOURCE(block, block->op2_to);
- } else if (target_block->op2_to &&
- target->opcode == INV_EX_COND_EX(last_op->opcode) &&
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[1];
+ ADD_SOURCE(block, block->successors[0]);
+ } else if (target->opcode == INV_EX_COND_EX(last_op->opcode) &&
(ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
(same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 &&
(same_t[VAR_NUM_EX(target->result)] & ZEND_RESULT_TYPE(target)) != 0 &&
- !target_block->protected) {
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* T = JMPZ_EX(X, L1), L1: T = JMPNZ_EX(T, L2) -> T = JMPZ_EX(X, L1+1) */
- del_source(block, block->op2_to);
- block->op2_to = target_block->follow_to;
- ADD_SOURCE(block, block->op2_to);
- } else if (target_block->op2_to &&
- target->opcode == last_op->opcode &&
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[1];
+ ADD_SOURCE(block, block->successors[0]);
+ } else if (target->opcode == last_op->opcode &&
(ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
(same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 &&
(same_t[VAR_NUM_EX(target->result)] & ZEND_RESULT_TYPE(target)) != 0 &&
- !target_block->protected) {
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* T = JMPZ_EX(X, L1), L1: T = JMPZ({X|T}, L2) -> T = JMPZ_EX(X, L2) */
- del_source(block, block->op2_to);
- block->op2_to = target_block->op2_to;
- ADD_SOURCE(block, block->op2_to);
- } else if (target_block->op1_to &&
- target->opcode == ZEND_JMP &&
- !target_block->protected) {
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[0];
+ ADD_SOURCE(block, block->successors[0]);
+ } else if (target->opcode == ZEND_JMP &&
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* T = JMPZ_EX(X, L), L: JMP(L2) -> T = JMPZ(X, L2) */
- del_source(block, block->op2_to);
- block->op2_to = target_block->op1_to;
- ADD_SOURCE(block, block->op2_to);
- } else if (target_block->op2_to &&
- target_block->ext_to &&
- target->opcode == ZEND_JMPZNZ &&
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[0];
+ ADD_SOURCE(block, block->successors[0]);
+ } else if (target->opcode == ZEND_JMPZNZ &&
(ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
(same_t[VAR_NUM_EX(target->op1)] & ZEND_OP1_TYPE(target)) != 0 &&
- !target_block->protected) {
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* T = JMPZ_EX(X, L), L: JMPZNZ({X|T}, L2, L3) -> T = JMPZ_EX(X, L2) */
- del_source(block, block->op2_to);
+ DEL_SOURCE(block, block->successors[0]);
if (last_op->opcode == ZEND_JMPZ_EX) {
- block->op2_to = target_block->op2_to;
+ block->successors[0] = target_block->successors[0];
} else {
- block->op2_to = target_block->ext_to;
+ block->successors[0] = target_block->successors[1];
}
- ADD_SOURCE(block, block->op2_to);
+ ADD_SOURCE(block, block->successors[0]);
}
}
break;
case ZEND_JMPZNZ: {
- zend_code_block *next = block->next;
+ int next = (block - blocks) + 1;
- while (next && !next->access) {
+ while (next < cfg->blocks_count && !(blocks[next].flags & ZEND_BB_REACHABLE)) {
/* find first accessed one */
- next = next->next;
+ next++;
}
if (ZEND_OP1_TYPE(last_op) == IS_CONST) {
if (!zend_is_true(&ZEND_OP1_LITERAL(last_op))) {
/* JMPZNZ(false,L1,L2) -> JMP(L1) */
- zend_code_block *todel;
-
literal_dtor(&ZEND_OP1_LITERAL(last_op));
last_op->opcode = ZEND_JMP;
SET_UNUSED(last_op->op1);
SET_UNUSED(last_op->op2);
- block->op1_to = block->op2_to;
- todel = block->ext_to;
- block->op2_to = NULL;
- block->ext_to = NULL;
- del_source(block, todel);
+ DEL_SOURCE(block, block->successors[1]);
+ block->successors[1] = -1;
} else {
/* JMPZNZ(true,L1,L2) -> JMP(L2) */
- zend_code_block *todel;
-
literal_dtor(&ZEND_OP1_LITERAL(last_op));
last_op->opcode = ZEND_JMP;
SET_UNUSED(last_op->op1);
SET_UNUSED(last_op->op2);
- block->op1_to = block->ext_to;
- todel = block->op2_to;
- block->op2_to = NULL;
- block->ext_to = NULL;
- del_source(block, todel);
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = block->successors[1];
+ block->successors[1] = -1;
}
- } else if (block->op2_to == block->ext_to) {
+ } else if (block->successors[0] == block->successors[1]) {
/* both goto the same one - it's JMP */
if (!(last_op->op1_type & (IS_VAR|IS_TMP_VAR))) {
/* JMPZNZ(?,L,L) -> JMP(L) */
last_op->opcode = ZEND_JMP;
SET_UNUSED(last_op->op1);
SET_UNUSED(last_op->op2);
- block->op1_to = block->op2_to;
- block->op2_to = NULL;
- block->ext_to = NULL;
+ block->successors[1] = -1;
}
- } else if (block->op2_to == next) {
+ } else if (block->successors[0] == next) {
/* jumping to next on Z - can follow to it and jump only on NZ */
/* JMPZNZ(X,L1,L2) L1: -> JMPNZ(X,L2) */
last_op->opcode = ZEND_JMPNZ;
- block->op2_to = block->ext_to;
- block->follow_to = next;
- block->ext_to = NULL;
- /* no need to add source - it's block->op2_to */
- } else if (block->ext_to == next) {
+ block->successors[0] = block->successors[1];
+ block->successors[1] = next;
+ /* no need to add source */
+ } else if (block->successors[1] == next) {
/* jumping to next on NZ - can follow to it and jump only on Z */
/* JMPZNZ(X,L1,L2) L2: -> JMPZ(X,L1) */
last_op->opcode = ZEND_JMPZ;
- block->follow_to = next;
- block->ext_to = NULL;
- /* no need to add source - it's block->ext_to */
+ /* no need to add source */
}
- if (last_op->opcode == ZEND_JMPZNZ && block->op2_to) {
+ if (last_op->opcode == ZEND_JMPZNZ) {
zend_uchar same_type = ZEND_OP1_TYPE(last_op);
zend_uchar same_var = VAR_NUM_EX(last_op->op1);
zend_op *target;
zend_op *target_end;
- zend_code_block *target_block = block->op2_to;
+ zend_basic_block *target_block = blocks + block->successors[0];
next_target_znz:
- target = target_block->start_opline;
- target_end = target_block->start_opline + target_block->len;
+ target = op_array->opcodes + target_block->start;
+ target_end = op_array->opcodes + target_block->end + 1;
while (target < target_end && target->opcode == ZEND_NOP) {
target++;
}
/* next block is only NOP's */
if (target == target_end) {
- target_block = target_block->follow_to;
+ target_block = blocks + target_block->successors[0];
goto next_target_znz;
- } else if (target_block->op2_to &&
- (target->opcode == ZEND_JMPZ || target->opcode == ZEND_JMPZNZ) &&
+ } else if ((target->opcode == ZEND_JMPZ || target->opcode == ZEND_JMPZNZ) &&
(ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
same_type == ZEND_OP1_TYPE(target) &&
same_var == VAR_NUM_EX(target->op1) &&
- !target_block->protected) {
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* JMPZNZ(X, L1, L2), L1: JMPZ(X, L3) -> JMPZNZ(X, L3, L2) */
- del_source(block, block->op2_to);
- block->op2_to = target_block->op2_to;
- ADD_SOURCE(block, block->op2_to);
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[0];
+ ADD_SOURCE(block, block->successors[0]);
} else if (target->opcode == ZEND_JMPNZ &&
(ZEND_OP1_TYPE(target) & (IS_TMP_VAR|IS_CV)) &&
same_type == ZEND_OP1_TYPE(target) &&
same_var == VAR_NUM_EX(target->op1) &&
- target_block->follow_to &&
- !target_block->protected) {
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* JMPZNZ(X, L1, L2), L1: X = JMPNZ(X, L3) -> JMPZNZ(X, L1+1, L2) */
- del_source(block, block->op2_to);
- block->op2_to = target_block->follow_to;
- ADD_SOURCE(block, block->op2_to);
- } else if (target_block->op1_to &&
- target->opcode == ZEND_JMP &&
- !target_block->protected) {
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[1];
+ ADD_SOURCE(block, block->successors[0]);
+ } else if (target->opcode == ZEND_JMP &&
+ !(target_block->flags & ZEND_BB_PROTECTED)) {
/* JMPZNZ(X, L1, L2), L1: JMP(L3) -> JMPZNZ(X, L3, L2) */
- del_source(block, block->op2_to);
- block->op2_to = target_block->op1_to;
- ADD_SOURCE(block, block->op2_to);
+ DEL_SOURCE(block, block->successors[0]);
+ block->successors[0] = target_block->successors[0];
+ ADD_SOURCE(block, block->successors[0]);
}
}
break;
@@ -1778,25 +1436,19 @@ next_target_znz:
/* Global data dependencies */
-#define T_USAGE(op) do { \
- if ((op ## _type & (IS_VAR | IS_TMP_VAR)) && \
- !zend_bitset_in(defined_here, VAR_NUM(op.var)) && !zend_bitset_in(used_ext, VAR_NUM(op.var))) { \
- zend_bitset_incl(used_ext, VAR_NUM(op.var)); \
- } \
- } while (0)
-
-#define NEVER_USED(op) ((op ## _type & (IS_VAR | IS_TMP_VAR)) && !zend_bitset_in(usage, VAR_NUM(op.var))) /* !zend_bitset_in(used_ext, op.var) && */
-#define RES_NEVER_USED(opline) (opline->result_type == IS_UNUSED || NEVER_USED(opline->result))
-
/* Find a set of variables which are used outside of the block where they are
* defined. We won't apply some optimization patterns for such variables. */
-static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, zend_bitset used_ext, zend_optimizer_ctx *ctx)
+static void zend_t_usage(zend_cfg *cfg, zend_op_array *op_array, zend_bitset used_ext, zend_optimizer_ctx *ctx)
{
- zend_code_block *next_block = block->next;
+ int n;
+ zend_basic_block *block;
+ uint32_t var_num;
uint32_t bitset_len;
zend_bitset usage;
zend_bitset defined_here;
void *checkpoint;
+ zend_op *opline, *end;
+
if (op_array->T == 0) {
/* shortcut - if no Ts, nothing to do */
@@ -1805,210 +1457,322 @@ static void zend_t_usage(zend_code_block *block, zend_op_array *op_array, zend_b
checkpoint = zend_arena_checkpoint(ctx->arena);
bitset_len = zend_bitset_len(op_array->last_var + op_array->T);
- usage = zend_arena_alloc(&ctx->arena, bitset_len * ZEND_BITSET_ELM_SIZE);
- zend_bitset_clear(usage, bitset_len);
+ usage = zend_arena_calloc(&ctx->arena, bitset_len, ZEND_BITSET_ELM_SIZE);
defined_here = zend_arena_alloc(&ctx->arena, bitset_len * ZEND_BITSET_ELM_SIZE);
- while (next_block) {
- zend_op *opline = next_block->start_opline;
- zend_op *end = opline + next_block->len;
+ for (n = 1; n < cfg->blocks_count; n++) {
+ block = cfg->blocks + n;
- if (!next_block->access) {
- next_block = next_block->next;
+ if (!(block->flags & ZEND_BB_REACHABLE)) {
continue;
}
+
+ opline = op_array->opcodes + block->start;
+ end = op_array->opcodes + block->end + 1;
zend_bitset_clear(defined_here, bitset_len);
while (opline<end) {
- T_USAGE(opline->op1);
- if (opline->op2_type & (IS_VAR | IS_TMP_VAR)) {
- if (opline->opcode == ZEND_FE_FETCH_R || opline->opcode == ZEND_FE_FETCH_RW) {
+ if (opline->op1_type == IS_VAR || opline->op1_type == 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);
+ }
+ }
+ if (opline->op2_type == IS_VAR) {
+ var_num = VAR_NUM(opline->op2.var);
+ if (opline->opcode == ZEND_FE_FETCH_R ||
+ opline->opcode == ZEND_FE_FETCH_RW) {
/* these opcode use the op2 as result */
- zend_bitset_incl(defined_here, VAR_NUM(ZEND_OP2(opline).var));
- } else {
- T_USAGE(opline->op2);
+ zend_bitset_incl(defined_here, var_num);
+ } else if (!zend_bitset_in(defined_here, var_num)) {
+ zend_bitset_incl(used_ext, var_num);
+ }
+ } else if (opline->op2_type == IS_TMP_VAR) {
+ var_num = VAR_NUM(opline->op2.var);
+ if (!zend_bitset_in(defined_here, var_num)) {
+ zend_bitset_incl(used_ext, var_num);
}
}
- if (RESULT_USED(opline)) {
- if (!zend_bitset_in(defined_here, VAR_NUM(ZEND_RESULT(opline).var)) && !zend_bitset_in(used_ext, VAR_NUM(ZEND_RESULT(opline).var)) &&
- opline->opcode == ZEND_ADD_ARRAY_ELEMENT) {
- /* these opcode use the result as argument */
- zend_bitset_incl(used_ext, VAR_NUM(ZEND_RESULT(opline).var));
+ if (opline->result_type == IS_VAR) {
+ var_num = VAR_NUM(opline->result.var);
+ zend_bitset_incl(defined_here, var_num);
+ } else if (opline->result_type == IS_TMP_VAR) {
+ var_num = VAR_NUM(opline->result.var);
+ switch (opline->opcode) {
+ case ZEND_ADD_ARRAY_ELEMENT:
+ case ZEND_ROPE_ADD:
+ /* these opcodes use the result as argument */
+ if (!zend_bitset_in(defined_here, var_num)) {
+ zend_bitset_incl(used_ext, var_num);
+ }
+ break;
+ default :
+ zend_bitset_incl(defined_here, var_num);
}
- zend_bitset_incl(defined_here, VAR_NUM(ZEND_RESULT(opline).var));
}
opline++;
}
- next_block = next_block->next;
}
-#if DEBUG_BLOCKPASS
+#if DEBUG_BLOCKPASS > 2
{
- int i;
+ int printed = 0;
+ uint32_t i;
+
for (i = op_array->last_var; i< op_array->T; i++) {
- fprintf(stderr, "T%d: %c\n", i, zend_bitset_in(used_ext, i) + '0');
+ if (zend_bitset_in(used_ext, i)) {
+ if (!printed) {
+ fprintf(stderr, "NON-LOCAL-VARS: %s: %d", op_array->function_name ? op_array->function_name->val : "(null)", i);
+ printed = 1;
+ } else {
+ fprintf(stderr, ", %d", i);
+ }
+ }
+ }
+ if (printed) {
+ fprintf(stderr, "\n");
+ zend_dump_op_array(op_array, cfg, 0);
}
}
#endif
- while (block) {
- zend_op *opline = block->start_opline + block->len - 1;
+ for (n = 0; n < cfg->blocks_count; n++) {
+ block = cfg->blocks + n;
- if (!block->access) {
- block = block->next;
+ if (!(block->flags & ZEND_BB_REACHABLE)) {
continue;
}
+ opline = op_array->opcodes + block->end;
+ end = op_array->opcodes + block->start;
zend_bitset_copy(usage, used_ext, bitset_len);
- while (opline >= block->start_opline) {
+ while (opline >= end) {
/* usage checks */
- if (RES_NEVER_USED(opline)) {
- switch (opline->opcode) {
- case ZEND_ASSIGN_ADD:
- case ZEND_ASSIGN_SUB:
- case ZEND_ASSIGN_MUL:
- case ZEND_ASSIGN_DIV:
- case ZEND_ASSIGN_POW:
- 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_PRE_INC:
- case ZEND_PRE_DEC:
- case ZEND_POST_INC:
- case ZEND_POST_DEC:
- case ZEND_ASSIGN:
- case ZEND_ASSIGN_REF:
- case ZEND_DO_FCALL:
- case ZEND_DO_ICALL:
- case ZEND_DO_UCALL:
- case ZEND_DO_FCALL_BY_NAME:
- if (ZEND_RESULT_TYPE(opline) == IS_VAR) {
- ZEND_RESULT_TYPE(opline) |= EXT_TYPE_UNUSED;
- }
- break;
- case ZEND_QM_ASSIGN:
- case ZEND_BOOL:
- case ZEND_BOOL_NOT:
- if (ZEND_OP1_TYPE(opline) == IS_CONST) {
- literal_dtor(&ZEND_OP1_LITERAL(opline));
- }
- MAKE_NOP(opline);
- break;
- case ZEND_JMPZ_EX:
- case ZEND_JMPNZ_EX:
- opline->opcode -= 3;
- SET_UNUSED(opline->result);
- break;
- }
- }
-
- if (opline->opcode == ZEND_ADD_ARRAY_ELEMENT) {
- if (ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_TMP_VAR) {
- zend_bitset_incl(usage, VAR_NUM(ZEND_RESULT(opline).var));
+ if (opline->result_type == IS_VAR) {
+ if (!zend_bitset_in(usage, VAR_NUM(opline->result.var))) {
+ switch (opline->opcode) {
+ case ZEND_ASSIGN_ADD:
+ case ZEND_ASSIGN_SUB:
+ case ZEND_ASSIGN_MUL:
+ case ZEND_ASSIGN_DIV:
+ case ZEND_ASSIGN_POW:
+ 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_PRE_INC:
+ case ZEND_PRE_DEC:
+ case ZEND_ASSIGN:
+ case ZEND_ASSIGN_REF:
+ case ZEND_DO_FCALL:
+ case ZEND_DO_ICALL:
+ case ZEND_DO_UCALL:
+ case ZEND_DO_FCALL_BY_NAME:
+ opline->result_type |= EXT_TYPE_UNUSED;
+ break;
+ }
+ } else {
+ zend_bitset_excl(usage, VAR_NUM(opline->result.var));
}
- } else {
- if (RESULT_USED(opline)) {
- zend_bitset_excl(usage, VAR_NUM(ZEND_RESULT(opline).var));
+ } else if (opline->result_type == IS_TMP_VAR) {
+ if (!zend_bitset_in(usage, VAR_NUM(opline->result.var))) {
+ switch (opline->opcode) {
+ case ZEND_POST_INC:
+ case ZEND_POST_DEC:
+ opline->opcode -= 2;
+ opline->result_type = IS_VAR | EXT_TYPE_UNUSED;
+ break;
+ case ZEND_QM_ASSIGN:
+ case ZEND_BOOL:
+ case ZEND_BOOL_NOT:
+ if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+ literal_dtor(&ZEND_OP1_LITERAL(opline));
+ }
+ MAKE_NOP(opline);
+ break;
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+ opline->opcode -= 3;
+ SET_UNUSED(opline->result);
+ break;
+ case ZEND_ADD_ARRAY_ELEMENT:
+ case ZEND_ROPE_ADD:
+ zend_bitset_incl(usage, VAR_NUM(opline->result.var));
+ break;
+ }
+ } else {
+ switch (opline->opcode) {
+ case ZEND_ADD_ARRAY_ELEMENT:
+ case ZEND_ROPE_ADD:
+ break;
+ default:
+ zend_bitset_excl(usage, VAR_NUM(opline->result.var));
+ break;
+ }
}
}
- if (ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_TMP_VAR) {
- zend_bitset_incl(usage, VAR_NUM(ZEND_OP1(opline).var));
+ if (opline->op2_type == IS_VAR) {
+ switch (opline->opcode) {
+ case ZEND_FE_FETCH_R:
+ case ZEND_FE_FETCH_RW:
+ zend_bitset_excl(usage, VAR_NUM(opline->op2.var));
+ break;
+ default:
+ zend_bitset_incl(usage, VAR_NUM(opline->op2.var));
+ break;
+ }
+ } else if (opline->op2_type == IS_TMP_VAR) {
+ zend_bitset_incl(usage, VAR_NUM(opline->op2.var));
}
- if (ZEND_OP2_TYPE(opline) == IS_VAR || ZEND_OP2_TYPE(opline) == IS_TMP_VAR) {
- zend_bitset_incl(usage, VAR_NUM(ZEND_OP2(opline).var));
+ if (opline->op1_type == IS_VAR || opline->op1_type == IS_TMP_VAR) {
+ zend_bitset_incl(usage, VAR_NUM(opline->op1.var));
}
- if ((ZEND_RESULT_TYPE(opline) & IS_VAR) &&
- (ZEND_RESULT_TYPE(opline) & EXT_TYPE_UNUSED) &&
- zend_bitset_in(usage, VAR_NUM(ZEND_RESULT(opline).var))) {
- ZEND_RESULT_TYPE(opline) &= ~EXT_TYPE_UNUSED;
- }
-
opline--;
}
- block = block->next;
- } /* end blocks */
+ }
zend_arena_release(&ctx->arena, checkpoint);
}
+static void zend_merge_blocks(zend_op_array *op_array, zend_cfg *cfg)
+{
+ int i;
+ zend_basic_block *b, *bb;
+ zend_basic_block *prev = NULL;
+
+ for (i = 0; i < cfg->blocks_count; i++) {
+ b = cfg->blocks + i;
+ if (b->flags & ZEND_BB_REACHABLE) {
+ if ((b->flags & ZEND_BB_FOLLOW) &&
+ !(b->flags & (ZEND_BB_TARGET | ZEND_BB_PROTECTED)) &&
+ prev &&
+ prev->successors[0] == i && prev->successors[1] == -1) {
+
+ if (op_array->opcodes[prev->end].opcode == ZEND_JMP) {
+ MAKE_NOP(op_array->opcodes + prev->end);
+ }
+
+ for (bb = prev + 1; bb != b; bb++) {
+ zend_op *op = op_array->opcodes + bb->start;
+ zend_op *end = op_array->opcodes + bb->end;
+ while (op <= end) {
+ if (ZEND_OP1_TYPE(op) == IS_CONST) {
+ literal_dtor(&ZEND_OP1_LITERAL(op));
+ }
+ if (ZEND_OP2_TYPE(op) == IS_CONST) {
+ literal_dtor(&ZEND_OP2_LITERAL(op));
+ }
+ MAKE_NOP(op);
+ op++;
+ }
+ /* make block empty */
+ bb->start = bb->end + 1;
+ }
+
+ /* re-link */
+ prev->flags |= (b->flags & ZEND_BB_EXIT);
+ prev->end = b->end;
+ prev->successors[0] = b->successors[0];
+ prev->successors[1] = b->successors[1];
+
+ /* unlink & make block empty and unreachable */
+ b->flags = 0;
+ b->start = b->end + 1;
+ b->successors[0] = -1;
+ b->successors[1] = -1;
+ } else {
+ prev = b;
+ }
+ }
+ }
+}
+
#define PASSES 3
void optimize_cfg(zend_op_array *op_array, zend_optimizer_ctx *ctx)
{
zend_cfg cfg;
- zend_code_block *cur_block;
+ zend_basic_block *blocks, *end, *b;
int pass;
uint32_t bitset_len;
zend_bitset usage;
void *checkpoint;
+ zend_op **Tsource;
+ zend_uchar *same_t;
#if DEBUG_BLOCKPASS
- fprintf(stderr, "File %s func %s\n", op_array->filename, op_array->function_name? op_array->function_name : "main");
+ fprintf(stderr, "File %s func %s\n", op_array->filename->val, op_array->function_name ? op_array->function_name->val : "main");
fflush(stderr);
#endif
- if (op_array->fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK) {
- return;
- }
-
/* Build CFG */
checkpoint = zend_arena_checkpoint(ctx->arena);
- if (!find_code_blocks(op_array, &cfg, ctx)) {
+ if (zend_build_cfg(&ctx->arena, op_array, 0, 0, &cfg, NULL) != SUCCESS) {
zend_arena_release(&ctx->arena, checkpoint);
return;
}
- zend_rebuild_access_path(&cfg, op_array, 0, ctx);
- /* full rebuild here to produce correct sources! */
+#if DEBUG_BLOCKPASS
+ fprintf(stderr, "\nBEFORE-BLOCK-PASS: %s:\n", op_array->function_name ? op_array->function_name->val : "(null)");
+ zend_dump_op_array(op_array, &cfg, 1);
+#endif
+
if (op_array->last_var || op_array->T) {
bitset_len = zend_bitset_len(op_array->last_var + op_array->T);
- cfg.Tsource = zend_arena_calloc(&ctx->arena, op_array->last_var + op_array->T, sizeof(zend_op *));
- cfg.same_t = zend_arena_alloc(&ctx->arena, op_array->last_var + op_array->T);
+ Tsource = zend_arena_calloc(&ctx->arena, op_array->last_var + op_array->T, sizeof(zend_op *));
+ same_t = zend_arena_alloc(&ctx->arena, op_array->last_var + op_array->T);
usage = zend_arena_alloc(&ctx->arena, bitset_len * ZEND_BITSET_ELM_SIZE);
} else {
bitset_len = 0;
- cfg.Tsource = NULL;
- cfg.same_t = NULL;
+ Tsource = NULL;
+ same_t = NULL;
usage = NULL;
}
+ blocks = cfg.blocks;
+ end = blocks + cfg.blocks_count;
for (pass = 0; pass < PASSES; pass++) {
/* Compute data dependencies */
zend_bitset_clear(usage, bitset_len);
- zend_t_usage(cfg.blocks, op_array, usage, ctx);
+ zend_t_usage(&cfg, op_array, usage, ctx);
/* optimize each basic block separately */
- for (cur_block = cfg.blocks; cur_block; cur_block = cur_block->next) {
- if (!cur_block->access) {
- continue;
+ for (b = blocks; b < end; b++) {
+ if (b->flags & ZEND_BB_REACHABLE) {
+ zend_optimize_block(b, op_array, usage, &cfg, Tsource);
}
- zend_optimize_block(cur_block, op_array, usage, &cfg, ctx);
}
/* Jump optimization for each block */
- for (cur_block = cfg.blocks; cur_block; cur_block = cur_block->next) {
- if (!cur_block->access) {
- continue;
+ for (b = blocks; b < end; b++) {
+ if (b->flags & ZEND_BB_REACHABLE) {
+ zend_jmp_optimization(b, op_array, &cfg, same_t);
}
- zend_jmp_optimization(cur_block, op_array, cfg.blocks, &cfg, ctx);
}
/* Eliminate unreachable basic blocks */
- zend_rebuild_access_path(&cfg, op_array, 1, ctx);
+ zend_remark_reachable_blocks(op_array, &cfg);
+
+ /* Merge Blocks */
+ zend_merge_blocks(op_array, &cfg);
}
zend_bitset_clear(usage, bitset_len);
- zend_t_usage(cfg.blocks, op_array, usage, ctx);
+ zend_t_usage(&cfg, op_array, usage, ctx);
assemble_code_blocks(&cfg, op_array);
+#if DEBUG_BLOCKPASS
+ fprintf(stderr, "\nAFTER-BLOCK-PASS: %s:\n", op_array->function_name ? op_array->function_name->val : "(null)");
+ zend_dump_op_array(op_array, &cfg, 0);
+#endif
+
/* Destroy CFG */
zend_arena_release(&ctx->arena, checkpoint);
}
diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c
index 7650ae1cc5..518708b625 100644
--- a/ext/opcache/Optimizer/compact_literals.c
+++ b/ext/opcache/Optimizer/compact_literals.c
@@ -177,25 +177,24 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
LITERAL_INFO(opline->op1.constant, LITERAL_CONST, 1, 1, 2);
break;
case ZEND_FETCH_CONSTANT:
- if (ZEND_OP1_TYPE(opline) == IS_UNUSED) {
- if ((opline->extended_value & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
- LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 5);
- } else {
- LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 3);
- }
+ if ((opline->extended_value & (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) == (IS_CONSTANT_IN_NAMESPACE|IS_CONSTANT_UNQUALIFIED)) {
+ LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 5);
} else {
- if (ZEND_OP1_TYPE(opline) == IS_CONST) {
- LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
- }
- optimizer_literal_class_info(
- info,
- opline->op1_type,
- opline->op1,
- opline->op2.constant,
- LITERAL_CLASS_CONST, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 1,
- op_array);
+ LITERAL_INFO(opline->op2.constant, LITERAL_CONST, 1, 1, 3);
}
break;
+ case ZEND_FETCH_CLASS_CONSTANT:
+ if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+ LITERAL_INFO(opline->op1.constant, LITERAL_CLASS, 1, 1, 2);
+ }
+ optimizer_literal_class_info(
+ info,
+ opline->op1_type,
+ opline->op1,
+ opline->op2.constant,
+ LITERAL_CLASS_CONST, (ZEND_OP1_TYPE(opline) == IS_CONST) ? 1 : 2, 1,
+ op_array);
+ break;
case ZEND_FETCH_R:
case ZEND_FETCH_W:
case ZEND_FETCH_RW:
@@ -204,23 +203,29 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
case ZEND_FETCH_FUNC_ARG:
case ZEND_UNSET_VAR:
case ZEND_ISSET_ISEMPTY_VAR:
- if (ZEND_OP2_TYPE(opline) == IS_UNUSED) {
- if (ZEND_OP1_TYPE(opline) == IS_CONST) {
- LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
- }
- } else {
- if (ZEND_OP2_TYPE(opline) == IS_CONST) {
- LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
- }
- if (ZEND_OP1_TYPE(opline) == IS_CONST) {
- optimizer_literal_class_info(
- info,
- opline->op2_type,
- opline->op2,
- opline->op1.constant,
- LITERAL_STATIC_PROPERTY, 2, 1,
- op_array);
- }
+ if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+ LITERAL_INFO(opline->op1.constant, LITERAL_VALUE, 1, 0, 1);
+ }
+ break;
+ case ZEND_FETCH_STATIC_PROP_R:
+ case ZEND_FETCH_STATIC_PROP_W:
+ case ZEND_FETCH_STATIC_PROP_RW:
+ case ZEND_FETCH_STATIC_PROP_IS:
+ case ZEND_FETCH_STATIC_PROP_UNSET:
+ case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
+ case ZEND_UNSET_STATIC_PROP:
+ case ZEND_ISSET_ISEMPTY_STATIC_PROP:
+ if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+ LITERAL_INFO(opline->op2.constant, LITERAL_CLASS, 1, 1, 2);
+ }
+ if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+ optimizer_literal_class_info(
+ info,
+ opline->op2_type,
+ opline->op2,
+ opline->op1.constant,
+ LITERAL_STATIC_PROPERTY, 2, 1,
+ op_array);
}
break;
case ZEND_FETCH_CLASS:
diff --git a/ext/opcache/Optimizer/nop_removal.c b/ext/opcache/Optimizer/nop_removal.c
index 0869bc715c..4f6983c795 100644
--- a/ext/opcache/Optimizer/nop_removal.c
+++ b/ext/opcache/Optimizer/nop_removal.c
@@ -39,15 +39,15 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
uint32_t *shiftlist;
ALLOCA_FLAG(use_heap);
- shiftlist = (uint32_t *)DO_ALLOCA(sizeof(uint32_t) * op_array->last);
+ shiftlist = (uint32_t *)do_alloca(sizeof(uint32_t) * op_array->last, use_heap);
i = new_count = shift = 0;
end = op_array->opcodes + op_array->last;
for (opline = op_array->opcodes; opline < end; opline++) {
/* Kill JMP-over-NOP-s */
- if (opline->opcode == ZEND_JMP && ZEND_OP1(opline).opline_num > i) {
+ if (opline->opcode == ZEND_JMP && ZEND_OP1_JMP_ADDR(opline) > op_array->opcodes + i) {
/* check if there are only NOPs under the branch */
- zend_op *target = op_array->opcodes + ZEND_OP1(opline).opline_num - 1;
+ zend_op *target = ZEND_OP1_JMP_ADDR(opline) - 1;
while (target->opcode == ZEND_NOP) {
target--;
@@ -63,7 +63,41 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
shift++;
} else {
if (shift) {
- op_array->opcodes[new_count] = *opline;
+ zend_op *new_opline = op_array->opcodes + new_count;
+
+ *new_opline = *opline;
+ switch (new_opline->opcode) {
+ case ZEND_JMP:
+ case ZEND_FAST_CALL:
+ case ZEND_DECLARE_ANON_CLASS:
+ case ZEND_DECLARE_ANON_INHERITED_CLASS:
+ ZEND_SET_OP_JMP_ADDR(new_opline, new_opline->op1, ZEND_OP1_JMP_ADDR(opline));
+ break;
+ case ZEND_JMPZNZ:
+ new_opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, new_opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
+ /* break missing intentionally */
+ case ZEND_JMPZ:
+ case ZEND_JMPNZ:
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+ case ZEND_FE_RESET_R:
+ case ZEND_FE_RESET_RW:
+ case ZEND_NEW:
+ case ZEND_JMP_SET:
+ case ZEND_COALESCE:
+ case ZEND_ASSERT_CHECK:
+ ZEND_SET_OP_JMP_ADDR(new_opline, new_opline->op2, ZEND_OP2_JMP_ADDR(opline));
+ break;
+ case ZEND_CATCH:
+ if (!opline->result.num) {
+ new_opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, new_opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
+ }
+ break;
+ case ZEND_FE_FETCH_R:
+ case ZEND_FE_FETCH_RW:
+ new_opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, new_opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
+ break;
+ }
}
new_count++;
}
@@ -80,8 +114,11 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
case ZEND_FAST_CALL:
case ZEND_DECLARE_ANON_CLASS:
case ZEND_DECLARE_ANON_INHERITED_CLASS:
- ZEND_OP1(opline).opline_num -= shiftlist[ZEND_OP1(opline).opline_num];
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op1, ZEND_OP1_JMP_ADDR(opline) - shiftlist[ZEND_OP1_JMP_ADDR(opline) - op_array->opcodes]);
break;
+ case ZEND_JMPZNZ:
+ opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value) - shiftlist[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]);
+ /* break missing intentionally */
case ZEND_JMPZ:
case ZEND_JMPNZ:
case ZEND_JMPZ_EX:
@@ -92,27 +129,20 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
case ZEND_JMP_SET:
case ZEND_COALESCE:
case ZEND_ASSERT_CHECK:
- ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num];
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(opline) - shiftlist[ZEND_OP2_JMP_ADDR(opline) - op_array->opcodes]);
break;
case ZEND_FE_FETCH_R:
case ZEND_FE_FETCH_RW:
- opline->extended_value -= shiftlist[opline->extended_value];
- break;
- case ZEND_JMPZNZ:
- ZEND_OP2(opline).opline_num -= shiftlist[ZEND_OP2(opline).opline_num];
- opline->extended_value -= shiftlist[opline->extended_value];
- break;
case ZEND_CATCH:
- opline->extended_value -= shiftlist[opline->extended_value];
+ opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value) - shiftlist[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]);
break;
}
}
/* update brk/cont array */
- for (j = 0; j < op_array->last_brk_cont; j++) {
- op_array->brk_cont_array[j].brk -= shiftlist[op_array->brk_cont_array[j].brk];
- op_array->brk_cont_array[j].cont -= shiftlist[op_array->brk_cont_array[j].cont];
- op_array->brk_cont_array[j].start -= shiftlist[op_array->brk_cont_array[j].start];
+ for (j = 0; j < op_array->last_live_range; j++) {
+ op_array->live_range[j].start -= shiftlist[op_array->live_range[j].start];
+ op_array->live_range[j].end -= shiftlist[op_array->live_range[j].end];
}
/* update try/catch array */
@@ -135,5 +165,5 @@ void zend_optimizer_nop_removal(zend_op_array *op_array)
} while (*opline_num != (uint32_t)-1);
}
}
- FREE_ALLOCA(shiftlist);
+ free_alloca(shiftlist, use_heap);
}
diff --git a/ext/opcache/Optimizer/optimize_func_calls.c b/ext/opcache/Optimizer/optimize_func_calls.c
index c82df24c58..68597b1d5d 100644
--- a/ext/opcache/Optimizer/optimize_func_calls.c
+++ b/ext/opcache/Optimizer/optimize_func_calls.c
@@ -105,15 +105,24 @@ void optimize_func_calls(zend_op_array *op_array, zend_optimizer_ctx *ctx)
call_stack[call].opline = NULL;
break;
case ZEND_FETCH_FUNC_ARG:
+ case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
case ZEND_FETCH_OBJ_FUNC_ARG:
case ZEND_FETCH_DIM_FUNC_ARG:
if (call_stack[call - 1].func) {
if (ARG_SHOULD_BE_SENT_BY_REF(call_stack[call - 1].func, (opline->extended_value & ZEND_FETCH_ARG_MASK))) {
opline->extended_value &= ZEND_FETCH_TYPE_MASK;
- opline->opcode -= 9;
+ if (opline->opcode != ZEND_FETCH_STATIC_PROP_FUNC_ARG) {
+ opline->opcode -= 9;
+ } else {
+ opline->opcode = ZEND_FETCH_STATIC_PROP_W;
+ }
} else {
opline->extended_value &= ZEND_FETCH_TYPE_MASK;
- opline->opcode -= 12;
+ if (opline->opcode != ZEND_FETCH_STATIC_PROP_FUNC_ARG) {
+ opline->opcode -= 12;
+ } else {
+ opline->opcode = ZEND_FETCH_STATIC_PROP_R;
+ }
}
}
break;
diff --git a/ext/opcache/Optimizer/optimize_temp_vars_5.c b/ext/opcache/Optimizer/optimize_temp_vars_5.c
index 172f9a1a62..586471017c 100644
--- a/ext/opcache/Optimizer/optimize_temp_vars_5.c
+++ b/ext/opcache/Optimizer/optimize_temp_vars_5.c
@@ -224,6 +224,14 @@ void optimize_temporary_variables(zend_op_array *op_array, zend_optimizer_ctx *c
opline--;
}
+ if (op_array->live_range) {
+ for (i = 0; i < op_array->last_live_range; i++) {
+ op_array->live_range[i].var =
+ NUM_VAR(map_T[VAR_NUM(op_array->live_range[i].var & ~ZEND_LIVE_MASK) - offset] + offset) |
+ (op_array->live_range[i].var & ZEND_LIVE_MASK);
+ }
+ }
+
zend_arena_release(&ctx->arena, checkpoint);
op_array->T = max + 1;
}
diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c
index 766eb2c2d4..abdc490c0a 100644
--- a/ext/opcache/Optimizer/pass1_5.c
+++ b/ext/opcache/Optimizer/pass1_5.c
@@ -238,8 +238,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
#endif
case ZEND_FETCH_CONSTANT:
- if (ZEND_OP1_TYPE(opline) == IS_UNUSED &&
- ZEND_OP2_TYPE(opline) == IS_CONST &&
+ if (ZEND_OP2_TYPE(opline) == IS_CONST &&
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING &&
Z_STRLEN(ZEND_OP2_LITERAL(opline)) == sizeof("__COMPILER_HALT_OFFSET__") - 1 &&
memcmp(Z_STRVAL(ZEND_OP2_LITERAL(opline)), "__COMPILER_HALT_OFFSET__", sizeof("__COMPILER_HALT_OFFSET__") - 1) == 0) {
@@ -263,8 +262,7 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
break;
}
- if (ZEND_OP1_TYPE(opline) == IS_UNUSED &&
- ZEND_OP2_TYPE(opline) == IS_CONST &&
+ if (ZEND_OP2_TYPE(opline) == IS_CONST &&
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
/* substitute persistent constants */
uint32_t tv = ZEND_RESULT(opline).var;
@@ -283,10 +281,10 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
MAKE_NOP(opline);
}
}
+ break;
- /* class constant */
- if (ZEND_OP1_TYPE(opline) != IS_UNUSED &&
- ZEND_OP2_TYPE(opline) == IS_CONST &&
+ case ZEND_FETCH_CLASS_CONSTANT:
+ if (ZEND_OP2_TYPE(opline) == IS_CONST &&
Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_STRING) {
zend_class_entry *ce = NULL;
@@ -304,15 +302,20 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
(ce->type == ZEND_INTERNAL_CLASS &&
ce->info.internal.module->type != MODULE_PERSISTENT) ||
(ce->type == ZEND_USER_CLASS &&
- ZEND_CE_FILENAME(ce) != op_array->filename)) {
+ ce->info.user.filename != op_array->filename)) {
break;
}
}
} else if (op_array->scope &&
+ ZEND_OP1_TYPE(opline) == IS_UNUSED &&
+ (opline->op1.num & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) {
+ /* for self::B */
+ ce = op_array->scope;
+ } else if (op_array->scope &&
ZEND_OP1_TYPE(opline) == IS_VAR &&
(opline - 1)->opcode == ZEND_FETCH_CLASS &&
(ZEND_OP1_TYPE(opline - 1) == IS_UNUSED &&
- ((opline - 1)->extended_value & ~ZEND_FETCH_CLASS_NO_AUTOLOAD) == ZEND_FETCH_CLASS_SELF) &&
+ ((opline - 1)->extended_value & ZEND_FETCH_CLASS_MASK) == ZEND_FETCH_CLASS_SELF) &&
ZEND_RESULT((opline - 1)).var == ZEND_OP1(opline).var) {
/* for self::B */
ce = op_array->scope;
@@ -338,12 +341,12 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
zval_copy_ctor(&t);
}
- if (ZEND_OP1_TYPE(opline) == IS_CONST) {
- literal_dtor(&ZEND_OP1_LITERAL(opline));
- } else {
- MAKE_NOP((opline - 1));
- }
if (zend_optimizer_replace_by_const(op_array, opline, IS_TMP_VAR, tv, &t)) {
+ if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+ literal_dtor(&ZEND_OP1_LITERAL(opline));
+ } else if (ZEND_OP1_TYPE(opline) == IS_VAR) {
+ MAKE_NOP((opline - 1));
+ }
literal_dtor(&ZEND_OP2_LITERAL(opline));
MAKE_NOP(opline);
}
@@ -642,68 +645,6 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
case ZEND_ASSERT_CHECK:
collect_constants = 0;
break;
- case ZEND_FETCH_R:
- case ZEND_FETCH_W:
- case ZEND_FETCH_RW:
- case ZEND_FETCH_FUNC_ARG:
- case ZEND_FETCH_IS:
- case ZEND_FETCH_UNSET:
- if (opline != op_array->opcodes &&
- (opline-1)->opcode == ZEND_BEGIN_SILENCE &&
- (opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_LOCAL &&
- opline->op1_type == IS_CONST &&
- opline->op2_type == IS_UNUSED &&
- Z_TYPE(ZEND_OP1_LITERAL(opline)) == IS_STRING &&
- (Z_STRLEN(ZEND_OP1_LITERAL(opline)) != sizeof("this")-1 ||
- memcmp(Z_STRVAL(ZEND_OP1_LITERAL(opline)), "this", sizeof("this") - 1) != 0)) {
-
- int var = opline->result.var;
- int level = 0;
- zend_op *op = opline + 1;
- zend_op *use = NULL;
-
- while (op < end) {
- if (op->opcode == ZEND_BEGIN_SILENCE) {
- level++;
- } else if (op->opcode == ZEND_END_SILENCE) {
- if (level == 0) {
- break;
- } else {
- level--;
- }
- }
- if (op->op1_type == IS_VAR && op->op1.var == var) {
- if (use) {
- /* used more than once */
- use = NULL;
- break;
- }
- use = op;
- } else if (op->op2_type == IS_VAR && op->op2.var == var) {
- if (use) {
- /* used more than once */
- use = NULL;
- break;
- }
- use = op;
- }
- op++;
- }
- if (use) {
- if (use->op1_type == IS_VAR && use->op1.var == var) {
- use->op1_type = IS_CV;
- use->op1.var = zend_optimizer_lookup_cv(op_array,
- Z_STR(ZEND_OP1_LITERAL(opline)));
- MAKE_NOP(opline);
- } else if (use->op2_type == IS_VAR && use->op2.var == var) {
- use->op2_type = IS_CV;
- use->op2.var = zend_optimizer_lookup_cv(op_array,
- Z_STR(ZEND_OP1_LITERAL(opline)));
- MAKE_NOP(opline);
- }
- }
- }
- break;
}
opline++;
i++;
diff --git a/ext/opcache/Optimizer/pass2.c b/ext/opcache/Optimizer/pass2.c
index 143167f816..3573c1038c 100644
--- a/ext/opcache/Optimizer/pass2.c
+++ b/ext/opcache/Optimizer/pass2.c
@@ -154,15 +154,15 @@ void zend_optimizer_pass2(zend_op_array *op_array)
if ((opline + 1)->opcode == ZEND_JMP) {
/* JMPZ(X, L1), JMP(L2) => JMPZNZ(X, L1, L2) */
/* JMPNZ(X, L1), JMP(L2) => JMPZNZ(X, L2, L1) */
- if (ZEND_OP2(opline).opline_num == ZEND_OP1(opline + 1).opline_num) {
+ if (ZEND_OP2_JMP_ADDR(opline) == ZEND_OP1_JMP_ADDR(opline + 1)) {
/* JMPZ(X, L1), JMP(L1) => NOP, JMP(L1) */
MAKE_NOP(opline);
} else {
if (opline->opcode == ZEND_JMPZ) {
- opline->extended_value = ZEND_OP1(opline + 1).opline_num;
+ opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP1_JMP_ADDR(opline + 1));
} else {
- opline->extended_value = ZEND_OP2(opline).opline_num;
- COPY_NODE(opline->op2, (opline + 1)->op1);
+ opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP2_JMP_ADDR(opline));
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(opline + 1));
}
opline->opcode = ZEND_JMPZNZ;
}
@@ -171,14 +171,15 @@ void zend_optimizer_pass2(zend_op_array *op_array)
case ZEND_JMPZNZ:
if (ZEND_OP1_TYPE(opline) == IS_CONST) {
- int opline_num;
+ zend_op *target_opline;
+
if (zend_is_true(&ZEND_OP1_LITERAL(opline))) {
- opline_num = opline->extended_value; /* JMPNZ */
+ target_opline = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value); /* JMPNZ */
} else {
- opline_num = ZEND_OP2(opline).opline_num; /* JMPZ */
+ target_opline = ZEND_OP2_JMP_ADDR(opline); /* JMPZ */
}
literal_dtor(&ZEND_OP1_LITERAL(opline));
- ZEND_OP1(opline).opline_num = opline_num;
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op1, target_opline);
ZEND_OP1_TYPE(opline) = IS_UNUSED;
opline->opcode = ZEND_JMP;
}
diff --git a/ext/opcache/Optimizer/pass3.c b/ext/opcache/Optimizer/pass3.c
index 3e589df628..6aeaf8310b 100644
--- a/ext/opcache/Optimizer/pass3.c
+++ b/ext/opcache/Optimizer/pass3.c
@@ -39,31 +39,31 @@
/* we use "jmp_hitlist" to avoid infinity loops during jmp optimization */
#define CHECK_JMP(target, label) \
for (i=0; i<jmp_hitlist_count; i++) { \
- if (jmp_hitlist[i] == ZEND_OP1(&op_array->opcodes[target]).opline_num) { \
+ if (jmp_hitlist[i] == ZEND_OP1_JMP_ADDR(target)) { \
goto label; \
} \
} \
- jmp_hitlist[jmp_hitlist_count++] = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+ jmp_hitlist[jmp_hitlist_count++] = ZEND_OP1_JMP_ADDR(target);
#define CHECK_JMP2(target, label) \
for (i=0; i<jmp_hitlist_count; i++) { \
- if (jmp_hitlist[i] == ZEND_OP2(&op_array->opcodes[target]).opline_num) { \
+ if (jmp_hitlist[i] == ZEND_OP2_JMP_ADDR(target)) { \
goto label; \
} \
} \
- jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2(&op_array->opcodes[target]).opline_num;
+ jmp_hitlist[jmp_hitlist_count++] = ZEND_OP2_JMP_ADDR(target);
void zend_optimizer_pass3(zend_op_array *op_array)
{
zend_op *opline;
zend_op *end = op_array->opcodes + op_array->last;
- uint32_t *jmp_hitlist;
+ zend_op **jmp_hitlist;
int jmp_hitlist_count;
int i;
uint32_t opline_num = 0;
ALLOCA_FLAG(use_heap);
- jmp_hitlist = (uint32_t *)DO_ALLOCA(sizeof(uint32_t)*op_array->last);
+ jmp_hitlist = (zend_op**)do_alloca(sizeof(zend_op*)*op_array->last, use_heap);
opline = op_array->opcodes;
while (opline < end) {
@@ -93,7 +93,7 @@ void zend_optimizer_pass3(zend_op_array *op_array)
break;
}
- if ((ZEND_OP2_TYPE(opline) == IS_VAR || ZEND_OP2_TYPE(opline) == IS_CV)
+ if ((ZEND_OP2_TYPE(opline) & (IS_VAR | IS_CV))
&& ZEND_OP2(opline).var == ZEND_OP1(next_opline).var &&
(opline->opcode == ZEND_ADD ||
opline->opcode == ZEND_MUL ||
@@ -112,7 +112,7 @@ void zend_optimizer_pass3(zend_op_array *op_array)
COPY_NODE(opline->op2, tmp);
}
}
- if ((ZEND_OP1_TYPE(opline) == IS_VAR || ZEND_OP1_TYPE(opline) == IS_CV)
+ if ((ZEND_OP1_TYPE(opline) & (IS_VAR | IS_CV))
&& ZEND_OP1(opline).var == ZEND_OP1(next_opline).var
&& ZEND_OP1_TYPE(opline) == ZEND_OP1_TYPE(next_opline)) {
switch (opline->opcode) {
@@ -167,17 +167,17 @@ void zend_optimizer_pass3(zend_op_array *op_array)
}
/* convert L: JMP L+1 to NOP */
- if (ZEND_OP1(opline).opline_num == opline_num + 1) {
+ if (ZEND_OP1_JMP_ADDR(opline) == opline + 1) {
MAKE_NOP(opline);
goto done_jmp_optimization;
}
/* convert JMP L1 ... L1: JMP L2 to JMP L2 .. L1: JMP L2 */
- while (ZEND_OP1(opline).opline_num < op_array->last
- && op_array->opcodes[ZEND_OP1(opline).opline_num].opcode == ZEND_JMP) {
- int target = ZEND_OP1(opline).opline_num;
+ while (ZEND_OP1_JMP_ADDR(opline) < end
+ && ZEND_OP1_JMP_ADDR(opline)->opcode == ZEND_JMP) {
+ zend_op *target = ZEND_OP1_JMP_ADDR(opline);
CHECK_JMP(target, done_jmp_optimization);
- ZEND_OP1(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op1, ZEND_OP1_JMP_ADDR(target));
}
break;
@@ -187,10 +187,10 @@ void zend_optimizer_pass3(zend_op_array *op_array)
break;
}
- while (ZEND_OP2(opline).opline_num < op_array->last) {
- int target = ZEND_OP2(opline).opline_num;
- if (op_array->opcodes[target].opcode == ZEND_JMP) {
- ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+ while (ZEND_OP2_JMP_ADDR(opline) < end) {
+ zend_op *target = ZEND_OP2_JMP_ADDR(opline);
+ if (target->opcode == ZEND_JMP) {
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
} else {
break;
}
@@ -202,40 +202,41 @@ void zend_optimizer_pass3(zend_op_array *op_array)
break;
}
- while (ZEND_OP2(opline).opline_num < op_array->last) {
- int target = ZEND_OP2(opline).opline_num;
+ while (ZEND_OP2_JMP_ADDR(opline) < end) {
+ zend_op *target = ZEND_OP2_JMP_ADDR(opline);
- if (op_array->opcodes[target].opcode == ZEND_JMP) {
+ if (target->opcode == ZEND_JMP) {
/* plain JMP */
/* JMPZ(X,L1), L1: JMP(L2) => JMPZ(X,L2), L1: JMP(L2) */
CHECK_JMP(target, done_jmp_optimization);
- ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
- } else if (op_array->opcodes[target].opcode == opline->opcode &&
- SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
+ } else if (target->opcode == opline->opcode &&
+ SAME_VAR(opline->op1, target->op1)) {
/* same opcode and same var as this opcode */
/* JMPZ(X,L1), L1: JMPZ(X,L2) => JMPZ(X,L2), L1: JMPZ(X,L2) */
CHECK_JMP2(target, done_jmp_optimization);
- ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;
- } else if (op_array->opcodes[target].opcode == opline->opcode + 3 &&
- SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
+ } else if (target->opcode == opline->opcode + 3 &&
+ SAME_VAR(opline->op1, target->op1)) {
/* convert JMPZ(X,L1), L1: T JMPZ_EX(X,L2) to
T = JMPZ_EX(X, L2) */
- ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;opline->opcode += 3;
- COPY_NODE(opline->result, op_array->opcodes[target].result);
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
+ opline->opcode += 3;
+ COPY_NODE(opline->result, target->result);
break;
- } else if (op_array->opcodes[target].opcode == INV_COND(opline->opcode) &&
- SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+ } else if (target->opcode == INV_COND(opline->opcode) &&
+ SAME_VAR(opline->op1, target->op1)) {
/* convert JMPZ(X,L1), L1: JMPNZ(X,L2) to
JMPZ(X,L1+1) */
- ZEND_OP2(opline).opline_num = target + 1;
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
break;
- } else if (op_array->opcodes[target].opcode == INV_COND_EX(opline->opcode) &&
- SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+ } else if (target->opcode == INV_COND_EX(opline->opcode) &&
+ SAME_VAR(opline->op1, target->op1)) {
/* convert JMPZ(X,L1), L1: T = JMPNZ_EX(X,L2) to
T = JMPZ_EX(X,L1+1) */
- ZEND_OP2(opline).opline_num = target + 1;
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
opline->opcode += 3;
- COPY_NODE(opline->result, op_array->opcodes[target].result);
+ COPY_NODE(opline->result, target->result);
break;
} else {
break;
@@ -254,7 +255,7 @@ void zend_optimizer_pass3(zend_op_array *op_array)
/* convert L: T = JMPZ_EX X,L+1 to T = BOOL(X) */
/* convert L: T = JMPZ_EX T,L+1 to NOP */
- if (ZEND_OP2(opline).opline_num == opline_num + 1) {
+ if (ZEND_OP2_JMP_ADDR(opline) == opline + 1) {
if (ZEND_OP1(opline).var == ZEND_RESULT(opline).var) {
MAKE_NOP(opline);
} else {
@@ -264,36 +265,38 @@ void zend_optimizer_pass3(zend_op_array *op_array)
goto done_jmp_optimization;
}
- while (ZEND_OP2(opline).opline_num < op_array->last) {
- int target = ZEND_OP2(opline).opline_num;
- if (SAME_OPCODE_EX(opline->opcode, op_array->opcodes[target].opcode) &&
- SAME_VAR(op_array->opcodes[target].op1, T)) {
+ while (ZEND_OP2_JMP_ADDR(opline) < end) {
+ zend_op *target = ZEND_OP2_JMP_ADDR(opline);
+
+ if (SAME_OPCODE_EX(opline->opcode, target->opcode) &&
+ SAME_VAR(target->op1, T)) {
/* Check for JMPZ_EX to JMPZ[_EX] with the same condition, either with _EX or not */
- if (op_array->opcodes[target].opcode == opline->opcode) {
+ if (target->opcode == opline->opcode) {
/* change T only if we have _EX opcode there */
- COPY_NODE(T, op_array->opcodes[target].result);
+ COPY_NODE(T, target->result);
}
CHECK_JMP2(target, continue_jmp_ex_optimization);
- ZEND_OP2(opline).opline_num = ZEND_OP2(&op_array->opcodes[target]).opline_num;
- } else if (op_array->opcodes[target].opcode == ZEND_JMPZNZ &&
- SAME_VAR(op_array->opcodes[target].op1, T)) {
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP2_JMP_ADDR(target));
+ } else if (target->opcode == ZEND_JMPZNZ &&
+ SAME_VAR(target->op1, T)) {
/* Check for JMPZNZ with same cond variable */
- int new_target;
+ zend_op *new_target;
+
CHECK_JMP2(target, continue_jmp_ex_optimization);
if (opline->opcode == ZEND_JMPZ_EX) {
- new_target = ZEND_OP2(&op_array->opcodes[target]).opline_num;
+ new_target = ZEND_OP2_JMP_ADDR(target);
} else {
/* JMPNZ_EX */
- new_target = op_array->opcodes[target].extended_value;
+ new_target = ZEND_OFFSET_TO_OPLINE(target, target->extended_value);
}
- ZEND_OP2(opline).opline_num = new_target;
- } else if ((op_array->opcodes[target].opcode == INV_EX_COND_EX(opline->opcode) ||
- op_array->opcodes[target].opcode == INV_EX_COND(opline->opcode)) &&
- SAME_VAR(opline->op1, op_array->opcodes[target].op1)) {
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, new_target);
+ } else if ((target->opcode == INV_EX_COND_EX(opline->opcode) ||
+ target->opcode == INV_EX_COND(opline->opcode)) &&
+ SAME_VAR(opline->op1, target->op1)) {
/* convert JMPZ_EX(X,L1), L1: JMPNZ_EX(X,L2) to
JMPZ_EX(X,L1+1) */
- ZEND_OP2(opline).opline_num = target + 1;
- break;
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, target + 1);
+ break;
} else {
break;
}
@@ -385,19 +388,19 @@ continue_jmp_ex_optimization:
}
/* JMPZNZ(X,L1,L2), L1: JMP(L3) => JMPZNZ(X,L3,L2), L1: JMP(L3) */
- while (ZEND_OP2(opline).opline_num < op_array->last
- && op_array->opcodes[ZEND_OP2(opline).opline_num].opcode == ZEND_JMP) {
- int target = ZEND_OP2(opline).opline_num;
+ while (ZEND_OP2_JMP_ADDR(opline) < end
+ && ZEND_OP2_JMP_ADDR(opline)->opcode == ZEND_JMP) {
+ zend_op *target = ZEND_OP2_JMP_ADDR(opline);
CHECK_JMP(target, continue_jmpznz_optimization);
- ZEND_OP2(opline).opline_num = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+ ZEND_SET_OP_JMP_ADDR(opline, opline->op2, ZEND_OP1_JMP_ADDR(target));
}
continue_jmpznz_optimization:
/* JMPZNZ(X,L1,L2), L2: JMP(L3) => JMPZNZ(X,L1,L3), L2: JMP(L3) */
- while (opline->extended_value < op_array->last
- && op_array->opcodes[opline->extended_value].opcode == ZEND_JMP) {
- int target = opline->extended_value;
+ while (ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value) < end
+ && ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value)->opcode == ZEND_JMP) {
+ zend_op *target = ZEND_OFFSET_TO_OPLINE(opline, opline->extended_value);
CHECK_JMP(target, done_jmp_optimization);
- opline->extended_value = ZEND_OP1(&op_array->opcodes[target]).opline_num;
+ opline->extended_value = ZEND_OPLINE_TO_OFFSET(opline, ZEND_OP1_JMP_ADDR(target));
}
break;
@@ -412,14 +415,7 @@ continue_jmpznz_optimization:
if (next_op->opcode == ZEND_FREE &&
ZEND_OP1(next_op).var == ZEND_RESULT(opline).var) {
MAKE_NOP(next_op);
- switch (opline->opcode) {
- case ZEND_POST_INC:
- opline->opcode = ZEND_PRE_INC;
- break;
- case ZEND_POST_DEC:
- opline->opcode = ZEND_PRE_DEC;
- break;
- }
+ opline->opcode -= 2;
ZEND_RESULT_TYPE(opline) = IS_VAR | EXT_TYPE_UNUSED;
}
}
@@ -429,5 +425,5 @@ done_jmp_optimization:
opline++;
opline_num++;
}
- FREE_ALLOCA(jmp_hitlist);
+ free_alloca(jmp_hitlist, use_heap);
}
diff --git a/ext/opcache/Optimizer/zend_cfg.c b/ext/opcache/Optimizer/zend_cfg.c
new file mode 100644
index 0000000000..374bf25e48
--- /dev/null
+++ b/ext/opcache/Optimizer/zend_cfg.c
@@ -0,0 +1,601 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine, CFG - Control Flow Graph |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#include "php.h"
+#include "zend_compile.h"
+#include "zend_cfg.h"
+
+static void zend_mark_reachable(zend_op *opcodes, zend_basic_block *blocks, zend_basic_block *b)
+{
+ zend_uchar opcode;
+ zend_basic_block *b0;
+ int successor_0, successor_1;
+
+ while (1) {
+ b->flags |= ZEND_BB_REACHABLE;
+ successor_0 = b->successors[0];
+ if (successor_0 >= 0) {
+ successor_1 = b->successors[1];
+ if (successor_1 >= 0) {
+ b0 = blocks + successor_0;
+ b0->flags |= ZEND_BB_TARGET;
+ if (!(b0->flags & ZEND_BB_REACHABLE)) {
+ zend_mark_reachable(opcodes, blocks, b0);
+ }
+ opcode = opcodes[b->end].opcode;
+ b = blocks + successor_1;
+ if (opcode == ZEND_JMPZNZ) {
+ b->flags |= ZEND_BB_TARGET;
+ } else {
+ b->flags |= ZEND_BB_FOLLOW;
+ }
+ } else {
+ opcode = opcodes[b->end].opcode;
+ b = blocks + successor_0;
+ if (opcode == ZEND_JMP) {
+ b->flags |= ZEND_BB_TARGET;
+ } else {
+ b->flags |= ZEND_BB_FOLLOW;
+
+ //TODO: support for stackless CFG???
+ if (0/*stackless*/) {
+ if (opcode == ZEND_INCLUDE_OR_EVAL ||
+ opcode == ZEND_YIELD ||
+ opcode == ZEND_YIELD_FROM ||
+ opcode == ZEND_DO_FCALL ||
+ opcode == ZEND_DO_UCALL ||
+ opcode == ZEND_DO_FCALL_BY_NAME) {
+ b->flags |= ZEND_BB_ENTRY;
+ }
+ }
+ }
+ }
+ if (b->flags & ZEND_BB_REACHABLE) return;
+ } else {
+ b->flags |= ZEND_BB_EXIT;
+ return;
+ }
+ }
+}
+
+static void zend_mark_reachable_blocks(zend_op_array *op_array, zend_cfg *cfg, int start)
+{
+ zend_basic_block *blocks = cfg->blocks;
+
+ blocks[start].flags = ZEND_BB_START;
+ zend_mark_reachable(op_array->opcodes, blocks, blocks + start);
+
+ if (op_array->last_live_range || op_array->last_try_catch) {
+ zend_basic_block *b;
+ int j, changed;
+ uint32_t *block_map = cfg->map;
+
+ do {
+ changed = 0;
+
+ /* Add brk/cont paths */
+ for (j = 0; j < op_array->last_live_range; j++) {
+ b = blocks + block_map[op_array->live_range[j].start];
+ if (b->flags & ZEND_BB_REACHABLE) {
+ 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));
+ }
+ }
+
+ /* Add exception paths */
+ for (j = 0; j < op_array->last_try_catch; j++) {
+
+ /* check for jumps into the middle of try block */
+ b = blocks + block_map[op_array->try_catch_array[j].try_op];
+ if (!(b->flags & ZEND_BB_REACHABLE)) {
+ zend_basic_block *end;
+
+ if (op_array->try_catch_array[j].catch_op) {
+ end = blocks + block_map[op_array->try_catch_array[j].catch_op];
+ while (b != end) {
+ if (b->flags & ZEND_BB_REACHABLE) {
+ op_array->try_catch_array[j].try_op = b->start;
+ break;
+ }
+ b++;
+ }
+ }
+ b = blocks + block_map[op_array->try_catch_array[j].try_op];
+ if (!(b->flags & ZEND_BB_REACHABLE)) {
+ if (op_array->try_catch_array[j].finally_op) {
+ end = blocks + block_map[op_array->try_catch_array[j].finally_op];
+ while (b != end) {
+ if (b->flags & ZEND_BB_REACHABLE) {
+ op_array->try_catch_array[j].try_op = op_array->try_catch_array[j].catch_op;
+ changed = 1;
+ zend_mark_reachable(op_array->opcodes, blocks, blocks + block_map[op_array->try_catch_array[j].try_op]);
+ break;
+ }
+ b++;
+ }
+ }
+ }
+ }
+
+ b = blocks + block_map[op_array->try_catch_array[j].try_op];
+ if (b->flags & ZEND_BB_REACHABLE) {
+ b->flags |= ZEND_BB_TRY;
+ if (op_array->try_catch_array[j].catch_op) {
+ b = blocks + block_map[op_array->try_catch_array[j].catch_op];
+ b->flags |= ZEND_BB_CATCH;
+ if (!(b->flags & ZEND_BB_REACHABLE)) {
+ changed = 1;
+ zend_mark_reachable(op_array->opcodes, blocks, b);
+ }
+ }
+ if (op_array->try_catch_array[j].finally_op) {
+ b = blocks + block_map[op_array->try_catch_array[j].finally_op];
+ b->flags |= ZEND_BB_FINALLY;
+ if (!(b->flags & ZEND_BB_REACHABLE)) {
+ changed = 1;
+ zend_mark_reachable(op_array->opcodes, blocks, b);
+ }
+ }
+ if (op_array->try_catch_array[j].finally_end) {
+ b = blocks + block_map[op_array->try_catch_array[j].finally_end];
+ b->flags |= ZEND_BB_FINALLY_END;
+ if (!(b->flags & ZEND_BB_REACHABLE)) {
+ changed = 1;
+ zend_mark_reachable(op_array->opcodes, blocks, b);
+ }
+ }
+ } else {
+ if (op_array->try_catch_array[j].catch_op) {
+ ZEND_ASSERT(!(blocks[block_map[op_array->try_catch_array[j].catch_op]].flags & ZEND_BB_REACHABLE));
+ }
+ if (op_array->try_catch_array[j].finally_op) {
+ ZEND_ASSERT(!(blocks[block_map[op_array->try_catch_array[j].finally_op]].flags & ZEND_BB_REACHABLE));
+ }
+ if (op_array->try_catch_array[j].finally_end) {
+ ZEND_ASSERT(!(blocks[block_map[op_array->try_catch_array[j].finally_end]].flags & ZEND_BB_REACHABLE));
+ }
+ }
+ }
+ } while (changed);
+ }
+}
+
+void zend_remark_reachable_blocks(zend_op_array *op_array, zend_cfg *cfg)
+{
+ zend_basic_block *blocks = cfg->blocks;
+ int i;
+ int start = 0;
+
+ for (i = 0; i < cfg->blocks_count; i++) {
+ if (blocks[i].flags & ZEND_BB_REACHABLE) {
+ start = i;
+ i++;
+ break;
+ }
+ }
+
+ /* clear all flags */
+ for (i = 0; i < cfg->blocks_count; i++) {
+ blocks[i].flags = 0;
+ }
+
+ zend_mark_reachable_blocks(op_array, cfg, start);
+}
+
+static void record_successor(zend_basic_block *blocks, int pred, int n, int succ)
+{
+ blocks[pred].successors[n] = succ;
+}
+
+#define BB_START(i) do { \
+ if (!block_map[i]) { blocks_count++;} \
+ block_map[i] = 1; \
+ } while (0)
+
+int zend_build_cfg(zend_arena **arena, zend_op_array *op_array, int rt_constants, int stackless, zend_cfg *cfg, uint32_t *func_flags) /* {{{ */
+{
+ uint32_t flags = 0;
+ uint32_t i;
+ int j;
+ uint32_t *block_map;
+ zend_function *fn;
+ int blocks_count = 0;
+ zend_basic_block *blocks;
+ zval *zv;
+
+ cfg->map = block_map = zend_arena_calloc(arena, op_array->last, sizeof(uint32_t));
+ if (!block_map) {
+ return FAILURE;
+ }
+
+ /* 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) {
+ case ZEND_RETURN:
+ case ZEND_RETURN_BY_REF:
+ case ZEND_GENERATOR_RETURN:
+ case ZEND_EXIT:
+ case ZEND_THROW:
+ if (i + 1 < op_array->last) {
+ BB_START(i + 1);
+ }
+ break;
+ case ZEND_INCLUDE_OR_EVAL:
+ case ZEND_YIELD:
+ case ZEND_YIELD_FROM:
+ flags |= ZEND_FUNC_TOO_DYNAMIC;
+ if (stackless) {
+ BB_START(i + 1);
+ }
+ break;
+ case ZEND_DO_FCALL:
+ case ZEND_DO_UCALL:
+ case ZEND_DO_FCALL_BY_NAME:
+ flags |= ZEND_FUNC_HAS_CALLS;
+ if (stackless) {
+ BB_START(i + 1);
+ }
+ break;
+ case ZEND_DO_ICALL:
+ flags |= ZEND_FUNC_HAS_CALLS;
+ break;
+ case ZEND_INIT_FCALL:
+ if (rt_constants) {
+ zv = RT_CONSTANT(op_array, opline->op2);
+ } else {
+ zv = CT_CONSTANT_EX(op_array, opline->op2.constant);
+ }
+ if ((fn = zend_hash_find_ptr(EG(function_table), Z_STR_P(zv))) != NULL) {
+ if (fn->type == ZEND_INTERNAL_FUNCTION) {
+ if (Z_STRLEN_P(zv) == sizeof("extract")-1 &&
+ memcmp(Z_STRVAL_P(zv), "extract", sizeof("extract")-1) == 0) {
+ flags |= ZEND_FUNC_TOO_DYNAMIC;
+ } else if (Z_STRLEN_P(zv) == sizeof("compact")-1 &&
+ memcmp(Z_STRVAL_P(zv), "compact", sizeof("compact")-1) == 0) {
+ flags |= ZEND_FUNC_TOO_DYNAMIC;
+ } else if (Z_STRLEN_P(zv) == sizeof("parse_str")-1 &&
+ memcmp(Z_STRVAL_P(zv), "parse_str", sizeof("parse_str")-1) == 0) {
+ flags |= ZEND_FUNC_TOO_DYNAMIC;
+ } else if (Z_STRLEN_P(zv) == sizeof("mb_parse_str")-1 &&
+ memcmp(Z_STRVAL_P(zv), "mb_parse_str", sizeof("mb_parse_str")-1) == 0) {
+ flags |= ZEND_FUNC_TOO_DYNAMIC;
+ } else if (Z_STRLEN_P(zv) == sizeof("get_defined_vars")-1 &&
+ memcmp(Z_STRVAL_P(zv), "get_defined_vars", sizeof("get_defined_vars")-1) == 0) {
+ flags |= ZEND_FUNC_TOO_DYNAMIC;
+ } else if (Z_STRLEN_P(zv) == sizeof("func_num_args")-1 &&
+ memcmp(Z_STRVAL_P(zv), "func_num_args", sizeof("func_num_args")-1) == 0) {
+ flags |= ZEND_FUNC_VARARG;
+ } else if (Z_STRLEN_P(zv) == sizeof("func_get_arg")-1 &&
+ memcmp(Z_STRVAL_P(zv), "func_get_arg", sizeof("func_get_arg")-1) == 0) {
+ flags |= ZEND_FUNC_VARARG;
+ } else if (Z_STRLEN_P(zv) == sizeof("func_get_args")-1 &&
+ memcmp(Z_STRVAL_P(zv), "func_get_args", sizeof("func_get_args")-1) == 0) {
+ flags |= ZEND_FUNC_VARARG;
+ }
+ }
+ }
+ 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);
+ }
+ break;
+ case ZEND_DECLARE_ANON_CLASS:
+ case ZEND_DECLARE_ANON_INHERITED_CLASS:
+ BB_START(OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes);
+ BB_START(i + 1);
+ break;
+ case ZEND_JMP:
+ BB_START(OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes);
+ if (i + 1 < op_array->last) {
+ BB_START(i + 1);
+ }
+ break;
+ case ZEND_JMPZNZ:
+ BB_START(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes);
+ BB_START(ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
+ if (i + 1 < op_array->last) {
+ BB_START(i + 1);
+ }
+ break;
+ case ZEND_JMPZ:
+ case ZEND_JMPNZ:
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+ case ZEND_JMP_SET:
+ case ZEND_COALESCE:
+ case ZEND_ASSERT_CHECK:
+ BB_START(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes);
+ 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));
+ }
+ BB_START(i + 1);
+ break;
+ case ZEND_FE_FETCH_R:
+ case ZEND_FE_FETCH_RW:
+ BB_START(ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
+ BB_START(i + 1);
+ break;
+ case ZEND_FE_RESET_R:
+ case ZEND_FE_RESET_RW:
+ case ZEND_NEW:
+ BB_START(OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes);
+ BB_START(i + 1);
+ break;
+ case ZEND_DECLARE_LAMBDA_FUNCTION: {
+//??? zend_op_array *lambda_op_array;
+//???
+//??? if (rt_constants) {
+//??? zv = RT_CONSTANT(op_array, opline->op1);
+//??? } else {
+//??? zv = CT_CONSTANT_EX(op_array, opline->op1.constant);
+//??? }
+//??? if (ctx->main_script &&
+//??? (lambda_op_array = zend_hash_find_ptr(&ctx->main_script->function_table, Z_STR_P(zv))) != NULL) {
+//??? if (lambda_op_array->type == ZEND_USER_FUNCTION &&
+//??? lambda_op_array->static_variables) {
+//??? // FIXME: Really we should try to perform alias
+//??? // analysis on variables used by the closure
+//??? info->flags |= ZEND_FUNC_TOO_DYNAMIC;
+//??? }
+//??? } else {
+//??? // FIXME: how to find the lambda function?
+ flags |= ZEND_FUNC_TOO_DYNAMIC;
+//??? }
+ }
+ break;
+ case ZEND_UNSET_VAR:
+ if (!(opline->extended_value & ZEND_QUICK_SET)) {
+ flags |= ZEND_FUNC_TOO_DYNAMIC;
+ }
+ break;
+ case ZEND_FETCH_R:
+ case ZEND_FETCH_W:
+ case ZEND_FETCH_RW:
+ case ZEND_FETCH_FUNC_ARG:
+ case ZEND_FETCH_IS:
+ case ZEND_FETCH_UNSET:
+ if ((opline->extended_value & ZEND_FETCH_TYPE_MASK) == ZEND_FETCH_LOCAL) {
+ flags |= ZEND_FUNC_TOO_DYNAMIC;
+ } 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;
+ }
+ 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 (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);
+ if (op_array->try_catch_array[j].catch_op) {
+ BB_START(op_array->try_catch_array[j].catch_op);
+ }
+ if (op_array->try_catch_array[j].finally_op) {
+ BB_START(op_array->try_catch_array[j].finally_op);
+ }
+ if (op_array->try_catch_array[j].finally_end) {
+ BB_START(op_array->try_catch_array[j].finally_end);
+ }
+ }
+ }
+
+ cfg->blocks_count = blocks_count;
+
+ /* Build CFG, Step 2: Build Array of Basic Blocks */
+ cfg->blocks = blocks = zend_arena_calloc(arena, sizeof(zend_basic_block), blocks_count);
+ if (!blocks) {
+ return FAILURE;
+ }
+
+ for (i = 0, blocks_count = -1; i < op_array->last; i++) {
+ if (block_map[i]) {
+ if (blocks_count >= 0) {
+ blocks[blocks_count].end = i - 1;
+ }
+ blocks_count++;
+ blocks[blocks_count].flags = 0;
+ blocks[blocks_count].start = i;
+ blocks[blocks_count].successors[0] = -1;
+ blocks[blocks_count].successors[1] = -1;
+ blocks[blocks_count].predecessors_count = 0;
+ blocks[blocks_count].predecessor_offset = -1;
+ blocks[blocks_count].idom = -1;
+ blocks[blocks_count].loop_header = -1;
+ blocks[blocks_count].level = -1;
+ blocks[blocks_count].children = -1;
+ blocks[blocks_count].next_child = -1;
+ block_map[i] = blocks_count;
+ } else {
+ block_map[i] = (uint32_t)-1;
+ }
+ }
+
+ blocks[blocks_count].end = i - 1;
+ blocks_count++;
+
+ /* Build CFG, Step 3: Calculate successors */
+ for (j = 0; j < blocks_count; j++) {
+ zend_op *opline = op_array->opcodes + blocks[j].end;
+ switch(opline->opcode) {
+ case ZEND_FAST_RET:
+ case ZEND_RETURN:
+ case ZEND_RETURN_BY_REF:
+ case ZEND_GENERATOR_RETURN:
+ case ZEND_EXIT:
+ case ZEND_THROW:
+ break;
+ case ZEND_DECLARE_ANON_CLASS:
+ case ZEND_DECLARE_ANON_INHERITED_CLASS:
+ record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes]);
+ record_successor(blocks, j, 1, j + 1);
+ break;
+ case ZEND_JMP:
+ record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes]);
+ break;
+ case ZEND_JMPZNZ:
+ record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]);
+ record_successor(blocks, j, 1, block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]);
+ break;
+ case ZEND_JMPZ:
+ case ZEND_JMPNZ:
+ case ZEND_JMPZ_EX:
+ case ZEND_JMPNZ_EX:
+ case ZEND_JMP_SET:
+ case ZEND_COALESCE:
+ case ZEND_ASSERT_CHECK:
+ record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]);
+ record_successor(blocks, j, 1, j + 1);
+ break;
+ case ZEND_CATCH:
+ if (!opline->result.num) {
+ record_successor(blocks, j, 0, block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]);
+ record_successor(blocks, j, 1, j + 1);
+ } else {
+ record_successor(blocks, j, 0, j + 1);
+ }
+ break;
+ case ZEND_FE_FETCH_R:
+ case ZEND_FE_FETCH_RW:
+ record_successor(blocks, j, 0, block_map[ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value)]);
+ record_successor(blocks, j, 1, j + 1);
+ break;
+ case ZEND_FE_RESET_R:
+ case ZEND_FE_RESET_RW:
+ case ZEND_NEW:
+ record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op2) - op_array->opcodes]);
+ record_successor(blocks, j, 1, j + 1);
+ break;
+ case ZEND_FAST_CALL:
+ record_successor(blocks, j, 0, block_map[OP_JMP_ADDR(opline, opline->op1) - op_array->opcodes]);
+ record_successor(blocks, j, 1, j + 1);
+ break;
+ default:
+ record_successor(blocks, j, 0, j + 1);
+ break;
+ }
+ }
+
+ /* Build CFG, Step 4, Mark Reachable Basic Blocks */
+ zend_mark_reachable_blocks(op_array, cfg, 0);
+
+ if (func_flags) {
+ *func_flags = flags;
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg) /* {{{ */
+{
+ int j, edges;
+ zend_basic_block *b;
+ zend_basic_block *blocks = cfg->blocks;
+ zend_basic_block *end = blocks + cfg->blocks_count;
+ int *predecessors;
+
+ edges = 0;
+ for (b = blocks; b < end; b++) {
+ b->predecessors_count = 0;
+ }
+ for (b = blocks; b < end; b++) {
+ if (!(b->flags & ZEND_BB_REACHABLE)) {
+ b->successors[0] = -1;
+ b->successors[1] = -1;
+ b->predecessors_count = 0;
+ } else {
+ if (b->successors[0] >= 0) {
+ edges++;
+ blocks[b->successors[0]].predecessors_count++;
+ if (b->successors[1] >= 0) {
+ edges++;
+ blocks[b->successors[1]].predecessors_count++;
+ }
+ }
+ }
+ }
+
+ cfg->predecessors = predecessors = (int*)zend_arena_calloc(arena, sizeof(int), edges);
+
+ if (!predecessors) {
+ return FAILURE;
+ }
+
+ edges = 0;
+ for (b = blocks; b < end; b++) {
+ if (b->flags & ZEND_BB_REACHABLE) {
+ b->predecessor_offset = edges;
+ edges += b->predecessors_count;
+ b->predecessors_count = 0;
+ }
+ }
+
+ for (j = 0; j < cfg->blocks_count; j++) {
+ if (blocks[j].flags & ZEND_BB_REACHABLE) {
+ if (blocks[j].successors[0] >= 0) {
+ 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) {
+ zend_basic_block *b = blocks + blocks[j].successors[1];
+ predecessors[b->predecessor_offset + b->predecessors_count] = j;
+ b->predecessors_count++;
+ }
+ }
+ }
+ }
+
+ return SUCCESS;
+}
+/* }}} */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/ext/opcache/Optimizer/zend_cfg.h b/ext/opcache/Optimizer/zend_cfg.h
new file mode 100644
index 0000000000..76d1bb44ab
--- /dev/null
+++ b/ext/opcache/Optimizer/zend_cfg.h
@@ -0,0 +1,111 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine, CFG - Control Flow Graph |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef ZEND_CFG_H
+#define ZEND_CFG_H
+
+/* func flags */
+#define ZEND_FUNC_TOO_DYNAMIC (1<<0)
+#define ZEND_FUNC_HAS_CALLS (1<<1)
+#define ZEND_FUNC_VARARG (1<<2)
+
+/* zend_basic_bloc.flags */
+#define ZEND_BB_START (1<<0) /* fist block */
+#define ZEND_BB_FOLLOW (1<<1) /* follows the next block */
+#define ZEND_BB_TARGET (1<<2) /* jump taget */
+#define ZEND_BB_EXIT (1<<3) /* without successors */
+#define ZEND_BB_ENTRY (1<<4) /* stackless entry */
+#define ZEND_BB_TRY (1<<5) /* start of try block */
+#define ZEND_BB_CATCH (1<<6) /* start of catch block */
+#define ZEND_BB_FINALLY (1<<7) /* start of finally block */
+#define ZEND_BB_FINALLY_END (1<<8) /* end of finally block */
+#define ZEND_BB_GEN_VAR (1<<9) /* start of live range */
+#define ZEND_BB_KILL_VAR (1<<10) /* end of live range */
+
+#define ZEND_BB_LOOP_HEADER (1<<16)
+#define ZEND_BB_IRREDUCIBLE_LOOP (1<<17)
+
+#define ZEND_BB_REACHABLE (1<<31)
+
+#define ZEND_BB_PROTECTED (ZEND_BB_ENTRY|ZEND_BB_TRY|ZEND_BB_CATCH|ZEND_BB_FINALLY|ZEND_BB_FINALLY_END|ZEND_BB_GEN_VAR|ZEND_BB_KILL_VAR)
+
+typedef struct _zend_basic_block {
+ uint32_t flags;
+ uint32_t start; /* first opcode number */
+ uint32_t end; /* last opcode number */
+ int successors[2]; /* up to 2 successor blocks */
+ int predecessors_count; /* number of predecessors */
+ int predecessor_offset; /* offset of 1-st predecessor */
+ int idom; /* immediate dominator block */
+ int loop_header; /* closest loop header, or -1 */
+ int level; /* steps away from the entry in the dom. tree */
+ int children; /* list of dominated blocks */
+ int next_child; /* next dominated block */
+} zend_basic_block;
+
+/*
++------------+---+---+---+---+---+
+| |OP1|OP2|EXT| 0 | 1 |
++------------+---+---+---+---+---+
+|JMP |ADR| | |OP1| - |
+|JMPZ | |ADR| |OP2|FOL|
+|JMPNZ | |ADR| |OP2|FOL|
+|JMPZNZ | |ADR|ADR|OP2|EXT|
+|JMPZ_EX | |ADR| |OP2|FOL|
+|JMPNZ_EX | |ADR| |OP2|FOL|
+|JMP_SET | |ADR| |OP2|FOL|
+|COALESCE | |ADR| |OP2|FOL|
+|ASSERT_CHK | |ADR| |OP2|FOL|
+|NEW | |ADR| |OP2|FOL|
+|DCL_ANON* |ADR| | |OP1|FOL|
+|FE_RESET_* | |ADR| |OP2|FOL|
+|FE_FETCH_* | | |ADR|EXT|FOL|
+|CATCH | | |ADR|EXT|FOL|
+|FAST_CALL |ADR| | |OP1|FOL|
+|FAST_RET | | | | - | - |
+|RETURN* | | | | - | - |
+|EXIT | | | | - | - |
+|THROW | | | | - | - |
+|* | | | |FOL| - |
++------------+---+---+---+---+---+
+*/
+
+typedef struct _zend_cfg {
+ int blocks_count; /* number of basic blocks */
+ zend_basic_block *blocks; /* array of basic blocks */
+ int *predecessors;
+ uint32_t *map;
+} zend_cfg;
+
+BEGIN_EXTERN_C()
+
+int zend_build_cfg(zend_arena **arena, zend_op_array *op_array, int rt_constants, int stackless, zend_cfg *cfg, uint32_t *func_flags);
+void zend_remark_reachable_blocks(zend_op_array *op_array, zend_cfg *cfg);
+int zend_cfg_build_predecessors(zend_arena **arena, zend_cfg *cfg);
+
+END_EXTERN_C()
+
+#endif /* ZEND_CFG_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/ext/opcache/Optimizer/zend_dump.c b/ext/opcache/Optimizer/zend_dump.c
new file mode 100644
index 0000000000..b5780e73b2
--- /dev/null
+++ b/ext/opcache/Optimizer/zend_dump.c
@@ -0,0 +1,292 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine, Bytecode Visualisation |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#include "php.h"
+#include "zend_compile.h"
+#include "zend_cfg.h"
+#include "zend_dump.h"
+
+static void zend_dump_const(const zval *zv)
+{
+ switch (Z_TYPE_P(zv)) {
+ case IS_NULL:
+ fprintf(stderr, " null");
+ break;
+ case IS_FALSE:
+ fprintf(stderr, " bool(false)");
+ break;
+ case IS_TRUE:
+ fprintf(stderr, " bool(true)");
+ break;
+ case IS_LONG:
+ fprintf(stderr, " int(" ZEND_LONG_FMT ")", Z_LVAL_P(zv));
+ break;
+ case IS_DOUBLE:
+ fprintf(stderr, " float(%g)", Z_DVAL_P(zv));
+ break;
+ case IS_STRING:
+ fprintf(stderr, " string(\"%s\")", Z_STRVAL_P(zv));
+ break;
+ case IS_ARRAY:
+ fprintf(stderr, " array(...)");
+ break;
+ default:
+ fprintf(stderr, " ???");
+ break;
+ }
+}
+
+static void zend_dump_op(const zend_op_array *op_array, const zend_basic_block *b, const zend_op *opline)
+{
+ const char *name = zend_get_opcode_name(opline->opcode);
+ uint32_t flags = zend_get_opcode_flags(opline->opcode);
+ uint32_t n = 0;
+
+ if (!b) {
+ fprintf(stderr, "L%u:", (uint32_t)(opline - op_array->opcodes));
+ }
+ fprintf(stderr, "\t%s", name ? (name + 5) : "???");
+ if (ZEND_VM_OP1_JMP_ADDR & flags) {
+ 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) {
+ fprintf(stderr, " %u", opline->op1.num);
+ } else if (opline->op1_type == IS_CONST) {
+ zend_dump_const(CT_CONSTANT_EX(op_array, opline->op1.constant));
+ } else if (opline->op1_type == IS_CV) {
+ fprintf(stderr, " CV%u", EX_VAR_TO_NUM(opline->op1.var));
+ } else if (opline->op1_type == IS_VAR) {
+ fprintf(stderr, " V%u", EX_VAR_TO_NUM(opline->op1.var));
+ } else if ( opline->op1_type == IS_TMP_VAR) {
+ fprintf(stderr, " T%u", EX_VAR_TO_NUM(opline->op1.var));
+ }
+ if (ZEND_VM_OP2_JMP_ADDR & flags) {
+ 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 if (ZEND_VM_OP2_NUM & flags) {
+ fprintf(stderr, " %u", opline->op2.num);
+ } else if (opline->op2_type == IS_CONST) {
+ zend_dump_const(CT_CONSTANT_EX(op_array, opline->op2.constant));
+ } else if (opline->op2_type == IS_CV) {
+ fprintf(stderr, " CV%u", EX_VAR_TO_NUM(opline->op2.var));
+ } else if (opline->op2_type == IS_VAR) {
+ fprintf(stderr, " V%u", EX_VAR_TO_NUM(opline->op2.var));
+ } else if ( opline->op2_type == IS_TMP_VAR) {
+ fprintf(stderr, " T%u", EX_VAR_TO_NUM(opline->op2.var));
+ }
+ if (ZEND_VM_EXT_JMP_ADDR & flags) {
+ if (opline->opcode != ZEND_CATCH || !opline->result.num) {
+ if (b) {
+ fprintf(stderr, " BB%d", b->successors[n++]);
+ } else {
+ fprintf(stderr, " L" ZEND_LONG_FMT, ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value));
+ }
+ }
+ }
+ if (opline->result_type == IS_CONST) {
+ zend_dump_const(CT_CONSTANT_EX(op_array, opline->result.constant));
+ } else if (opline->result_type == IS_CV) {
+ fprintf(stderr, " -> CV%u", EX_VAR_TO_NUM(opline->result.var));
+ } else if (opline->result_type & IS_VAR) {
+ if (opline->result_type & EXT_TYPE_UNUSED) {
+ fprintf(stderr, " -> U%u", EX_VAR_TO_NUM(opline->result.var));
+ } else {
+ fprintf(stderr, " -> V%u", EX_VAR_TO_NUM(opline->result.var));
+ }
+ } else if ( opline->result_type == IS_TMP_VAR) {
+ fprintf(stderr, " -> T%u", EX_VAR_TO_NUM(opline->result.var));
+ }
+ fprintf(stderr, "\n");
+}
+
+void zend_dump_op_array(const zend_op_array *op_array, const zend_cfg *cfg, int all)
+{
+ int i;
+
+ if (cfg) {
+ int n;
+ zend_basic_block *b;
+
+ for (n = 0; n < cfg->blocks_count; n++) {
+ b = cfg->blocks + n;
+ if (all || (b->flags & ZEND_BB_REACHABLE)) {
+ const zend_op *opline;
+ const zend_op *end;
+ int printed = 0;
+
+ fprintf(stderr, "BB%d:", n);
+ if (b->flags & ZEND_BB_START) {
+ fprintf(stderr, " start");
+ }
+ if (b->flags & ZEND_BB_FOLLOW) {
+ fprintf(stderr, " follow");
+ }
+ if (b->flags & ZEND_BB_TARGET) {
+ fprintf(stderr, " target");
+ }
+ if (b->flags & ZEND_BB_EXIT) {
+ fprintf(stderr, " exit");
+ }
+ if (b->flags & ZEND_BB_ENTRY) {
+ fprintf(stderr, " entry");
+ }
+ if (b->flags & ZEND_BB_TRY) {
+ fprintf(stderr, " try");
+ }
+ if (b->flags & ZEND_BB_CATCH) {
+ fprintf(stderr, " catch");
+ }
+ if (b->flags & ZEND_BB_FINALLY) {
+ fprintf(stderr, " finally");
+ }
+ if (b->flags & ZEND_BB_FINALLY_END) {
+ fprintf(stderr, " finally_end");
+ }
+ if (b->flags & ZEND_BB_GEN_VAR) {
+ fprintf(stderr, " gen_var");
+ }
+ if (b->flags & ZEND_BB_KILL_VAR) {
+ fprintf(stderr, " kill_var");
+ }
+ if (all & !(b->flags & ZEND_BB_REACHABLE)) {
+ fprintf(stderr, " unreachable");
+ }
+
+ if (b->predecessors_count) {
+ int *p = cfg->predecessors + b->predecessor_offset;
+ int *end = p + b->predecessors_count;
+
+ fprintf(stderr, " from=(BB%d", *p);
+ for (p++; p < end; p++) {
+ fprintf(stderr, ", BB%d", *p);
+ }
+ fprintf(stderr, ")");
+ }
+
+ if (b->successors[0] != -1) {
+ fprintf(stderr, " to=(BB%d", b->successors[0]);
+ printed = 1;
+ if (b->successors[1] != -1) {
+ fprintf(stderr, " , BB%d", b->successors[1]);
+ }
+ }
+ if (printed) {
+ fprintf(stderr, ")");
+ }
+ fprintf(stderr, "\n");
+
+ opline = op_array->opcodes + b->start;
+ end = op_array->opcodes + b->end + 1;
+ while (opline < end) {
+ zend_dump_op(op_array, b, opline);
+ opline++;
+ }
+ }
+ }
+ if (op_array->last_live_range) {
+ fprintf(stderr, "LIVE RANGES:\n");
+ for (i = 0; i < op_array->last_live_range; i++) {
+ fprintf(stderr, "\t%u: BB%u - BB%u\n",
+ 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 (op_array->last_try_catch) {
+ fprintf(stderr, "EXCEPTION TABLE:\n");
+ for (i = 0; i < op_array->last_try_catch; i++) {
+ fprintf(stderr, "\tBB%u",
+ cfg->map[op_array->try_catch_array[i].try_op]);
+ if (op_array->try_catch_array[i].catch_op) {
+ fprintf(stderr, ", BB%u",
+ cfg->map[op_array->try_catch_array[i].catch_op]);
+ } else {
+ fprintf(stderr, ", -");
+ }
+ if (op_array->try_catch_array[i].finally_op) {
+ fprintf(stderr, ", BB%u",
+ cfg->map[op_array->try_catch_array[i].finally_op]);
+ } else {
+ fprintf(stderr, ", -");
+ }
+ if (op_array->try_catch_array[i].finally_end) {
+ fprintf(stderr, ", BB%u\n",
+ cfg->map[op_array->try_catch_array[i].finally_end]);
+ } else {
+ fprintf(stderr, ", -\n");
+ }
+ }
+ }
+ } else {
+ const zend_op *opline = op_array->opcodes;
+ const zend_op *end = opline + op_array->last;
+
+ while (opline < end) {
+ zend_dump_op(op_array, NULL, opline);
+ opline++;
+ }
+ if (op_array->last_live_range) {
+ fprintf(stderr, "LIVE RANGES:\n");
+ for (i = 0; i < op_array->last_live_range; i++) {
+ fprintf(stderr, "\t%u: L%u - L%u\n",
+ 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);
+ }
+ }
+ if (op_array->last_try_catch) {
+ fprintf(stderr, "EXCEPTION TABLE:\n");
+ for (i = 0; i < op_array->last_try_catch; i++) {
+ fprintf(stderr, "\tL%u",
+ op_array->try_catch_array[i].try_op);
+ if (op_array->try_catch_array[i].catch_op) {
+ fprintf(stderr, ", L%u",
+ op_array->try_catch_array[i].catch_op);
+ } else {
+ fprintf(stderr, ", -");
+ }
+ if (op_array->try_catch_array[i].finally_op) {
+ fprintf(stderr, ", L%u",
+ op_array->try_catch_array[i].finally_op);
+ } else {
+ fprintf(stderr, ", -");
+ }
+ if (op_array->try_catch_array[i].finally_end) {
+ fprintf(stderr, ", L%u\n",
+ op_array->try_catch_array[i].finally_end);
+ } else {
+ fprintf(stderr, ", -\n");
+ }
+ }
+ }
+ }
+}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/ext/opcache/Optimizer/zend_dump.h b/ext/opcache/Optimizer/zend_dump.h
new file mode 100644
index 0000000000..6e2577c04f
--- /dev/null
+++ b/ext/opcache/Optimizer/zend_dump.h
@@ -0,0 +1,36 @@
+/*
+ +----------------------------------------------------------------------+
+ | Zend Engine, Bytecode Visualisation |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1998-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Authors: Dmitry Stogov <dmitry@zend.com> |
+ +----------------------------------------------------------------------+
+*/
+
+#ifndef ZEND_DUMP_H
+#define ZEND_DUMP_H
+
+BEGIN_EXTERN_C()
+
+void zend_dump_op_array(const zend_op_array *op_array, const zend_cfg *cfg, int all);
+
+END_EXTERN_C()
+
+#endif /* ZEND_DUMP_H */
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * indent-tabs-mode: t
+ * End:
+ */
diff --git a/ext/opcache/Optimizer/zend_optimizer.c b/ext/opcache/Optimizer/zend_optimizer.c
index aa5b6a8a23..bc7e875ed3 100644
--- a/ext/opcache/Optimizer/zend_optimizer.c
+++ b/ext/opcache/Optimizer/zend_optimizer.c
@@ -164,6 +164,7 @@ int zend_optimizer_update_op1_const(zend_op_array *op_array,
case ZEND_INIT_STATIC_METHOD_CALL:
case ZEND_CATCH:
case ZEND_FETCH_CONSTANT:
+ case ZEND_FETCH_CLASS_CONSTANT:
case ZEND_DEFINED:
case ZEND_NEW:
REQUIRES_STRING(val);
@@ -199,20 +200,20 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
case ZEND_ASSIGN_REF:
zval_dtor(val);
return 0;
- case ZEND_FETCH_R:
- case ZEND_FETCH_W:
- case ZEND_FETCH_RW:
- case ZEND_FETCH_IS:
- case ZEND_FETCH_UNSET:
- case ZEND_FETCH_FUNC_ARG:
case ZEND_FETCH_CLASS:
case ZEND_INIT_FCALL_BY_NAME:
/*case ZEND_INIT_NS_FCALL_BY_NAME:*/
- case ZEND_UNSET_VAR:
- case ZEND_ISSET_ISEMPTY_VAR:
case ZEND_ADD_INTERFACE:
case ZEND_ADD_TRAIT:
case ZEND_INSTANCEOF:
+ case ZEND_FETCH_STATIC_PROP_R:
+ case ZEND_FETCH_STATIC_PROP_W:
+ case ZEND_FETCH_STATIC_PROP_RW:
+ case ZEND_FETCH_STATIC_PROP_IS:
+ case ZEND_FETCH_STATIC_PROP_UNSET:
+ case ZEND_FETCH_STATIC_PROP_FUNC_ARG:
+ case ZEND_UNSET_STATIC_PROP:
+ case ZEND_ISSET_ISEMPTY_STATIC_PROP:
REQUIRES_STRING(val);
drop_leading_backslash(val);
opline->op2.constant = zend_optimizer_add_literal(op_array, val);
@@ -248,7 +249,7 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
zend_optimizer_add_literal_string(op_array, zend_string_tolower(Z_STR_P(val)));
alloc_cache_slots_op2(op_array, opline, 2);
break;
- /*case ZEND_FETCH_CONSTANT:*/
+ /*case ZEND_FETCH_CLASS_CONSTANT:*/
case ZEND_ASSIGN_OBJ:
case ZEND_FETCH_OBJ_R:
case ZEND_FETCH_OBJ_W:
@@ -346,6 +347,42 @@ int zend_optimizer_update_op2_const(zend_op_array *op_array,
return 1;
}
+void zend_optimizer_remove_live_range(zend_op_array *op_array, uint32_t var)
+{
+ if (op_array->last_live_range) {
+ int i = 0;
+ int j = 0;
+ uint32_t *map;
+ ALLOCA_FLAG(use_heap);
+
+ map = (uint32_t *)do_alloca(sizeof(uint32_t) * op_array->last_live_range, use_heap);
+
+ do {
+ if ((op_array->live_range[i].var & ~ZEND_LIVE_MASK) != var) {
+ map[i] = j;
+ if (i != j) {
+ op_array->live_range[j] = op_array->live_range[i];
+ }
+ j++;
+ }
+ 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];
+ }
+ opline++;
+ }
+ }
+ }
+}
+
int zend_optimizer_replace_by_const(zend_op_array *op_array,
zend_op *opline,
zend_uchar type,
@@ -400,11 +437,11 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
case ZEND_FREE:
case ZEND_CASE: {
zend_op *m, *n;
- int brk = op_array->last_brk_cont;
+ int brk = op_array->last_live_range;
zend_bool in_switch = 0;
while (brk--) {
- if (op_array->brk_cont_array[brk].start <= (opline - op_array->opcodes) &&
- op_array->brk_cont_array[brk].brk > (opline - op_array->opcodes)) {
+ if (op_array->live_range[brk].start <= (uint32_t)(opline - op_array->opcodes) &&
+ op_array->live_range[brk].end > (uint32_t)(opline - op_array->opcodes)) {
in_switch = 1;
break;
}
@@ -418,7 +455,13 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
}
m = opline;
- n = op_array->opcodes + op_array->brk_cont_array[brk].brk + 1;
+ n = op_array->opcodes + op_array->live_range[brk].end;
+ if (n->opcode == ZEND_FREE &&
+ !(n->extended_value & ZEND_FREE_ON_RETURN)) {
+ n++;
+ } else {
+ n = op_array->opcodes + op_array->last;
+ }
while (m < n) {
if (ZEND_OP1_TYPE(m) == type &&
ZEND_OP1(m).var == var) {
@@ -437,6 +480,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
m++;
}
zval_dtor(val);
+ zend_optimizer_remove_live_range(op_array, var);
return 1;
}
case ZEND_VERIFY_RETURN_TYPE: {
@@ -450,18 +494,26 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
return 0;
}
MAKE_NOP(opline);
- zend_optimizer_update_op1_const(op_array, opline + 1, val);
- return 1;
+ opline++;
+ break;
}
default:
break;
}
- return zend_optimizer_update_op1_const(op_array, opline, val);
+ if (zend_optimizer_update_op1_const(op_array, opline, val)) {
+ zend_optimizer_remove_live_range(op_array, var);
+ return 1;
+ }
+ return 0;
}
if (ZEND_OP2_TYPE(opline) == type &&
ZEND_OP2(opline).var == var) {
- return zend_optimizer_update_op2_const(op_array, opline, val);
+ if (zend_optimizer_update_op2_const(op_array, opline, val)) {
+ zend_optimizer_remove_live_range(op_array, var);
+ return 1;
+ }
+ return 0;
}
opline++;
}
@@ -482,7 +534,7 @@ static void zend_optimize(zend_op_array *op_array,
* - optimize series of ADD_STRING and/or ADD_CHAR
* - convert CAST(IS_BOOL,x) into BOOL(x)
*/
- if (ZEND_OPTIMIZER_PASS_1 & OPTIMIZATION_LEVEL) {
+ if (ZEND_OPTIMIZER_PASS_1 & ctx->optimization_level) {
zend_optimizer_pass1(op_array, ctx);
}
@@ -492,7 +544,7 @@ static void zend_optimize(zend_op_array *op_array,
* - optimize static BRKs and CONTs
* - pre-evaluate constant function calls
*/
- if (ZEND_OPTIMIZER_PASS_2 & OPTIMIZATION_LEVEL) {
+ if (ZEND_OPTIMIZER_PASS_2 & ctx->optimization_level) {
zend_optimizer_pass2(op_array);
}
@@ -501,48 +553,48 @@ static void zend_optimize(zend_op_array *op_array,
* - optimize series of JMPs
* - change $i++ to ++$i where possible
*/
- if (ZEND_OPTIMIZER_PASS_3 & OPTIMIZATION_LEVEL) {
+ if (ZEND_OPTIMIZER_PASS_3 & ctx->optimization_level) {
zend_optimizer_pass3(op_array);
}
/* pass 4:
* - INIT_FCALL_BY_NAME -> DO_FCALL
*/
- if (ZEND_OPTIMIZER_PASS_4 & OPTIMIZATION_LEVEL) {
+ if (ZEND_OPTIMIZER_PASS_4 & ctx->optimization_level) {
optimize_func_calls(op_array, ctx);
}
/* pass 5:
* - CFG optimization
*/
- if (ZEND_OPTIMIZER_PASS_5 & OPTIMIZATION_LEVEL) {
+ if (ZEND_OPTIMIZER_PASS_5 & ctx->optimization_level) {
optimize_cfg(op_array, ctx);
}
/* pass 9:
* - Optimize temp variables usage
*/
- if (ZEND_OPTIMIZER_PASS_9 & OPTIMIZATION_LEVEL) {
+ if (ZEND_OPTIMIZER_PASS_9 & ctx->optimization_level) {
optimize_temporary_variables(op_array, ctx);
}
/* pass 10:
* - remove NOPs
*/
- if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & OPTIMIZATION_LEVEL) == ZEND_OPTIMIZER_PASS_10) {
+ if (((ZEND_OPTIMIZER_PASS_10|ZEND_OPTIMIZER_PASS_5) & ctx->optimization_level) == ZEND_OPTIMIZER_PASS_10) {
zend_optimizer_nop_removal(op_array);
}
/* pass 11:
* - Compact literals table
*/
- if (ZEND_OPTIMIZER_PASS_11 & OPTIMIZATION_LEVEL) {
+ if (ZEND_OPTIMIZER_PASS_11 & ctx->optimization_level) {
zend_optimizer_compact_literals(op_array, ctx);
}
}
-static void zend_accel_optimize(zend_op_array *op_array,
- zend_optimizer_ctx *ctx)
+static void zend_optimize_op_array(zend_op_array *op_array,
+ zend_optimizer_ctx *ctx)
{
zend_op *opline, *end;
@@ -556,34 +608,6 @@ static void zend_accel_optimize(zend_op_array *op_array,
if (opline->op2_type == IS_CONST) {
ZEND_PASS_TWO_UNDO_CONSTANT(op_array, opline->op2);
}
- switch (opline->opcode) {
- case ZEND_JMP:
- case ZEND_FAST_CALL:
- case ZEND_DECLARE_ANON_CLASS:
- case ZEND_DECLARE_ANON_INHERITED_CLASS:
- ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, ZEND_OP1(opline));
- break;
- case ZEND_JMPZNZ:
- /* relative offset into absolute index */
- opline->extended_value = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
- /* break omitted intentionally */
- case ZEND_JMPZ:
- case ZEND_JMPNZ:
- case ZEND_JMPZ_EX:
- case ZEND_JMPNZ_EX:
- case ZEND_JMP_SET:
- case ZEND_COALESCE:
- case ZEND_NEW:
- case ZEND_FE_RESET_R:
- case ZEND_FE_RESET_RW:
- case ZEND_ASSERT_CHECK:
- ZEND_PASS_TWO_UNDO_JMP_TARGET(op_array, opline, ZEND_OP2(opline));
- break;
- case ZEND_FE_FETCH_R:
- case ZEND_FE_FETCH_RW:
- opline->extended_value = ZEND_OFFSET_TO_OPLINE_NUM(op_array, opline, opline->extended_value);
- break;
- }
opline++;
}
@@ -600,40 +624,12 @@ static void zend_accel_optimize(zend_op_array *op_array,
if (opline->op2_type == IS_CONST) {
ZEND_PASS_TWO_UPDATE_CONSTANT(op_array, opline->op2);
}
- switch (opline->opcode) {
- case ZEND_JMP:
- case ZEND_FAST_CALL:
- case ZEND_DECLARE_ANON_CLASS:
- case ZEND_DECLARE_ANON_INHERITED_CLASS:
- ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, ZEND_OP1(opline));
- break;
- case ZEND_JMPZNZ:
- /* absolute index to relative offset */
- opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
- /* break omitted intentionally */
- case ZEND_JMPZ:
- case ZEND_JMPNZ:
- case ZEND_JMPZ_EX:
- case ZEND_JMPNZ_EX:
- case ZEND_JMP_SET:
- case ZEND_COALESCE:
- case ZEND_NEW:
- case ZEND_FE_RESET_R:
- case ZEND_FE_RESET_RW:
- case ZEND_ASSERT_CHECK:
- ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, ZEND_OP2(opline));
- break;
- case ZEND_FE_FETCH_R:
- case ZEND_FE_FETCH_RW:
- opline->extended_value = ZEND_OPLINE_NUM_TO_OFFSET(op_array, opline, opline->extended_value);
- break;
- }
ZEND_VM_SET_OPCODE_HANDLER(opline);
opline++;
}
}
-static void zend_accel_adjust_fcall_stack_size(zend_op_array *op_array, zend_optimizer_ctx *ctx)
+static void zend_adjust_fcall_stack_size(zend_op_array *op_array, zend_optimizer_ctx *ctx)
{
zend_function *func;
zend_op *opline, *end;
@@ -653,7 +649,7 @@ static void zend_accel_adjust_fcall_stack_size(zend_op_array *op_array, zend_opt
}
}
-int zend_accel_script_optimize(zend_persistent_script *script)
+int zend_optimize_script(zend_script *script, zend_long optimization_level)
{
uint idx, j;
Bucket *p, *q;
@@ -664,14 +660,15 @@ int zend_accel_script_optimize(zend_persistent_script *script)
ctx.arena = zend_arena_create(64 * 1024);
ctx.script = script;
ctx.constants = NULL;
+ ctx.optimization_level = optimization_level;
- zend_accel_optimize(&script->main_op_array, &ctx);
+ zend_optimize_op_array(&script->main_op_array, &ctx);
for (idx = 0; idx < script->function_table.nNumUsed; idx++) {
p = script->function_table.arData + idx;
if (Z_TYPE(p->val) == IS_UNDEF) continue;
op_array = (zend_op_array*)Z_PTR(p->val);
- zend_accel_optimize(op_array, &ctx);
+ zend_optimize_op_array(op_array, &ctx);
}
for (idx = 0; idx < script->class_table.nNumUsed; idx++) {
@@ -683,7 +680,7 @@ int zend_accel_script_optimize(zend_persistent_script *script)
if (Z_TYPE(q->val) == IS_UNDEF) continue;
op_array = (zend_op_array*)Z_PTR(q->val);
if (op_array->scope == ce) {
- zend_accel_optimize(op_array, &ctx);
+ zend_optimize_op_array(op_array, &ctx);
} else if (op_array->type == ZEND_USER_FUNCTION) {
zend_op_array *orig_op_array;
if ((orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, q->key)) != NULL) {
@@ -695,14 +692,14 @@ int zend_accel_script_optimize(zend_persistent_script *script)
}
}
- if (ZEND_OPTIMIZER_PASS_12 & OPTIMIZATION_LEVEL) {
- zend_accel_adjust_fcall_stack_size(&script->main_op_array, &ctx);
+ if (ZEND_OPTIMIZER_PASS_12 & optimization_level) {
+ zend_adjust_fcall_stack_size(&script->main_op_array, &ctx);
for (idx = 0; idx < script->function_table.nNumUsed; idx++) {
p = script->function_table.arData + idx;
if (Z_TYPE(p->val) == IS_UNDEF) continue;
op_array = (zend_op_array*)Z_PTR(p->val);
- zend_accel_adjust_fcall_stack_size(op_array, &ctx);
+ zend_adjust_fcall_stack_size(op_array, &ctx);
}
for (idx = 0; idx < script->class_table.nNumUsed; idx++) {
@@ -714,7 +711,7 @@ int zend_accel_script_optimize(zend_persistent_script *script)
if (Z_TYPE(q->val) == IS_UNDEF) continue;
op_array = (zend_op_array*)Z_PTR(q->val);
if (op_array->scope == ce) {
- zend_accel_adjust_fcall_stack_size(op_array, &ctx);
+ zend_adjust_fcall_stack_size(op_array, &ctx);
} else if (op_array->type == ZEND_USER_FUNCTION) {
zend_op_array *orig_op_array;
if ((orig_op_array = zend_hash_find_ptr(&op_array->scope->function_table, q->key)) != NULL) {
diff --git a/ext/opcache/Optimizer/zend_optimizer.h b/ext/opcache/Optimizer/zend_optimizer.h
index 27c6159b7d..9c2a805e76 100644
--- a/ext/opcache/Optimizer/zend_optimizer.h
+++ b/ext/opcache/Optimizer/zend_optimizer.h
@@ -44,4 +44,13 @@
#define DEFAULT_OPTIMIZATION_LEVEL "0xFFFFFFFF"
+typedef struct _zend_script {
+ zend_string *filename;
+ zend_op_array main_op_array;
+ HashTable function_table;
+ HashTable class_table;
+} zend_script;
+
+int zend_optimize_script(zend_script *script, zend_long optimization_level);
+
#endif
diff --git a/ext/opcache/Optimizer/zend_optimizer_internal.h b/ext/opcache/Optimizer/zend_optimizer_internal.h
index 90df3cfadc..529727d7c9 100644
--- a/ext/opcache/Optimizer/zend_optimizer_internal.h
+++ b/ext/opcache/Optimizer/zend_optimizer_internal.h
@@ -22,7 +22,16 @@
#ifndef ZEND_OPTIMIZER_INTERNAL_H
#define ZEND_OPTIMIZER_INTERNAL_H
-#include "ZendAccelerator.h"
+#define ZEND_RESULT_TYPE(opline) (opline)->result_type
+#define ZEND_RESULT(opline) (opline)->result
+#define ZEND_OP1_TYPE(opline) (opline)->op1_type
+#define ZEND_OP1(opline) (opline)->op1
+#define ZEND_OP1_LITERAL(opline) (op_array)->literals[(opline)->op1.constant]
+#define ZEND_OP1_JMP_ADDR(opline) OP_JMP_ADDR(opline, (opline)->op1)
+#define ZEND_OP2_TYPE(opline) (opline)->op2_type
+#define ZEND_OP2(opline) (opline)->op2
+#define ZEND_OP2_LITERAL(opline) (op_array)->literals[(opline)->op2.constant]
+#define ZEND_OP2_JMP_ADDR(opline) OP_JMP_ADDR(opline, (opline)->op2)
#define VAR_NUM(v) EX_VAR_TO_NUM(v)
#define NUM_VAR(v) ((uint32_t)(zend_uintptr_t)ZEND_CALL_VAR_NUM(0, v))
@@ -32,65 +41,16 @@
#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)
-#undef MAKE_NOP
-
-#define MAKE_NOP(opline) do { \
- (opline)->op1.num = 0; \
- (opline)->op2.num = 0; \
- (opline)->result.num = 0; \
- (opline)->opcode = ZEND_NOP; \
- (opline)->op1_type = IS_UNUSED; \
- (opline)->op2_type = IS_UNUSED; \
- (opline)->result_type = IS_UNUSED; \
- zend_vm_set_opcode_handler(opline); \
-} while (0)
-
-#define RESULT_USED(op) (((op->result_type & IS_VAR) && !(op->result_type & EXT_TYPE_UNUSED)) || op->result_type == IS_TMP_VAR)
#define RESULT_UNUSED(op) ((op->result_type & EXT_TYPE_UNUSED) != 0)
-#define SAME_VAR(op1, op2) ((((op1 ## _type & IS_VAR) && (op2 ## _type & IS_VAR)) || (op1 ## _type == IS_TMP_VAR && op2 ## _type == IS_TMP_VAR)) && op1.var == op2.var)
+#define SAME_VAR(op1, op2) (op1 ## _type == op2 ## _type && op1.var == op2.var)
typedef struct _zend_optimizer_ctx {
zend_arena *arena;
- zend_persistent_script *script;
+ zend_script *script;
HashTable *constants;
+ zend_long optimization_level;
} zend_optimizer_ctx;
-typedef struct _zend_code_block zend_code_block;
-typedef struct _zend_block_source zend_block_source;
-
-struct _zend_code_block {
- int access;
- zend_op *start_opline;
- int start_opline_no;
- int len;
- zend_code_block *op1_to;
- zend_code_block *op2_to;
- zend_code_block *ext_to;
- zend_code_block *follow_to;
- zend_code_block *next;
- zend_block_source *sources;
- zend_bool protected; /* don't merge this block with others */
-};
-
-typedef struct _zend_cfg {
- zend_code_block *blocks;
- zend_code_block **try;
- zend_code_block **catch;
- zend_code_block **loop_start;
- zend_code_block **loop_cont;
- zend_code_block **loop_brk;
- zend_op **Tsource;
- char *same_t;
-} zend_cfg;
-
-struct _zend_block_source {
- zend_code_block *from;
- zend_block_source *next;
-};
-
-#define OPTIMIZATION_LEVEL \
- ZCG(accel_directives).optimization_level
-
#define LITERAL_LONG(op, val) do { \
zval _c; \
ZVAL_LONG(&_c, val); \
@@ -130,6 +90,7 @@ int zend_optimizer_replace_by_const(zend_op_array *op_array,
uint32_t var,
zval *val);
+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);
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index e23e7515b8..32e6d78a2f 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -851,17 +851,17 @@ static inline int do_validate_timestamps(zend_persistent_script *persistent_scri
* See bug #15140
*/
if (file_handle->opened_path) {
- if (persistent_script->full_path != file_handle->opened_path &&
- (ZSTR_LEN(persistent_script->full_path) != ZSTR_LEN(file_handle->opened_path) ||
- memcmp(ZSTR_VAL(persistent_script->full_path), ZSTR_VAL(file_handle->opened_path), ZSTR_LEN(file_handle->opened_path)) != 0)) {
+ if (persistent_script->script.filename != file_handle->opened_path &&
+ (ZSTR_LEN(persistent_script->script.filename) != ZSTR_LEN(file_handle->opened_path) ||
+ memcmp(ZSTR_VAL(persistent_script->script.filename), ZSTR_VAL(file_handle->opened_path), ZSTR_LEN(file_handle->opened_path)) != 0)) {
return FAILURE;
}
} else {
full_path_ptr = accelerator_orig_zend_resolve_path(file_handle->filename, strlen(file_handle->filename));
if (full_path_ptr &&
- persistent_script->full_path != full_path_ptr &&
- (ZSTR_LEN(persistent_script->full_path) != ZSTR_LEN(full_path_ptr) ||
- memcmp(ZSTR_VAL(persistent_script->full_path), ZSTR_VAL(full_path_ptr), ZSTR_LEN(full_path_ptr)) != 0)) {
+ persistent_script->script.filename != full_path_ptr &&
+ (ZSTR_LEN(persistent_script->script.filename) != ZSTR_LEN(full_path_ptr) ||
+ memcmp(ZSTR_VAL(persistent_script->script.filename), ZSTR_VAL(full_path_ptr), ZSTR_LEN(full_path_ptr)) != 0)) {
zend_string_release(full_path_ptr);
return FAILURE;
}
@@ -889,8 +889,8 @@ static inline int do_validate_timestamps(zend_persistent_script *persistent_scri
}
ps_handle.type = ZEND_HANDLE_FILENAME;
- ps_handle.filename = ZSTR_VAL(persistent_script->full_path);
- ps_handle.opened_path = persistent_script->full_path;
+ ps_handle.filename = ZSTR_VAL(persistent_script->script.filename);
+ ps_handle.opened_path = persistent_script->script.filename;
if (zend_get_file_handle_timestamp(&ps_handle, NULL) == persistent_script->timestamp) {
return SUCCESS;
@@ -1157,7 +1157,7 @@ static zend_persistent_script *cache_script_in_file_cache(zend_persistent_script
return new_persistent_script;
}
- if (!zend_accel_script_optimize(new_persistent_script)) {
+ if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level)) {
return new_persistent_script;
}
@@ -1181,16 +1181,16 @@ static zend_persistent_script *cache_script_in_file_cache(zend_persistent_script
zend_shared_alloc_destroy_xlat_table();
new_persistent_script->is_phar =
- new_persistent_script->full_path &&
- strstr(ZSTR_VAL(new_persistent_script->full_path), ".phar") &&
- !strstr(ZSTR_VAL(new_persistent_script->full_path), "://");
+ new_persistent_script->script.filename &&
+ strstr(ZSTR_VAL(new_persistent_script->script.filename), ".phar") &&
+ !strstr(ZSTR_VAL(new_persistent_script->script.filename), "://");
/* Consistency check */
if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) {
zend_accel_error(
((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
"Internal error: wrong size calculation: %s start=0x%08x, end=0x%08x, real=0x%08x\n",
- ZSTR_VAL(new_persistent_script->full_path),
+ ZSTR_VAL(new_persistent_script->script.filename),
new_persistent_script->mem,
(char *)new_persistent_script->mem + new_persistent_script->size,
ZCG(mem));
@@ -1215,7 +1215,7 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
return new_persistent_script;
}
- if (!zend_accel_script_optimize(new_persistent_script)) {
+ if (!zend_optimize_script(&new_persistent_script->script, ZCG(accel_directives).optimization_level)) {
return new_persistent_script;
}
@@ -1233,7 +1233,7 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
/* Check if we still need to put the file into the cache (may be it was
* already stored by another process. This final check is done under
* exclusive lock) */
- bucket = zend_accel_hash_find_entry(&ZCSG(hash), new_persistent_script->full_path);
+ bucket = zend_accel_hash_find_entry(&ZCSG(hash), new_persistent_script->script.filename);
if (bucket) {
zend_persistent_script *existing_persistent_script = (zend_persistent_script *)bucket->data;
@@ -1275,16 +1275,16 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
zend_shared_alloc_destroy_xlat_table();
new_persistent_script->is_phar =
- new_persistent_script->full_path &&
- strstr(ZSTR_VAL(new_persistent_script->full_path), ".phar") &&
- !strstr(ZSTR_VAL(new_persistent_script->full_path), "://");
+ new_persistent_script->script.filename &&
+ strstr(ZSTR_VAL(new_persistent_script->script.filename), ".phar") &&
+ !strstr(ZSTR_VAL(new_persistent_script->script.filename), "://");
/* Consistency check */
if ((char*)new_persistent_script->mem + new_persistent_script->size != (char*)ZCG(mem)) {
zend_accel_error(
((char*)new_persistent_script->mem + new_persistent_script->size < (char*)ZCG(mem)) ? ACCEL_LOG_ERROR : ACCEL_LOG_WARNING,
"Internal error: wrong size calculation: %s start=0x%08x, end=0x%08x, real=0x%08x\n",
- ZSTR_VAL(new_persistent_script->full_path),
+ ZSTR_VAL(new_persistent_script->script.filename),
new_persistent_script->mem,
(char *)new_persistent_script->mem + new_persistent_script->size,
ZCG(mem));
@@ -1293,14 +1293,14 @@ static zend_persistent_script *cache_script_in_shared_memory(zend_persistent_scr
new_persistent_script->dynamic_members.checksum = zend_accel_script_checksum(new_persistent_script);
/* store script structure in the hash table */
- bucket = zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(new_persistent_script->full_path), ZSTR_LEN(new_persistent_script->full_path), 0, new_persistent_script);
+ bucket = zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(new_persistent_script->script.filename), ZSTR_LEN(new_persistent_script->script.filename), 0, new_persistent_script);
if (bucket) {
- zend_accel_error(ACCEL_LOG_INFO, "Cached script '%s'", new_persistent_script->full_path);
+ zend_accel_error(ACCEL_LOG_INFO, "Cached script '%s'", new_persistent_script->script.filename);
if (key &&
/* key may contain non-persistent PHAR aliases (see issues #115 and #149) */
memcmp(key, "phar://", sizeof("phar://") - 1) != 0 &&
- (ZSTR_LEN(new_persistent_script->full_path) != key_length ||
- memcmp(ZSTR_VAL(new_persistent_script->full_path), key, key_length) != 0)) {
+ (ZSTR_LEN(new_persistent_script->script.filename) != key_length ||
+ memcmp(ZSTR_VAL(new_persistent_script->script.filename), key, key_length) != 0)) {
/* link key to the same persistent script in hash table */
if (zend_accel_hash_update(&ZCSG(hash), key, key_length, 1, bucket)) {
zend_accel_error(ACCEL_LOG_INFO, "Added key '%s'", key);
@@ -1468,7 +1468,7 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
/* Override them with ours */
CG(function_table) = &ZCG(function_table);
- EG(class_table) = CG(class_table) = &new_persistent_script->class_table;
+ EG(class_table) = CG(class_table) = &new_persistent_script->script.class_table;
ZVAL_UNDEF(&EG(user_error_handler));
zend_try {
@@ -1505,8 +1505,8 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
Here we aren't sure we would store it, but we will need it
further anyway.
*/
- zend_accel_move_user_functions(&ZCG(function_table), &new_persistent_script->function_table);
- new_persistent_script->main_op_array = *op_array;
+ zend_accel_move_user_functions(&ZCG(function_table), &new_persistent_script->script.function_table);
+ new_persistent_script->script.main_op_array = *op_array;
efree(op_array); /* we have valid persistent_script, so it's safe to free op_array */
@@ -1527,11 +1527,11 @@ static zend_persistent_script *opcache_compile_file(zend_file_handle *file_handl
}
if (file_handle->opened_path) {
- new_persistent_script->full_path = zend_string_copy(file_handle->opened_path);
+ new_persistent_script->script.filename = zend_string_copy(file_handle->opened_path);
} else {
- new_persistent_script->full_path = zend_string_init(file_handle->filename, strlen(file_handle->filename), 0);
+ new_persistent_script->script.filename = zend_string_init(file_handle->filename, strlen(file_handle->filename), 0);
}
- zend_string_hash_val(new_persistent_script->full_path);
+ zend_string_hash_val(new_persistent_script->script.filename);
/* Now persistent_script structure is ready in process memory */
return new_persistent_script;
@@ -1565,21 +1565,21 @@ zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int type)
persistent_script = zend_file_cache_script_load(file_handle);
if (persistent_script) {
/* see bug #15471 (old BTS) */
- if (persistent_script->full_path) {
+ if (persistent_script->script.filename) {
if (!EG(current_execute_data) || !EG(current_execute_data)->opline ||
!EG(current_execute_data)->func ||
!ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
EG(current_execute_data)->opline->opcode != ZEND_INCLUDE_OR_EVAL ||
(EG(current_execute_data)->opline->extended_value != ZEND_INCLUDE_ONCE &&
EG(current_execute_data)->opline->extended_value != ZEND_REQUIRE_ONCE)) {
- if (zend_hash_add_empty_element(&EG(included_files), persistent_script->full_path) != NULL) {
+ if (zend_hash_add_empty_element(&EG(included_files), persistent_script->script.filename) != NULL) {
/* ext/phar has to load phar's metadata into memory */
if (persistent_script->is_phar) {
php_stream_statbuf ssb;
- char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->full_path));
+ char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->script.filename));
memcpy(fname, "phar://", sizeof("phar://") - 1);
- memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->full_path), ZSTR_LEN(persistent_script->full_path) + 1);
+ memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->script.filename), ZSTR_LEN(persistent_script->script.filename) + 1);
php_stream_stat_path(fname, &ssb);
efree(fname);
}
@@ -1741,7 +1741,7 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
if (checksum != persistent_script->dynamic_members.checksum ) {
/* The checksum is wrong */
zend_accel_error(ACCEL_LOG_INFO, "Checksum failed for '%s': expected=0x%0.8X, found=0x%0.8X",
- persistent_script->full_path, persistent_script->dynamic_members.checksum, checksum);
+ persistent_script->script.filename, persistent_script->dynamic_members.checksum, checksum);
zend_shared_alloc_lock();
if (!persistent_script->corrupted) {
persistent_script->corrupted = 1;
@@ -1818,21 +1818,21 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
#endif
/* see bug #15471 (old BTS) */
- if (persistent_script->full_path) {
+ if (persistent_script->script.filename) {
if (!EG(current_execute_data) || !EG(current_execute_data)->opline ||
!EG(current_execute_data)->func ||
!ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
EG(current_execute_data)->opline->opcode != ZEND_INCLUDE_OR_EVAL ||
(EG(current_execute_data)->opline->extended_value != ZEND_INCLUDE_ONCE &&
EG(current_execute_data)->opline->extended_value != ZEND_REQUIRE_ONCE)) {
- if (zend_hash_add_empty_element(&EG(included_files), persistent_script->full_path) != NULL) {
+ if (zend_hash_add_empty_element(&EG(included_files), persistent_script->script.filename) != NULL) {
/* ext/phar has to load phar's metadata into memory */
if (persistent_script->is_phar) {
php_stream_statbuf ssb;
- char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->full_path));
+ char *fname = emalloc(sizeof("phar://") + ZSTR_LEN(persistent_script->script.filename));
memcpy(fname, "phar://", sizeof("phar://") - 1);
- memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->full_path), ZSTR_LEN(persistent_script->full_path) + 1);
+ memcpy(fname + sizeof("phar://") - 1, ZSTR_VAL(persistent_script->script.filename), ZSTR_LEN(persistent_script->script.filename) + 1);
php_stream_stat_path(fname, &ssb);
efree(fname);
}
@@ -1871,7 +1871,7 @@ static int persistent_stream_open_function(const char *filename, zend_file_handl
/* we are in include_once or FastCGI request */
handle->filename = (char*)filename;
handle->free_filename = 0;
- handle->opened_path = zend_string_copy(ZCG(cache_persistent_script)->full_path);
+ handle->opened_path = zend_string_copy(ZCG(cache_persistent_script)->script.filename);
handle->type = ZEND_HANDLE_FILENAME;
return SUCCESS;
}
@@ -1913,7 +1913,7 @@ static zend_string* persistent_zend_resolve_path(const char *filename, int filen
if (!persistent_script->corrupted) {
ZCG(cache_opline) = EG(current_execute_data) ? EG(current_execute_data)->opline : NULL;
ZCG(cache_persistent_script) = persistent_script;
- return zend_string_copy(persistent_script->full_path);
+ return zend_string_copy(persistent_script->script.filename);
}
}
} else {
diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h
index 798b2d7365..c709503666 100644
--- a/ext/opcache/ZendAccelerator.h
+++ b/ext/opcache/ZendAccelerator.h
@@ -87,14 +87,6 @@
# include <sys/param.h>
#endif
-#define PHP_5_0_X_API_NO 220040412
-#define PHP_5_1_X_API_NO 220051025
-#define PHP_5_2_X_API_NO 220060519
-#define PHP_5_3_X_API_NO 220090626
-#define PHP_5_4_X_API_NO 220100525
-#define PHP_5_5_X_API_NO 220121212
-#define PHP_5_6_X_API_NO 220131226
-
/*** file locking ***/
#ifndef ZEND_WIN32
extern int lock_file;
@@ -127,18 +119,6 @@ extern int lock_file;
# endif
#endif
-#define PZ_REFCOUNT_P(pz) (pz)->refcount__gc
-#define PZ_SET_REFCOUNT_P(pz, v) (pz)->refcount__gc = (v)
-#define PZ_ADDREF_P(pz) ++((pz)->refcount__gc)
-#define PZ_DELREF_P(pz) --((pz)->refcount__gc)
-#define PZ_ISREF_P(pz) (pz)->is_ref__gc
-#define PZ_SET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 1)
-#define PZ_UNSET_ISREF_P(pz) Z_SET_ISREF_TO_P(pz, 0)
-#define PZ_SET_ISREF_TO_P(pz, isref) (pz)->is_ref__gc = (isref)
-
-#define DO_ALLOCA(x) do_alloca(x, use_heap)
-#define FREE_ALLOCA(x) free_alloca(x, use_heap)
-
#if defined(HAVE_OPCACHE_FILE_CACHE) && defined(ZEND_WIN32)
# define ENABLE_FILE_CACHE_FALLBACK 1
#endif
@@ -156,11 +136,8 @@ typedef enum _zend_accel_restart_reason {
} zend_accel_restart_reason;
typedef struct _zend_persistent_script {
- zend_string *full_path; /* full real path with resolved symlinks */
- zend_op_array main_op_array;
- HashTable function_table;
- HashTable class_table;
- zend_long compiler_halt_offset; /* position of __HALT_COMPILER or -1 */
+ zend_script script;
+ zend_long compiler_halt_offset; /* position of __HALT_COMPILER or -1 */
int ping_auto_globals_mask; /* which autoglobals are used by the script */
accel_time_t timestamp; /* the script modification time */
zend_bool corrupted;
@@ -325,37 +302,15 @@ 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);
int validate_timestamp_and_record(zend_persistent_script *persistent_script, zend_file_handle *file_handle);
int zend_accel_invalidate(const char *filename, int filename_len, zend_bool force);
-int zend_accel_script_optimize(zend_persistent_script *persistent_script);
int accelerator_shm_read_lock(void);
void accelerator_shm_read_unlock(void);
char *accel_make_persistent_key(const char *path, int path_length, int *key_len);
zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type);
-#if !defined(ZEND_DECLARE_INHERITED_CLASS_DELAYED)
-# define ZEND_DECLARE_INHERITED_CLASS_DELAYED 145
-#endif
-
-#define ZEND_DECLARE_INHERITED_CLASS_DELAYED_FLAG 0x80
-
#define IS_ACCEL_INTERNED(str) \
((char*)(str) >= ZCSG(interned_strings_start) && (char*)(str) < ZCSG(interned_strings_end))
zend_string *accel_new_interned_string(zend_string *str);
-# define ZEND_RESULT_TYPE(opline) (opline)->result_type
-# define ZEND_RESULT(opline) (opline)->result
-# define ZEND_OP1_TYPE(opline) (opline)->op1_type
-# define ZEND_OP1(opline) (opline)->op1
-# define ZEND_OP1_CONST(opline) (*(opline)->op1.zv)
-# define ZEND_OP1_LITERAL(opline) (op_array)->literals[(opline)->op1.constant]
-# define ZEND_OP2_TYPE(opline) (opline)->op2_type
-# define ZEND_OP2(opline) (opline)->op2
-# define ZEND_OP2_CONST(opline) (*(opline)->op2.zv)
-# define ZEND_OP2_LITERAL(opline) (op_array)->literals[(opline)->op2.constant]
-# define ZEND_DONE_PASS_TWO(op_array) (((op_array)->fn_flags & ZEND_ACC_DONE_PASS_TWO) != 0)
-# define ZEND_CE_FILENAME(ce) (ce)->info.user.filename
-# define ZEND_CE_DOC_COMMENT(ce) (ce)->info.user.doc_comment
-# define ZEND_CE_DOC_COMMENT_LEN(ce) (ce)->info.user.doc_comment_len
-
#endif /* ZEND_ACCELERATOR_H */
diff --git a/ext/opcache/config.m4 b/ext/opcache/config.m4
index fbe18f8e2c..88468b1355 100644
--- a/ext/opcache/config.m4
+++ b/ext/opcache/config.m4
@@ -400,7 +400,9 @@ fi
Optimizer/block_pass.c \
Optimizer/optimize_temp_vars_5.c \
Optimizer/nop_removal.c \
- Optimizer/compact_literals.c,
+ Optimizer/compact_literals.c \
+ Optimizer/zend_cfg.c \
+ Optimizer/zend_dump.c,
shared,,-DZEND_ENABLE_STATIC_TSRMLS_CACHE=1,,yes)
PHP_ADD_BUILD_DIR([$ext_builddir/Optimizer], 1)
diff --git a/ext/opcache/config.w32 b/ext/opcache/config.w32
index ba6fd621bd..7354a6ee6d 100644
--- a/ext/opcache/config.w32
+++ b/ext/opcache/config.w32
@@ -23,7 +23,7 @@ if (PHP_OPCACHE != "no") {
zend_shared_alloc.c \
shared_alloc_win32.c", true, "/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
- ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c pass1_5.c pass2.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c", "opcache", "OptimizerObj");
+ ADD_SOURCES(configure_module_dirname + "/Optimizer", "zend_optimizer.c pass1_5.c pass2.c pass3.c optimize_func_calls.c block_pass.c optimize_temp_vars_5.c nop_removal.c compact_literals.c zend_cfg.c zend_dump.c", "opcache", "OptimizerObj");
ADD_FLAG('CFLAGS_OPCACHE', "/I " + configure_module_dirname);
diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c
index f65e270000..8514e2b391 100644
--- a/ext/opcache/zend_accelerator_module.c
+++ b/ext/opcache/zend_accelerator_module.c
@@ -545,7 +545,7 @@ static int accelerator_get_scripts(zval *return_value)
script = (zend_persistent_script *)cache_entry->data;
array_init(&persistent_script_report);
- add_assoc_str(&persistent_script_report, "full_path", zend_string_dup(script->full_path, 0));
+ add_assoc_str(&persistent_script_report, "full_path", zend_string_dup(script->script.filename, 0));
add_assoc_long(&persistent_script_report, "hits", (zend_long)script->dynamic_members.hits);
add_assoc_long(&persistent_script_report, "memory_consumption", script->dynamic_members.memory_consumption);
ta = localtime(&script->dynamic_members.last_used);
diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c
index cfb03a00e4..ab048c6df3 100644
--- a/ext/opcache/zend_accelerator_util_funcs.c
+++ b/ext/opcache/zend_accelerator_util_funcs.c
@@ -72,12 +72,12 @@ zend_persistent_script* create_persistent_script(void)
zend_persistent_script *persistent_script = (zend_persistent_script *) emalloc(sizeof(zend_persistent_script));
memset(persistent_script, 0, sizeof(zend_persistent_script));
- zend_hash_init(&persistent_script->function_table, 128, NULL, ZEND_FUNCTION_DTOR, 0);
+ zend_hash_init(&persistent_script->script.function_table, 128, NULL, ZEND_FUNCTION_DTOR, 0);
/* class_table is usually destroyed by free_persistent_script() that
* overrides destructor. ZEND_CLASS_DTOR may be used by standard
* PHP compiler
*/
- zend_hash_init(&persistent_script->class_table, 16, NULL, ZEND_CLASS_DTOR, 0);
+ zend_hash_init(&persistent_script->script.class_table, 16, NULL, ZEND_CLASS_DTOR, 0);
return persistent_script;
}
@@ -85,18 +85,18 @@ zend_persistent_script* create_persistent_script(void)
void free_persistent_script(zend_persistent_script *persistent_script, int destroy_elements)
{
if (destroy_elements) {
- persistent_script->function_table.pDestructor = zend_accel_destroy_zend_function;
- persistent_script->class_table.pDestructor = zend_accel_destroy_zend_class;
+ persistent_script->script.function_table.pDestructor = zend_accel_destroy_zend_function;
+ persistent_script->script.class_table.pDestructor = zend_accel_destroy_zend_class;
} else {
- persistent_script->function_table.pDestructor = NULL;
- persistent_script->class_table.pDestructor = NULL;
+ persistent_script->script.function_table.pDestructor = NULL;
+ persistent_script->script.class_table.pDestructor = NULL;
}
- zend_hash_destroy(&persistent_script->function_table);
- zend_hash_destroy(&persistent_script->class_table);
+ zend_hash_destroy(&persistent_script->script.function_table);
+ zend_hash_destroy(&persistent_script->script.class_table);
- if (persistent_script->full_path) {
- zend_string_release(persistent_script->full_path);
+ if (persistent_script->script.filename) {
+ zend_string_release(persistent_script->script.filename);
}
efree(persistent_script);
@@ -679,7 +679,7 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
zend_op_array *op_array;
op_array = (zend_op_array *) emalloc(sizeof(zend_op_array));
- *op_array = persistent_script->main_op_array;
+ *op_array = persistent_script->script.main_op_array;
if (EXPECTED(from_shared_memory)) {
zend_hash_init(&ZCG(bind_hash), 10, NULL, NULL, 0);
@@ -699,22 +699,22 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
}
/* Copy all the necessary stuff from shared memory to regular memory, and protect the shared script */
- if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
- zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, (unique_copy_ctor_func_t) zend_class_copy_ctor);
+ if (zend_hash_num_elements(&persistent_script->script.class_table) > 0) {
+ zend_accel_class_hash_copy(CG(class_table), &persistent_script->script.class_table, (unique_copy_ctor_func_t) zend_class_copy_ctor);
}
/* we must first to copy all classes and then prepare functions, since functions may try to bind
classes - which depend on pre-bind class entries existent in the class table */
- if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
- zend_accel_function_hash_copy_from_shm(CG(function_table), &persistent_script->function_table);
+ if (zend_hash_num_elements(&persistent_script->script.function_table) > 0) {
+ zend_accel_function_hash_copy_from_shm(CG(function_table), &persistent_script->script.function_table);
}
/* Register __COMPILER_HALT_OFFSET__ constant */
if (persistent_script->compiler_halt_offset != 0 &&
- persistent_script->full_path) {
+ persistent_script->script.filename) {
zend_string *name;
char haltoff[] = "__COMPILER_HALT_OFFSET__";
- name = zend_mangle_property_name(haltoff, sizeof(haltoff) - 1, ZSTR_VAL(persistent_script->full_path), ZSTR_LEN(persistent_script->full_path), 0);
+ name = zend_mangle_property_name(haltoff, sizeof(haltoff) - 1, ZSTR_VAL(persistent_script->script.filename), ZSTR_LEN(persistent_script->script.filename), 0);
if (!zend_hash_exists(EG(zend_constants), name)) {
zend_register_long_constant(ZSTR_VAL(name), ZSTR_LEN(name), persistent_script->compiler_halt_offset, CONST_CS, 0);
}
@@ -724,17 +724,17 @@ zend_op_array* zend_accel_load_script(zend_persistent_script *persistent_script,
zend_hash_destroy(&ZCG(bind_hash));
ZCG(current_persistent_script) = NULL;
} else /* if (!from_shared_memory) */ {
- if (zend_hash_num_elements(&persistent_script->function_table) > 0) {
- zend_accel_function_hash_copy(CG(function_table), &persistent_script->function_table);
+ if (zend_hash_num_elements(&persistent_script->script.function_table) > 0) {
+ zend_accel_function_hash_copy(CG(function_table), &persistent_script->script.function_table);
}
- if (zend_hash_num_elements(&persistent_script->class_table) > 0) {
- zend_accel_class_hash_copy(CG(class_table), &persistent_script->class_table, NULL);
+ if (zend_hash_num_elements(&persistent_script->script.class_table) > 0) {
+ zend_accel_class_hash_copy(CG(class_table), &persistent_script->script.class_table, NULL);
}
}
if (op_array->early_binding != (uint32_t)-1) {
zend_string *orig_compiled_filename = CG(compiled_filename);
- CG(compiled_filename) = persistent_script->full_path;
+ CG(compiled_filename) = persistent_script->script.filename;
zend_do_delayed_early_binding(op_array);
CG(compiled_filename) = orig_compiled_filename;
}
diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c
index 7c615e927b..3054e57a6f 100644
--- a/ext/opcache/zend_file_cache.c
+++ b/ext/opcache/zend_file_cache.c
@@ -381,10 +381,10 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
end = opline + op_array->last;
while (opline < end) {
# if ZEND_USE_ABS_CONST_ADDR
- if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+ if (opline->op1_type == IS_CONST) {
SERIALIZE_PTR(opline->op1.zv);
}
- if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+ if (opline->op2_type == IS_CONST) {
SERIALIZE_PTR(opline->op2.zv);
}
# endif
@@ -463,7 +463,7 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
SERIALIZE_STR(op_array->function_name);
SERIALIZE_STR(op_array->filename);
- SERIALIZE_PTR(op_array->brk_cont_array);
+ SERIALIZE_PTR(op_array->live_range);
SERIALIZE_PTR(op_array->scope);
SERIALIZE_STR(op_array->doc_comment);
SERIALIZE_PTR(op_array->try_catch_array);
@@ -546,8 +546,8 @@ static void zend_file_cache_serialize_class(zval *zv,
}
}
zend_file_cache_serialize_hash(&ce->constants_table, script, info, buf, zend_file_cache_serialize_zval);
- SERIALIZE_STR(ZEND_CE_FILENAME(ce));
- SERIALIZE_STR(ZEND_CE_DOC_COMMENT(ce));
+ SERIALIZE_STR(ce->info.user.filename);
+ SERIALIZE_STR(ce->info.user.doc_comment);
zend_file_cache_serialize_hash(&ce->properties_info, script, info, buf, zend_file_cache_serialize_prop_info);
if (ce->trait_aliases) {
@@ -659,11 +659,11 @@ static void zend_file_cache_serialize(zend_persistent_script *script,
memcpy(buf, script->mem, script->size);
new_script = (zend_persistent_script*)((char*)buf + info->script_offset);
- SERIALIZE_STR(new_script->full_path);
+ SERIALIZE_STR(new_script->script.filename);
- zend_file_cache_serialize_hash(&new_script->class_table, script, info, buf, zend_file_cache_serialize_class);
- zend_file_cache_serialize_hash(&new_script->function_table, script, info, buf, zend_file_cache_serialize_func);
- zend_file_cache_serialize_op_array(&new_script->main_op_array, script, info, buf);
+ zend_file_cache_serialize_hash(&new_script->script.class_table, script, info, buf, zend_file_cache_serialize_class);
+ zend_file_cache_serialize_hash(&new_script->script.function_table, script, info, buf, zend_file_cache_serialize_func);
+ zend_file_cache_serialize_op_array(&new_script->script.main_op_array, script, info, buf);
SERIALIZE_PTR(new_script->arena_mem);
new_script->mem = NULL;
@@ -711,7 +711,7 @@ int zend_file_cache_script_store(zend_persistent_script *script, int in_shm)
#endif
void *mem, *buf;
- filename = zend_file_cache_get_bin_file_path(script->full_path);
+ filename = zend_file_cache_get_bin_file_path(script->script.filename);
if (zend_file_cache_mkdir(filename, strlen(ZCG(accel_directives).file_cache)) != SUCCESS) {
zend_accel_error(ACCEL_LOG_WARNING, "opcache cannot create directory for file '%s'\n", filename);
@@ -936,10 +936,10 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
end = opline + op_array->last;
while (opline < end) {
# if ZEND_USE_ABS_CONST_ADDR
- if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+ if (opline->op1_type == IS_CONST) {
UNSERIALIZE_PTR(opline->op1.zv);
}
- if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+ if (opline->op2_type == IS_CONST) {
UNSERIALIZE_PTR(opline->op2.zv);
}
# endif
@@ -1014,7 +1014,7 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
UNSERIALIZE_STR(op_array->function_name);
UNSERIALIZE_STR(op_array->filename);
- UNSERIALIZE_PTR(op_array->brk_cont_array);
+ UNSERIALIZE_PTR(op_array->live_range);
UNSERIALIZE_PTR(op_array->scope);
UNSERIALIZE_STR(op_array->doc_comment);
UNSERIALIZE_PTR(op_array->try_catch_array);
@@ -1091,8 +1091,8 @@ static void zend_file_cache_unserialize_class(zval *zv,
}
zend_file_cache_unserialize_hash(&ce->constants_table,
script, buf, zend_file_cache_unserialize_zval, NULL);
- UNSERIALIZE_STR(ZEND_CE_FILENAME(ce));
- UNSERIALIZE_STR(ZEND_CE_DOC_COMMENT(ce));
+ UNSERIALIZE_STR(ce->info.user.filename);
+ UNSERIALIZE_STR(ce->info.user.doc_comment);
zend_file_cache_unserialize_hash(&ce->properties_info,
script, buf, zend_file_cache_unserialize_prop_info, ZVAL_PTR_DTOR);
@@ -1192,13 +1192,13 @@ static void zend_file_cache_unserialize(zend_persistent_script *script,
{
script->mem = buf;
- UNSERIALIZE_STR(script->full_path);
+ UNSERIALIZE_STR(script->script.filename);
- zend_file_cache_unserialize_hash(&script->class_table,
+ zend_file_cache_unserialize_hash(&script->script.class_table,
script, buf, zend_file_cache_unserialize_class, ZEND_CLASS_DTOR);
- zend_file_cache_unserialize_hash(&script->function_table,
+ zend_file_cache_unserialize_hash(&script->script.function_table,
script, buf, zend_file_cache_unserialize_func, ZEND_FUNCTION_DTOR);
- zend_file_cache_unserialize_op_array(&script->main_op_array, script, buf);
+ zend_file_cache_unserialize_op_array(&script->script.main_op_array, script, buf);
UNSERIALIZE_PTR(script->arena_mem);
}
@@ -1351,7 +1351,7 @@ use_process_mem:
if (cache_it) {
script->dynamic_members.checksum = zend_accel_script_checksum(script);
- zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(script->full_path), ZSTR_LEN(script->full_path), 0, script);
+ zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(script->script.filename), ZSTR_LEN(script->script.filename), 0, script);
zend_shared_alloc_unlock();
zend_arena_release(&CG(arena), checkpoint);
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c
index 1f5abb4652..11cf33ee4a 100644
--- a/ext/opcache/zend_persist.c
+++ b/ext/opcache/zend_persist.c
@@ -517,22 +517,22 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
for (; opline < end ; opline++, offset++) {
# if ZEND_USE_ABS_CONST_ADDR
- if (ZEND_OP1_TYPE(opline) == IS_CONST) {
+ if (opline->op1_type == IS_CONST) {
opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals));
}
- if (ZEND_OP2_TYPE(opline) == IS_CONST) {
+ if (opline->op2_type == IS_CONST) {
opline->op2.zv = (zval*)((char*)opline->op2.zv + ((char*)op_array->literals - (char*)orig_literals));
}
# endif
# if ZEND_USE_ABS_JMP_ADDR
- if (ZEND_DONE_PASS_TWO(op_array)) {
+ if (op_array->fn_flags & ZEND_ACC_DONE_PASS_TWO) {
/* fix jumps to point to new array */
switch (opline->opcode) {
case ZEND_JMP:
case ZEND_FAST_CALL:
case ZEND_DECLARE_ANON_CLASS:
case ZEND_DECLARE_ANON_INHERITED_CLASS:
- ZEND_OP1(opline).jmp_addr = &new_opcodes[ZEND_OP1(opline).jmp_addr - op_array->opcodes];
+ opline->op1.jmp_addr = &new_opcodes[opline->op1.jmp_addr - op_array->opcodes];
break;
case ZEND_JMPZNZ:
/* relative extended_value don't have to be changed */
@@ -547,7 +547,7 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
case ZEND_FE_RESET_R:
case ZEND_FE_RESET_RW:
case ZEND_ASSERT_CHECK:
- ZEND_OP2(opline).jmp_addr = &new_opcodes[ZEND_OP2(opline).jmp_addr - op_array->opcodes];
+ opline->op2.jmp_addr = &new_opcodes[opline->op2.jmp_addr - op_array->opcodes];
break;
case ZEND_FE_FETCH_R:
case ZEND_FE_FETCH_RW:
@@ -617,8 +617,8 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
op_array->arg_info = arg_info;
}
- if (op_array->brk_cont_array) {
- zend_accel_store(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont);
+ if (op_array->live_range) {
+ zend_accel_store(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
}
if (op_array->scope) {
@@ -747,19 +747,19 @@ static void zend_persist_class_entry(zval *zv)
zend_hash_persist(&ce->constants_table, zend_persist_zval);
- if (ZEND_CE_FILENAME(ce)) {
+ if (ce->info.user.filename) {
/* do not free! PHP has centralized filename storage, compiler will free it */
- zend_accel_memdup_string(ZEND_CE_FILENAME(ce));
+ zend_accel_memdup_string(ce->info.user.filename);
}
- if (ZEND_CE_DOC_COMMENT(ce)) {
+ if (ce->info.user.doc_comment) {
if (ZCG(accel_directives).save_comments) {
- zend_accel_store_string(ZEND_CE_DOC_COMMENT(ce));
+ zend_accel_store_string(ce->info.user.doc_comment);
} else {
- if (!zend_shared_alloc_get_xlat_entry(ZEND_CE_DOC_COMMENT(ce))) {
- zend_shared_alloc_register_xlat_entry(ZEND_CE_DOC_COMMENT(ce), ZEND_CE_DOC_COMMENT(ce));
- zend_string_release(ZEND_CE_DOC_COMMENT(ce));
+ if (!zend_shared_alloc_get_xlat_entry(ce->info.user.doc_comment)) {
+ zend_shared_alloc_register_xlat_entry(ce->info.user.doc_comment, ce->info.user.doc_comment);
+ zend_string_release(ce->info.user.doc_comment);
}
- ZEND_CE_DOC_COMMENT(ce) = NULL;
+ ce->info.user.doc_comment = NULL;
}
}
zend_hash_persist(&ce->properties_info, zend_persist_property_info);
@@ -906,7 +906,7 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
if (key && *key) {
*key = zend_accel_memdup(*key, key_length + 1);
}
- zend_accel_store_string(script->full_path);
+ zend_accel_store_string(script->script.filename);
#ifdef __SSE2__
/* Align to 64-byte boundary */
@@ -918,9 +918,9 @@ zend_persistent_script *zend_accel_script_persist(zend_persistent_script *script
script->arena_mem = ZCG(arena_mem) = ZCG(mem);
ZCG(mem) = (void*)((char*)ZCG(mem) + script->arena_size);
- zend_accel_persist_class_table(&script->class_table);
- zend_hash_persist(&script->function_table, zend_persist_op_array);
- zend_persist_op_array_ex(&script->main_op_array, script);
+ zend_accel_persist_class_table(&script->script.class_table);
+ zend_hash_persist(&script->script.function_table, zend_persist_op_array);
+ zend_persist_op_array_ex(&script->script.main_op_array, script);
return script;
}
diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c
index 42d962b7cb..a3c2d1a905 100644
--- a/ext/opcache/zend_persist_calc.c
+++ b/ext/opcache/zend_persist_calc.c
@@ -234,8 +234,8 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array)
}
}
- if (op_array->brk_cont_array) {
- ADD_DUP_SIZE(op_array->brk_cont_array, sizeof(zend_brk_cont_element) * op_array->last_brk_cont);
+ if (op_array->live_range) {
+ ADD_DUP_SIZE(op_array->live_range, sizeof(zend_live_range) * op_array->last_live_range);
}
if (ZCG(accel_directives).save_comments && op_array->doc_comment) {
@@ -318,11 +318,11 @@ static void zend_persist_class_entry_calc(zval *zv)
}
zend_hash_persist_calc(&ce->constants_table, zend_persist_zval_calc);
- if (ZEND_CE_FILENAME(ce)) {
- ADD_STRING(ZEND_CE_FILENAME(ce));
+ if (ce->info.user.filename) {
+ ADD_STRING(ce->info.user.filename);
}
- if (ZCG(accel_directives).save_comments && ZEND_CE_DOC_COMMENT(ce)) {
- ADD_STRING(ZEND_CE_DOC_COMMENT(ce));
+ if (ZCG(accel_directives).save_comments && ce->info.user.doc_comment) {
+ ADD_STRING(ce->info.user.doc_comment);
}
zend_hash_persist_calc(&ce->properties_info, zend_persist_property_info_calc);
@@ -391,16 +391,16 @@ uint zend_accel_script_persist_calc(zend_persistent_script *new_persistent_scrip
if (key) {
ADD_DUP_SIZE(key, key_length + 1);
}
- ADD_STRING(new_persistent_script->full_path);
+ ADD_STRING(new_persistent_script->script.filename);
#ifdef __SSE2__
/* Align size to 64-byte boundary */
new_persistent_script->size = (new_persistent_script->size + 63) & ~63;
#endif
- zend_accel_persist_class_table_calc(&new_persistent_script->class_table);
- zend_hash_persist_calc(&new_persistent_script->function_table, zend_persist_op_array_calc);
- zend_persist_op_array_calc_ex(&new_persistent_script->main_op_array);
+ zend_accel_persist_class_table_calc(&new_persistent_script->script.class_table);
+ zend_hash_persist_calc(&new_persistent_script->script.function_table, zend_persist_op_array_calc);
+ zend_persist_op_array_calc_ex(&new_persistent_script->script.main_op_array);
#ifdef __SSE2__
/* Align size to 64-byte boundary */
diff --git a/ext/pdo_mysql/php_pdo_mysql_int.h b/ext/pdo_mysql/php_pdo_mysql_int.h
index 1ae09ab50b..2d238e3cf2 100644
--- a/ext/pdo_mysql/php_pdo_mysql_int.h
+++ b/ext/pdo_mysql/php_pdo_mysql_int.h
@@ -126,9 +126,9 @@ typedef struct {
const MYSQL_FIELD *fields;
MYSQL_ROW current_data;
#if PDO_USE_MYSQLND
- zend_ulong *current_lengths;
+ const size_t *current_lengths;
#else
- zend_long *current_lengths;
+ zend_long *current_lengths;
#endif
pdo_mysql_error_info einfo;
#if PDO_USE_MYSQLND
@@ -144,7 +144,7 @@ typedef struct {
#endif
PDO_MYSQL_PARAM_BIND *bound_result;
my_bool *out_null;
- zend_ulong *out_length;
+ zend_ulong *out_length;
unsigned int params_given;
unsigned max_length:1;
} pdo_mysql_stmt;
diff --git a/ext/readline/readline.c b/ext/readline/readline.c
index 47e59d8363..11fa5964b6 100644
--- a/ext/readline/readline.c
+++ b/ext/readline/readline.c
@@ -305,7 +305,7 @@ PHP_FUNCTION(readline_info)
oldval = rl_erase_empty_line;
if (value) {
convert_to_long_ex(value);
- rl_erase_empty_line = Z_LVAL_PP(value);
+ rl_erase_empty_line = Z_LVAL_P(value);
}
RETVAL_LONG(oldval);
#endif
diff --git a/ext/shmop/php_shmop.h b/ext/shmop/php_shmop.h
index 805f3a380c..71ab801a50 100644
--- a/ext/shmop/php_shmop.h
+++ b/ext/shmop/php_shmop.h
@@ -38,7 +38,7 @@ PHP_FUNCTION(shmop_write);
PHP_FUNCTION(shmop_delete);
#ifdef PHP_WIN32
-typedef int key_t;
+# include "win32/ipc.h"
#endif
struct php_shmop
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 9462ba3ea4..5334e26439 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -23,6 +23,7 @@
#include "php_streams.h"
#include "php_main.h"
#include "php_globals.h"
+#include "php_variables.h"
#include "php_ini.h"
#include "php_standard.h"
#include "php_math.h"
@@ -632,7 +633,7 @@ ZEND_BEGIN_ARG_INFO(arginfo_long2ip, 0)
ZEND_ARG_INFO(0, proper_address)
ZEND_END_ARG_INFO()
-ZEND_BEGIN_ARG_INFO(arginfo_getenv, 0)
+ZEND_BEGIN_ARG_INFO_EX(arginfo_getenv, 0, 0, 0)
ZEND_ARG_INFO(0, varname)
ZEND_END_ARG_INFO()
@@ -2598,6 +2599,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_get_headers, 0, 0, 1)
ZEND_ARG_INFO(0, url)
ZEND_ARG_INFO(0, format)
+ ZEND_ARG_INFO(0, context)
ZEND_END_ARG_INFO()
/* }}} */
/* {{{ user_filters.c */
@@ -4008,17 +4010,24 @@ PHP_FUNCTION(long2ip)
* System Functions *
********************/
-/* {{{ proto string getenv(string varname)
- Get the value of an environment variable */
+/* {{{ proto string getenv([string varname])
+ Get the value of an environment variable or every available environment variable
+ if no varname is present */
PHP_FUNCTION(getenv)
{
- char *ptr, *str;
+ char *ptr, *str = NULL;
size_t str_len;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s", &str, &str_len) == FAILURE) {
RETURN_FALSE;
}
+ if (!str) {
+ array_init(return_value);
+ php_import_environment_variables(return_value);
+ return;
+ }
+
/* SAPI method returns an emalloc()'d string */
ptr = sapi_getenv(str, str_len);
if (ptr) {
diff --git a/ext/standard/ftok.c b/ext/standard/ftok.c
index 40e56f1851..334d6d10e1 100644
--- a/ext/standard/ftok.c
+++ b/ext/standard/ftok.c
@@ -26,6 +26,10 @@
#include <sys/ipc.h>
#endif
+#ifdef PHP_WIN32
+#include "win32/ipc.h"
+#endif
+
#if HAVE_FTOK
/* {{{ proto int ftok(string pathname, string proj)
Convert a pathname and a project identifier to a System V IPC key */
diff --git a/ext/standard/random.c b/ext/standard/random.c
index 70568799de..bf3a2bc321 100644
--- a/ext/standard/random.c
+++ b/ext/standard/random.c
@@ -144,8 +144,8 @@ static int php_random_bytes(void *bytes, size_t size)
}
/* Does the file exist and is it a character device? */
if (fstat(fd, &st) != 0 ||
-# ifdef S_IFNAM
- !(S_IFNAM(st.st_mode) || S_ISCHR(st.st_mode))
+# ifdef S_ISNAM
+ !(S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))
# else
!S_ISCHR(st.st_mode)
# endif
diff --git a/ext/standard/string.c b/ext/standard/string.c
index 3d5b76caa2..3922ff497d 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -2426,10 +2426,6 @@ PHP_FUNCTION(substr)
}
}
- if (f > (zend_long)ZSTR_LEN(str)) {
- RETURN_FALSE;
- }
-
if ((f + l) > (zend_long)ZSTR_LEN(str)) {
l = ZSTR_LEN(str) - f;
}
diff --git a/ext/standard/tests/general_functions/getenv.phpt b/ext/standard/tests/general_functions/getenv.phpt
new file mode 100644
index 0000000000..006378a337
--- /dev/null
+++ b/ext/standard/tests/general_functions/getenv.phpt
@@ -0,0 +1,16 @@
+--TEST--
+getenv() basic tests
+--ENV--
+FOO=bar
+--FILE--
+<?php
+
+var_dump(getenv("FOO"));
+var_dump(getenv()["FOO"]);
+
+echo "Done\n";
+?>
+--EXPECTF--
+string(3) "bar"
+string(3) "bar"
+Done
diff --git a/ext/standard/tests/url/get_headers_error_001.phpt b/ext/standard/tests/url/get_headers_error_001.phpt
index 8d5fd11f60..270c8350c0 100644
--- a/ext/standard/tests/url/get_headers_error_001.phpt
+++ b/ext/standard/tests/url/get_headers_error_001.phpt
@@ -5,7 +5,7 @@ June Henriksen <juneih@redpill-linpro.com>
#PHPTestFest2009 Norway 2009-06-09 \o/
--FILE--
<?php
-/* Prototype : proto array get_headers(string url[, int format])
+/* Prototype : proto array get_headers(string url[, int format[, resource $context]])
* Description: Fetches all the headers sent by the server in response to a HTTP request
* Source code: ext/standard/url.c
* Alias to functions:
@@ -21,8 +21,9 @@ var_dump( get_headers() );
echo "\n-- Testing get_headers() function with more than expected no. of arguments --\n";
$url = 'string_val';
$format = 1;
+$context = stream_context_get_default();
$extra_arg = 10;
-var_dump( get_headers($url, $format, $extra_arg) );
+var_dump( get_headers($url, $format, $context, $extra_arg) );
echo "Done";
?>
@@ -36,7 +37,7 @@ NULL
-- Testing get_headers() function with more than expected no. of arguments --
-Warning: get_headers() expects at most 2 parameters, 3 given in %s on line 19
+Warning: get_headers() expects at most 3 parameters, 4 given in %s on line 20
NULL
Done
diff --git a/ext/standard/tests/url/get_headers_error_003.phpt b/ext/standard/tests/url/get_headers_error_003.phpt
new file mode 100644
index 0000000000..6c8878513c
--- /dev/null
+++ b/ext/standard/tests/url/get_headers_error_003.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Test get_headers() function : test with context
+--FILE--
+<?php
+
+include dirname(__FILE__)."/../../../../sapi/cli/tests/php_cli_server.inc";
+php_cli_server_start('header("X-Request-Method: ".$_SERVER["REQUEST_METHOD"]);');
+
+$opts = array(
+ 'http' => array(
+ 'method' => 'HEAD'
+ )
+);
+
+$context = stream_context_create($opts);
+$headers = get_headers("http://".PHP_CLI_SERVER_ADDRESS, 1, $context);
+echo $headers["X-Request-Method"]."\n";
+
+stream_context_set_default($opts);
+$headers = get_headers("http://".PHP_CLI_SERVER_ADDRESS, 1);
+echo $headers["X-Request-Method"]."\n";
+
+echo "Done";
+?>
+--EXPECTF--
+HEAD
+HEAD
+Done
+
+
+
diff --git a/ext/standard/url.c b/ext/standard/url.c
index 8609e11e0e..42020cff51 100644
--- a/ext/standard/url.c
+++ b/ext/standard/url.c
@@ -708,22 +708,24 @@ PHPAPI size_t php_raw_url_decode(char *str, size_t len)
}
/* }}} */
-/* {{{ proto array get_headers(string url[, int format])
+/* {{{ proto array get_headers(string url[, int format[, resource context]])
fetches all the headers sent by the server in response to a HTTP request */
PHP_FUNCTION(get_headers)
{
char *url;
size_t url_len;
- php_stream_context *context;
php_stream *stream;
zval *prev_val, *hdr = NULL, *h;
HashTable *hashT;
zend_long format = 0;
+ zval *zcontext = NULL;
+ php_stream_context *context;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &url, &url_len, &format) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|lr!", &url, &url_len, &format, &zcontext) == FAILURE) {
return;
}
- context = FG(default_context) ? FG(default_context) : (FG(default_context) = php_stream_context_alloc());
+
+ context = php_stream_context_from_zval(zcontext, 0);
if (!(stream = php_stream_open_wrapper_ex(url, "r", REPORT_ERRORS | STREAM_USE_URL | STREAM_ONLY_GET_HEADERS, NULL, context))) {
RETURN_FALSE;
diff --git a/ext/sysvshm/php_sysvshm.h b/ext/sysvshm/php_sysvshm.h
index 36ec0fb650..07acb47fb7 100644
--- a/ext/sysvshm/php_sysvshm.h
+++ b/ext/sysvshm/php_sysvshm.h
@@ -33,7 +33,7 @@ extern zend_module_entry sysvshm_module_entry;
#ifdef PHP_WIN32
# include <TSRM/tsrm_win32.h>
-typedef int key_t;
+# include "win32/ipc.h"
# ifndef THREAD_LS
# define THREAD_LS
# endif
diff --git a/main/php_ini.c b/main/php_ini.c
index 17d4e31aeb..1748199bb5 100644
--- a/main/php_ini.c
+++ b/main/php_ini.c
@@ -638,7 +638,7 @@ int php_init_config(void)
}
if (!debpath[0]) {
/* empty string means default builtin value
- to allow "/foo/phd.d:" or ":/foo/php.d" */
+ to allow "/foo/php.d:" or ":/foo/php.d" */
debpath = PHP_CONFIG_FILE_SCAN_DIR;
}
lenpath = (int)strlen(debpath);
diff --git a/main/php_streams.h b/main/php_streams.h
index 255b065bd4..c37d104cc8 100644
--- a/main/php_streams.h
+++ b/main/php_streams.h
@@ -573,10 +573,10 @@ PHPAPI const char *php_stream_locate_eol(php_stream *stream, zend_string *buf);
#define php_stream_open_wrapper_ex(path, mode, options, opened, context) _php_stream_open_wrapper_ex((path), (mode), (options), (opened), (context) STREAMS_CC)
#define php_stream_get_from_zval(stream, zstream, mode, options, opened, context) \
- if (Z_TYPE_PP((zstream)) == IS_RESOURCE) { \
+ if (Z_TYPE_P((zstream)) == IS_RESOURCE) { \
php_stream_from_zval((stream), (zstream)); \
- } else (stream) = Z_TYPE_PP((zstream)) == IS_STRING ? \
- php_stream_open_wrapper_ex(Z_STRVAL_PP((zstream)), (mode), (options), (opened), (context)) : NULL
+ } else (stream) = Z_TYPE_P((zstream)) == IS_STRING ? \
+ 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
diff --git a/main/php_version.h b/main/php_version.h
index 3c21a7f665..4714e5dc4b 100644
--- a/main/php_version.h
+++ b/main/php_version.h
@@ -1,8 +1,8 @@
/* automatically generated by configure */
/* edit configure.in to change version number */
#define PHP_MAJOR_VERSION 7
-#define PHP_MINOR_VERSION 0
-#define PHP_RELEASE_VERSION 1
+#define PHP_MINOR_VERSION 1
+#define PHP_RELEASE_VERSION 0
#define PHP_EXTRA_VERSION "-dev"
-#define PHP_VERSION "7.0.1-dev"
-#define PHP_VERSION_ID 70001
+#define PHP_VERSION "7.1.0-dev"
+#define PHP_VERSION_ID 70100
diff --git a/run-tests.php b/run-tests.php
index a607f1cda2..be3d3d46f3 100755
--- a/run-tests.php
+++ b/run-tests.php
@@ -4,7 +4,7 @@
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2010 The PHP Group |
+ | Copyright (c) 1997-2015 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -59,27 +59,6 @@ NO_PROC_OPEN_ERROR;
exit;
}
-// Version constants only available as of 5.2.8
-if (!defined("PHP_VERSION_ID")) {
- list($major, $minor, $bug) = explode(".", phpversion(), 3);
- $bug = (int)$bug; // Many distros make up their own versions
- if ($bug < 10) {
- $bug = "0$bug";
- }
-
- define("PHP_VERSION_ID", "{$major}0{$minor}$bug");
- define("PHP_MAJOR_VERSION", $major);
-}
-
-// __DIR__ is available from 5.3.0
-if (PHP_VERSION_ID < 50300) {
- define('__DIR__', realpath(dirname(__FILE__)));
- // FILE_BINARY is available from 5.2.7
- if (PHP_VERSION_ID < 50207) {
- define('FILE_BINARY', 0);
- }
-}
-
// If timezone is not set, use UTC.
if (ini_get('date.timezone') == '') {
date_default_timezone_set('UTC');
@@ -113,22 +92,6 @@ while(@ob_end_clean());
if (ob_get_level()) echo "Not all buffers were deleted.\n";
error_reporting(E_ALL);
-if (PHP_MAJOR_VERSION < 6) {
- if (ini_get('safe_mode')) {
- echo <<< SAFE_MODE_WARNING
-
-+-----------------------------------------------------------+
-| ! WARNING ! |
-| You are running the test-suite with "safe_mode" ENABLED ! |
-| |
-| Chances are high that no test will work at all, |
-| depending on how you configured "safe_mode" ! |
-+-----------------------------------------------------------+
-
-
-SAFE_MODE_WARNING;
- }
-}
$environment = isset($_ENV) ? $_ENV : array();
if ((substr(PHP_OS, 0, 3) == "WIN") && empty($environment["SystemRoot"])) {
@@ -240,7 +203,6 @@ $exts_to_test = array();
$ini_overwrites = array(
'output_handler=',
'open_basedir=',
- 'safe_mode=0',
'disable_functions=',
'output_buffering=Off',
'error_reporting=' . (E_ALL | E_STRICT),
diff --git a/sapi/fpm/fpm/fpm_events.c b/sapi/fpm/fpm/fpm_events.c
index ca45cb1665..2b8e8cf13a 100644
--- a/sapi/fpm/fpm/fpm_events.c
+++ b/sapi/fpm/fpm/fpm_events.c
@@ -291,7 +291,7 @@ int fpm_event_pre_init(char *machanism) /* {{{ */
}
return -1;
}
-/* }} */
+/* }}} */
const char *fpm_event_machanism_name() /* {{{ */
{
@@ -538,4 +538,3 @@ int fpm_event_del(struct fpm_event_s *ev) /* {{{ */
}
/* }}} */
-/* }}} */
diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c
index 13bca0cab3..a296261e1a 100644
--- a/sapi/litespeed/lsapi_main.c
+++ b/sapi/litespeed/lsapi_main.c
@@ -602,11 +602,12 @@ static int alter_ini( const char * pKey, int keyLen, const char * pValue, int va
else
{
#if PHP_MAJOR_VERSION >= 7
- psKey = zend_string_init(pKey, keyLen, 1);
+ --keyLen;
+ psKey = zend_string_init(pKey, keyLen, 1);
zend_alter_ini_entry_chars(psKey,
(char *)pValue, valLen,
type, PHP_INI_STAGE_ACTIVATE);
- zend_string_release(psKey);
+ zend_string_release(psKey);
#else
zend_alter_ini_entry((char *)pKey, keyLen,
(char *)pValue, valLen,
diff --git a/sapi/phpdbg/phpdbg_help.c b/sapi/phpdbg/phpdbg_help.c
index a99191d510..a0dd457324 100644
--- a/sapi/phpdbg/phpdbg_help.c
+++ b/sapi/phpdbg/phpdbg_help.c
@@ -810,7 +810,7 @@ phpdbg_help_text_t phpdbg_help_text[] = {
{"run",
"Enter the vm, startinging execution. Execution will then continue until the next breakpoint "
-"or completion of the script. Add parameters you want to use as $argv"
+"or completion of the script. Add parameters you want to use as $argv" CR CR
"**Examples**" CR CR
" $P run" CR
" $P r" CR
diff --git a/sapi/phpdbg/phpdbg_opcode.c b/sapi/phpdbg/phpdbg_opcode.c
index 44170c8c9e..a792090275 100644
--- a/sapi/phpdbg/phpdbg_opcode.c
+++ b/sapi/phpdbg/phpdbg_opcode.c
@@ -121,7 +121,7 @@ char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op) /*{{{ */
case ZEND_FAST_CALL:
case ZEND_FAST_RET:
if (op->extended_value != 0) {
- spprintf(&decode[2], 0, "J%" PRIu32, op->op2.opline_num);
+ spprintf(&decode[2], 0, "%" PRIu32, op->op2.num);
}
break;
diff --git a/sapi/phpdbg/tests/breakpoints_001.phpt b/sapi/phpdbg/tests/breakpoints_001.phpt
index 934f0d3554..17e7c65cbf 100644
--- a/sapi/phpdbg/tests/breakpoints_001.phpt
+++ b/sapi/phpdbg/tests/breakpoints_001.phpt
@@ -11,23 +11,23 @@ q
[Successful compilation of %s]
prompt> [Breakpoint #0 added at %s:3]
prompt> [Breakpoint #0 at %s:3, hits: 1]
->00003: echo 1;
- 00004: echo 2;
- 00005: echo 3;
+>00003: echo $i++;
+ 00004: echo $i++;
+ 00005: echo $i++;
prompt> [Breakpoint #1 added at %s:4]
prompt> 1
[Breakpoint #1 at %s:4, hits: 1]
->00004: echo 2;
- 00005: echo 3;
- 00006: echo 4;
+>00004: echo $i++;
+ 00005: echo $i++;
+ 00006: echo $i++;
prompt> 234
[Script ended normally]
prompt>
--FILE--
<?php
-
-echo 1;
-echo 2;
-echo 3;
-echo 4;
+$i = 1;
+echo $i++;
+echo $i++;
+echo $i++;
+echo $i++;
diff --git a/sapi/phpdbg/tests/breakpoints_002.phpt b/sapi/phpdbg/tests/breakpoints_002.phpt
index 18aaef1f36..96c98194b1 100644
--- a/sapi/phpdbg/tests/breakpoints_002.phpt
+++ b/sapi/phpdbg/tests/breakpoints_002.phpt
@@ -14,27 +14,27 @@ q
prompt> [Breakpoint #0 added at %s:4]
prompt> 1
[Breakpoint #0 at %s:4, hits: 1]
->00004: echo 2;
- 00005: echo 3;
- 00006: echo 4;
+>00004: echo $i++;
+ 00005: echo $i++;
+ 00006: echo $i++;
prompt> [Breakpoint #1 added at %s:3]
prompt> Do you really want to restart execution? (type y or n): [Breakpoint #1 at %s:3, hits: 1]
->00003: echo 1;
- 00004: echo 2;
- 00005: echo 3;
+>00003: echo $i++;
+ 00004: echo $i++;
+ 00005: echo $i++;
prompt> 1
[Breakpoint #0 at %s:4, hits: 1]
->00004: echo 2;
- 00005: echo 3;
- 00006: echo 4;
+>00004: echo $i++;
+ 00005: echo $i++;
+ 00006: echo $i++;
prompt> 234
[Script ended normally]
prompt>
--FILE--
<?php
-
-echo 1;
-echo 2;
-echo 3;
-echo 4;
+$i = 1;
+echo $i++;
+echo $i++;
+echo $i++;
+echo $i++;
diff --git a/sapi/phpdbg/tests/breakpoints_003.phpt b/sapi/phpdbg/tests/breakpoints_003.phpt
index 8caa64632b..12b2504487 100644
--- a/sapi/phpdbg/tests/breakpoints_003.phpt
+++ b/sapi/phpdbg/tests/breakpoints_003.phpt
@@ -16,8 +16,8 @@ prompt> [Deleted breakpoint #0]
prompt> [Breakpoint #1 added at %s:5]
prompt> 12
[Breakpoint #1 at %s:5, hits: 1]
->00005: echo 3;
- 00006: echo 4;
+>00005: echo $i++;
+ 00006: echo $i++;
00007:
prompt> [Deleted breakpoint #1]
prompt> Do you really want to restart execution? (type y or n): 1234
@@ -25,9 +25,9 @@ prompt> Do you really want to restart execution? (type y or n): 1234
prompt>
--FILE--
<?php
-
-echo 1;
-echo 2;
-echo 3;
-echo 4;
+$i = 1;
+echo $i++;
+echo $i++;
+echo $i++;
+echo $i++;
diff --git a/sapi/phpdbg/tests/breakpoints_004.phpt b/sapi/phpdbg/tests/breakpoints_004.phpt
index 27ebd0bea2..917e908efb 100644
--- a/sapi/phpdbg/tests/breakpoints_004.phpt
+++ b/sapi/phpdbg/tests/breakpoints_004.phpt
@@ -12,30 +12,30 @@ q
[Successful compilation of %s]
prompt> [Breakpoint #0 added at ZEND_ECHO]
prompt> [Breakpoint #0 in ZEND_ECHO at %s:3, hits: 1]
->00003: echo 1;
- 00004: echo 2;
- 00005: echo 3;
+>00003: echo $i++;
+ 00004: echo $i++;
+ 00005: echo $i++;
prompt> 1
[Breakpoint #0 in ZEND_ECHO at %s:4, hits: 2]
->00004: echo 2;
- 00005: echo 3;
- 00006: echo 4;
+>00004: echo $i++;
+ 00005: echo $i++;
+ 00006: echo $i++;
prompt> 2
[Breakpoint #0 in ZEND_ECHO at %s:5, hits: 3]
->00005: echo 3;
- 00006: echo 4;
+>00005: echo $i++;
+ 00006: echo $i++;
00007:
prompt> 3
[Breakpoint #0 in ZEND_ECHO at %s:6, hits: 4]
->00006: echo 4;
+>00006: echo $i++;
00007:
prompt> 4
[Script ended normally]
prompt>
--FILE--
<?php
-
-echo 1;
-echo 2;
-echo 3;
-echo 4;
+$i = 1;
+echo $i++;
+echo $i++;
+echo $i++;
+echo $i++;
diff --git a/sapi/phpdbg/tests/exceptions_003.phpt b/sapi/phpdbg/tests/exceptions_003.phpt
index fffe7a9296..c83eb7517a 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 J7 %s]
+[L7 %s FAST_RET<TO_CATCH> ~%d 0 %s]
[L9 %s CATCH "Error" $e 1 %s]
>00005: x();
00006: } finally {
diff --git a/server-tests.php b/server-tests.php
index 8c2ae8607b..110147c21e 100755
--- a/server-tests.php
+++ b/server-tests.php
@@ -3,7 +3,7 @@
+----------------------------------------------------------------------+
| PHP Version 7 |
+----------------------------------------------------------------------+
- | Copyright (c) 1997-2010 The PHP Group |
+ | Copyright (c) 1997-2015 The PHP Group |
+----------------------------------------------------------------------+
| This source file is subject to version 3.01 of the PHP license, |
| that is bundled with this package in the file LICENSE, and is |
@@ -48,14 +48,6 @@ define('PCRE_MISSING_ERROR',
| with --with-pcre-regex or if you have compiled pcre as a |
| shared module load it via php.ini. |
+-----------------------------------------------------------+');
-define('SAFE_MODE_WARNING',
-'+-----------------------------------------------------------+
-| ! WARNING ! |
-| You are running the test-suite with "safe_mode" ENABLED ! |
-| |
-| Chances are high that no test will work at all, |
-| depending on how you configured "safe_mode" ! |
-+-----------------------------------------------------------+');
define('TMP_MISSING',
'+-----------------------------------------------------------+
| ! ERROR ! |
@@ -456,7 +448,6 @@ class testHarness {
'output_handler'=>'',
'zlib.output_compression'=>'Off',
'open_basedir'=>'',
- 'safe_mode'=>'0',
'disable_functions'=>'',
'output_buffering'=>'Off',
'error_reporting'=>'4095',
@@ -736,7 +727,7 @@ class testHarness {
}
function checkRequirements() {
- if (version_compare(phpversion(), "5.0") < 0) {
+ if (version_compare(phpversion(), "5.4") < 0) {
$this->writemsg(REQ_PHP_VERSION);
exit;
}
@@ -753,9 +744,6 @@ class testHarness {
$this->writemsg(PCRE_MISSING_ERROR);
exit;
}
- if (ini_get('safe_mode')) {
- $this->writemsg(SAFE_MODE_WARNING);
- }
}
//
diff --git a/win32/build/buildconf.js b/win32/build/buildconf.js
index a3a4f1e9aa..d7975d0139 100644
--- a/win32/build/buildconf.js
+++ b/win32/build/buildconf.js
@@ -244,6 +244,8 @@ for (i = 0; i < calls.length; i++) {
}
C.WriteBlankLines(1);
+C.WriteLine("STDOUT.WriteLine(\"PHP Version: \" + PHP_VERSION_STRING);");
+C.WriteLine("STDOUT.WriteBlankLines(1);");
C.WriteLine("conf_process_args();");
C.WriteBlankLines(1);
diff --git a/win32/build/config.w32 b/win32/build/config.w32
index b7e5e49220..609f5c5d46 100644
--- a/win32/build/config.w32
+++ b/win32/build/config.w32
@@ -160,7 +160,8 @@ ADD_SOURCES("main/streams", "streams.c cast.c memory.c filter.c plain_wrapper.c
ADD_FLAG("CFLAGS_BD_MAIN_STREAMS", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
ADD_SOURCES("win32", "dllmain.c glob.c readdir.c \
- registry.c select.c sendmail.c time.c winutil.c wsyslog.c globals.c getrusage.c");
+ registry.c select.c sendmail.c time.c winutil.c wsyslog.c globals.c \
+ getrusage.c ftok.c");
ADD_FLAG("CFLAGS_BD_WIN32", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
diff --git a/win32/build/config.w32.h.in b/win32/build/config.w32.h.in
index b2ee6f1958..d73678b1ec 100644
--- a/win32/build/config.w32.h.in
+++ b/win32/build/config.w32.h.in
@@ -183,3 +183,4 @@
#define HAVE_GETRUSAGE
+#define HAVE_FTOK 1
diff --git a/win32/build/confutils.js b/win32/build/confutils.js
index 355327156d..c2852cfd43 100644
--- a/win32/build/confutils.js
+++ b/win32/build/confutils.js
@@ -100,10 +100,10 @@ if (typeof(CWD) == "undefined") {
/* defaults; we pick up the precise versions from configure.in */
var PHP_VERSION = 7;
-var PHP_MINOR_VERSION = 0;
+var PHP_MINOR_VERSION = 1;
var PHP_RELEASE_VERSION = 0;
var PHP_EXTRA_VERSION = "";
-var PHP_VERSION_STRING = "7.0.0";
+var PHP_VERSION_STRING = "7.1.0";
/* Get version numbers and DEFINE as a string */
function get_version_numbers()
diff --git a/win32/ftok.c b/win32/ftok.c
new file mode 100644
index 0000000000..1ae8fda179
--- /dev/null
+++ b/win32/ftok.c
@@ -0,0 +1,52 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Anatol Belski <ab@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include "ipc.h"
+
+#include <windows.h>
+#include <sys/stat.h>
+
+
+PHPAPI key_t
+ftok(const char *pathname, int proj_id)
+{
+ HANDLE fh;
+ struct stat st;
+ BY_HANDLE_FILE_INFORMATION bhfi;
+ key_t ret;
+
+ if (stat(pathname, &st) < 0) {
+ return (key_t)-1;
+ }
+
+ if ((fh = CreateFile(pathname, GENERIC_READ, 0, 0, OPEN_EXISTING, 0, 0)) == INVALID_HANDLE_VALUE) {
+ return (key_t)-1;
+ }
+
+ if (!GetFileInformationByHandle(fh, &bhfi)) {
+ CloseHandle(fh);
+ return (key_t)-1;
+ }
+
+ ret = (key_t) ((proj_id & 0xff) << 24 | (st.st_dev & 0xff) << 16 | ((bhfi.nFileIndexLow | (__int64)bhfi.nFileIndexHigh << 32) & 0xffff));
+
+ CloseHandle(fh);
+
+ return ret;
+}
+
diff --git a/win32/ipc.h b/win32/ipc.h
new file mode 100644
index 0000000000..1d4acfae28
--- /dev/null
+++ b/win32/ipc.h
@@ -0,0 +1,29 @@
+/*
+ +----------------------------------------------------------------------+
+ | PHP Version 7 |
+ +----------------------------------------------------------------------+
+ | Copyright (c) 1997-2015 The PHP Group |
+ +----------------------------------------------------------------------+
+ | This source file is subject to version 3.01 of the PHP license, |
+ | that is bundled with this package in the file LICENSE, and is |
+ | available through the world-wide-web at the following url: |
+ | http://www.php.net/license/3_01.txt |
+ | If you did not receive a copy of the PHP license and are unable to |
+ | obtain it through the world-wide-web, please send a note to |
+ | license@php.net so we can mail you a copy immediately. |
+ +----------------------------------------------------------------------+
+ | Author: Anatol Belski <ab@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef PHP_WIN32_IPC_H
+#define PHP_WIN32_IPC_H 1
+
+#include "php.h"
+
+typedef int key_t;
+
+PHPAPI key_t ftok(const char *path, int id);
+
+
+#endif /* PHP_WIN32_IPC_H */