summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAaron Piotrowski <aaron@trowski.com>2015-06-14 18:53:11 -0500
committerAaron Piotrowski <aaron@trowski.com>2015-06-14 18:53:11 -0500
commit110e0a5a2cda3bfa7778bb871502ff2b50e59f76 (patch)
treefa736924b4befce442cc72429b4e07812856c541
parent5c54bf015dc4fd930394709d80665d9a731f6f99 (diff)
parent6cb7b48846d129f088b50c4a8c4b00b7dc886f5c (diff)
downloadphp-git-110e0a5a2cda3bfa7778bb871502ff2b50e59f76.tar.gz
Merge branch 'master' into throwable-interface
# Conflicts: # Zend/zend_language_scanner.c # Zend/zend_language_scanner.l # ext/simplexml/tests/SimpleXMLElement_xpath.phpt
-rw-r--r--CONTRIBUTING.md73
-rw-r--r--Makefile.global15
-rw-r--r--NEWS71
-rw-r--r--UPGRADING53
-rw-r--r--UPGRADING.INTERNALS20
-rw-r--r--Zend/Zend.m42
-rw-r--r--Zend/bug69756.phpt12
-rw-r--r--Zend/tests/anon/006.phpt2
-rw-r--r--Zend/tests/anon/007.phpt2
-rw-r--r--Zend/tests/array_offset.phpt21
-rw-r--r--Zend/tests/array_type_hint_001.phpt2
-rw-r--r--Zend/tests/assert/expect_015.phpt6
-rw-r--r--Zend/tests/bug39003.phpt2
-rw-r--r--Zend/tests/bug42802.phpt2
-rw-r--r--Zend/tests/bug43332_1.phpt2
-rw-r--r--Zend/tests/bug68446.phpt2
-rw-r--r--Zend/tests/bug69551.phpt16
-rw-r--r--Zend/tests/bug69676.phpt19
-rw-r--r--Zend/tests/bug69732.phpt30
-rw-r--r--Zend/tests/bug69740.phpt28
-rw-r--r--Zend/tests/bug69754.phpt25
-rw-r--r--Zend/tests/bug69755.phpt8
-rw-r--r--Zend/tests/bug69758.phpt27
-rw-r--r--Zend/tests/bug69761.phpt15
-rw-r--r--Zend/tests/bug69767.phpt8
-rw-r--r--Zend/tests/bug69788.phpt8
-rw-r--r--Zend/tests/bug69805.phpt8
-rw-r--r--Zend/tests/bug69825.phpt30
-rw-r--r--Zend/tests/closure_027.phpt2
-rw-r--r--Zend/tests/gc_024.phpt2
-rw-r--r--Zend/tests/grammar/regression_001.phpt33
-rw-r--r--Zend/tests/grammar/regression_002.phpt22
-rw-r--r--Zend/tests/grammar/regression_003.phpt13
-rw-r--r--Zend/tests/grammar/regression_004.phpt15
-rw-r--r--Zend/tests/grammar/regression_005.phpt14
-rw-r--r--Zend/tests/grammar/regression_006.phpt30
-rw-r--r--Zend/tests/grammar/regression_007.phpt44
-rw-r--r--Zend/tests/grammar/regression_008.phpt21
-rw-r--r--Zend/tests/grammar/regression_009.phpt18
-rw-r--r--Zend/tests/grammar/regression_010.phpt14
-rw-r--r--Zend/tests/grammar/regression_011.phpt18
-rw-r--r--Zend/tests/grammar/regression_012.phpt13
-rw-r--r--Zend/tests/grammar/regression_013.phpt13
-rw-r--r--Zend/tests/grammar/semi_reserved_001.phpt209
-rw-r--r--Zend/tests/grammar/semi_reserved_002.phpt207
-rw-r--r--Zend/tests/grammar/semi_reserved_003.phpt210
-rw-r--r--Zend/tests/grammar/semi_reserved_004.phpt210
-rw-r--r--Zend/tests/grammar/semi_reserved_005.phpt207
-rw-r--r--Zend/tests/grammar/semi_reserved_006.phpt80
-rw-r--r--Zend/tests/grammar/semi_reserved_007.phpt37
-rw-r--r--Zend/tests/grammar/semi_reserved_008.phpt68
-rw-r--r--Zend/tests/grammar/semi_reserved_009.phpt25
-rw-r--r--Zend/tests/grammar/semi_reserved_010.phpt31
-rw-r--r--Zend/tests/loop_free_on_return.phpt16
-rw-r--r--Zend/tests/ns_071.phpt2
-rw-r--r--Zend/tests/ns_072.phpt2
-rw-r--r--Zend/tests/objects_022.phpt2
-rw-r--r--Zend/tests/return_types/028.phpt20
-rw-r--r--Zend/tests/typehints/explicit_weak_include_strict.phpt2
-rw-r--r--Zend/tests/typehints/strict_call_weak.phpt2
-rw-r--r--Zend/tests/typehints/strict_call_weak_explicit.phpt2
-rw-r--r--Zend/tests/typehints/weak_include_strict.phpt2
-rw-r--r--Zend/tests/variadic/closure_invoke.phpt17
-rw-r--r--Zend/tests/variadic/typehint_error.phpt2
-rw-r--r--Zend/zend.c6
-rw-r--r--Zend/zend_API.c182
-rw-r--r--Zend/zend_API.h46
-rw-r--r--Zend/zend_alloc.c1
-rw-r--r--Zend/zend_ast.c10
-rw-r--r--Zend/zend_ast.h1
-rw-r--r--Zend/zend_builtin_functions.c17
-rw-r--r--Zend/zend_closures.c5
-rw-r--r--Zend/zend_compile.c629
-rw-r--r--Zend/zend_compile.h23
-rw-r--r--Zend/zend_exceptions.c6
-rw-r--r--Zend/zend_execute.c202
-rw-r--r--Zend/zend_generators.c29
-rw-r--r--Zend/zend_globals.h9
-rw-r--r--Zend/zend_hash.c27
-rw-r--r--Zend/zend_hash.h20
-rw-r--r--Zend/zend_inheritance.c2
-rw-r--r--Zend/zend_ini_scanner.c2
-rw-r--r--Zend/zend_ini_scanner.l2
-rw-r--r--Zend/zend_language_parser.y97
-rw-r--r--Zend/zend_language_scanner.c1097
-rw-r--r--Zend/zend_language_scanner.h4
-rw-r--r--Zend/zend_language_scanner.l371
-rw-r--r--Zend/zend_long.h2
-rw-r--r--Zend/zend_object_handlers.c23
-rw-r--r--Zend/zend_objects.c10
-rw-r--r--Zend/zend_opcode.c47
-rw-r--r--Zend/zend_operators.c80
-rw-r--r--Zend/zend_operators.h3
-rw-r--r--Zend/zend_portability.h1
-rw-r--r--Zend/zend_types.h19
-rw-r--r--Zend/zend_virtual_cwd.c34
-rw-r--r--Zend/zend_virtual_cwd.h29
-rw-r--r--Zend/zend_vm_def.h1287
-rw-r--r--Zend/zend_vm_execute.h10172
-rw-r--r--Zend/zend_vm_gen.php25
-rw-r--r--Zend/zend_vm_opcodes.c4
-rw-r--r--Zend/zend_vm_opcodes.h2
-rw-r--r--configure.in7
-rw-r--r--ext/curl/interface.c6
-rw-r--r--ext/date/lib/timelib_structs.h2
-rw-r--r--ext/date/php_date.c86
-rw-r--r--ext/date/tests/009_win32.phpt10
-rw-r--r--ext/date/tests/bug55407.phpt2
-rw-r--r--ext/date/tests/gmstrftime_variation11.phpt6
-rw-r--r--ext/date/tests/gmstrftime_variation13.phpt20
-rw-r--r--ext/date/tests/gmstrftime_variation15.phpt16
-rw-r--r--ext/date/tests/gmstrftime_variation17.phpt8
-rw-r--r--ext/date/tests/gmstrftime_variation19.phpt14
-rw-r--r--ext/date/tests/gmstrftime_variation21.phpt6
-rw-r--r--ext/date/tests/gmstrftime_variation9.phpt12
-rw-r--r--ext/date/tests/strftime_variation11.phpt8
-rw-r--r--ext/date/tests/strftime_variation13.phpt20
-rw-r--r--ext/date/tests/strftime_variation15.phpt16
-rw-r--r--ext/date/tests/strftime_variation17.phpt8
-rw-r--r--ext/date/tests/strftime_variation19.phpt12
-rw-r--r--ext/date/tests/strftime_variation21.phpt6
-rw-r--r--ext/date/tests/strftime_variation9.phpt12
-rw-r--r--ext/dba/config.w322
-rw-r--r--ext/dba/dba_db3.c13
-rw-r--r--ext/dom/document.c26
-rw-r--r--ext/dom/tests/DOMDocument_loadHTMLfile_error2.phpt4
-rw-r--r--ext/fileinfo/fileinfo.c4
-rw-r--r--ext/ftp/ftp.c2
-rw-r--r--ext/gd/config.m429
-rw-r--r--ext/gd/config.w3210
-rw-r--r--ext/gd/gd.c579
-rw-r--r--ext/gd/libgd/webpimg.c14
-rw-r--r--ext/gd/php_gd.h3
-rw-r--r--ext/gd/tests/gd_info_variation1.phpt4
-rw-r--r--ext/gmp/gmp.c26
-rw-r--r--ext/gmp/tests/bug69803.phpt22
-rw-r--r--ext/gmp/tests/gmp_random_range.phpt4
-rw-r--r--ext/hash/hash.c15
-rw-r--r--ext/hash/tests/skip_mhash.inc2
-rw-r--r--ext/iconv/config.m44
-rw-r--r--ext/iconv/iconv.c14
-rw-r--r--ext/intl/breakiterator/breakiterator_iterators.cpp3
-rw-r--r--ext/intl/common/common_enum.cpp3
-rw-r--r--ext/intl/tests/collator_get_sort_key_variant4.phpt3
-rw-r--r--ext/intl/tests/collator_get_sort_key_variant5.phpt98
-rw-r--r--ext/intl/tests/dateformat_calendars_variant3.phpt7
-rw-r--r--ext/intl/tests/dateformat_formatObject_calendar_variant4.phpt1
-rw-r--r--ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt40
-rw-r--r--ext/intl/tests/dateformat_formatObject_datetime_variant4.phpt1
-rw-r--r--ext/intl/tests/dateformat_formatObject_datetime_variant5.phpt33
-rw-r--r--ext/intl/tests/dateformat_get_set_timezone_variant4.phpt1
-rw-r--r--ext/intl/tests/dateformat_get_set_timezone_variant5.phpt62
-rw-r--r--ext/intl/tests/spoofchecker_004.phpt1
-rw-r--r--ext/intl/tests/spoofchecker_005.phpt29
-rw-r--r--ext/intl/tests/timezone_getDisplayName_variant3-49+.phpt8
-rw-r--r--ext/intl/timezone/timezone_methods.cpp2
-rw-r--r--ext/json/json_parser.tab.c88
-rw-r--r--ext/json/json_parser.y97
-rw-r--r--ext/libxml/libxml.c5
-rw-r--r--ext/libxml/tests/bug54138.phpt23
-rw-r--r--ext/libxml/tests/bug54138_1.phpt24
-rw-r--r--ext/libxml/tests/bug54138_2.phpt25
-rw-r--r--ext/libxml/tests/bug69753.phpt19
-rw-r--r--ext/libxml/tests/bug69753.xml4
-rw-r--r--ext/mysqli/mysqli.c4
-rw-r--r--ext/mysqlnd/mysqlnd_ps.c2
-rw-r--r--ext/opcache/Optimizer/block_pass.c7
-rw-r--r--ext/opcache/Optimizer/compact_literals.c14
-rw-r--r--ext/opcache/Optimizer/pass1_5.c2
-rw-r--r--ext/opcache/Optimizer/pass2.c53
-rw-r--r--ext/opcache/Optimizer/pass3.c4
-rw-r--r--ext/opcache/ZendAccelerator.c4
-rw-r--r--ext/opcache/tests/bug69688.phpt18
-rw-r--r--ext/opcache/tests/optimize_func_calls.phpt6
-rw-r--r--ext/opcache/zend_accelerator_module.c4
-rw-r--r--ext/opcache/zend_accelerator_util_funcs.c317
-rw-r--r--ext/opcache/zend_file_cache.c22
-rw-r--r--ext/opcache/zend_persist.c4
-rw-r--r--ext/opcache/zend_persist_calc.c3
-rw-r--r--ext/opcache/zend_shared_alloc.c2
-rw-r--r--ext/openssl/openssl.c4
-rw-r--r--ext/pcre/pcrelib/config.h6
-rw-r--r--ext/pdo/pdo_dbh.c9
-rw-r--r--ext/pdo_pgsql/pgsql_driver.c59
-rw-r--r--ext/pdo_pgsql/pgsql_statement.c12
-rw-r--r--ext/pdo_pgsql/tests/bug69344.phpt44
-rw-r--r--ext/pdo_pgsql/tests/bug69362.phpt63
-rw-r--r--ext/pdo_pgsql/tests/bug69752.phpt55
-rw-r--r--ext/pgsql/pgsql.c13
-rw-r--r--ext/pgsql/tests/pg_insert_002.phpt27
-rw-r--r--ext/phar/Makefile.frag2
-rw-r--r--ext/phar/func_interceptors.c12
-rw-r--r--ext/phar/phar_object.c18
-rw-r--r--ext/phar/tar.c4
-rw-r--r--ext/phar/tests/bug69441.phpt2
-rw-r--r--ext/phar/tests/bug69453.phpt6
-rw-r--r--ext/reflection/php_reflection.c210
-rw-r--r--ext/reflection/php_reflection.h1
-rw-r--r--ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt19
-rw-r--r--ext/reflection/tests/ReflectionType_001.phpt185
-rw-r--r--ext/reflection/tests/ReflectionType_002.phpt17
-rw-r--r--ext/session/session.c3
-rw-r--r--ext/simplexml/simplexml.c20
-rw-r--r--ext/simplexml/sxe.c11
-rw-r--r--ext/simplexml/tests/SimpleXMLElement_xpath.phpt22
-rw-r--r--ext/simplexml/tests/SimpleXMLElement_xpath_3.phpt21
-rw-r--r--ext/simplexml/tests/SimpleXMLElement_xpath_4.phpt22
-rw-r--r--ext/simplexml/tests/bug61335.phpt19
-rw-r--r--ext/simplexml/tests/bug62639.phpt63
-rw-r--r--ext/simplexml/tests/bug67116.phpt93
-rw-r--r--ext/simplexml/tests/bug67572.phpt33
-rw-r--r--ext/simplexml/tests/bug69169.phpt70
-rw-r--r--ext/simplexml/tests/bug69491.phpt20
-rw-r--r--ext/soap/php_encoding.c19
-rw-r--r--ext/sockets/tests/socket_import_stream-4-win.phpt4
-rw-r--r--ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp-win32.phpt2
-rw-r--r--ext/spl/spl_array.c10
-rw-r--r--ext/spl/spl_directory.c14
-rw-r--r--ext/spl/spl_heap.c3
-rw-r--r--ext/spl/spl_iterators.c23
-rw-r--r--ext/spl/spl_observer.c6
-rw-r--r--ext/spl/tests/bug67805.phpt15
-rw-r--r--ext/spl/tests/bug69737.phpt21
-rw-r--r--ext/spl/tests/fileobject_setmaxlinelen_basic.phpt2
-rw-r--r--ext/sqlite3/libsqlite/sqlite3.c6325
-rw-r--r--ext/sqlite3/libsqlite/sqlite3.h700
-rw-r--r--ext/standard/array.c39
-rw-r--r--ext/standard/assert.c2
-rw-r--r--ext/standard/basic_functions.c2
-rw-r--r--ext/standard/credits.c4
-rw-r--r--ext/standard/credits_sapi.h1
-rw-r--r--ext/standard/crypt.c15
-rw-r--r--ext/standard/exec.c8
-rw-r--r--ext/standard/file.c5
-rw-r--r--ext/standard/filestat.c12
-rw-r--r--ext/standard/http.c12
-rw-r--r--ext/standard/info.c42
-rw-r--r--ext/standard/mail.c44
-rw-r--r--ext/standard/math.c14
-rw-r--r--ext/standard/microtime.c9
-rw-r--r--ext/standard/password.c23
-rw-r--r--ext/standard/php_crypt.h2
-rw-r--r--ext/standard/php_string.h3
-rw-r--r--ext/standard/proc_open.c17
-rw-r--r--ext/standard/proc_open.h4
-rw-r--r--ext/standard/streamsfuncs.c8
-rw-r--r--ext/standard/string.c112
-rw-r--r--ext/standard/tests/array/bug69723.phpt40
-rw-r--r--ext/standard/tests/file/bug69628.phpt49
-rw-r--r--ext/standard/tests/file/glob_variation.phpt3
-rw-r--r--ext/standard/tests/file/tempnam_variation3-win32.phpt5
-rw-r--r--ext/standard/tests/general_functions/bug69646.phpt47
-rw-r--r--ext/standard/tests/general_functions/getrusage_basic.phpt5
-rw-r--r--ext/standard/tests/general_functions/getrusage_error.phpt5
-rw-r--r--ext/standard/tests/general_functions/getrusage_variation1.phpt3
-rw-r--r--ext/standard/tests/general_functions/proc_open_pipes.inc22
-rw-r--r--ext/standard/tests/general_functions/proc_open_pipes1.phpt86
-rw-r--r--ext/standard/tests/general_functions/proc_open_pipes2.phpt28
-rw-r--r--ext/standard/tests/general_functions/proc_open_pipes3.phpt64
-rw-r--r--ext/standard/tests/mail/mail_basic6.phpt329
-rw-r--r--ext/standard/tests/password/password_verify.phpt10
-rw-r--r--ext/standard/tests/php_version_win_const.phpt18
-rw-r--r--ext/standard/tests/strings/004.phpt96
-rw-r--r--ext/standard/type.c6
-rw-r--r--ext/sysvmsg/sysvmsg.c2
-rw-r--r--ext/tokenizer/tests/bug67395.phpt2
-rw-r--r--ext/tokenizer/tests/token_get_all_TOKEN_PARSE_000.phpt19
-rw-r--r--ext/tokenizer/tests/token_get_all_TOKEN_PARSE_001.phpt81
-rw-r--r--ext/tokenizer/tests/token_get_all_TOKEN_PARSE_002.phpt68
-rw-r--r--ext/tokenizer/tests/token_get_all_error.phpt8
-rw-r--r--ext/tokenizer/tokenizer.c143
-rw-r--r--ext/zip/php_zip.c6
-rw-r--r--ext/zlib/tests/dictionary_usage.phpt5
-rw-r--r--ext/zlib/zlib.c123
-rwxr-xr-xgenfiles11
-rw-r--r--main/fastcgi.c (renamed from sapi/cgi/fastcgi.c)324
-rw-r--r--main/fastcgi.h (renamed from sapi/cgi/fastcgi.h)88
-rw-r--r--main/fopen_wrappers.c4
-rw-r--r--main/main.c4
-rw-r--r--main/php_ini.c4
-rw-r--r--main/php_variables.c13
-rw-r--r--main/streams/php_streams_int.h4
-rw-r--r--main/win95nt.h3
-rw-r--r--php.ini-development59
-rw-r--r--php.ini-production59
-rwxr-xr-xrun-tests.php23
-rw-r--r--sapi/cgi/Makefile.frag2
-rw-r--r--sapi/cgi/cgi_main.c201
-rw-r--r--sapi/cgi/config.w323
-rw-r--r--sapi/cgi/config9.m410
-rw-r--r--sapi/cli/php_cli_server.c4
-rw-r--r--sapi/fpm/Makefile.frag2
-rw-r--r--sapi/fpm/config.m49
-rw-r--r--sapi/fpm/fpm/fastcgi.c1340
-rw-r--r--sapi/fpm/fpm/fastcgi.h151
-rw-r--r--sapi/fpm/fpm/fpm_main.c127
-rw-r--r--sapi/fpm/fpm/zlog.c19
-rw-r--r--sapi/fpm/fpm/zlog.h4
-rw-r--r--sapi/litespeed/lsapilib.c18
-rw-r--r--sapi/nsapi/CREDITS2
-rw-r--r--sapi/nsapi/config.m439
-rw-r--r--sapi/nsapi/config.w3220
-rw-r--r--sapi/nsapi/nsapi-readme.txt154
-rw-r--r--sapi/nsapi/nsapi.c1102
-rw-r--r--sapi/phpdbg/phpdbg_bp.c4
-rw-r--r--sapi/phpdbg/phpdbg_io.c8
-rw-r--r--sapi/phpdbg/phpdbg_opcode.c63
-rw-r--r--sapi/phpdbg/phpdbg_print.c8
-rw-r--r--sapi/phpdbg/phpdbg_utils.c2
-rw-r--r--sapi/phpdbg/tests/commands/0102_print.test8
-rw-r--r--sapi/tests/test005.phpt4
-rw-r--r--sapi/tests/test006.phpt2
-rw-r--r--tests/basic/bug51709_1.phpt16
-rw-r--r--tests/basic/bug51709_2.phpt16
-rw-r--r--tests/classes/autoload_009.phpt2
-rw-r--r--tests/classes/type_hinting_001.phpt2
-rw-r--r--tests/classes/type_hinting_002.phpt2
-rw-r--r--tests/classes/type_hinting_003.phpt2
-rw-r--r--tests/lang/bug24658.phpt2
-rw-r--r--tests/lang/catchable_error_001.phpt2
-rw-r--r--tests/lang/string/unicode_escape_incomplete.phpt2
-rw-r--r--tests/lang/type_hints_001.phpt2
-rw-r--r--win32/build/Makefile4
-rw-r--r--win32/build/config.w324
-rw-r--r--win32/build/config.w32.h.in2
-rw-r--r--win32/build/confutils.js33
-rw-r--r--win32/build/default.manifest17
-rw-r--r--win32/build/deplister.c1
-rw-r--r--win32/build/libs_version.txt6
-rw-r--r--win32/build/mkdist.php16
-rw-r--r--win32/dllmain.c74
-rw-r--r--win32/fnmatch.c9
-rw-r--r--win32/getrusage.c84
-rw-r--r--win32/getrusage.h117
-rw-r--r--win32/glob.c21
-rw-r--r--win32/globals.c8
-rw-r--r--win32/inet.c27
-rw-r--r--win32/inet.h19
-rw-r--r--win32/install.txt144
-rw-r--r--win32/php_registry.h18
-rw-r--r--win32/readdir.c9
-rw-r--r--win32/registry.c27
-rw-r--r--win32/sendmail.c9
-rw-r--r--win32/sockets.c9
-rw-r--r--win32/time.c106
-rw-r--r--win32/time.h6
-rw-r--r--win32/winutil.c8
-rw-r--r--win32/wsyslog.c9
348 files changed, 19373 insertions, 14081 deletions
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
new file mode 100644
index 0000000000..aacb25bc5c
--- /dev/null
+++ b/CONTRIBUTING.md
@@ -0,0 +1,73 @@
+# Contributing to PHP
+
+Anybody who programs in PHP can be a contributing member of the community that
+develops and deploys it; the task of deploying PHP, documentation and
+associated websites is a never ending one. With every release, or release
+candidate comes a wave of work, which takes a lot of organization and
+co-ordination.
+
+## Pull requests
+
+PHP welcomes pull requests to [add tests](#writing-tests), fix bugs and to
+implement RFCs. Please be sure to include tests as appropriate!
+
+If you are fixing a bug, then please submit your PR against the lowest branch
+of PHP that the bug affects, or the oldest fully supported version (the first
+green branch on
+[the supported version page](http://php.net/supported-versions.php). For
+example, at the time of writing in mid-2015, this is PHP 5.5, which corresponds
+to the `PHP-5.5` branch in Git. Please also make sure you add a link to the PR
+in the bug on [the bug tracker](https://bugs.php.net/).
+
+Pull requests to implement RFCs should be submitted against `master`.
+
+## Filing bugs
+
+Bugs can be filed on the [PHP bug tracker](https://bugs.php.net/). If this is
+the first time you've filed a bug, we suggest reading the
+[guide to reporting a bug](https://bugs.php.net/how-to-report.php).
+
+Where possible, please include a self-contained reproduction case!
+
+## Feature requests
+
+Feature requests are generally submitted in the form of
+[Requests for Comment](https://wiki.php.net/rfc/howto), ideally accompanied by
+[pull requests](#pull-requests). You can find the extremely large list of RFCs
+that have been previously considered on the
+[PHP Wiki](https://wiki.php.net/rfc).
+
+You may want to read
+[The Mysterious PHP RFC Process](https://blogs.oracle.com/opal/entry/the_mysterious_php_rfc_process)
+for additional notes on the best way to approach submitting an RFC.
+
+## Writing tests
+
+We love getting new tests! PHP is a huge project and improving code coverage is
+a huge win for every PHP user.
+
+[Our QA site includes a page detailing how to write test cases.](http://qa.php.net/write-test.php)
+Please note that the section on submitting pull requests is outdated: in
+addition to the process listed there, you can also
+[submit pull requests](#pull-requests).
+
+## Writing documentation
+
+There are two ways to contribute to the PHP manual. You can edit the manual and
+send patches anonymously via [the online editor](https://edit.php.net/), or you
+can check the XML source out from Subversion and edit that and build it
+[per the instructions on the documentation site](http://doc.php.net/tutorial/).
+Patches created that way should be sent to the
+[documentation mailing list](mailto:phpdoc@lists.php.net).
+
+## Getting help
+
+If you are having trouble contributing to PHP, or just want to talk to a human
+about what you're working on, you can contact us via the
+[internals mailing list](mailto:internals@lists.php.net), or the
+[documentation mailing list](mailto:phpdoc@lists.php.net) for documentation
+issues.
+
+Although not a formal channel, you can also find a number of core developers on
+the #php.pecl channel on [EFnet](http://www.efnet.org/). Similarly, many
+documentation writers can be found on #php.doc.
diff --git a/Makefile.global b/Makefile.global
index f833efa5e7..c571f3455d 100644
--- a/Makefile.global
+++ b/Makefile.global
@@ -130,5 +130,18 @@ distclean: clean
fi
$(EGREP) define'.*include/php' $(top_srcdir)/configure | $(SED) 's/.*>//'|xargs rm -f
-.PHONY: all clean install distclean test
+prof-gen:
+ CCACHE_DISABLE=1 $(MAKE) PROF_FLAGS=-fprofile-generate all
+
+prof-clean:
+ find . -name \*.lo -o -name \*.o | xargs rm -f
+ find . -name \*.la -o -name \*.a | xargs rm -f
+ find . -name \*.so | xargs rm -f
+ rm -f libphp$(PHP_MAJOR_VERSION).la $(SAPI_CLI_PATH) $(SAPI_CGI_PATH) $(SAPI_MILTER_PATH) $(SAPI_LITESPEED_PATH) $(SAPI_FPM_PATH) $(OVERALL_TARGET) modules/* libs/*
+
+prof-use:
+ CCACHE_DISABLE=1 $(MAKE) PROF_FLAGS=-fprofile-use all
+
+
+.PHONY: all clean install distclean test prof-gen prof-clean prof-use
.NOEXPORT:
diff --git a/NEWS b/NEWS
index 2a3019a4c9..538c38b4af 100644
--- a/NEWS
+++ b/NEWS
@@ -1,14 +1,40 @@
-PHP NEWS
+PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-?? ??? 20??, PHP 7.0.0
+25 Jun 2015, PHP 7.0.0 Alpha 2
-- 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)
+- Core:
+ . 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 #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)
+
+- mysqlnd:
+ . Fixed Bug #69796 (mysqli_stmt::fetch doesn't assign null values to
+ bound variables). (Laruence);
+
+- Curl:
+ . Fixed bug #69831 (Segmentation fault in curl_getinfo). (im dot denisenko at
+ yahoo dot com)
+
+- PDO_pgsql:
+ . Fixed bug #69752 (PDOStatement::execute() leaks memory with DML
+ Statements when closeCuror() is u). (Philip Hofstetter)
+
+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)
@@ -77,7 +103,16 @@
. 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 `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)
@@ -104,6 +139,7 @@
- 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)
@@ -117,7 +153,7 @@
. Implement request #67106 (Split main fpm config). (Elan Ruusamäe, Remi)
- FTP:
- . Fixed bug #69082 FTPS support on Windows
+ . Fixed bug #69082 (FTPS support on Windows). (Anatol)
- Intl:
. Removed deprecated aliases datefmt_set_timezone_id() and
@@ -135,12 +171,18 @@
- 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
@@ -181,6 +223,8 @@
- 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)
@@ -198,13 +242,14 @@
nor curruption state). (Julien)
. Fixed bug #66405 (RecursiveDirectoryIterator::CURRENT_AS_PATHNAME
breaks the RecursiveIterator). (Paul Garvin)
- . Fixed bug #68479 (Added escape parameter to SplFileObject::fputcsv). (Salathe)
- 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)
@@ -220,7 +265,11 @@
. 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)
+ . 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).
diff --git a/UPGRADING b/UPGRADING
index 77f3cbc49c..109b461d21 100644
--- a/UPGRADING
+++ b/UPGRADING
@@ -461,6 +461,10 @@ Other
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().
@@ -488,7 +492,7 @@ Other
- PCRE:
. Removed support for /e (PREG_REPLACE_EVAL) modifier. Use
- preg_reaplace_callback() instead.
+ preg_replace_callback() instead.
- PDO_pgsql:
. Removed PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT attribute in favor of
@@ -530,6 +534,12 @@ Other
(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 declatarations 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)
- OpenSSL
. Added "alpn_protocols" SSL context option allowing encrypted client/server
@@ -538,7 +548,12 @@ Other
accessible through stream_get_meta_data() output.
- Reflection
- . Added a ReflectionGenerator class (yield from Traces, current file/line etc.)
+ . 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.
========================================
3. Changes in SAPI modules
@@ -575,6 +590,10 @@ Other
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.
========================================
6. New Functions
@@ -611,6 +630,7 @@ Other
- sapi/continuity
- sapi/isapi
- sapi/milter
+- sapi/nsapi
- sapi/phttpd
- sapi/pi3web
- sapi/roxen
@@ -618,8 +638,17 @@ Other
- sapi/tux
- sapi/webjames
- ext/mssql
+- ext/mysql
- ext/sybase_ct
-For more details see https://wiki.php.net/rfc/removal_of_dead_sapis_and_exts
+- 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
@@ -643,6 +672,23 @@ For more details see https://wiki.php.net/rfc/removal_of_dead_sapis_and_exts
. 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
========================================
@@ -659,6 +705,7 @@ For more details see https://wiki.php.net/rfc/removal_of_dead_sapis_and_exts
- 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
diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS
index 632c87e1c4..60ae493434 100644
--- a/UPGRADING.INTERNALS
+++ b/UPGRADING.INTERNALS
@@ -2,6 +2,7 @@ $Id$
PHP 7.0 INTERNALS UPGRADE NOTES
+0. Wiki Examples
1. Internal API changes
e. New data types
f. zend_parse_parameters() specs
@@ -23,6 +24,14 @@ PHP 7.0 INTERNALS UPGRADE NOTES
b. Windows build system changes
+================
+0. Wiki Examples
+================
+
+The wiki contains multiple examples and further explanations of the internal
+changes. See: https://wiki.php.net/phpng-upgrading
+
+
========================
1. Internal API changes
========================
@@ -169,7 +178,7 @@ PHP 7.0 INTERNALS UPGRADE NOTES
before any globals was accessed.
Porting an extension or SAPI is usually as easy as removing all the TSRMLS_*
- ocurrences and integrating the macros mentioned above. However if tsrm_ls
+ 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.
@@ -196,10 +205,10 @@ PHP 7.0 INTERNALS UPGRADE NOTES
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_INTI, ZEND_ROPE_ADD,
+ 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 alloca te and construct the resulting string once.
+ collect all the strings and then allocate and construct the resulting string once.
========================
@@ -230,7 +239,8 @@ PHP 7.0 INTERNALS UPGRADE NOTES
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 and can be disabled with the special "disable" keyword.
+ enabled by default for release builds and can be disabled with the special
+ "disable" keyword.
========================
3. Module changes
@@ -251,7 +261,7 @@ PHP 7.0 INTERNALS UPGRADE NOTES
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 timestap on read, so it does not need to update timestamp. Return
+ 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.
diff --git a/Zend/Zend.m4 b/Zend/Zend.m4
index 868a04d91e..6104dc0bc9 100644
--- a/Zend/Zend.m4
+++ b/Zend/Zend.m4
@@ -462,4 +462,4 @@ if test "$ZEND_GCC_GLOBAL_REGS" = "yes"; then
else
HAVE_GCC_GLOBAL_REGS=no
fi
-AC_MSG_RESULT(ZEND_GCC_GLOBAL_REGS)
+AC_MSG_RESULT($ZEND_GCC_GLOBAL_REGS)
diff --git a/Zend/bug69756.phpt b/Zend/bug69756.phpt
new file mode 100644
index 0000000000..ca638fb2d6
--- /dev/null
+++ b/Zend/bug69756.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Fixed bug #69756 (Fatal error: Nesting level too deep - recursive dependency? with ===).
+--FILE--
+<?php
+$arr = range(1, 2);
+foreach($arr as &$item ) {
+ var_dump($arr === array(1, 2));
+}
+?>
+--EXPECT--
+bool(true)
+bool(true)
diff --git a/Zend/tests/anon/006.phpt b/Zend/tests/anon/006.phpt
index e5dc1226d8..2b8888c497 100644
--- a/Zend/tests/anon/006.phpt
+++ b/Zend/tests/anon/006.phpt
@@ -10,6 +10,6 @@ namespace {
var_dump ($hello);
}
--EXPECTF--
-object(lone\class@%s)#1 (0) {
+object(class@%s)#1 (0) {
}
diff --git a/Zend/tests/anon/007.phpt b/Zend/tests/anon/007.phpt
index 12f4da6653..59d2441760 100644
--- a/Zend/tests/anon/007.phpt
+++ b/Zend/tests/anon/007.phpt
@@ -18,6 +18,6 @@ namespace lone {
new Outer();
}
--EXPECTF--
-object(lone\class@%s)#2 (0) {
+object(class@%s)#2 (0) {
}
diff --git a/Zend/tests/array_offset.phpt b/Zend/tests/array_offset.phpt
new file mode 100644
index 0000000000..76c25f9298
--- /dev/null
+++ b/Zend/tests/array_offset.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Ensure "undefined offset" notice formats message corectly when undefined key is negative
+--FILE--
+<?php
+
+[][-1];
+[][-1.1];
+(new ArrayObject)[-1];
+(new ArrayObject)[-1.1];
+
+echo "Done\n";
+?>
+--EXPECTF--
+Notice: Undefined offset: -1 in %s on line 3
+
+Notice: Undefined offset: -1 in %s on line 4
+
+Notice: Undefined offset: -1 in %s on line 5
+
+Notice: Undefined offset: -1 in %s on line 6
+Done
diff --git a/Zend/tests/array_type_hint_001.phpt b/Zend/tests/array_type_hint_001.phpt
index 474ffa8e59..2b473c56b4 100644
--- a/Zend/tests/array_type_hint_001.phpt
+++ b/Zend/tests/array_type_hint_001.phpt
@@ -14,6 +14,6 @@ foo(123);
Fatal error: Uncaught TypeError: Argument 1 passed to foo() must be of the type array, integer given, called in %sarray_type_hint_001.php on line 7 and defined in %sarray_type_hint_001.php:2
Stack trace:
-#0 %s(%d): foo()
+#0 %s(%d): foo(123)
#1 {main}
thrown in %sarray_type_hint_001.php on line 2
diff --git a/Zend/tests/assert/expect_015.phpt b/Zend/tests/assert/expect_015.phpt
index 80f1bd8aa8..030913f7f9 100644
--- a/Zend/tests/assert/expect_015.phpt
+++ b/Zend/tests/assert/expect_015.phpt
@@ -144,12 +144,6 @@ assert(0 && ($a = function () {
?>
--EXPECTF--
-Warning: Unsupported declare 'A' in %sexpect_015.php on line %d
-
-Warning: Unsupported declare 'B' in %sexpect_015.php on line %d
-
-Warning: Unsupported declare 'C' in %sexpect_015.php on line %d
-
Warning: assert(): assert(0 && ($a = function () {
global $a;
global $$b;
diff --git a/Zend/tests/bug39003.phpt b/Zend/tests/bug39003.phpt
index f4f9e4d9b6..add14512c8 100644
--- a/Zend/tests/bug39003.phpt
+++ b/Zend/tests/bug39003.phpt
@@ -23,6 +23,6 @@ echo "Done\n";
--EXPECTF--
Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of OtherClassName, instance of ClassName given, called in %s on line %d and defined in %s:%d
Stack trace:
-#0 %s(%d): test()
+#0 %s(%d): test(Object(ClassName))
#1 {main}
thrown in %s on line %d
diff --git a/Zend/tests/bug42802.phpt b/Zend/tests/bug42802.phpt
index 6dad5feccb..3b00408e01 100644
--- a/Zend/tests/bug42802.phpt
+++ b/Zend/tests/bug42802.phpt
@@ -39,6 +39,6 @@ ok
Fatal error: Uncaught TypeError: Argument 1 passed to foo\test5() must be an instance of bar, instance of foo\bar given, called in %sbug42802.php on line %d and defined in %sbug42802.php:%d
Stack trace:
-#0 %s(%d): foo\test5()
+#0 %s(%d): foo\test5(Object(foo\bar))
#1 {main}
thrown in %sbug42802.php on line %d
diff --git a/Zend/tests/bug43332_1.phpt b/Zend/tests/bug43332_1.phpt
index 5fe734cfea..fc035ab2b6 100644
--- a/Zend/tests/bug43332_1.phpt
+++ b/Zend/tests/bug43332_1.phpt
@@ -14,6 +14,6 @@ $foo->bar(new \stdclass); // Error, ok!
--EXPECTF--
Fatal error: Uncaught TypeError: Argument 1 passed to foobar\foo::bar() must be an instance of foobar\foo, instance of stdClass given, called in %sbug43332_1.php on line 10 and defined in %sbug43332_1.php:5
Stack trace:
-#0 %s(%d): foobar\foo->bar()
+#0 %s(%d): foobar\foo->bar(Object(stdClass))
#1 {main}
thrown in %sbug43332_1.php on line 5
diff --git a/Zend/tests/bug68446.phpt b/Zend/tests/bug68446.phpt
index 2dad15d411..994699e5de 100644
--- a/Zend/tests/bug68446.phpt
+++ b/Zend/tests/bug68446.phpt
@@ -34,7 +34,7 @@ array(1) {
Fatal error: Uncaught TypeError: Argument 1 passed to a() must be of the type array, null given, called in %s on line %d and defined in %s:%d
Stack trace:
-#0 %s(%d): a()
+#0 %s(%d): a(NULL)
#1 {main}
thrown in %s on line %d
diff --git a/Zend/tests/bug69551.phpt b/Zend/tests/bug69551.phpt
new file mode 100644
index 0000000000..096852a2fa
--- /dev/null
+++ b/Zend/tests/bug69551.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Bug #69551 - parse_ini_file() and parse_ini_string() segmentation fault
+--FILE--
+<?php
+$ini = <<<INI
+[Network.eth0]
+SubnetMask = "
+"
+INI;
+$settings = parse_ini_string($ini, false, INI_SCANNER_RAW);
+var_dump($settings);
+?>
+--EXPECTF--
+Warning: syntax error, unexpected '"' in Unknown on line %d
+ in %s on line %d
+bool(false)
diff --git a/Zend/tests/bug69676.phpt b/Zend/tests/bug69676.phpt
new file mode 100644
index 0000000000..54b9d40047
--- /dev/null
+++ b/Zend/tests/bug69676.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #69676: Resolution of self::FOO in class constants not correct
+--FILE--
+<?php
+class A {
+ const myConst = "const in A";
+ const myDynConst = self::myConst;
+}
+
+class B extends A {
+ const myConst = "const in B";
+}
+
+var_dump(B::myDynConst);
+var_dump(A::myDynConst);
+?>
+--EXPECT--
+string(10) "const in A"
+string(10) "const in A"
diff --git a/Zend/tests/bug69732.phpt b/Zend/tests/bug69732.phpt
new file mode 100644
index 0000000000..bc6206d113
--- /dev/null
+++ b/Zend/tests/bug69732.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #69732 (can induce segmentation fault with basic php code)
+--FILE--
+<?php
+class wpq {
+ private $unreferenced;
+
+ public function __get($name) {
+ return $this->$name . "XXX";
+ }
+}
+
+function ret_assoc() {
+ $x = "XXX";
+ return array('foo' => 'bar', $x);
+}
+
+$wpq = new wpq;
+$wpq->interesting =& ret_assoc();
+$x = $wpq->interesting;
+printf("%s\n", $x);
+--EXPECTF--
+Notice: Undefined property: wpq::$interesting in %sbug69732.php on line 6
+
+Notice: Indirect modification of overloaded property wpq::$interesting has no effect in %sbug69732.php on line 16
+
+Notice: Only variables should be assigned by reference in %sbug69732.php on line 16
+
+Notice: Undefined property: wpq::$interesting in %sbug69732.php on line 6
+XXX
diff --git a/Zend/tests/bug69740.phpt b/Zend/tests/bug69740.phpt
new file mode 100644
index 0000000000..c8910b22d8
--- /dev/null
+++ b/Zend/tests/bug69740.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Bug #69740: finally in generator (yield) swallows exception in iteration
+--FILE--
+<?php
+
+function generate() {
+ try {
+ yield 1;
+ yield 2;
+ } finally {
+ echo "finally\n";
+ }
+}
+
+foreach (generate() as $i) {
+ echo $i, "\n";
+ throw new Exception();
+}
+
+?>
+--EXPECTF--
+1
+finally
+
+Fatal error: Uncaught Exception in %s:%d
+Stack trace:
+#0 {main}
+ thrown in %s on line %d
diff --git a/Zend/tests/bug69754.phpt b/Zend/tests/bug69754.phpt
new file mode 100644
index 0000000000..be55ae2b78
--- /dev/null
+++ b/Zend/tests/bug69754.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #69754 (Use of ::class inside array causes compile error)
+--FILE--
+<?php
+
+class Example {
+ public function test() {
+ var_dump(static::class);
+ var_dump(static::class . 'IsAwesome');
+ var_dump(static::class . date('Ymd'));
+ var_dump([static::class]);
+ }
+}
+
+(new Example)->test();
+
+?>
+--EXPECTF--
+string(7) "Example"
+string(16) "ExampleIsAwesome"
+string(15) "Example%d"
+array(1) {
+ [0]=>
+ string(7) "Example"
+}
diff --git a/Zend/tests/bug69755.phpt b/Zend/tests/bug69755.phpt
new file mode 100644
index 0000000000..67c0ed3383
--- /dev/null
+++ b/Zend/tests/bug69755.phpt
@@ -0,0 +1,8 @@
+--TEST--
+Bug #69755: segfault in ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDLER
+--FILE--
+<?php
+c . 10;
+?>
+--EXPECTF--
+Notice: Use of undefined constant c - assumed 'c' in %sbug69755.php on line 2
diff --git a/Zend/tests/bug69758.phpt b/Zend/tests/bug69758.phpt
new file mode 100644
index 0000000000..f0b3588139
--- /dev/null
+++ b/Zend/tests/bug69758.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Bug #69758 (Item added to array not being removed by array_pop/shift)
+--FILE--
+<?php
+$tokens = array();
+$conditions = array();
+for ($i = 0; $i <= 10; $i++) {
+ $tokens[$i] = $conditions;
+
+ // First integer must be less than 8
+ // and second must be 8, 9 or 10
+ if ($i !== 0 && $i !== 8) {
+ continue;
+ }
+
+ // Add condition and then pop off straight away.
+ // Can also use array_shift() here.
+ $conditions[$i] = true;
+ $oldCondition = array_pop($conditions);
+}
+
+// Conditions should be empty.
+var_dump($conditions);
+?>
+--EXPECT--
+array(0) {
+}
diff --git a/Zend/tests/bug69761.phpt b/Zend/tests/bug69761.phpt
new file mode 100644
index 0000000000..4b7e2787d8
--- /dev/null
+++ b/Zend/tests/bug69761.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #69761 (Serialization of anonymous classes should be prevented)
+--FILE--
+<?php
+$instance = new class('foo') {
+ public function __construct($i) {
+ }
+};
+var_dump(serialize($instance));
+?>
+--EXPECTF--
+Fatal error: Uncaught Exception: Serialization of 'class@%s' is not allowed in %sbug69761.php:%d
+Stack trace:
+#0 %sbug69761.php(%d): serialize(Object(class@%s
+ thrown in %sbug69761.php on line %d
diff --git a/Zend/tests/bug69767.phpt b/Zend/tests/bug69767.phpt
new file mode 100644
index 0000000000..cf4d4e7f93
--- /dev/null
+++ b/Zend/tests/bug69767.phpt
@@ -0,0 +1,8 @@
+--TEST--
+Bug #69767 (Default parameter value with wrong type segfaults)
+--FILE--
+<?php
+function foo(String $bar = 0) {}
+?>
+--EXPECTF--
+Fatal error: Default value for parameters with a string type hint can only be string or NULL in %sbug69767.php on line %d
diff --git a/Zend/tests/bug69788.phpt b/Zend/tests/bug69788.phpt
new file mode 100644
index 0000000000..e48486625f
--- /dev/null
+++ b/Zend/tests/bug69788.phpt
@@ -0,0 +1,8 @@
+--TEST--
+Bug #69788: Malformed script causes Uncaught EngineException in php-cgi, valgrind SIGILL
+--FILE--
+<?php [t.[]]; ?>
+--EXPECTF--
+Notice: Array to string conversion in %s on line %d
+
+Notice: Use of undefined constant t - assumed 't' in %s on line %d
diff --git a/Zend/tests/bug69805.phpt b/Zend/tests/bug69805.phpt
new file mode 100644
index 0000000000..c3ca62dc11
--- /dev/null
+++ b/Zend/tests/bug69805.phpt
@@ -0,0 +1,8 @@
+--TEST--
+Bug #69805 (null ptr deref and seg fault in zend_resolve_class_name)
+--FILE--
+<?php
+class p{public function c(){(0)::t;}}?>
+?>
+--EXPECTF--
+Fatal error: Illegal class name in %sbug69805.php on line %d
diff --git a/Zend/tests/bug69825.phpt b/Zend/tests/bug69825.phpt
new file mode 100644
index 0000000000..1349dee5ae
--- /dev/null
+++ b/Zend/tests/bug69825.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #69825 (Short-circuiting failure)
+--FILE--
+<?php
+
+print "AND\n";
+var_dump(0 && 1);
+var_dump(0 && 0);
+var_dump(1 && 0);
+var_dump(1 && 1);
+
+print "OR\n";
+var_dump(0 || 1);
+var_dump(0 || 0);
+var_dump(1 || 0);
+var_dump(1 || 1);
+
+?>
+--EXPECT--
+AND
+bool(false)
+bool(false)
+bool(false)
+bool(true)
+OR
+bool(true)
+bool(false)
+bool(true)
+bool(true)
+
diff --git a/Zend/tests/closure_027.phpt b/Zend/tests/closure_027.phpt
index a56b78013c..db42ae9307 100644
--- a/Zend/tests/closure_027.phpt
+++ b/Zend/tests/closure_027.phpt
@@ -30,6 +30,6 @@ NULL
Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of Closure, instance of stdClass given, called in %s on line %d and defined in %s:%d
Stack trace:
-#0 %s(%d): test()
+#0 %s(%d): test(Object(stdClass))
#1 {main}
thrown in %s on line %d
diff --git a/Zend/tests/gc_024.phpt b/Zend/tests/gc_024.phpt
index 9a2ceb88f5..ca78da63d3 100644
--- a/Zend/tests/gc_024.phpt
+++ b/Zend/tests/gc_024.phpt
@@ -13,5 +13,5 @@ var_dump(gc_collect_cycles());
echo "ok\n";
?>
--EXPECT--
-int(1)
+int(2)
ok
diff --git a/Zend/tests/grammar/regression_001.phpt b/Zend/tests/grammar/regression_001.phpt
new file mode 100644
index 0000000000..73d5eacdf6
--- /dev/null
+++ b/Zend/tests/grammar/regression_001.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Test to check static method calls syntax regression
+--FILE--
+<?php
+
+class Foo {
+ public static function function(){ echo __METHOD__, PHP_EOL; }
+}
+
+Foo::function();
+
+Foo::
+function();
+
+Foo::
+ function();
+
+
+Foo::
+ function(
+
+);
+
+echo "\nDone\n";
+
+--EXPECTF--
+
+Foo::function
+Foo::function
+Foo::function
+Foo::function
+
+Done
diff --git a/Zend/tests/grammar/regression_002.phpt b/Zend/tests/grammar/regression_002.phpt
new file mode 100644
index 0000000000..dd307c99d8
--- /dev/null
+++ b/Zend/tests/grammar/regression_002.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Test to ensure ::class still works
+--FILE--
+<?php
+
+class Foo {}
+
+var_dump(Foo::class);
+
+var_dump(Foo:: class);
+
+var_dump(Foo:: CLASS);
+
+var_dump(Foo::
+
+CLASS);
+
+--EXPECTF--
+string(3) "Foo"
+string(3) "Foo"
+string(3) "Foo"
+string(3) "Foo"
diff --git a/Zend/tests/grammar/regression_003.phpt b/Zend/tests/grammar/regression_003.phpt
new file mode 100644
index 0000000000..e475754ccd
--- /dev/null
+++ b/Zend/tests/grammar/regression_003.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Test to ensure ::class is still reserved in obj scope
+--FILE--
+<?php
+
+class Obj
+{
+ const CLASS = 'class';
+}
+
+?>
+--EXPECTF--
+Fatal error: A class constant must not be called 'class'; it is reserved for class name fetching in %s on line %d
diff --git a/Zend/tests/grammar/regression_004.phpt b/Zend/tests/grammar/regression_004.phpt
new file mode 100644
index 0000000000..e95674d8c9
--- /dev/null
+++ b/Zend/tests/grammar/regression_004.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Test possible function naming regression on procedural scope
+--FILE--
+<?php
+
+class Obj
+{
+ function echo(){} // valid
+ function return(){} // valid
+}
+
+function echo(){} // not valid
+
+--EXPECTF--
+Parse error: syntax error, unexpected 'echo' (T_ECHO), expecting identifier (T_STRING) or '(' in %s on line 9
diff --git a/Zend/tests/grammar/regression_005.phpt b/Zend/tests/grammar/regression_005.phpt
new file mode 100644
index 0000000000..7704375d6e
--- /dev/null
+++ b/Zend/tests/grammar/regression_005.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Test possible constant naming regression on procedural scope
+--FILE--
+<?php
+
+class Obj
+{
+ const return = 'yep';
+}
+
+const return = 'nope';
+
+--EXPECTF--
+Parse error: syntax error, unexpected 'return' (T_RETURN), expecting identifier (T_STRING) in %s on line 8
diff --git a/Zend/tests/grammar/regression_006.phpt b/Zend/tests/grammar/regression_006.phpt
new file mode 100644
index 0000000000..6aae0ba24b
--- /dev/null
+++ b/Zend/tests/grammar/regression_006.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Test to ensure const list syntax declaration works
+--FILE--
+<?php
+
+class Obj
+{
+ const DECLARE = 'declare',
+ RETURN = 'return',
+ FUNCTION = 'function',
+ USE = 'use';
+}
+
+echo Obj::DECLARE, PHP_EOL;
+echo Obj::RETURN, PHP_EOL;
+echo Obj::FUNCTION, PHP_EOL;
+echo Obj::USE, PHP_EOL;
+echo Obj::
+
+ USE, PHP_EOL;
+echo "\nDone\n";
+
+--EXPECTF--
+declare
+return
+function
+use
+use
+
+Done
diff --git a/Zend/tests/grammar/regression_007.phpt b/Zend/tests/grammar/regression_007.phpt
new file mode 100644
index 0000000000..92b22531a4
--- /dev/null
+++ b/Zend/tests/grammar/regression_007.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Test to ensure semi reserved words allow deference
+--FILE--
+<?php
+
+class Foo {
+ const use = 'yay';
+
+ public static function new() {
+ echo __METHOD__, PHP_EOL;
+ return new static();
+ }
+
+ public function self() {
+ echo __METHOD__, PHP_EOL;
+ return $this;
+ }
+}
+
+Foo::new()::new()::new();
+
+var_dump(
+ (new Foo)->self()::new()->self()->self()::use
+);
+
+Foo::{'new'}();
+
+var_dump(Foo::use);
+
+echo "\nDone\n";
+
+--EXPECTF--
+Foo::new
+Foo::new
+Foo::new
+Foo::self
+Foo::new
+Foo::self
+Foo::self
+string(3) "yay"
+Foo::new
+string(3) "yay"
+
+Done
diff --git a/Zend/tests/grammar/regression_008.phpt b/Zend/tests/grammar/regression_008.phpt
new file mode 100644
index 0000000000..7741ed036c
--- /dev/null
+++ b/Zend/tests/grammar/regression_008.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Test to check regressions on string interpolation with class members access
+--FILE--
+<?php
+
+class Friday {
+ public $require = "fun";
+}
+
+$friday = new Friday;
+
+echo "$friday->require ($friday->require) {$friday->require}", PHP_EOL;
+
+echo "\nDone\n";
+
+
+--EXPECTF--
+
+fun (fun) fun
+
+Done
diff --git a/Zend/tests/grammar/regression_009.phpt b/Zend/tests/grammar/regression_009.phpt
new file mode 100644
index 0000000000..589d90316b
--- /dev/null
+++ b/Zend/tests/grammar/regression_009.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Test to check regressions on use statements and lexer state
+--FILE--
+<?php
+
+use A\B\C\D;
+
+class Foo
+{
+ private static $foo;
+
+}
+
+echo PHP_EOL, "Done", PHP_EOL;
+
+--EXPECTF--
+
+Done
diff --git a/Zend/tests/grammar/regression_010.phpt b/Zend/tests/grammar/regression_010.phpt
new file mode 100644
index 0000000000..5dc90f288a
--- /dev/null
+++ b/Zend/tests/grammar/regression_010.phpt
@@ -0,0 +1,14 @@
+--TEST--
+Test to check regressions on T_IMPLEMENTS followed by a T_NS_SEPARATOR
+--FILE--
+<?php
+
+interface A{}
+
+class B implements\A {}
+
+echo "Done", PHP_EOL;
+
+--EXPECTF--
+
+Done
diff --git a/Zend/tests/grammar/regression_011.phpt b/Zend/tests/grammar/regression_011.phpt
new file mode 100644
index 0000000000..c79c077187
--- /dev/null
+++ b/Zend/tests/grammar/regression_011.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Testing instantiation using namespace:: prefix
+--FILE--
+<?php
+
+namespace foo;
+
+class bar {
+}
+
+class_alias('foo\bar', 'foo\baz');
+
+var_dump(new namespace\baz);
+
+?>
+--EXPECTF--
+object(foo\bar)#%d (0) {
+}
diff --git a/Zend/tests/grammar/regression_012.phpt b/Zend/tests/grammar/regression_012.phpt
new file mode 100644
index 0000000000..3b4925afa6
--- /dev/null
+++ b/Zend/tests/grammar/regression_012.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Testing for regression on const list syntax and arrays
+--FILE--
+<?php
+
+class A {
+ const A = [1, FOREACH];
+}
+
+?>
+--EXPECTF--
+
+Parse error: syntax error, unexpected 'FOREACH' (T_FOREACH), expecting ']' in %s on line %d
diff --git a/Zend/tests/grammar/regression_013.phpt b/Zend/tests/grammar/regression_013.phpt
new file mode 100644
index 0000000000..1c60ffc273
--- /dev/null
+++ b/Zend/tests/grammar/regression_013.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Testing for regression with encapsed variables in class declaration context
+--FILE--
+<?php
+
+class A { function foo() { "{${$a}}"; } function list() {} }
+
+echo "Done", PHP_EOL;
+
+?>
+--EXPECTF--
+
+Done
diff --git a/Zend/tests/grammar/semi_reserved_001.phpt b/Zend/tests/grammar/semi_reserved_001.phpt
new file mode 100644
index 0000000000..c6bfd46611
--- /dev/null
+++ b/Zend/tests/grammar/semi_reserved_001.phpt
@@ -0,0 +1,209 @@
+--TEST--
+Test semi-reserved words as class methods
+--FILE--
+<?php
+
+class Obj
+{
+ function empty(){ echo __METHOD__, PHP_EOL; }
+ function callable(){ echo __METHOD__, PHP_EOL; }
+ function trait(){ echo __METHOD__, PHP_EOL; }
+ function extends(){ echo __METHOD__, PHP_EOL; }
+ function implements(){ echo __METHOD__, PHP_EOL; }
+ function const(){ echo __METHOD__, PHP_EOL; }
+ function enddeclare(){ echo __METHOD__, PHP_EOL; }
+ function endfor(){ echo __METHOD__, PHP_EOL; }
+ function endforeach(){ echo __METHOD__, PHP_EOL; }
+ function endif(){ echo __METHOD__, PHP_EOL; }
+ function endwhile(){ echo __METHOD__, PHP_EOL; }
+ function and(){ echo __METHOD__, PHP_EOL; }
+ function global(){ echo __METHOD__, PHP_EOL; }
+ function goto(){ echo __METHOD__, PHP_EOL; }
+ function instanceof(){ echo __METHOD__, PHP_EOL; }
+ function insteadof(){ echo __METHOD__, PHP_EOL; }
+ function interface(){ echo __METHOD__, PHP_EOL; }
+ function new(){ echo __METHOD__, PHP_EOL; }
+ function or(){ echo __METHOD__, PHP_EOL; }
+ function xor(){ echo __METHOD__, PHP_EOL; }
+ function try(){ echo __METHOD__, PHP_EOL; }
+ function use(){ echo __METHOD__, PHP_EOL; }
+ function var(){ echo __METHOD__, PHP_EOL; }
+ function exit(){ echo __METHOD__, PHP_EOL; }
+ function list(){ echo __METHOD__, PHP_EOL; }
+ function clone(){ echo __METHOD__, PHP_EOL; }
+ function include(){ echo __METHOD__, PHP_EOL; }
+ function include_once(){ echo __METHOD__, PHP_EOL; }
+ function throw(){ echo __METHOD__, PHP_EOL; }
+ function array(){ echo __METHOD__, PHP_EOL; }
+ function print(){ echo __METHOD__, PHP_EOL; }
+ function echo(){ echo __METHOD__, PHP_EOL; }
+ function require(){ echo __METHOD__, PHP_EOL; }
+ function require_once(){ echo __METHOD__, PHP_EOL; }
+ function return(){ echo __METHOD__, PHP_EOL; }
+ function else(){ echo __METHOD__, PHP_EOL; }
+ function elseif(){ echo __METHOD__, PHP_EOL; }
+ function default(){ echo __METHOD__, PHP_EOL; }
+ function break(){ echo __METHOD__, PHP_EOL; }
+ function continue(){ echo __METHOD__, PHP_EOL; }
+ function switch(){ echo __METHOD__, PHP_EOL; }
+ function yield(){ echo __METHOD__, PHP_EOL; }
+ function function(){ echo __METHOD__, PHP_EOL; }
+ function if(){ echo __METHOD__, PHP_EOL; }
+ function endswitch(){ echo __METHOD__, PHP_EOL; }
+ function finally(){ echo __METHOD__, PHP_EOL; }
+ function for(){ echo __METHOD__, PHP_EOL; }
+ function foreach(){ echo __METHOD__, PHP_EOL; }
+ function declare(){ echo __METHOD__, PHP_EOL; }
+ function case(){ echo __METHOD__, PHP_EOL; }
+ function do(){ echo __METHOD__, PHP_EOL; }
+ function while(){ echo __METHOD__, PHP_EOL; }
+ function as(){ echo __METHOD__, PHP_EOL; }
+ function catch(){ echo __METHOD__, PHP_EOL; }
+ function die(){ echo __METHOD__, PHP_EOL; }
+ function self(){ echo __METHOD__, PHP_EOL; }
+ function parent(){ echo __METHOD__, PHP_EOL; }
+ function public(){ echo __METHOD__, PHP_EOL; }
+ function protected(){ echo __METHOD__, PHP_EOL; }
+ function private(){ echo __METHOD__, PHP_EOL; }
+ function static(){ echo __METHOD__, PHP_EOL; }
+ function abstract(){ echo __METHOD__, PHP_EOL; }
+ function final(){ echo __METHOD__, PHP_EOL; }
+ function class(){ echo __METHOD__, PHP_EOL; }
+}
+
+$obj = new Obj;
+
+$obj->empty();
+$obj->callable();
+$obj->trait();
+$obj->extends();
+$obj->implements();
+$obj->const();
+$obj->enddeclare();
+$obj->endfor();
+$obj->endforeach();
+$obj->endif();
+$obj->endwhile();
+$obj->and();
+$obj->global();
+$obj->goto();
+$obj->instanceof();
+$obj->insteadof();
+$obj->interface();
+$obj->new();
+$obj->or();
+$obj->xor();
+$obj->try();
+$obj->use();
+$obj->var();
+$obj->exit();
+$obj->list();
+$obj->clone();
+$obj->include();
+$obj->include_once();
+$obj->throw();
+$obj->array();
+$obj->print();
+$obj->echo();
+$obj->require();
+$obj->require_once();
+$obj->return();
+$obj->else();
+$obj->elseif();
+$obj->default();
+$obj->break();
+$obj->continue();
+$obj->switch();
+$obj->yield();
+$obj->function();
+$obj->if();
+$obj->endswitch();
+$obj->finally();
+$obj->for();
+$obj->foreach();
+$obj->declare();
+$obj->case();
+$obj->do();
+$obj->while();
+$obj->as();
+$obj->catch();
+$obj->die();
+$obj->self();
+$obj->parent();
+$obj->public();
+$obj->protected();
+$obj->private();
+$obj->static();
+$obj->abstract();
+$obj->final();
+$obj->class();
+
+echo "\nDone\n";
+
+--EXPECTF--
+Obj::empty
+Obj::callable
+Obj::trait
+Obj::extends
+Obj::implements
+Obj::const
+Obj::enddeclare
+Obj::endfor
+Obj::endforeach
+Obj::endif
+Obj::endwhile
+Obj::and
+Obj::global
+Obj::goto
+Obj::instanceof
+Obj::insteadof
+Obj::interface
+Obj::new
+Obj::or
+Obj::xor
+Obj::try
+Obj::use
+Obj::var
+Obj::exit
+Obj::list
+Obj::clone
+Obj::include
+Obj::include_once
+Obj::throw
+Obj::array
+Obj::print
+Obj::echo
+Obj::require
+Obj::require_once
+Obj::return
+Obj::else
+Obj::elseif
+Obj::default
+Obj::break
+Obj::continue
+Obj::switch
+Obj::yield
+Obj::function
+Obj::if
+Obj::endswitch
+Obj::finally
+Obj::for
+Obj::foreach
+Obj::declare
+Obj::case
+Obj::do
+Obj::while
+Obj::as
+Obj::catch
+Obj::die
+Obj::self
+Obj::parent
+Obj::public
+Obj::protected
+Obj::private
+Obj::static
+Obj::abstract
+Obj::final
+Obj::class
+
+Done
diff --git a/Zend/tests/grammar/semi_reserved_002.phpt b/Zend/tests/grammar/semi_reserved_002.phpt
new file mode 100644
index 0000000000..b2c20028ca
--- /dev/null
+++ b/Zend/tests/grammar/semi_reserved_002.phpt
@@ -0,0 +1,207 @@
+--TEST--
+Test semi-reserved words as static class methods
+--FILE--
+<?php
+
+class Obj
+{
+ static function empty(){ echo __METHOD__, PHP_EOL; }
+ static function callable(){ echo __METHOD__, PHP_EOL; }
+ static function trait(){ echo __METHOD__, PHP_EOL; }
+ static function extends(){ echo __METHOD__, PHP_EOL; }
+ static function implements(){ echo __METHOD__, PHP_EOL; }
+ static function const(){ echo __METHOD__, PHP_EOL; }
+ static function enddeclare(){ echo __METHOD__, PHP_EOL; }
+ static function endfor(){ echo __METHOD__, PHP_EOL; }
+ static function endforeach(){ echo __METHOD__, PHP_EOL; }
+ static function endif(){ echo __METHOD__, PHP_EOL; }
+ static function endwhile(){ echo __METHOD__, PHP_EOL; }
+ static function and(){ echo __METHOD__, PHP_EOL; }
+ static function global(){ echo __METHOD__, PHP_EOL; }
+ static function goto(){ echo __METHOD__, PHP_EOL; }
+ static function instanceof(){ echo __METHOD__, PHP_EOL; }
+ static function insteadof(){ echo __METHOD__, PHP_EOL; }
+ static function interface(){ echo __METHOD__, PHP_EOL; }
+ static function new(){ echo __METHOD__, PHP_EOL; }
+ static function or(){ echo __METHOD__, PHP_EOL; }
+ static function xor(){ echo __METHOD__, PHP_EOL; }
+ static function try(){ echo __METHOD__, PHP_EOL; }
+ static function use(){ echo __METHOD__, PHP_EOL; }
+ static function var(){ echo __METHOD__, PHP_EOL; }
+ static function exit(){ echo __METHOD__, PHP_EOL; }
+ static function list(){ echo __METHOD__, PHP_EOL; }
+ static function clone(){ echo __METHOD__, PHP_EOL; }
+ static function include(){ echo __METHOD__, PHP_EOL; }
+ static function include_once(){ echo __METHOD__, PHP_EOL; }
+ static function throw(){ echo __METHOD__, PHP_EOL; }
+ static function array(){ echo __METHOD__, PHP_EOL; }
+ static function print(){ echo __METHOD__, PHP_EOL; }
+ static function echo(){ echo __METHOD__, PHP_EOL; }
+ static function require(){ echo __METHOD__, PHP_EOL; }
+ static function require_once(){ echo __METHOD__, PHP_EOL; }
+ static function return(){ echo __METHOD__, PHP_EOL; }
+ static function else(){ echo __METHOD__, PHP_EOL; }
+ static function elseif(){ echo __METHOD__, PHP_EOL; }
+ static function default(){ echo __METHOD__, PHP_EOL; }
+ static function break(){ echo __METHOD__, PHP_EOL; }
+ static function continue(){ echo __METHOD__, PHP_EOL; }
+ static function switch(){ echo __METHOD__, PHP_EOL; }
+ static function yield(){ echo __METHOD__, PHP_EOL; }
+ static function function(){ echo __METHOD__, PHP_EOL; }
+ static function if(){ echo __METHOD__, PHP_EOL; }
+ static function endswitch(){ echo __METHOD__, PHP_EOL; }
+ static function finally(){ echo __METHOD__, PHP_EOL; }
+ static function for(){ echo __METHOD__, PHP_EOL; }
+ static function foreach(){ echo __METHOD__, PHP_EOL; }
+ static function declare(){ echo __METHOD__, PHP_EOL; }
+ static function case(){ echo __METHOD__, PHP_EOL; }
+ static function do(){ echo __METHOD__, PHP_EOL; }
+ static function while(){ echo __METHOD__, PHP_EOL; }
+ static function as(){ echo __METHOD__, PHP_EOL; }
+ static function catch(){ echo __METHOD__, PHP_EOL; }
+ static function die(){ echo __METHOD__, PHP_EOL; }
+ static function self(){ echo __METHOD__, PHP_EOL; }
+ static function parent(){ echo __METHOD__, PHP_EOL; }
+ static function public(){ echo __METHOD__, PHP_EOL; }
+ static function protected(){ echo __METHOD__, PHP_EOL; }
+ static function private(){ echo __METHOD__, PHP_EOL; }
+ static function static(){ echo __METHOD__, PHP_EOL; }
+ static function abstract(){ echo __METHOD__, PHP_EOL; }
+ static function final(){ echo __METHOD__, PHP_EOL; }
+ static function class(){ echo __METHOD__, PHP_EOL; }
+}
+
+Obj::empty();
+Obj::callable();
+Obj::trait();
+Obj::extends();
+Obj::implements();
+Obj::const();
+Obj::enddeclare();
+Obj::endfor();
+Obj::endforeach();
+Obj::endif();
+Obj::endwhile();
+Obj::and();
+Obj::global();
+Obj::goto();
+Obj::instanceof();
+Obj::insteadof();
+Obj::interface();
+Obj::new();
+Obj::or();
+Obj::xor();
+Obj::try();
+Obj::use();
+Obj::var();
+Obj::exit();
+Obj::list();
+Obj::clone();
+Obj::include();
+Obj::include_once();
+Obj::throw();
+Obj::array();
+Obj::print();
+Obj::echo();
+Obj::require();
+Obj::require_once();
+Obj::return();
+Obj::else();
+Obj::elseif();
+Obj::default();
+Obj::break();
+Obj::continue();
+Obj::switch();
+Obj::yield();
+Obj::function();
+Obj::if();
+Obj::endswitch();
+Obj::finally();
+Obj::for();
+Obj::foreach();
+Obj::declare();
+Obj::case();
+Obj::do();
+Obj::while();
+Obj::as();
+Obj::catch();
+Obj::die();
+Obj::self();
+Obj::parent();
+Obj::public();
+Obj::protected();
+Obj::private();
+Obj::static();
+Obj::abstract();
+Obj::final();
+Obj::class();
+
+echo "\nDone\n";
+
+--EXPECTF--
+Obj::empty
+Obj::callable
+Obj::trait
+Obj::extends
+Obj::implements
+Obj::const
+Obj::enddeclare
+Obj::endfor
+Obj::endforeach
+Obj::endif
+Obj::endwhile
+Obj::and
+Obj::global
+Obj::goto
+Obj::instanceof
+Obj::insteadof
+Obj::interface
+Obj::new
+Obj::or
+Obj::xor
+Obj::try
+Obj::use
+Obj::var
+Obj::exit
+Obj::list
+Obj::clone
+Obj::include
+Obj::include_once
+Obj::throw
+Obj::array
+Obj::print
+Obj::echo
+Obj::require
+Obj::require_once
+Obj::return
+Obj::else
+Obj::elseif
+Obj::default
+Obj::break
+Obj::continue
+Obj::switch
+Obj::yield
+Obj::function
+Obj::if
+Obj::endswitch
+Obj::finally
+Obj::for
+Obj::foreach
+Obj::declare
+Obj::case
+Obj::do
+Obj::while
+Obj::as
+Obj::catch
+Obj::die
+Obj::self
+Obj::parent
+Obj::public
+Obj::protected
+Obj::private
+Obj::static
+Obj::abstract
+Obj::final
+Obj::class
+
+Done
diff --git a/Zend/tests/grammar/semi_reserved_003.phpt b/Zend/tests/grammar/semi_reserved_003.phpt
new file mode 100644
index 0000000000..fe2c44dc4c
--- /dev/null
+++ b/Zend/tests/grammar/semi_reserved_003.phpt
@@ -0,0 +1,210 @@
+--TEST--
+Test semi-reserved words as class properties
+--FILE--
+<?php
+
+class Obj
+{
+ var $empty = 'empty';
+ var $callable = 'callable';
+ var $class = 'class';
+ var $trait = 'trait';
+ var $extends = 'extends';
+ var $implements = 'implements';
+ var $static = 'static';
+ var $abstract = 'abstract';
+ var $final = 'final';
+ var $public = 'public';
+ var $protected = 'protected';
+ var $private = 'private';
+ var $const = 'const';
+ var $enddeclare = 'enddeclare';
+ var $endfor = 'endfor';
+ var $endforeach = 'endforeach';
+ var $endif = 'endif';
+ var $endwhile = 'endwhile';
+ var $and = 'and';
+ var $global = 'global';
+ var $goto = 'goto';
+ var $instanceof = 'instanceof';
+ var $insteadof = 'insteadof';
+ var $interface = 'interface';
+ var $namespace = 'namespace';
+ var $new = 'new';
+ var $or = 'or';
+ var $xor = 'xor';
+ var $try = 'try';
+ var $use = 'use';
+ var $var = 'var';
+ var $exit = 'exit';
+ var $list = 'list';
+ var $clone = 'clone';
+ var $include = 'include';
+ var $include_once = 'include_once';
+ var $throw = 'throw';
+ var $array = 'array';
+ var $print = 'print';
+ var $echo = 'echo';
+ var $require = 'require';
+ var $require_once = 'require_once';
+ var $return = 'return';
+ var $else = 'else';
+ var $elseif = 'elseif';
+ var $default = 'default';
+ var $break = 'break';
+ var $continue = 'continue';
+ var $switch = 'switch';
+ var $yield = 'yield';
+ var $function = 'function';
+ var $if = 'if';
+ var $endswitch = 'endswitch';
+ var $finally = 'finally';
+ var $for = 'for';
+ var $foreach = 'foreach';
+ var $declare = 'declare';
+ var $case = 'case';
+ var $do = 'do';
+ var $while = 'while';
+ var $as = 'as';
+ var $catch = 'catch';
+ var $die = 'die';
+ var $self = 'self';
+}
+
+$obj = new Obj;
+
+echo $obj->empty, PHP_EOL;
+echo $obj->callable, PHP_EOL;
+echo $obj->class, PHP_EOL;
+echo $obj->trait, PHP_EOL;
+echo $obj->extends, PHP_EOL;
+echo $obj->implements, PHP_EOL;
+echo $obj->static, PHP_EOL;
+echo $obj->abstract, PHP_EOL;
+echo $obj->final, PHP_EOL;
+echo $obj->public, PHP_EOL;
+echo $obj->protected, PHP_EOL;
+echo $obj->private, PHP_EOL;
+echo $obj->const, PHP_EOL;
+echo $obj->enddeclare, PHP_EOL;
+echo $obj->endfor, PHP_EOL;
+echo $obj->endforeach, PHP_EOL;
+echo $obj->endif, PHP_EOL;
+echo $obj->endwhile, PHP_EOL;
+echo $obj->and, PHP_EOL;
+echo $obj->global, PHP_EOL;
+echo $obj->goto, PHP_EOL;
+echo $obj->instanceof, PHP_EOL;
+echo $obj->insteadof, PHP_EOL;
+echo $obj->interface, PHP_EOL;
+echo $obj->namespace, PHP_EOL;
+echo $obj->new, PHP_EOL;
+echo $obj->or, PHP_EOL;
+echo $obj->xor, PHP_EOL;
+echo $obj->try, PHP_EOL;
+echo $obj->use, PHP_EOL;
+echo $obj->var, PHP_EOL;
+echo $obj->exit, PHP_EOL;
+echo $obj->list, PHP_EOL;
+echo $obj->clone, PHP_EOL;
+echo $obj->include, PHP_EOL;
+echo $obj->include_once, PHP_EOL;
+echo $obj->throw, PHP_EOL;
+echo $obj->array, PHP_EOL;
+echo $obj->print, PHP_EOL;
+echo $obj->echo, PHP_EOL;
+echo $obj->require, PHP_EOL;
+echo $obj->require_once, PHP_EOL;
+echo $obj->return, PHP_EOL;
+echo $obj->else, PHP_EOL;
+echo $obj->elseif, PHP_EOL;
+echo $obj->default, PHP_EOL;
+echo $obj->break, PHP_EOL;
+echo $obj->continue, PHP_EOL;
+echo $obj->switch, PHP_EOL;
+echo $obj->yield, PHP_EOL;
+echo $obj->function, PHP_EOL;
+echo $obj->if, PHP_EOL;
+echo $obj->endswitch, PHP_EOL;
+echo $obj->finally, PHP_EOL;
+echo $obj->for, PHP_EOL;
+echo $obj->foreach, PHP_EOL;
+echo $obj->declare, PHP_EOL;
+echo $obj->case, PHP_EOL;
+echo $obj->do, PHP_EOL;
+echo $obj->while, PHP_EOL;
+echo $obj->as, PHP_EOL;
+echo $obj->catch, PHP_EOL;
+echo $obj->die, PHP_EOL;
+echo $obj->self, PHP_EOL;
+
+echo "\nDone\n";
+
+?>
+--EXPECTF--
+empty
+callable
+class
+trait
+extends
+implements
+static
+abstract
+final
+public
+protected
+private
+const
+enddeclare
+endfor
+endforeach
+endif
+endwhile
+and
+global
+goto
+instanceof
+insteadof
+interface
+namespace
+new
+or
+xor
+try
+use
+var
+exit
+list
+clone
+include
+include_once
+throw
+array
+print
+echo
+require
+require_once
+return
+else
+elseif
+default
+break
+continue
+switch
+yield
+function
+if
+endswitch
+finally
+for
+foreach
+declare
+case
+do
+while
+as
+catch
+die
+self
+
+Done
diff --git a/Zend/tests/grammar/semi_reserved_004.phpt b/Zend/tests/grammar/semi_reserved_004.phpt
new file mode 100644
index 0000000000..40c5df14ef
--- /dev/null
+++ b/Zend/tests/grammar/semi_reserved_004.phpt
@@ -0,0 +1,210 @@
+--TEST--
+Test semi-reserved words as static class properties
+--FILE--
+<?php
+
+class Obj
+{
+ static $empty = 'empty';
+ static $callable = 'callable';
+ static $class = 'class';
+ static $trait = 'trait';
+ static $extends = 'extends';
+ static $implements = 'implements';
+ static $static = 'static';
+ static $abstract = 'abstract';
+ static $final = 'final';
+ static $public = 'public';
+ static $protected = 'protected';
+ static $private = 'private';
+ static $const = 'const';
+ static $enddeclare = 'enddeclare';
+ static $endfor = 'endfor';
+ static $endforeach = 'endforeach';
+ static $endif = 'endif';
+ static $endwhile = 'endwhile';
+ static $and = 'and';
+ static $global = 'global';
+ static $goto = 'goto';
+ static $instanceof = 'instanceof';
+ static $insteadof = 'insteadof';
+ static $interface = 'interface';
+ static $namespace = 'namespace';
+ static $new = 'new';
+ static $or = 'or';
+ static $xor = 'xor';
+ static $try = 'try';
+ static $use = 'use';
+ static $var = 'var';
+ static $exit = 'exit';
+ static $list = 'list';
+ static $clone = 'clone';
+ static $include = 'include';
+ static $include_once = 'include_once';
+ static $throw = 'throw';
+ static $array = 'array';
+ static $print = 'print';
+ static $echo = 'echo';
+ static $require = 'require';
+ static $require_once = 'require_once';
+ static $return = 'return';
+ static $else = 'else';
+ static $elseif = 'elseif';
+ static $default = 'default';
+ static $break = 'break';
+ static $continue = 'continue';
+ static $switch = 'switch';
+ static $yield = 'yield';
+ static $function = 'function';
+ static $if = 'if';
+ static $endswitch = 'endswitch';
+ static $finally = 'finally';
+ static $for = 'for';
+ static $foreach = 'foreach';
+ static $declare = 'declare';
+ static $case = 'case';
+ static $do = 'do';
+ static $while = 'while';
+ static $as = 'as';
+ static $catch = 'catch';
+ static $die = 'die';
+ static $self = 'self';
+ static $parent = 'parent';
+}
+
+echo Obj::$empty, PHP_EOL;
+echo Obj::$callable, PHP_EOL;
+echo Obj::$class, PHP_EOL;
+echo Obj::$trait, PHP_EOL;
+echo Obj::$extends, PHP_EOL;
+echo Obj::$implements, PHP_EOL;
+echo Obj::$static, PHP_EOL;
+echo Obj::$abstract, PHP_EOL;
+echo Obj::$final, PHP_EOL;
+echo Obj::$public, PHP_EOL;
+echo Obj::$protected, PHP_EOL;
+echo Obj::$private, PHP_EOL;
+echo Obj::$const, PHP_EOL;
+echo Obj::$enddeclare, PHP_EOL;
+echo Obj::$endfor, PHP_EOL;
+echo Obj::$endforeach, PHP_EOL;
+echo Obj::$endif, PHP_EOL;
+echo Obj::$endwhile, PHP_EOL;
+echo Obj::$and, PHP_EOL;
+echo Obj::$global, PHP_EOL;
+echo Obj::$goto, PHP_EOL;
+echo Obj::$instanceof, PHP_EOL;
+echo Obj::$insteadof, PHP_EOL;
+echo Obj::$interface, PHP_EOL;
+echo Obj::$namespace, PHP_EOL;
+echo Obj::$new, PHP_EOL;
+echo Obj::$or, PHP_EOL;
+echo Obj::$xor, PHP_EOL;
+echo Obj::$try, PHP_EOL;
+echo Obj::$use, PHP_EOL;
+echo Obj::$var, PHP_EOL;
+echo Obj::$exit, PHP_EOL;
+echo Obj::$list, PHP_EOL;
+echo Obj::$clone, PHP_EOL;
+echo Obj::$include, PHP_EOL;
+echo Obj::$include_once, PHP_EOL;
+echo Obj::$throw, PHP_EOL;
+echo Obj::$array, PHP_EOL;
+echo Obj::$print, PHP_EOL;
+echo Obj::$echo, PHP_EOL;
+echo Obj::$require, PHP_EOL;
+echo Obj::$require_once, PHP_EOL;
+echo Obj::$return, PHP_EOL;
+echo Obj::$else, PHP_EOL;
+echo Obj::$elseif, PHP_EOL;
+echo Obj::$default, PHP_EOL;
+echo Obj::$break, PHP_EOL;
+echo Obj::$continue, PHP_EOL;
+echo Obj::$switch, PHP_EOL;
+echo Obj::$yield, PHP_EOL;
+echo Obj::$function, PHP_EOL;
+echo Obj::$if, PHP_EOL;
+echo Obj::$endswitch, PHP_EOL;
+echo Obj::$finally, PHP_EOL;
+echo Obj::$for, PHP_EOL;
+echo Obj::$foreach, PHP_EOL;
+echo Obj::$declare, PHP_EOL;
+echo Obj::$case, PHP_EOL;
+echo Obj::$do, PHP_EOL;
+echo Obj::$while, PHP_EOL;
+echo Obj::$as, PHP_EOL;
+echo Obj::$catch, PHP_EOL;
+echo Obj::$die, PHP_EOL;
+echo Obj::$self, PHP_EOL;
+echo Obj::$parent, PHP_EOL;
+
+echo "\nDone\n";
+
+--EXPECTF--
+empty
+callable
+class
+trait
+extends
+implements
+static
+abstract
+final
+public
+protected
+private
+const
+enddeclare
+endfor
+endforeach
+endif
+endwhile
+and
+global
+goto
+instanceof
+insteadof
+interface
+namespace
+new
+or
+xor
+try
+use
+var
+exit
+list
+clone
+include
+include_once
+throw
+array
+print
+echo
+require
+require_once
+return
+else
+elseif
+default
+break
+continue
+switch
+yield
+function
+if
+endswitch
+finally
+for
+foreach
+declare
+case
+do
+while
+as
+catch
+die
+self
+parent
+
+Done
diff --git a/Zend/tests/grammar/semi_reserved_005.phpt b/Zend/tests/grammar/semi_reserved_005.phpt
new file mode 100644
index 0000000000..3ad0830b09
--- /dev/null
+++ b/Zend/tests/grammar/semi_reserved_005.phpt
@@ -0,0 +1,207 @@
+--TEST--
+Test semi-reserved words as class constants
+--FILE--
+<?php
+
+class Obj
+{
+ const EMPTY = 'empty';
+ const CALLABLE = 'callable';
+ const TRAIT = 'trait';
+ const EXTENDS = 'extends';
+ const IMPLEMENTS = 'implements';
+ const CONST = 'const';
+ const ENDDECLARE = 'enddeclare';
+ const ENDFOR = 'endfor';
+ const ENDFOREACH = 'endforeach';
+ const ENDIF = 'endif';
+ const ENDWHILE = 'endwhile';
+ const AND = 'and';
+ const GLOBAL = 'global';
+ const GOTO = 'goto';
+ const INSTANCEOF = 'instanceof';
+ const INSTEADOF = 'insteadof';
+ const INTERFACE = 'interface';
+ const NAMESPACE = 'namespace';
+ const NEW = 'new';
+ const OR = 'or';
+ const XOR = 'xor';
+ const TRY = 'try';
+ const USE = 'use';
+ const VAR = 'var';
+ const EXIT = 'exit';
+ const LIST = 'list';
+ const CLONE = 'clone';
+ const INCLUDE = 'include';
+ const INCLUDE_ONCE = 'include_once';
+ const THROW = 'throw';
+ const ARRAY = 'array';
+ const PRINT = 'print';
+ const ECHO = 'echo';
+ const REQUIRE = 'require';
+ const REQUIRE_ONCE = 'require_once';
+ const RETURN = 'return';
+ const ELSE = 'else';
+ const ELSEIF = 'elseif';
+ const DEFAULT = 'default';
+ const BREAK = 'break';
+ const CONTINUE = 'continue';
+ const SWITCH = 'switch';
+ const YIELD = 'yield';
+ const FUNCTION = 'function';
+ const IF = 'if';
+ const ENDSWITCH = 'endswitch';
+ const FINALLY = 'finally';
+ const FOR = 'for';
+ const FOREACH = 'foreach';
+ const DECLARE = 'declare';
+ const CASE = 'case';
+ const DO = 'do';
+ const WHILE = 'while';
+ const AS = 'as';
+ const CATCH = 'catch';
+ const DIE = 'die';
+ const SELF = 'self';
+ const PARENT = 'parent';
+ const PUBLIC = 'public';
+ const PROTECTED = 'protected';
+ const PRIVATE = 'private';
+ const STATIC = 'static';
+ const ABSTRACT = 'abstract';
+ const FINAL = 'final';
+}
+
+echo Obj::EMPTY, PHP_EOL;
+echo Obj::CALLABLE, PHP_EOL;
+echo Obj::TRAIT, PHP_EOL;
+echo Obj::EXTENDS, PHP_EOL;
+echo Obj::IMPLEMENTS, PHP_EOL;
+echo Obj::CONST, PHP_EOL;
+echo Obj::ENDDECLARE, PHP_EOL;
+echo Obj::ENDFOR, PHP_EOL;
+echo Obj::ENDFOREACH, PHP_EOL;
+echo Obj::ENDIF, PHP_EOL;
+echo Obj::ENDWHILE, PHP_EOL;
+echo Obj::AND, PHP_EOL;
+echo Obj::GLOBAL, PHP_EOL;
+echo Obj::GOTO, PHP_EOL;
+echo Obj::INSTANCEOF, PHP_EOL;
+echo Obj::INSTEADOF, PHP_EOL;
+echo Obj::INTERFACE, PHP_EOL;
+echo Obj::NAMESPACE, PHP_EOL;
+echo Obj::NEW, PHP_EOL;
+echo Obj::OR, PHP_EOL;
+echo Obj::XOR, PHP_EOL;
+echo Obj::TRY, PHP_EOL;
+echo Obj::USE, PHP_EOL;
+echo Obj::VAR, PHP_EOL;
+echo Obj::EXIT, PHP_EOL;
+echo Obj::LIST, PHP_EOL;
+echo Obj::CLONE, PHP_EOL;
+echo Obj::INCLUDE, PHP_EOL;
+echo Obj::INCLUDE_ONCE, PHP_EOL;
+echo Obj::THROW, PHP_EOL;
+echo Obj::ARRAY, PHP_EOL;
+echo Obj::PRINT, PHP_EOL;
+echo Obj::ECHO, PHP_EOL;
+echo Obj::REQUIRE, PHP_EOL;
+echo Obj::REQUIRE_ONCE, PHP_EOL;
+echo Obj::RETURN, PHP_EOL;
+echo Obj::ELSE, PHP_EOL;
+echo Obj::ELSEIF, PHP_EOL;
+echo Obj::DEFAULT, PHP_EOL;
+echo Obj::BREAK, PHP_EOL;
+echo Obj::CONTINUE, PHP_EOL;
+echo Obj::SWITCH, PHP_EOL;
+echo Obj::YIELD, PHP_EOL;
+echo Obj::FUNCTION, PHP_EOL;
+echo Obj::IF, PHP_EOL;
+echo Obj::ENDSWITCH, PHP_EOL;
+echo Obj::FINALLY, PHP_EOL;
+echo Obj::FOR, PHP_EOL;
+echo Obj::FOREACH, PHP_EOL;
+echo Obj::DECLARE, PHP_EOL;
+echo Obj::CASE, PHP_EOL;
+echo Obj::DO, PHP_EOL;
+echo Obj::WHILE, PHP_EOL;
+echo Obj::AS, PHP_EOL;
+echo Obj::CATCH, PHP_EOL;
+echo Obj::DIE, PHP_EOL;
+echo Obj::SELF, PHP_EOL;
+echo Obj::PARENT, PHP_EOL;
+echo Obj::PUBLIC, PHP_EOL;
+echo Obj::PROTECTED, PHP_EOL;
+echo Obj::PRIVATE, PHP_EOL;
+echo Obj::STATIC, PHP_EOL;
+echo Obj::ABSTRACT, PHP_EOL;
+echo Obj::FINAL, PHP_EOL;
+
+echo "\nDone\n";
+
+--EXPECTF--
+empty
+callable
+trait
+extends
+implements
+const
+enddeclare
+endfor
+endforeach
+endif
+endwhile
+and
+global
+goto
+instanceof
+insteadof
+interface
+namespace
+new
+or
+xor
+try
+use
+var
+exit
+list
+clone
+include
+include_once
+throw
+array
+print
+echo
+require
+require_once
+return
+else
+elseif
+default
+break
+continue
+switch
+yield
+function
+if
+endswitch
+finally
+for
+foreach
+declare
+case
+do
+while
+as
+catch
+die
+self
+parent
+public
+protected
+private
+static
+abstract
+final
+
+Done
diff --git a/Zend/tests/grammar/semi_reserved_006.phpt b/Zend/tests/grammar/semi_reserved_006.phpt
new file mode 100644
index 0000000000..334d09ac36
--- /dev/null
+++ b/Zend/tests/grammar/semi_reserved_006.phpt
@@ -0,0 +1,80 @@
+--TEST--
+Test semi-reserved method and constant names and trait conflict resolution
+--FILE--
+<?php
+
+trait TraitA
+{
+ public function catch(){ echo __METHOD__, PHP_EOL; }
+ private function list(){ echo __METHOD__, PHP_EOL; }
+}
+
+trait TraitB
+{
+ static $list = ['a' => ['b' => ['c']]];
+
+ public static function catch(){ echo __METHOD__, PHP_EOL; }
+ private static function throw(){ echo __METHOD__, PHP_EOL; }
+ private static function self(){ echo __METHOD__, PHP_EOL; }
+}
+
+trait TraitC
+{
+ public static function exit(){ echo __METHOD__, PHP_EOL; }
+ protected static function try(){ echo __METHOD__, PHP_EOL; }
+}
+
+class Foo
+{
+ use TraitA, TraitB {
+ TraitA
+ ::
+ catch insteadof namespace\TraitB;
+ TraitA::list as public foreach;
+ TraitB::throw as public;
+ TraitB::self as public;
+ }
+
+ use TraitC {
+ try as public attempt;
+ exit as die;
+ \TraitC::exit as bye;
+ namespace\TraitC::exit as byebye;
+ TraitC
+ ::
+ exit as farewell;
+ }
+}
+
+(new Foo)->catch();
+(new Foo)->foreach();
+Foo::throw();
+Foo::self();
+var_dump(Foo::$list['a']);
+Foo::attempt();
+Foo::die();
+Foo::bye();
+Foo::byebye();
+Foo::farewell();
+
+echo "\nDone\n";
+
+--EXPECTF--
+TraitA::catch
+TraitA::list
+TraitB::throw
+TraitB::self
+array(1) {
+ ["b"]=>
+ array(1) {
+ [0]=>
+ string(1) "c"
+ }
+}
+TraitC::try
+TraitC::exit
+TraitC::exit
+TraitC::exit
+TraitC::exit
+
+Done
diff --git a/Zend/tests/grammar/semi_reserved_007.phpt b/Zend/tests/grammar/semi_reserved_007.phpt
new file mode 100644
index 0000000000..5105629cbe
--- /dev/null
+++ b/Zend/tests/grammar/semi_reserved_007.phpt
@@ -0,0 +1,37 @@
+--TEST--
+Edge case: self::self, self::parent, parent::self semi reserved constants access
+--FILE--
+<?php
+
+class Foo {
+ const self = "self";
+ const parent = "parent";
+ public function __construct() {
+ echo "From ", __METHOD__, ":", PHP_EOL;
+ echo self::self, PHP_EOL;
+ echo self::parent, PHP_EOL;
+ }
+}
+
+class Bar extends Foo {
+ public function __construct() {
+ parent::__construct();
+ echo "From ", __METHOD__, ":", PHP_EOL;
+ echo parent::self, PHP_EOL;
+ echo parent::parent, PHP_EOL;
+ }
+}
+
+new Bar;
+
+echo "\nDone\n";
+
+--EXPECTF--
+From Foo::__construct:
+self
+parent
+From Bar::__construct:
+self
+parent
+
+Done \ No newline at end of file
diff --git a/Zend/tests/grammar/semi_reserved_008.phpt b/Zend/tests/grammar/semi_reserved_008.phpt
new file mode 100644
index 0000000000..43218b1b05
--- /dev/null
+++ b/Zend/tests/grammar/semi_reserved_008.phpt
@@ -0,0 +1,68 @@
+--TEST--
+Testing with comments around semi-reserved names (not intended to be legible)
+--FILE--
+<?php
+
+trait TraitA
+{
+ public static function list(){ echo __METHOD__, PHP_EOL; }
+ public static function /* comment */ catch(){ echo __METHOD__, PHP_EOL; }
+ private static function // comment
+ throw(){ echo __METHOD__, PHP_EOL; }
+ private static function
+ # comment
+ self(){ echo __METHOD__, PHP_EOL; }
+}
+
+trait TraitB
+{
+ public static function exit(){ echo __METHOD__, PHP_EOL; }
+ protected static function try(){ echo __METHOD__, PHP_EOL; }
+}
+
+class Foo
+{
+ use TraitA {
+ TraitA::
+ //
+ /** doc comment */
+ #
+ catch /* comment */
+ // comment
+ # comment
+ insteadof TraitB;
+
+ TraitA::list as public /**/ foreach;
+ }
+
+ use TraitB {
+ try /*comment*/ as public attempt;
+ exit // comment
+ as/*comment*/die; // non qualified
+ \TraitB::exit as bye; // full qualified
+ namespace\TraitB::exit #
+ as byebye; // even more full qualified
+ TraitB
+ ::
+ /** */
+ exit as farewell; // full qualified with weird spacing
+ }
+}
+
+Foo /**/
+#
+//
+/** */
+::
+/**/
+#
+//
+/** */
+attempt();
+
+echo PHP_EOL, "Done", PHP_EOL;
+
+--EXPECTF--
+TraitB::try
+
+Done
diff --git a/Zend/tests/grammar/semi_reserved_009.phpt b/Zend/tests/grammar/semi_reserved_009.phpt
new file mode 100644
index 0000000000..1a7b0fc371
--- /dev/null
+++ b/Zend/tests/grammar/semi_reserved_009.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Edge case: T_STRING<as> as T_STRING<?>
+--FILE--
+<?php
+
+trait TraitA
+{
+ public static function as(){ echo __METHOD__, PHP_EOL; }
+}
+
+class Foo
+{
+ use TraitA {
+ as as try;
+ }
+}
+
+Foo::try();
+
+echo PHP_EOL, "Done", PHP_EOL;
+
+--EXPECTF--
+TraitA::as
+
+Done
diff --git a/Zend/tests/grammar/semi_reserved_010.phpt b/Zend/tests/grammar/semi_reserved_010.phpt
new file mode 100644
index 0000000000..508a7867a4
--- /dev/null
+++ b/Zend/tests/grammar/semi_reserved_010.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Edge case: T_STRING<insteadof> insteadof T_STRING<?>
+--FILE--
+<?php
+
+trait TraitA
+{
+ public static function insteadof(){ echo __METHOD__, PHP_EOL; }
+}
+
+trait TraitB
+{
+ public static function insteadof(){ echo __METHOD__, PHP_EOL; }
+}
+
+class Foo
+{
+ use TraitA , TraitB {
+ TraitB::insteadof
+ insteadof TraitA;
+ }
+}
+
+Foo::insteadof();
+
+echo PHP_EOL, "Done", PHP_EOL;
+
+--EXPECTF--
+TraitB::insteadof
+
+Done
diff --git a/Zend/tests/loop_free_on_return.phpt b/Zend/tests/loop_free_on_return.phpt
new file mode 100644
index 0000000000..525a50955a
--- /dev/null
+++ b/Zend/tests/loop_free_on_return.phpt
@@ -0,0 +1,16 @@
+--TEST--
+Break out of while loop that is followed by a return statement and inside a foreach loop
+--FILE--
+<?php
+
+$a = [42];
+foreach ($a as $b) {
+ while (1) {
+ break 2;
+ }
+ return;
+}
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/ns_071.phpt b/Zend/tests/ns_071.phpt
index 53ff7f018a..2f2fcfad1a 100644
--- a/Zend/tests/ns_071.phpt
+++ b/Zend/tests/ns_071.phpt
@@ -20,6 +20,6 @@ NULL
Fatal error: Uncaught TypeError: Argument 1 passed to foo\bar::__construct() must be of the type array, object given, called in %s on line %d and defined in %s:%d
Stack trace:
-#0 %s(%d): foo\bar->__construct()
+#0 %s(%d): foo\bar->__construct(Object(stdClass))
#1 {main}
thrown in %s on line %d
diff --git a/Zend/tests/ns_072.phpt b/Zend/tests/ns_072.phpt
index 877095df4a..6375682890 100644
--- a/Zend/tests/ns_072.phpt
+++ b/Zend/tests/ns_072.phpt
@@ -32,6 +32,6 @@ NULL
Fatal error: Uncaught TypeError: Argument 1 passed to foo\bar::__construct() must implement interface foo\foo, instance of stdClass given, called in %s on line %d and defined in %s:%d
Stack trace:
-#0 %s(%d): foo\bar->__construct()
+#0 %s(%d): foo\bar->__construct(Object(stdClass))
#1 {main}
thrown in %s on line %d
diff --git a/Zend/tests/objects_022.phpt b/Zend/tests/objects_022.phpt
index 913de7d990..01f961bae1 100644
--- a/Zend/tests/objects_022.phpt
+++ b/Zend/tests/objects_022.phpt
@@ -38,6 +38,6 @@ object(baz)#%d (0) {
Fatal error: Uncaught TypeError: Argument 1 passed to foo::testFoo() must be an instance of foo, instance of stdClass given, called in %s on line %d and defined in %s:%d
Stack trace:
-#0 %s(%d): foo->testFoo()
+#0 %s(%d): foo->testFoo(Object(stdClass))
#1 {main}
thrown in %s on line %d
diff --git a/Zend/tests/return_types/028.phpt b/Zend/tests/return_types/028.phpt
new file mode 100644
index 0000000000..d2a78ede4a
--- /dev/null
+++ b/Zend/tests/return_types/028.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Memory leak when returning TMP/VAR with wrong return type
+--FILE--
+<?php
+
+function foo(): stdClass {
+ $a = new stdClass;
+ $b = [];
+ return [$a, $b];
+}
+
+try {
+ foo();
+} catch (Error $e) {
+ print $e->getMessage();
+}
+
+?>
+--EXPECTF--
+Return value of foo() must be an instance of stdClass, array returned in %s on line %d
diff --git a/Zend/tests/typehints/explicit_weak_include_strict.phpt b/Zend/tests/typehints/explicit_weak_include_strict.phpt
index 1593c70950..fb53d8ce11 100644
--- a/Zend/tests/typehints/explicit_weak_include_strict.phpt
+++ b/Zend/tests/typehints/explicit_weak_include_strict.phpt
@@ -13,7 +13,7 @@ require 'weak_include_strict_2.inc';
--EXPECTF--
Fatal error: Uncaught TypeError: Argument 1 passed to takes_int() must be of the type integer, float given, called in %sweak_include_strict_2.inc on line 9 and defined in %sweak_include_strict_2.inc:5
Stack trace:
-#0 %s(%d): takes_int()
+#0 %s(%d): takes_int(1)
#1 %s(%d): require('%s')
#2 {main}
thrown in %sweak_include_strict_2.inc on line 5
diff --git a/Zend/tests/typehints/strict_call_weak.phpt b/Zend/tests/typehints/strict_call_weak.phpt
index 8ebed2216b..e3a606ec12 100644
--- a/Zend/tests/typehints/strict_call_weak.phpt
+++ b/Zend/tests/typehints/strict_call_weak.phpt
@@ -15,7 +15,7 @@ function_declared_in_weak_mode(1.0);
--EXPECTF--
Fatal error: Uncaught TypeError: Argument 1 passed to function_declared_in_weak_mode() must be of the type integer, float given, called in %sstrict_call_weak.php on line 10 and defined in %sstrict_call_weak_2.inc:5
Stack trace:
-#0 %s(%d): function_declared_in_weak_mode()
+#0 %s(%d): function_declared_in_weak_mode(1)
#1 {main}
thrown in %sstrict_call_weak_2.inc on line 5
diff --git a/Zend/tests/typehints/strict_call_weak_explicit.phpt b/Zend/tests/typehints/strict_call_weak_explicit.phpt
index 215a0b1fcb..22c5b4319c 100644
--- a/Zend/tests/typehints/strict_call_weak_explicit.phpt
+++ b/Zend/tests/typehints/strict_call_weak_explicit.phpt
@@ -15,7 +15,7 @@ function_declared_in_weak_mode(1.0);
--EXPECTF--
Fatal error: Uncaught TypeError: Argument 1 passed to function_declared_in_weak_mode() must be of the type integer, float given, called in %sstrict_call_weak_explicit.php on line 10 and defined in %sstrict_call_weak_explicit_2.inc:5
Stack trace:
-#0 %s(%d): function_declared_in_weak_mode()
+#0 %s(%d): function_declared_in_weak_mode(1)
#1 {main}
thrown in %sstrict_call_weak_explicit_2.inc on line 5
diff --git a/Zend/tests/typehints/weak_include_strict.phpt b/Zend/tests/typehints/weak_include_strict.phpt
index 5cd1895d66..e49485dbe5 100644
--- a/Zend/tests/typehints/weak_include_strict.phpt
+++ b/Zend/tests/typehints/weak_include_strict.phpt
@@ -13,7 +13,7 @@ require 'weak_include_strict_2.inc';
--EXPECTF--
Fatal error: Uncaught TypeError: Argument 1 passed to takes_int() must be of the type integer, float given, called in %sweak_include_strict_2.inc on line 9 and defined in %sweak_include_strict_2.inc:5
Stack trace:
-#0 %s(%d): takes_int()
+#0 %s(%d): takes_int(1)
#1 %s(%d): require('%s')
#2 {main}
thrown in %sweak_include_strict_2.inc on line 5
diff --git a/Zend/tests/variadic/closure_invoke.phpt b/Zend/tests/variadic/closure_invoke.phpt
new file mode 100644
index 0000000000..6641ff8fb0
--- /dev/null
+++ b/Zend/tests/variadic/closure_invoke.phpt
@@ -0,0 +1,17 @@
+--TEST--
+Closure::__invoke() with variadic parameter
+--FILE--
+<?php
+
+$closure = function(&...$refs) {};
+$closure->__invoke(
+ $v1, $v2, $v3, $v4,
+ $v5, $v6, $v7, $v8,
+ $v9, $v10, $v11, $v12,
+ $v13
+);
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/variadic/typehint_error.phpt b/Zend/tests/variadic/typehint_error.phpt
index 9f9a97bc56..26842bbcc2 100644
--- a/Zend/tests/variadic/typehint_error.phpt
+++ b/Zend/tests/variadic/typehint_error.phpt
@@ -35,6 +35,6 @@ array(3) {
Fatal error: Uncaught TypeError: Argument 3 passed to test() must be of the type array, integer given, called in %s:%d
Stack trace:
-#0 %s(%d): test(Array, Array)
+#0 %s(%d): test(Array, Array, 2)
#1 {main}
thrown in %s on line %d
diff --git a/Zend/zend.c b/Zend/zend.c
index 1c2cfd6c77..7fd6f7fc7b 100644
--- a/Zend/zend.c
+++ b/Zend/zend.c
@@ -727,6 +727,9 @@ int zend_startup(zend_utility_functions *utility_functions, char **extensions) /
ini_scanner_globals_ctor(&ini_scanner_globals);
php_scanner_globals_ctor(&language_scanner_globals);
zend_set_default_compile_time_values();
+#ifdef ZEND_WIN32
+ zend_get_windows_version_info(&EG(windows_version_info));
+#endif
#endif
EG(error_reporting) = E_ALL & ~E_NOTICE;
@@ -798,9 +801,6 @@ void zend_post_startup(void) /* {{{ */
global_persistent_list = &EG(persistent_list);
zend_copy_ini_directives();
#else
-#ifdef ZEND_WIN32
- zend_get_windows_version_info(&EG(windows_version_info));
-#endif
virtual_cwd_deactivate();
#endif
}
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 7f8587ab4f..f49957a7ff 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -476,7 +476,7 @@ ZEND_API int ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest
zval_dtor(arg);
ZVAL_NULL(arg);
if (!zend_make_printable_zval(z, arg)) {
- ZVAL_ZVAL(arg, z, 1, 1);
+ ZVAL_COPY_VALUE(arg, z);
}
*dest = Z_STR_P(arg);
return 1;
@@ -1118,104 +1118,84 @@ ZEND_API void zend_merge_properties(zval *obj, HashTable *properties) /* {{{ */
}
/* }}} */
-static int zval_update_class_constant(zval *pp, int is_static, uint32_t offset) /* {{{ */
-{
- ZVAL_DEREF(pp);
- if (Z_CONSTANT_P(pp)) {
- zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry);
-
- if ((*scope)->parent) {
- zend_class_entry *ce = *scope;
- zend_property_info *prop_info;
-
- do {
- ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
- if (is_static == ((prop_info->flags & ZEND_ACC_STATIC) != 0) &&
- offset == prop_info->offset) {
- int ret;
- zend_class_entry *old_scope = *scope;
- *scope = prop_info->ce;
- ret = zval_update_constant_ex(pp, 1, NULL);
- *scope = old_scope;
- return ret;
- }
- } ZEND_HASH_FOREACH_END();
- ce = ce->parent;
- } while (ce);
-
- }
- return zval_update_constant_ex(pp, 1, NULL);
- }
- return SUCCESS;
-}
-/* }}} */
-
ZEND_API int zend_update_class_constants(zend_class_entry *class_type) /* {{{ */
{
- int i;
-
- /* initialize static members of internal class */
- if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
- zval *p;
+ if (!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED)) {
+ class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
if (class_type->parent) {
if (UNEXPECTED(zend_update_class_constants(class_type->parent) != SUCCESS)) {
return FAILURE;
}
}
+
+ if (!CE_STATIC_MEMBERS(class_type) && class_type->default_static_members_count) {
+ /* initialize static members of internal class */
+ int i;
+ zval *p;
+
#if ZTS
- CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval) * class_type->default_static_members_count);
+ CG(static_members_table)[(zend_intptr_t)(class_type->static_members_table)] = emalloc(sizeof(zval) * class_type->default_static_members_count);
#else
- class_type->static_members_table = emalloc(sizeof(zval) * class_type->default_static_members_count);
+ class_type->static_members_table = emalloc(sizeof(zval) * class_type->default_static_members_count);
#endif
- for (i = 0; i < class_type->default_static_members_count; i++) {
- p = &class_type->default_static_members_table[i];
- if (Z_ISREF_P(p) &&
- class_type->parent &&
- i < class_type->parent->default_static_members_count &&
- p == &class_type->parent->default_static_members_table[i] &&
- Z_TYPE(CE_STATIC_MEMBERS(class_type->parent)[i]) != IS_UNDEF
- ) {
- zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];
-
- ZVAL_NEW_REF(q, q);
- ZVAL_COPY_VALUE(&CE_STATIC_MEMBERS(class_type)[i], q);
- Z_ADDREF_P(q);
- } else {
- ZVAL_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
- }
- }
- }
-
- if ((class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED) == 0) {
- zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry);
- zend_class_entry *old_scope = *scope;
- zval *val;
-
- *scope = class_type;
-
- ZEND_HASH_FOREACH_VAL(&class_type->constants_table, val) {
- if (UNEXPECTED(zval_update_constant_ex(val, 1, class_type) != SUCCESS)) {
- return FAILURE;
+ for (i = 0; i < class_type->default_static_members_count; i++) {
+ p = &class_type->default_static_members_table[i];
+ if (Z_ISREF_P(p) &&
+ class_type->parent &&
+ i < class_type->parent->default_static_members_count &&
+ p == &class_type->parent->default_static_members_table[i] &&
+ Z_TYPE(CE_STATIC_MEMBERS(class_type->parent)[i]) != IS_UNDEF
+ ) {
+ zval *q = &CE_STATIC_MEMBERS(class_type->parent)[i];
+
+ ZVAL_NEW_REF(q, q);
+ ZVAL_COPY_VALUE(&CE_STATIC_MEMBERS(class_type)[i], q);
+ Z_ADDREF_P(q);
+ } else {
+ ZVAL_DUP(&CE_STATIC_MEMBERS(class_type)[i], p);
+ }
}
- } ZEND_HASH_FOREACH_END();
+ } else {
+ zend_class_entry **scope = EG(current_execute_data) ? &EG(scope) : &CG(active_class_entry);
+ zend_class_entry *old_scope = *scope;
+ zend_class_entry *ce;
+ zval *val;
+ zend_property_info *prop_info;
- for (i = 0; i < class_type->default_properties_count; i++) {
- if (Z_TYPE(class_type->default_properties_table[i]) != IS_UNDEF) {
- if (UNEXPECTED(zval_update_class_constant(&class_type->default_properties_table[i], 0, OBJ_PROP_TO_OFFSET(i)) != SUCCESS)) {
- return FAILURE;
+ *scope = class_type;
+ ZEND_HASH_FOREACH_VAL(&class_type->constants_table, val) {
+ ZVAL_DEREF(val);
+ if (Z_CONSTANT_P(val)) {
+ if (UNEXPECTED(zval_update_constant_ex(val, 1, class_type) != SUCCESS)) {
+ return FAILURE;
+ }
}
- }
- }
+ } ZEND_HASH_FOREACH_END();
- for (i = 0; i < class_type->default_static_members_count; i++) {
- if (UNEXPECTED(zval_update_class_constant(&CE_STATIC_MEMBERS(class_type)[i], 1, i) != SUCCESS)) {
- return FAILURE;
+ ce = class_type;
+ while (ce) {
+ ZEND_HASH_FOREACH_PTR(&ce->properties_info, prop_info) {
+ if (prop_info->ce == ce) {
+ if (prop_info->flags & ZEND_ACC_STATIC) {
+ val = CE_STATIC_MEMBERS(class_type) + prop_info->offset;
+ } else {
+ val = (zval*)((char*)class_type->default_properties_table + prop_info->offset - OBJ_PROP_TO_OFFSET(0));
+ }
+ ZVAL_DEREF(val);
+ if (Z_CONSTANT_P(val)) {
+ *scope = ce;
+ if (UNEXPECTED(zval_update_constant_ex(val, 1, NULL) != SUCCESS)) {
+ return FAILURE;
+ }
+ }
+ }
+ } ZEND_HASH_FOREACH_END();
+ ce = ce->parent;
}
- }
- *scope = old_scope;
- class_type->ce_flags |= ZEND_ACC_CONSTANTS_UPDATED;
+ *scope = old_scope;
+ }
}
return SUCCESS;
}
@@ -1313,10 +1293,12 @@ ZEND_API int _object_and_properties_init(zval *arg, zend_class_entry *class_type
return FAILURE;
}
- if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) {
- ZVAL_NULL(arg);
- Z_OBJ_P(arg) = NULL;
- return FAILURE;
+ if (UNEXPECTED(!(class_type->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
+ if (UNEXPECTED(zend_update_class_constants(class_type) != SUCCESS)) {
+ ZVAL_NULL(arg);
+ Z_OBJ_P(arg) = NULL;
+ return FAILURE;
+ }
}
if (class_type->create_object == NULL) {
@@ -3632,13 +3614,16 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
if (ce->type == ZEND_INTERNAL_CLASS) {
property_info = pemalloc(sizeof(zend_property_info), 1);
+ if ((access_type & ZEND_ACC_STATIC) || Z_CONSTANT_P(property)) {
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ }
} else {
property_info = zend_arena_alloc(&CG(arena), sizeof(zend_property_info));
+ if (Z_CONSTANT_P(property)) {
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
+ }
}
- if (Z_CONSTANT_P(property)) {
- ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
- }
if (!(access_type & ZEND_ACC_PPP_MASK)) {
access_type |= ZEND_ACC_PUBLIC;
}
@@ -3680,18 +3665,13 @@ ZEND_API int zend_declare_property_ex(zend_class_entry *ce, zend_string *name, z
break;
}
}
- switch (access_type & ZEND_ACC_PPP_MASK) {
- case ZEND_ACC_PRIVATE: {
- property_info->name = zend_mangle_property_name(ce->name->val, ce->name->len, name->val, name->len, ce->type & ZEND_INTERNAL_CLASS);
- }
- break;
- case ZEND_ACC_PROTECTED: {
- property_info->name = zend_mangle_property_name("*", 1, name->val, name->len, ce->type & ZEND_INTERNAL_CLASS);
- }
- break;
- case ZEND_ACC_PUBLIC:
- property_info->name = zend_string_copy(name);
- break;
+ if (access_type & ZEND_ACC_PUBLIC) {
+ property_info->name = zend_string_copy(name);
+ } else if (access_type & ZEND_ACC_PRIVATE) {
+ property_info->name = zend_mangle_property_name(ce->name->val, ce->name->len, name->val, name->len, ce->type & ZEND_INTERNAL_CLASS);
+ } else {
+ ZEND_ASSERT(access_type & ZEND_ACC_PROTECTED);
+ property_info->name = zend_mangle_property_name("*", 1, name->val, name->len, ce->type & ZEND_INTERNAL_CLASS);
}
property_info->name = zend_new_interned_string(property_info->name);
diff --git a/Zend/zend_API.h b/Zend/zend_API.h
index f61091ae72..83e5265fd4 100644
--- a/Zend/zend_API.h
+++ b/Zend/zend_API.h
@@ -68,9 +68,9 @@ typedef struct _zend_fcall_info_cache {
#define ZEND_FUNCTION(name) ZEND_NAMED_FUNCTION(ZEND_FN(name))
#define ZEND_METHOD(classname, name) ZEND_NAMED_FUNCTION(ZEND_MN(classname##_##name))
-#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },
+#define ZEND_FENTRY(zend_name, name, arg_info, flags) { #zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags },
-#define ZEND_RAW_FENTRY(zend_name, name, arg_info, flags) { zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_arg_info)-1), flags },
+#define ZEND_RAW_FENTRY(zend_name, name, arg_info, flags) { zend_name, name, arg_info, (uint32_t) (sizeof(arg_info)/sizeof(struct _zend_internal_arg_info)-1), flags },
#define ZEND_RAW_NAMED_FE(zend_name, name, arg_info) ZEND_RAW_FENTRY(#zend_name, name, arg_info, 0)
#define ZEND_NAMED_FE(zend_name, name, arg_info) ZEND_FENTRY(zend_name, name, arg_info, 0)
@@ -593,20 +593,17 @@ END_EXTERN_C()
zval *__z = (z); \
zval *__zv = (zv); \
if (EXPECTED(!Z_ISREF_P(__zv))) { \
- ZVAL_COPY_VALUE(__z, __zv); \
- } else { \
- ZVAL_COPY_VALUE(__z, \
- Z_REFVAL_P(__zv)); \
- } \
- if (copy) { \
- zval_opt_copy_ctor(__z); \
- } \
- if (dtor) { \
- if (!copy) { \
- ZVAL_NULL(__zv); \
+ if (copy && !dtor) { \
+ ZVAL_COPY(__z, __zv); \
+ } else { \
+ ZVAL_COPY_VALUE(__z, __zv); \
+ } \
+ } else { \
+ ZVAL_COPY(__z, Z_REFVAL_P(__zv)); \
+ if (dtor || !copy) { \
+ zval_ptr_dtor(__zv); \
} \
- zval_ptr_dtor(__zv); \
- } \
+ } \
} while (0)
#define RETVAL_BOOL(b) ZVAL_BOOL(return_value, b)
@@ -645,18 +642,6 @@ END_EXTERN_C()
#define RETURN_FALSE { RETVAL_FALSE; return; }
#define RETURN_TRUE { RETVAL_TRUE; return; }
-#define RETVAL_ZVAL_FAST(z) do { \
- zval *_z = (z); \
- if (Z_ISREF_P(_z)) { \
- RETVAL_ZVAL(_z, 1, 0); \
- } else { \
- zval_ptr_dtor(return_value); \
- ZVAL_COPY(return_value, _z); \
- } \
-} while (0)
-
-#define RETURN_ZVAL_FAST(z) { RETVAL_ZVAL_FAST(z); return; }
-
#define HASH_OF(p) (Z_TYPE_P(p)==IS_ARRAY ? Z_ARRVAL_P(p) : ((Z_TYPE_P(p)==IS_OBJECT ? Z_OBJ_HT_P(p)->get_properties((p)) : NULL)))
#define ZVAL_IS_NULL(z) (Z_TYPE_P(z) == IS_NULL)
@@ -774,6 +759,8 @@ ZEND_API void ZEND_FASTCALL zend_wrong_callback_error(int severity, int num, cha
#define Z_PARAM_PROLOGUE(separate) \
++_i; \
+ ZEND_ASSERT(_i <= _min_num_args || _optional==1); \
+ ZEND_ASSERT(_i > _min_num_args || _optional==0); \
if (_optional) { \
if (UNEXPECTED(_i >_num_args)) break; \
} \
@@ -1010,7 +997,10 @@ ZEND_API void ZEND_FASTCALL zend_wrong_callback_error(int severity, int num, cha
Z_PARAM_PROLOGUE(separate); \
zend_parse_arg_zval_deref(_arg, &dest, check_null); \
} else { \
- if (UNEXPECTED(++_i >_num_args)) break; \
+ ++_i; \
+ ZEND_ASSERT(_i <= _min_num_args || _optional==1); \
+ ZEND_ASSERT(_i > _min_num_args || _optional==0); \
+ if (_optional && UNEXPECTED(_i >_num_args)) break; \
_real_arg++; \
zend_parse_arg_zval(_real_arg, &dest, check_null); \
}
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index 8f88368bc3..2d47b643c3 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -2048,6 +2048,7 @@ void zend_mm_shutdown(zend_mm_heap *heap, int full, int silent)
#endif
#if ZEND_MM_STAT
heap->real_peak = ZEND_MM_CHUNK_SIZE;
+ heap->size = heap->peak = 0;
#endif
}
}
diff --git a/Zend/zend_ast.c b/Zend/zend_ast.c
index 34a2e132f9..fe78bfd31b 100644
--- a/Zend/zend_ast.c
+++ b/Zend/zend_ast.c
@@ -394,7 +394,12 @@ ZEND_API int zend_ast_evaluate(zval *result, zend_ast *ast, zend_class_entry *sc
zval tmp;
zend_fetch_dimension_by_zval(&tmp, &op1, &op2);
- ZVAL_ZVAL(result, &tmp, 1, 1);
+ if (UNEXPECTED(Z_ISREF(tmp))) {
+ ZVAL_DUP(result, Z_REFVAL(tmp));
+ } else {
+ ZVAL_DUP(result, &tmp);
+ }
+ zval_ptr_dtor(&tmp);
zval_dtor(&op1);
zval_dtor(&op2);
}
@@ -1149,9 +1154,6 @@ simple_list:
case ZEND_AST_CONST:
zend_ast_export_ns_name(str, ast->child[0], 0, indent);
break;
- case ZEND_AST_RESOLVE_CLASS_NAME:
- zend_ast_export_ns_name(str, ast->child[0], 0, indent);
- APPEND_STR("::class");
case ZEND_AST_UNPACK:
smart_str_appends(str, "...");
ast = ast->child[0];
diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h
index 33aa292fb7..2b8d4d37b8 100644
--- a/Zend/zend_ast.h
+++ b/Zend/zend_ast.h
@@ -66,7 +66,6 @@ enum _zend_ast_kind {
/* 1 child node */
ZEND_AST_VAR = 1 << ZEND_AST_NUM_CHILDREN_SHIFT,
ZEND_AST_CONST,
- ZEND_AST_RESOLVE_CLASS_NAME,
ZEND_AST_UNPACK,
ZEND_AST_UNARY_PLUS,
ZEND_AST_UNARY_MINUS,
diff --git a/Zend/zend_builtin_functions.c b/Zend/zend_builtin_functions.c
index 7313b32065..8989e93fa6 100644
--- a/Zend/zend_builtin_functions.c
+++ b/Zend/zend_builtin_functions.c
@@ -459,7 +459,8 @@ ZEND_FUNCTION(func_get_arg)
} else {
arg = ZEND_CALL_ARG(ex, requested_offset + 1);
}
- RETURN_ZVAL_FAST(arg);
+ ZVAL_DEREF(arg);
+ ZVAL_COPY(return_value, arg);
}
/* }}} */
@@ -1105,8 +1106,10 @@ ZEND_FUNCTION(get_class_vars)
RETURN_FALSE;
} else {
array_init(return_value);
- if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
- return;
+ if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
+ if (UNEXPECTED(zend_update_class_constants(ce) != SUCCESS)) {
+ return;
+ }
}
add_class_vars(ce, 0, return_value);
add_class_vars(ce, 1, return_value);
@@ -1684,7 +1687,7 @@ ZEND_FUNCTION(set_error_handler)
}
if (Z_TYPE(EG(user_error_handler)) != IS_UNDEF) {
- RETVAL_ZVAL(&EG(user_error_handler), 1, 0);
+ ZVAL_COPY(return_value, &EG(user_error_handler));
zend_stack_push(&EG(user_error_handlers_error_reporting), &EG(user_error_handler_error_reporting));
zend_stack_push(&EG(user_error_handlers), &EG(user_error_handler));
@@ -1695,7 +1698,7 @@ ZEND_FUNCTION(set_error_handler)
return;
}
- ZVAL_DUP(&EG(user_error_handler), error_handler);
+ ZVAL_COPY(&EG(user_error_handler), error_handler);
EG(user_error_handler_error_reporting) = (int)error_type;
}
/* }}} */
@@ -1752,7 +1755,7 @@ ZEND_FUNCTION(set_exception_handler)
}
if (Z_TYPE(EG(user_exception_handler)) != IS_UNDEF) {
- RETVAL_ZVAL(&EG(user_exception_handler), 1, 0);
+ ZVAL_COPY(return_value, &EG(user_exception_handler));
zend_stack_push(&EG(user_exception_handlers), &EG(user_exception_handler));
}
@@ -1762,7 +1765,7 @@ ZEND_FUNCTION(set_exception_handler)
return;
}
- ZVAL_DUP(&EG(user_exception_handler), exception_handler);
+ ZVAL_COPY(&EG(user_exception_handler), exception_handler);
}
/* }}} */
diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c
index e656f8d6ca..2eeaec639d 100644
--- a/Zend/zend_closures.c
+++ b/Zend/zend_closures.c
@@ -203,6 +203,8 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object) /* {
{
zend_closure *closure = (zend_closure *)object;
zend_function *invoke = (zend_function*)emalloc(sizeof(zend_function));
+ const uint32_t keep_flags =
+ ZEND_ACC_RETURN_REFERENCE | ZEND_ACC_VARIADIC | ZEND_ACC_HAS_RETURN_TYPE;
invoke->common = closure->func.common;
/* We return ZEND_INTERNAL_FUNCTION, but arg_info representation is the
@@ -210,7 +212,8 @@ ZEND_API zend_function *zend_get_closure_invoke_method(zend_object *object) /* {
* This is not a problem, because ZEND_ACC_HAS_TYPE_HINTS is never set,
* and we won't check arguments on internal function */
invoke->type = ZEND_INTERNAL_FUNCTION;
- invoke->internal_function.fn_flags = ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & ZEND_ACC_RETURN_REFERENCE);
+ invoke->internal_function.fn_flags =
+ ZEND_ACC_PUBLIC | ZEND_ACC_CALL_VIA_HANDLER | (closure->func.common.fn_flags & keep_flags);
invoke->internal_function.handler = ZEND_MN(Closure___invoke);
invoke->internal_function.module = 0;
invoke->internal_function.scope = zend_ce_closure;
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 78f8ae3207..bd7b65f1e8 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -102,19 +102,12 @@ static zend_string *zend_build_runtime_definition_key(zend_string *name, unsigne
{
zend_string *result;
char char_pos_buf[32];
- size_t filename_len, char_pos_len = zend_sprintf(char_pos_buf, "%p", lex_pos);
+ size_t char_pos_len = zend_sprintf(char_pos_buf, "%p", lex_pos);
+ zend_string *filename = CG(active_op_array)->filename;
- const char *filename;
- if (CG(active_op_array)->filename) {
- filename = CG(active_op_array)->filename->val;
- filename_len = CG(active_op_array)->filename->len;
- } else {
- filename = "-";
- filename_len = sizeof("-") - 1;
- }
/* NULL, name length, filename length, last accepting char position length */
- result = zend_string_alloc(1 + name->len + filename_len + char_pos_len, 0);
- sprintf(result->val, "%c%s%s%s", '\0', name->val, filename, char_pos_buf);
+ result = zend_string_alloc(1 + name->len + filename->len + char_pos_len, 0);
+ sprintf(result->val, "%c%s%s%s", '\0', name->val, filename->val, char_pos_buf);
return zend_new_interned_string(result);
}
/* }}} */
@@ -179,13 +172,13 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *name) /* {{{ */
}
/* }}} */
-typedef struct _scalar_typehint_info {
+typedef struct _builtin_type_info {
const char* name;
const size_t name_len;
const zend_uchar type;
-} scalar_typehint_info;
+} builtin_type_info;
-static const scalar_typehint_info scalar_typehints[] = {
+static const builtin_type_info builtin_types[] = {
{"int", sizeof("int") - 1, IS_LONG},
{"float", sizeof("float") - 1, IS_DOUBLE},
{"string", sizeof("string") - 1, IS_STRING},
@@ -193,31 +186,20 @@ static const scalar_typehint_info scalar_typehints[] = {
{NULL, 0, IS_UNDEF}
};
-static zend_always_inline const scalar_typehint_info* zend_find_scalar_typehint(const zend_string *name) /* {{{ */
+
+static zend_always_inline zend_uchar zend_lookup_builtin_type_by_name(const zend_string *name) /* {{{ */
{
- const scalar_typehint_info *info = &scalar_typehints[0];
+ const builtin_type_info *info = &builtin_types[0];
for (; info->name; ++info) {
if (name->len == info->name_len
&& zend_binary_strcasecmp(name->val, name->len, info->name, info->name_len) == 0
) {
- return info;
+ return info->type;
}
}
- return NULL;
-}
-/* }}} */
-
-static zend_always_inline zend_uchar zend_lookup_scalar_typehint_by_name(const zend_string *const_name) /* {{{ */
-{
- const scalar_typehint_info *info = zend_find_scalar_typehint(const_name);
-
- if (info) {
- return info->type;
- } else {
- return 0;
- }
+ return 0;
}
/* }}} */
@@ -568,34 +550,44 @@ static int zend_add_const_name_literal(zend_op_array *op_array, zend_string *nam
op.constant = zend_add_literal(CG(active_op_array), &_c); \
} while (0)
-void zend_stop_lexing(void) {
+void zend_stop_lexing(void)
+{
+ if(LANG_SCNG(on_event)) LANG_SCNG(on_event)(ON_STOP, END, 0);
+
LANG_SCNG(yy_cursor) = LANG_SCNG(yy_limit);
}
-static inline void zend_begin_loop(void) /* {{{ */
+static inline void zend_begin_loop(const znode *loop_var) /* {{{ */
{
zend_brk_cont_element *brk_cont_element;
- int parent;
+ int parent = CG(context).current_brk_cont;
- parent = CG(context).current_brk_cont;
CG(context).current_brk_cont = CG(active_op_array)->last_brk_cont;
brk_cont_element = get_next_brk_cont_element(CG(active_op_array));
- brk_cont_element->start = get_next_op_number(CG(active_op_array));
brk_cont_element->parent = parent;
+
+ if (loop_var) {
+ zend_stack_push(&CG(loop_var_stack), loop_var);
+ brk_cont_element->start = get_next_op_number(CG(active_op_array));
+ } else {
+ /* The start field is used to free temporary variables in case of exceptions.
+ * We won't try to free something of we don't have loop variable. */
+ brk_cont_element->start = -1;
+ }
}
/* }}} */
-static inline void zend_end_loop(int cont_addr, int has_loop_var) /* {{{ */
+static inline void zend_end_loop(int cont_addr) /* {{{ */
{
- if (!has_loop_var) {
- /* The start fileld is used to free temporary variables in case of exceptions.
- * We won't try to free something of we don't have loop variable.
- */
- CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].start = -1;
+ zend_brk_cont_element *brk_cont_element
+ = &CG(active_op_array)->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));
+ CG(context).current_brk_cont = brk_cont_element->parent;
+
+ if (brk_cont_element->start >= 0) {
+ zend_stack_del_top(&CG(loop_var_stack));
}
- CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].cont = cont_addr;
- CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].brk = get_next_op_number(CG(active_op_array));
- CG(context).current_brk_cont = CG(active_op_array)->brk_cont_array[CG(context).current_brk_cont].parent;
}
/* }}} */
@@ -863,8 +855,11 @@ zend_string *zend_resolve_class_name(zend_string *name, uint32_t type) /* {{{ */
zend_string *zend_resolve_class_name_ast(zend_ast *ast) /* {{{ */
{
- zend_string *name = zend_ast_get_str(ast);
- return zend_resolve_class_name(name, ast->attr);
+ zval *class_name = zend_ast_get_zval(ast);
+ if (Z_TYPE_P(class_name) != IS_STRING) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Illegal class name");
+ }
+ return zend_resolve_class_name(Z_STR_P(class_name), ast->attr);
}
/* }}} */
@@ -1325,14 +1320,10 @@ static inline zend_bool zend_is_scope_known() /* {{{ */
return 0;
}
- if (!CG(active_op_array)->function_name) {
- /* A file/eval will be run in the including/eval'ing scope */
- return 0;
- }
-
if (!CG(active_class_entry)) {
- /* Not being in a scope is a known scope */
- return 1;
+ /* The scope is known if we're in a free function (no scope), but not if we're in
+ * a file/eval (which inherits including/eval'ing scope). */
+ return CG(active_op_array)->function_name != NULL;
}
/* For traits self etc refers to the using class, not the trait itself */
@@ -1353,6 +1344,88 @@ static inline zend_bool class_name_refers_to_active_ce(zend_string *class_name,
}
/* }}} */
+uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
+{
+ if (zend_string_equals_literal_ci(name, "self")) {
+ return ZEND_FETCH_CLASS_SELF;
+ } else if (zend_string_equals_literal_ci(name, "parent")) {
+ return ZEND_FETCH_CLASS_PARENT;
+ } else if (zend_string_equals_literal_ci(name, "static")) {
+ return ZEND_FETCH_CLASS_STATIC;
+ } else {
+ return ZEND_FETCH_CLASS_DEFAULT;
+ }
+}
+/* }}} */
+
+static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */
+{
+ /* Fully qualified names are always default refs */
+ if (name_ast->attr == ZEND_NAME_FQ) {
+ return ZEND_FETCH_CLASS_DEFAULT;
+ }
+
+ return zend_get_class_fetch_type(zend_ast_get_str(name_ast));
+}
+/* }}} */
+
+static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
+{
+ if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry) && zend_is_scope_known()) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active",
+ fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
+ fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
+ }
+}
+/* }}} */
+
+static zend_bool zend_try_compile_const_expr_resolve_class_name(zval *zv, zend_ast *class_ast, zend_ast *name_ast, zend_bool constant) /* {{{ */
+{
+ uint32_t fetch_type;
+
+ if (name_ast->kind != ZEND_AST_ZVAL) {
+ return 0;
+ }
+
+ if (!zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "class")) {
+ return 0;
+ }
+
+ if (class_ast->kind != ZEND_AST_ZVAL) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Dynamic class names are not allowed in compile-time ::class fetch");
+ }
+
+ fetch_type = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
+ zend_ensure_valid_class_fetch_type(fetch_type);
+
+ switch (fetch_type) {
+ case ZEND_FETCH_CLASS_SELF:
+ if (constant || (CG(active_class_entry) && zend_is_scope_known())) {
+ ZVAL_STR_COPY(zv, CG(active_class_entry)->name);
+ } else {
+ ZVAL_NULL(zv);
+ }
+ return 1;
+ case ZEND_FETCH_CLASS_STATIC:
+ case ZEND_FETCH_CLASS_PARENT:
+ if (constant) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "%s::class cannot be used for compile-time class name resolution",
+ fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
+ );
+ } else {
+ ZVAL_NULL(zv);
+ }
+ return 1;
+ case ZEND_FETCH_CLASS_DEFAULT:
+ ZVAL_STR(zv, zend_resolve_class_name_ast(class_ast));
+ return 1;
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+}
+/* }}} */
+
static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name, zend_string *name) /* {{{ */
{
uint32_t fetch_type = zend_get_class_fetch_type(class_name);
@@ -1385,18 +1458,7 @@ static zend_bool zend_try_ct_eval_class_const(zval *zv, zend_string *class_name,
}
/* }}} */
-void zend_init_list(void *result, void *item) /* {{{ */
-{
- void** list = emalloc(sizeof(void*) * 2);
-
- list[0] = item;
- list[1] = NULL;
-
- *(void**)result = list;
-}
-/* }}} */
-
-void zend_add_to_list(void *result, void *item) /* {{{ */
+static void zend_add_to_list(void *result, void *item) /* {{{ */
{
void** list = *(void**)result;
size_t n = 0;
@@ -1633,41 +1695,6 @@ ZEND_API void zend_initialize_class_data(zend_class_entry *ce, zend_bool nullify
}
/* }}} */
-uint32_t zend_get_class_fetch_type(zend_string *name) /* {{{ */
-{
- if (zend_string_equals_literal_ci(name, "self")) {
- return ZEND_FETCH_CLASS_SELF;
- } else if (zend_string_equals_literal_ci(name, "parent")) {
- return ZEND_FETCH_CLASS_PARENT;
- } else if (zend_string_equals_literal_ci(name, "static")) {
- return ZEND_FETCH_CLASS_STATIC;
- } else {
- return ZEND_FETCH_CLASS_DEFAULT;
- }
-}
-/* }}} */
-
-static uint32_t zend_get_class_fetch_type_ast(zend_ast *name_ast) /* {{{ */
-{
- /* Fully qualified names are always default refs */
- if (name_ast->attr == ZEND_NAME_FQ) {
- return ZEND_FETCH_CLASS_DEFAULT;
- }
-
- return zend_get_class_fetch_type(zend_ast_get_str(name_ast));
-}
-/* }}} */
-
-static void zend_ensure_valid_class_fetch_type(uint32_t fetch_type) /* {{{ */
-{
- if (fetch_type != ZEND_FETCH_CLASS_DEFAULT && !CG(active_class_entry) && zend_is_scope_known()) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot use \"%s\" when no class scope is active",
- fetch_type == ZEND_FETCH_CLASS_SELF ? "self" :
- fetch_type == ZEND_FETCH_CLASS_PARENT ? "parent" : "static");
- }
-}
-/* }}} */
-
ZEND_API zend_string *zend_get_compiled_variable_name(const zend_op_array *op_array, uint32_t var) /* {{{ */
{
return op_array->vars[EX_VAR_TO_NUM(var)];
@@ -2172,14 +2199,6 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint
znode name_node;
zend_op *opline;
- /* there is a chance someone is accessing $this */
- if (ast->kind != ZEND_AST_ZVAL
- && CG(active_op_array)->scope && CG(active_op_array)->this_var == (uint32_t)-1
- ) {
- zend_string *key = zend_string_init("this", sizeof("this") - 1, 0);
- CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), key);
- }
-
zend_compile_expr(&name_node, name_ast);
if (name_node.op_type == IS_CONST) {
convert_to_string(&name_node.u.constant);
@@ -2191,10 +2210,18 @@ static zend_op *zend_compile_simple_var_no_cv(znode *result, zend_ast *ast, uint
opline = zend_emit_op(result, ZEND_FETCH_R, &name_node, NULL);
}
- opline->extended_value = ZEND_FETCH_LOCAL;
- if (name_node.op_type == IS_CONST) {
- if (zend_is_auto_global(Z_STR(name_node.u.constant))) {
- opline->extended_value = ZEND_FETCH_GLOBAL;
+ if (name_node.op_type == IS_CONST &&
+ zend_is_auto_global(Z_STR(name_node.u.constant))) {
+
+ opline->extended_value = ZEND_FETCH_GLOBAL;
+ } else {
+ opline->extended_value = ZEND_FETCH_LOCAL;
+ /* there is a chance someone is accessing $this */
+ if (ast->kind != ZEND_AST_ZVAL
+ && CG(active_op_array)->scope && CG(active_op_array)->this_var == (uint32_t)-1
+ ) {
+ zend_string *key = zend_string_init("this", sizeof("this") - 1, 0);
+ CG(active_op_array)->this_var = lookup_cv(CG(active_op_array), key);
}
}
@@ -2873,7 +2900,13 @@ int zend_compile_func_strlen(znode *result, zend_ast_list *args) /* {{{ */
}
zend_compile_expr(&arg_node, args->child[0]);
- zend_emit_op_tmp(result, ZEND_STRLEN, &arg_node, NULL);
+ if (arg_node.op_type == IS_CONST && Z_TYPE(arg_node.u.constant) == IS_STRING) {
+ result->op_type = IS_CONST;
+ ZVAL_LONG(&result->u.constant, Z_STRLEN(arg_node.u.constant));
+ zval_dtor(&arg_node.u.constant);
+ } else {
+ zend_emit_op_tmp(result, ZEND_STRLEN, &arg_node, NULL);
+ }
return SUCCESS;
}
/* }}} */
@@ -3452,17 +3485,7 @@ void zend_compile_unset(zend_ast *ast) /* {{{ */
static void zend_free_foreach_and_switch_variables(void) /* {{{ */
{
- uint32_t opnum_start, opnum_end, i;
-
- opnum_start = get_next_op_number(CG(active_op_array));
-
zend_stack_apply(&CG(loop_var_stack), ZEND_STACK_APPLY_TOPDOWN, (int (*)(void *element)) generate_free_loop_var);
-
- opnum_end = get_next_op_number(CG(active_op_array));
-
- for (i = opnum_start; i < opnum_end; ++i) {
- CG(active_op_array)->opcodes[i].extended_value |= EXT_TYPE_FREE_ON_RETURN;
- }
}
/* }}} */
@@ -3535,26 +3558,27 @@ void zend_compile_break_continue(zend_ast *ast) /* {{{ */
{
zend_ast *depth_ast = ast->child[0];
- znode depth_node;
zend_op *opline;
+ int depth;
ZEND_ASSERT(ast->kind == ZEND_AST_BREAK || ast->kind == ZEND_AST_CONTINUE);
if (depth_ast) {
+ zval *depth_zv;
if (depth_ast->kind != ZEND_AST_ZVAL) {
zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator with non-constant operand "
"is no longer supported", ast->kind == ZEND_AST_BREAK ? "break" : "continue");
}
- zend_compile_expr(&depth_node, depth_ast);
-
- if (Z_TYPE(depth_node.u.constant) != IS_LONG || Z_LVAL(depth_node.u.constant) < 1) {
+ depth_zv = zend_ast_get_zval(depth_ast);
+ if (Z_TYPE_P(depth_zv) != IS_LONG || Z_LVAL_P(depth_zv) < 1) {
zend_error_noreturn(E_COMPILE_ERROR, "'%s' operator accepts only positive numbers",
ast->kind == ZEND_AST_BREAK ? "break" : "continue");
}
+
+ depth = Z_LVAL_P(depth_zv);
} else {
- depth_node.op_type = IS_CONST;
- ZVAL_LONG(&depth_node.u.constant, 1);
+ depth = 1;
}
if (CG(context).current_brk_cont == -1) {
@@ -3562,20 +3586,27 @@ void zend_compile_break_continue(zend_ast *ast) /* {{{ */
ast->kind == ZEND_AST_BREAK ? "break" : "continue");
} else {
int array_offset = CG(context).current_brk_cont;
- zend_long nest_level = Z_LVAL(depth_node.u.constant);
+ zend_long nest_level = depth;
+ znode *loop_var = zend_stack_top(&CG(loop_var_stack));
do {
if (array_offset == -1) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot '%s' %d level%s",
ast->kind == ZEND_AST_BREAK ? "break" : "continue",
- Z_LVAL(depth_node.u.constant), (Z_LVAL(depth_node.u.constant) == 1) ? "" : "s");
+ depth, depth == 1 ? "" : "s");
}
+
+ if (nest_level > 1 && CG(active_op_array)->brk_cont_array[array_offset].start >= 0) {
+ generate_free_loop_var(loop_var);
+ loop_var--;
+ }
+
array_offset = CG(active_op_array)->brk_cont_array[array_offset].parent;
} while (--nest_level > 0);
}
- opline = zend_emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT,
- NULL, &depth_node);
- opline->op1.opline_num = CG(context).current_brk_cont;
+ opline = zend_emit_op(NULL, ast->kind == ZEND_AST_BREAK ? ZEND_BRK : ZEND_CONT, NULL, NULL);
+ opline->op1.num = CG(context).current_brk_cont;
+ opline->op2.num = depth;
}
/* }}} */
@@ -3620,7 +3651,7 @@ void zend_compile_while(zend_ast *ast) /* {{{ */
opnum_jmp = zend_emit_jump(0);
- zend_begin_loop();
+ zend_begin_loop(NULL);
opnum_start = get_next_op_number(CG(active_op_array));
zend_compile_stmt(stmt_ast);
@@ -3631,7 +3662,7 @@ void zend_compile_while(zend_ast *ast) /* {{{ */
zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
- zend_end_loop(opnum_cond, 0);
+ zend_end_loop(opnum_cond);
}
/* }}} */
@@ -3643,7 +3674,7 @@ void zend_compile_do_while(zend_ast *ast) /* {{{ */
znode cond_node;
uint32_t opnum_start, opnum_cond;
- zend_begin_loop();
+ zend_begin_loop(NULL);
opnum_start = get_next_op_number(CG(active_op_array));
zend_compile_stmt(stmt_ast);
@@ -3653,7 +3684,7 @@ void zend_compile_do_while(zend_ast *ast) /* {{{ */
zend_emit_cond_jump(ZEND_JMPNZ, &cond_node, opnum_start);
- zend_end_loop(opnum_cond, 0);
+ zend_end_loop(opnum_cond);
}
/* }}} */
@@ -3694,7 +3725,7 @@ void zend_compile_for(zend_ast *ast) /* {{{ */
opnum_jmp = zend_emit_jump(0);
- zend_begin_loop();
+ zend_begin_loop(NULL);
opnum_start = get_next_op_number(CG(active_op_array));
zend_compile_stmt(stmt_ast);
@@ -3709,7 +3740,7 @@ void zend_compile_for(zend_ast *ast) /* {{{ */
zend_emit_cond_jump(ZEND_JMPNZ, &result, opnum_start);
- zend_end_loop(opnum_loop, 0);
+ zend_end_loop(opnum_loop);
}
/* }}} */
@@ -3753,9 +3784,6 @@ 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);
- reset_node.flag = 1; /* generate FE_FREE */
- zend_stack_push(&CG(loop_var_stack), &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);
@@ -3779,7 +3807,8 @@ void zend_compile_foreach(zend_ast *ast) /* {{{ */
zend_emit_assign_znode(key_ast, &key_node);
}
- zend_begin_loop();
+ reset_node.flag = 1; /* generate FE_FREE */
+ zend_begin_loop(&reset_node);
zend_compile_stmt(stmt_ast);
@@ -3791,10 +3820,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, 1);
+ zend_end_loop(opnum_fetch);
generate_free_loop_var(&reset_node);
- zend_stack_del_top(&CG(loop_var_stack));
}
/* }}} */
@@ -3855,10 +3883,8 @@ void zend_compile_switch(zend_ast *ast) /* {{{ */
zend_compile_expr(&expr_node, expr_ast);
- expr_node.flag = 0;
- zend_stack_push(&CG(loop_var_stack), &expr_node);
-
- zend_begin_loop();
+ expr_node.flag = 0; /* Generate normal FREE */
+ zend_begin_loop(&expr_node);
case_node.op_type = IS_TMP_VAR;
case_node.u.op.var = get_temporary_variable(CG(active_op_array));
@@ -3917,16 +3943,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)), 1);
+ zend_end_loop(get_next_op_number(CG(active_op_array)));
if (expr_node.op_type == IS_VAR || expr_node.op_type == IS_TMP_VAR) {
- zend_emit_op(NULL, ZEND_FREE,
- &expr_node, NULL);
+ zend_emit_op(NULL, ZEND_FREE, &expr_node, NULL);
} else if (expr_node.op_type == IS_CONST) {
zval_dtor(&expr_node.u.constant);
}
- zend_stack_del_top(&CG(loop_var_stack));
efree(jmpnz_opnums);
}
/* }}} */
@@ -4198,6 +4222,37 @@ ZEND_API void zend_set_function_arg_flags(zend_function *func) /* {{{ */
}
/* }}} */
+
+static void zend_compile_typename(zend_ast *ast, zend_arg_info *arg_info) /* {{{ */
+{
+ if (ast->kind == ZEND_AST_TYPE) {
+ arg_info->type_hint = ast->attr;
+ } else {
+ zend_string *class_name = zend_ast_get_str(ast);
+ zend_uchar type = zend_lookup_builtin_type_by_name(class_name);
+
+ if (type != 0) {
+ arg_info->type_hint = type;
+ } else {
+ uint32_t fetch_type = zend_get_class_fetch_type_ast(ast);
+ if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
+ class_name = zend_resolve_class_name_ast(ast);
+ zend_assert_valid_class_name(class_name);
+ arg_info->lower_class_name = zend_string_tolower(class_name);
+ } else {
+ zend_ensure_valid_class_fetch_type(fetch_type);
+ zend_string_addref(class_name);
+ arg_info->lower_class_name = NULL;
+ }
+
+ arg_info->type_hint = IS_OBJECT;
+ arg_info->class_name = class_name;
+ }
+ }
+}
+/* }}} */
+
+
void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
{
zend_ast_list *list = zend_ast_get_list(ast);
@@ -4215,28 +4270,7 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
arg_infos->allow_null = 0;
arg_infos->class_name = NULL;
- if (return_type_ast->kind == ZEND_AST_TYPE) {
- arg_infos->type_hint = return_type_ast->attr;
- } else {
- zend_string *class_name = zend_ast_get_str(return_type_ast);
- zend_uchar type = zend_lookup_scalar_typehint_by_name(class_name);
-
- if (type != 0) {
- arg_infos->type_hint = type;
- } else {
- uint32_t fetch_type = zend_get_class_fetch_type_ast(return_type_ast);
- if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
- class_name = zend_resolve_class_name_ast(return_type_ast);
- zend_assert_valid_class_name(class_name);
- } else {
- zend_ensure_valid_class_fetch_type(fetch_type);
- zend_string_addref(class_name);
- }
-
- arg_infos->type_hint = IS_OBJECT;
- arg_infos->class_name = class_name;
- }
- }
+ zend_compile_typename(return_type_ast, arg_infos);
arg_infos++;
op_array->fn_flags |= ZEND_ACC_HAS_RETURN_TYPE;
@@ -4327,8 +4361,9 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
op_array->fn_flags |= ZEND_ACC_HAS_TYPE_HINTS;
arg_info->allow_null = has_null_default;
+ zend_compile_typename(type_ast, arg_info);
+
if (type_ast->kind == ZEND_AST_TYPE) {
- arg_info->type_hint = type_ast->attr;
if (arg_info->type_hint == IS_ARRAY) {
if (default_ast && !has_null_default
&& Z_TYPE(default_node.u.constant) != IS_ARRAY
@@ -4344,32 +4379,14 @@ void zend_compile_params(zend_ast *ast, zend_ast *return_type_ast) /* {{{ */
}
}
} else {
- zend_string *class_name = zend_ast_get_str(type_ast);
- zend_uchar type;
-
- type = zend_lookup_scalar_typehint_by_name(class_name);
- if (type != 0) {
- arg_info->type_hint = type;
- } else {
- uint32_t fetch_type = zend_get_class_fetch_type_ast(type_ast);
- if (fetch_type == ZEND_FETCH_CLASS_DEFAULT) {
- class_name = zend_resolve_class_name_ast(type_ast);
- zend_assert_valid_class_name(class_name);
- } else {
- zend_ensure_valid_class_fetch_type(fetch_type);
- zend_string_addref(class_name);
- }
-
- arg_info->type_hint = IS_OBJECT;
- arg_info->class_name = class_name;
- }
if (default_ast && !has_null_default && !Z_CONSTANT(default_node.u.constant)) {
if (arg_info->class_name) {
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
"with a class type hint can only be NULL");
} else if (!ZEND_SAME_FAKE_TYPE(arg_info->type_hint, Z_TYPE(default_node.u.constant))) {
zend_error_noreturn(E_COMPILE_ERROR, "Default value for parameters "
- "with a %s type hint can only be %s or NULL", class_name->val, class_name->val);
+ "with a %s type hint can only be %s or NULL",
+ zend_get_type_by_const(arg_info->type_hint), zend_get_type_by_const(arg_info->type_hint));
}
}
}
@@ -4774,6 +4791,11 @@ void zend_compile_class_const_decl(zend_ast *ast) /* {{{ */
zend_string *name = zend_ast_get_str(name_ast);
zval value_zv;
+ if (zend_string_equals_literal_ci(name, "class")) {
+ zend_error(E_COMPILE_ERROR,
+ "A class constant must not be called 'class'; it is reserved for class name fetching");
+ }
+
zend_const_expr_to_zval(&value_zv, value_ast);
name = zend_new_interned_string_safe(name);
@@ -4953,19 +4975,12 @@ static zend_string *zend_generate_anon_class_name(unsigned char *lex_pos) /* {{{
{
zend_string *result;
char char_pos_buf[32];
- size_t filename_len, char_pos_len = zend_sprintf(char_pos_buf, "%p", lex_pos);
+ size_t char_pos_len = zend_sprintf(char_pos_buf, "%p", lex_pos);
+ zend_string *filename = CG(active_op_array)->filename;
- const char *filename;
- if (CG(active_op_array)->filename) {
- filename = CG(active_op_array)->filename->val;
- filename_len = CG(active_op_array)->filename->len;
- } else {
- filename = "-";
- filename_len = sizeof("-") - 1;
- }
/* NULL, name length, filename length, last accepting char position length */
- result = zend_string_alloc(sizeof("class@anonymous") + filename_len + char_pos_len, 0);
- sprintf(result->val, "class@anonymous%c%s%s", '\0', filename, char_pos_buf);
+ result = zend_string_alloc(sizeof("class@anonymous") + filename->len + char_pos_len, 0);
+ sprintf(result->val, "class@anonymous%c%s%s", '\0', filename->val, char_pos_buf);
return zend_new_interned_string(result);
}
/* }}} */
@@ -4976,8 +4991,7 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
zend_ast *extends_ast = decl->child[0];
zend_ast *implements_ast = decl->child[1];
zend_ast *stmt_ast = decl->child[2];
-
- zend_string *name = decl->name, *lcname, *import_name = NULL;
+ zend_string *name, *lcname, *import_name = NULL;
zend_class_entry *ce = zend_arena_alloc(&CG(arena), sizeof(zend_class_entry));
zend_op *opline;
znode declare_node, extends_node;
@@ -4985,43 +4999,37 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
zend_class_entry *original_ce = CG(active_class_entry);
znode original_implementing_class = FC(implementing_class);
- if (decl->flags & ZEND_ACC_ANON_CLASS) {
- decl->name = name = zend_generate_anon_class_name(decl->lex_pos);
-
- /* Serialization is not supported for anonymous classes */
- ce->serialize = zend_class_serialize_deny;
- ce->unserialize = zend_class_unserialize_deny;
- }
-
- if (CG(active_class_entry) && !(decl->flags & ZEND_ACC_ANON_CLASS)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
- }
-
- zend_assert_valid_class_name(name);
+ if (EXPECTED((decl->flags & ZEND_ACC_ANON_CLASS) == 0)) {
+ if (CG(active_class_entry)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Class declarations may not be nested");
+ }
+ name = decl->name;
+ zend_assert_valid_class_name(name);
+ lcname = zend_string_tolower(name);
+ if (FC(current_namespace)) {
+ name = zend_prefix_with_ns(name);
- lcname = zend_string_tolower(name);
+ zend_string_release(lcname);
+ lcname = zend_string_tolower(name);
+ } else {
+ zend_string_addref(name);
+ }
- if (FC(imports)) {
- import_name = zend_hash_find_ptr(FC(imports), lcname);
- }
+ if (FC(imports)) {
+ import_name = zend_hash_find_ptr(FC(imports), lcname);
+ }
- if (FC(current_namespace)) {
- name = zend_prefix_with_ns(name);
+ if (import_name && !zend_string_equals_ci(lcname, import_name)) {
+ zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s "
+ "because the name is already in use", name->val);
+ }
- zend_string_release(lcname);
- lcname = zend_string_tolower(name);
+ name = zend_new_interned_string(name);
+ lcname = zend_new_interned_string(lcname);
} else {
- zend_string_addref(name);
- }
-
- if (import_name && !zend_string_equals_ci(lcname, import_name)) {
- zend_error_noreturn(E_COMPILE_ERROR, "Cannot declare class %s "
- "because the name is already in use", name->val);
+ lcname = name = zend_generate_anon_class_name(decl->lex_pos);
}
- name = zend_new_interned_string(name);
- lcname = zend_new_interned_string(lcname);
-
ce->type = ZEND_USER_CLASS;
ce->name = name;
zend_initialize_class_data(ce, 1);
@@ -5030,10 +5038,17 @@ void zend_compile_class_decl(zend_ast *ast) /* {{{ */
ce->info.user.filename = zend_get_compiled_filename();
ce->info.user.line_start = decl->start_lineno;
ce->info.user.line_end = decl->end_lineno;
+
if (decl->doc_comment) {
ce->info.user.doc_comment = zend_string_copy(decl->doc_comment);
}
+ if (UNEXPECTED((decl->flags & ZEND_ACC_ANON_CLASS))) {
+ /* Serialization is not supported for anonymous classes */
+ ce->serialize = zend_class_serialize_deny;
+ ce->unserialize = zend_class_unserialize_deny;
+ }
+
if (extends_ast) {
if (!zend_is_const_default_class_ref(extends_ast)) {
zend_string *extends_name = zend_ast_get_str(extends_ast);
@@ -5576,6 +5591,13 @@ static inline void zend_ct_eval_binary_op(zval *result, uint32_t opcode, zval *o
}
/* }}} */
+static inline void zend_ct_eval_unary_op(zval *result, uint32_t opcode, zval *op) /* {{{ */
+{
+ unary_op_type fn = get_unary_op(opcode);
+ fn(result, op);
+}
+/* }}} */
+
static inline void zend_ct_eval_unary_pm(zval *result, zend_ast_kind kind, zval *op) /* {{{ */
{
binary_op_type fn = kind == ZEND_AST_UNARY_PLUS
@@ -5719,6 +5741,15 @@ void zend_compile_binary_op(znode *result, zend_ast *ast) /* {{{ */
}
}
}
+ if (opcode == ZEND_CONCAT) {
+ /* convert constant operands to strings at compile-time */
+ if (left_node.op_type == IS_CONST) {
+ convert_to_string(&left_node.u.constant);
+ }
+ if (right_node.op_type == IS_CONST) {
+ convert_to_string(&right_node.u.constant);
+ }
+ }
zend_emit_op_tmp(result, opcode, &left_node, &right_node);
} while (0);
}
@@ -5760,6 +5791,14 @@ void zend_compile_unary_op(znode *result, zend_ast *ast) /* {{{ */
znode expr_node;
zend_compile_expr(&expr_node, expr_ast);
+ if (expr_node.op_type == IS_CONST) {
+ result->op_type = IS_CONST;
+ zend_ct_eval_unary_op(&result->u.constant, opcode,
+ &expr_node.u.constant);
+ zval_ptr_dtor(&expr_node.u.constant);
+ return;
+ }
+
zend_emit_op_tmp(result, opcode, &expr_node, NULL);
}
/* }}} */
@@ -5801,6 +5840,28 @@ void zend_compile_short_circuiting(znode *result, zend_ast *ast) /* {{{ */
zend_compile_expr(&left_node, left_ast);
+ if (left_node.op_type == IS_CONST) {
+ if ((ast->kind == ZEND_AST_AND && !zend_is_true(&left_node.u.constant))
+ || (ast->kind == ZEND_AST_OR && zend_is_true(&left_node.u.constant))) {
+ result->op_type = IS_CONST;
+ ZVAL_BOOL(&result->u.constant, zend_is_true(&left_node.u.constant));
+ } else {
+ zend_compile_expr(&right_node, right_ast);
+
+ if (right_node.op_type == IS_CONST) {
+ result->op_type = IS_CONST;
+ ZVAL_BOOL(&result->u.constant, zend_is_true(&right_node.u.constant));
+
+ zval_ptr_dtor(&right_node.u.constant);
+ } else {
+ zend_emit_op(result, ZEND_BOOL, &right_node, NULL);
+ }
+ }
+
+ zval_ptr_dtor(&left_node.u.constant);
+ return;
+ }
+
opnum_jmpz = get_next_op_number(CG(active_op_array));
opline_jmpz = zend_emit_op(NULL, ast->kind == ZEND_AST_AND ? ZEND_JMPZ_EX : ZEND_JMPNZ_EX,
&left_node, NULL);
@@ -5811,10 +5872,26 @@ void zend_compile_short_circuiting(znode *result, zend_ast *ast) /* {{{ */
opline_jmpz->result.var = get_temporary_variable(CG(active_op_array));
opline_jmpz->result_type = IS_TMP_VAR;
}
- GET_NODE(result, opline_jmpz->result);
zend_compile_expr(&right_node, right_ast);
+ if (right_node.op_type == IS_CONST && opnum_jmpz == get_next_op_number(CG(active_op_array)) - 1) {
+ if ((ast->kind == ZEND_AST_AND && !zend_is_true(&right_node.u.constant))
+ || (ast->kind == ZEND_AST_OR && zend_is_true(&right_node.u.constant))) {
+ CG(active_op_array)->last--;
+ result->op_type = IS_CONST;
+ ZVAL_BOOL(&result->u.constant, zend_is_true(&right_node.u.constant));
+ } else {
+ opline_jmpz->opcode = ZEND_BOOL;
+ zend_make_var_result(result, opline_jmpz);
+ }
+
+ zval_ptr_dtor(&right_node.u.constant);
+ return;
+ }
+
+ GET_NODE(result, opline_jmpz->result);
+
opline_bool = zend_emit_op(NULL, ZEND_BOOL, &right_node, NULL);
SET_NODE(opline_bool->result, result);
@@ -6340,6 +6417,16 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
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) {
+ zend_op *opline = zend_emit_op_tmp(result, ZEND_FETCH_CLASS_NAME, NULL, NULL);
+ opline->extended_value = zend_get_class_fetch_type(zend_ast_get_str(class_ast));
+ } else {
+ result->op_type = IS_CONST;
+ }
+ return;
+ }
+
zend_eval_const_expr(&class_ast);
zend_eval_const_expr(&const_ast);
@@ -6351,6 +6438,10 @@ void zend_compile_class_const(znode *result, zend_ast *ast) /* {{{ */
return;
}
}
+ 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;
@@ -6563,7 +6654,7 @@ zend_bool zend_is_allowed_in_const_expr(zend_ast_kind kind) /* {{{ */
|| kind == ZEND_AST_CONDITIONAL || kind == ZEND_AST_DIM
|| kind == ZEND_AST_ARRAY || kind == ZEND_AST_ARRAY_ELEM
|| kind == ZEND_AST_CONST || kind == ZEND_AST_CLASS_CONST
- || kind == ZEND_AST_RESOLVE_CLASS_NAME || kind == ZEND_AST_MAGIC_CONST;
+ || kind == ZEND_AST_MAGIC_CONST;
}
/* }}} */
@@ -6582,6 +6673,11 @@ void zend_compile_const_expr_class_const(zend_ast **ast_ptr) /* {{{ */
"Dynamic class names are not allowed in compile-time class constant references");
}
+ if (zend_try_compile_const_expr_resolve_class_name(&result, class_ast, const_ast, 1)) {
+ *ast_ptr = zend_ast_create_zval(&result);
+ return;
+ }
+
class_name = zend_ast_get_str(class_ast);
fetch_type = zend_get_class_fetch_type(class_name);
@@ -6637,36 +6733,6 @@ void zend_compile_const_expr_const(zend_ast **ast_ptr) /* {{{ */
}
/* }}} */
-void zend_compile_const_expr_resolve_class_name(zend_ast **ast_ptr) /* {{{ */
-{
- zend_ast *ast = *ast_ptr;
- zend_ast *name_ast = ast->child[0];
- zval result;
- uint32_t fetch_type = zend_get_class_fetch_type(zend_ast_get_str(name_ast));
- zend_ensure_valid_class_fetch_type(fetch_type);
-
- switch (fetch_type) {
- case ZEND_FETCH_CLASS_SELF:
- ZVAL_STR_COPY(&result, CG(active_class_entry)->name);
- break;
- case ZEND_FETCH_CLASS_STATIC:
- case ZEND_FETCH_CLASS_PARENT:
- zend_error_noreturn(E_COMPILE_ERROR,
- "%s::class cannot be used for compile-time class name resolution",
- fetch_type == ZEND_FETCH_CLASS_STATIC ? "static" : "parent"
- );
- break;
- case ZEND_FETCH_CLASS_DEFAULT:
- ZVAL_STR(&result, zend_resolve_class_name_ast(name_ast));
- break;
- EMPTY_SWITCH_DEFAULT_CASE()
- }
-
- zend_ast_destroy(ast);
- *ast_ptr = zend_ast_create_zval(&result);
-}
-/* }}} */
-
void zend_compile_const_expr_magic_const(zend_ast **ast_ptr) /* {{{ */
{
zend_ast *ast = *ast_ptr;
@@ -6705,9 +6771,6 @@ void zend_compile_const_expr(zend_ast **ast_ptr) /* {{{ */
case ZEND_AST_CONST:
zend_compile_const_expr_const(ast_ptr);
break;
- case ZEND_AST_RESOLVE_CLASS_NAME:
- zend_compile_const_expr_resolve_class_name(ast_ptr);
- break;
case ZEND_AST_MAGIC_CONST:
zend_compile_const_expr_magic_const(ast_ptr);
break;
@@ -6982,9 +7045,6 @@ void zend_compile_expr(znode *result, zend_ast *ast) /* {{{ */
case ZEND_AST_CLASS_CONST:
zend_compile_class_const(result, ast);
return;
- case ZEND_AST_RESOLVE_CLASS_NAME:
- zend_compile_resolve_class_name(result, ast);
- return;
case ZEND_AST_ENCAPS_LIST:
zend_compile_encaps_list(result, ast);
return;
@@ -7154,9 +7214,22 @@ void zend_eval_const_expr(zend_ast **ast_ptr) /* {{{ */
zend_ast *name_ast = ast->child[1];
zend_string *resolved_name;
+ if (zend_try_compile_const_expr_resolve_class_name(&result, class_ast, name_ast, 0)) {
+ if (Z_TYPE(result) == IS_NULL) {
+ return;
+ } else {
+ break;
+ }
+ }
+
zend_eval_const_expr(&class_ast);
zend_eval_const_expr(&name_ast);
+ if (name_ast->kind == ZEND_AST_ZVAL && zend_string_equals_literal_ci(zend_ast_get_str(name_ast), "class")) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Dynamic class names are not allowed in compile-time ::class fetch");
+ }
+
if (class_ast->kind != ZEND_AST_ZVAL || name_ast->kind != ZEND_AST_ZVAL) {
return;
}
diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h
index 2027bfdfd2..eccbb84aff 100644
--- a/Zend/zend_compile.h
+++ b/Zend/zend_compile.h
@@ -183,16 +183,6 @@ typedef struct _zend_try_catch_element {
uint32_t finally_end;
} zend_try_catch_element;
-#if SIZEOF_ZEND_LONG == 8
-# ifdef _WIN32
-# define THIS_HASHVAL 6385726429Ui64
-# else
-# define THIS_HASHVAL 6385726429ULL
-# endif
-#else
-#define THIS_HASHVAL 2090759133UL
-#endif
-
/* method flags (types) */
#define ZEND_ACC_STATIC 0x01
#define ZEND_ACC_ABSTRACT 0x02
@@ -307,6 +297,7 @@ typedef struct _zend_internal_arg_info {
zend_uchar pass_by_reference;
zend_bool allow_null;
zend_bool is_variadic;
+ void *reserved; /* to align with zend_arg_info */
} zend_internal_arg_info;
/* arg_info for user functions */
@@ -317,6 +308,7 @@ typedef struct _zend_arg_info {
zend_uchar pass_by_reference;
zend_bool allow_null;
zend_bool is_variadic;
+ zend_string *lower_class_name;
} zend_arg_info;
/* the following structure repeats the layout of zend_internal_arg_info,
@@ -711,10 +703,6 @@ ZEND_API zend_class_entry *do_bind_class(const zend_op_array *op_array, const ze
ZEND_API zend_class_entry *do_bind_inherited_class(const zend_op_array *op_array, const zend_op *opline, HashTable *class_table, zend_class_entry *parent_ce, zend_bool compile_time);
ZEND_API void zend_do_delayed_early_binding(const zend_op_array *op_array);
-/* Functions for a null terminated pointer list, used for traits parsing and compilation */
-void zend_init_list(void *result, void *item);
-void zend_add_to_list(void *result, void *item);
-
void zend_do_extended_info(void);
void zend_do_extended_fcall_begin(void);
void zend_do_extended_fcall_end(void);
@@ -884,8 +872,6 @@ ZEND_API void zend_assert_valid_class_name(const zend_string *const_name);
#define ZEND_FETCH_ARG_MASK 0x000fffff
-#define EXT_TYPE_FREE_ON_RETURN (1<<2)
-
#define ZEND_MEMBER_FUNC_CALL 1<<0
#define ZEND_ARG_SEND_BY_REF (1<<0)
@@ -961,6 +947,11 @@ static zend_always_inline int zend_check_arg_send_type(const zend_function *zf,
#define ZEND_ARRAY_NOT_PACKED (1<<1)
#define ZEND_ARRAY_SIZE_SHIFT 2
+/* Pseudo-opcodes that are used only temporarily during compilation */
+#define ZEND_BRK 254
+#define ZEND_CONT 255
+
+
END_EXTERN_C()
#define ZEND_CLONE_FUNC_NAME "__clone"
diff --git a/Zend/zend_exceptions.c b/Zend/zend_exceptions.c
index 422c4bb5fd..ae55c1fcea 100644
--- a/Zend/zend_exceptions.c
+++ b/Zend/zend_exceptions.c
@@ -38,7 +38,7 @@ static zend_class_entry *type_error_ce;
static zend_object_handlers default_exception_handlers;
ZEND_API void (*zend_throw_exception_hook)(zval *ex);
-static zend_class_entry *zend_get_exception_base(zval *object)
+static inline zend_class_entry *zend_get_exception_base(zval *object)
{
return instanceof_function(Z_OBJCE_P(object), default_exception_ce) ? default_exception_ce : error_ce;
}
@@ -131,7 +131,7 @@ ZEND_API void zend_throw_exception_internal(zval *exception) /* {{{ */
if (!EG(current_execute_data)->func ||
!ZEND_USER_CODE(EG(current_execute_data)->func->common.type) ||
- (EG(current_execute_data)->opline+1)->opcode == ZEND_HANDLE_EXCEPTION) {
+ EG(current_execute_data)->opline->opcode == ZEND_HANDLE_EXCEPTION) {
/* no need to rethrow the exception */
return;
}
@@ -573,7 +573,7 @@ ZEND_METHOD(exception, getTraceAsString)
object = getThis();
base_ce = zend_get_exception_base(object);
- trace = zend_read_property(base_ce, getThis(), "trace", sizeof("trace")-1, 1, &rv);
+ trace = zend_read_property(base_ce, object, "trace", sizeof("trace")-1, 1, &rv);
if (Z_TYPE_P(trace) != IS_ARRAY) {
RETURN_FALSE;
}
diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c
index d29014d3b2..e63fc2dd32 100644
--- a/Zend/zend_execute.c
+++ b/Zend/zend_execute.c
@@ -57,6 +57,7 @@ typedef int (ZEND_FASTCALL *incdec_t)(zval *);
#define get_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type)
#define get_zval_ptr_ptr_undef(op_type, node, ex, should_free, type) _get_zval_ptr_ptr(op_type, node, ex, should_free, type)
#define get_obj_zval_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr(op_type, node, ex, should_free, type)
+#define get_obj_zval_ptr_undef(op_type, node, ex, should_free, type) _get_obj_zval_ptr_undef(op_type, node, ex, should_free, type)
#define get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type) _get_obj_zval_ptr_ptr(op_type, node, ex, should_free, type)
/* Prototypes */
@@ -516,6 +517,15 @@ static inline zval *_get_obj_zval_ptr(int op_type, znode_op op, zend_execute_dat
return get_zval_ptr(op_type, op, execute_data, should_free, type);
}
+static inline zval *_get_obj_zval_ptr_undef(int op_type, znode_op op, zend_execute_data *execute_data, zend_free_op *should_free, int type)
+{
+ if (op_type == IS_UNUSED) {
+ *should_free = NULL;
+ return &EX(This);
+ }
+ return get_zval_ptr_undef(op_type, op, execute_data, should_free, type);
+}
+
static inline zval *_get_obj_zval_ptr_ptr(int op_type, znode_op node, zend_execute_data *execute_data, zend_free_op *should_free, int type)
{
if (op_type == IS_UNUSED) {
@@ -577,7 +587,12 @@ ZEND_API char * zend_verify_internal_arg_class_kind(const zend_internal_arg_info
ZEND_API char * zend_verify_arg_class_kind(const zend_arg_info *cur_arg_info, char **class_name, zend_class_entry **pce)
{
- *pce = zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
+ /* optimization to not always recalculate the lowercase name and hash */
+ if (cur_arg_info->lower_class_name) {
+ *pce = zend_hash_find_ptr(EG(class_table), cur_arg_info->lower_class_name);
+ } else { /* "extra" fetch type */
+ *pce = zend_fetch_class(cur_arg_info->class_name, (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
+ }
*class_name = (*pce) ? (*pce)->name->val : cur_arg_info->class_name->val;
if (*pce && (*pce)->ce_flags & ZEND_ACC_INTERFACE) {
@@ -593,7 +608,6 @@ ZEND_API void zend_verify_arg_error(const zend_function *zf, uint32_t arg_num, c
const char *fname = zf->common.function_name->val;
const char *fsep;
const char *fclass;
- zval old_arg;
if (zf->common.scope) {
fsep = "::";
@@ -604,11 +618,6 @@ ZEND_API void zend_verify_arg_error(const zend_function *zf, uint32_t arg_num, c
}
if (zf->common.type == ZEND_USER_FUNCTION) {
- if (arg) {
- ZVAL_COPY_VALUE(&old_arg, arg);
- ZVAL_UNDEF(arg);
- }
-
if (ptr && ptr->func && ZEND_USER_CODE(ptr->func->common.type)) {
zend_type_error("Argument %d passed to %s%s%s() must %s%s, %s%s given, called in %s on line %d",
arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind,
@@ -616,10 +625,6 @@ ZEND_API void zend_verify_arg_error(const zend_function *zf, uint32_t arg_num, c
} else {
zend_type_error("Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
}
-
- if (arg) {
- ZVAL_COPY_VALUE(arg, &old_arg);
- }
} else {
zend_type_error("Argument %d passed to %s%s%s() must %s%s, %s%s given", arg_num, fclass, fsep, fname, need_msg, need_kind, given_msg, given_kind);
}
@@ -1246,6 +1251,133 @@ static void zend_assign_to_string_offset(zval *str, zend_long offset, zval *valu
}
}
+static zend_never_inline void zend_post_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc, zval *result)
+{
+ if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
+ zval rv, obj;
+ zval *z;
+ zval z_copy;
+
+ ZVAL_OBJ(&obj, Z_OBJ_P(object));
+ Z_ADDREF(obj);
+ z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
+ if (UNEXPECTED(EG(exception))) {
+ OBJ_RELEASE(Z_OBJ(obj));
+ return;
+ }
+
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
+ zval rv2;
+ zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
+ if (z == &rv) {
+ zval_ptr_dtor(&rv);
+ }
+ ZVAL_COPY_VALUE(z, value);
+ }
+ ZVAL_COPY(result, z);
+ ZVAL_DUP(&z_copy, z);
+ if (inc) {
+ increment_function(&z_copy);
+ } else {
+ decrement_function(&z_copy);
+ }
+ if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
+ Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, cache_slot);
+ OBJ_RELEASE(Z_OBJ(obj));
+ zval_ptr_dtor(&z_copy);
+ zval_ptr_dtor(z);
+ } else {
+ zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
+ ZVAL_NULL(result);
+ }
+}
+
+static zend_never_inline void zend_pre_incdec_overloaded_property(zval *object, zval *property, void **cache_slot, int inc, zval *result)
+{
+ zval rv;
+
+ if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
+ zval *z, obj;
+
+ ZVAL_OBJ(&obj, Z_OBJ_P(object));
+ Z_ADDREF(obj);
+ z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv);
+ if (UNEXPECTED(EG(exception))) {
+ OBJ_RELEASE(Z_OBJ(obj));
+ return;
+ }
+
+ if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
+ zval rv2;
+ zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
+
+ if (z == &rv) {
+ zval_ptr_dtor(&rv);
+ }
+ ZVAL_COPY_VALUE(z, value);
+ }
+ ZVAL_DEREF(z);
+ SEPARATE_ZVAL_NOREF(z);
+ if (inc) {
+ increment_function(z);
+ } else {
+ decrement_function(z);
+ }
+ if (UNEXPECTED(result)) {
+ ZVAL_COPY(result, z);
+ }
+ Z_OBJ_HT(obj)->write_property(&obj, property, z, cache_slot);
+ OBJ_RELEASE(Z_OBJ(obj));
+ zval_ptr_dtor(z);
+ } else {
+ zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
+ if (UNEXPECTED(result)) {
+ ZVAL_NULL(result);
+ }
+ }
+}
+
+static zend_never_inline void zend_assign_op_overloaded_property(zval *object, zval *property, void **cache_slot, zval *value, binary_op_type binary_op, zval *result)
+{
+ zval *z;
+ zval rv, obj;
+ zval *zptr;
+
+ ZVAL_OBJ(&obj, Z_OBJ_P(object));
+ Z_ADDREF(obj);
+ if (Z_OBJ_HT(obj)->read_property &&
+ (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, cache_slot, &rv)) != NULL) {
+ if (UNEXPECTED(EG(exception))) {
+ OBJ_RELEASE(Z_OBJ(obj));
+ return;
+ }
+ if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
+ zval rv2;
+ zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
+
+ if (z == &rv) {
+ zval_ptr_dtor(&rv);
+ }
+ ZVAL_COPY_VALUE(z, value);
+ }
+ zptr = z;
+ ZVAL_DEREF(z);
+ SEPARATE_ZVAL_NOREF(z);
+ binary_op(z, z, value);
+ Z_OBJ_HT(obj)->write_property(&obj, property, z, cache_slot);
+ if (UNEXPECTED(result)) {
+ ZVAL_COPY(result, z);
+ }
+ zval_ptr_dtor(zptr);
+ } else {
+ zend_error(E_WARNING, "Attempt to assign property of non-object");
+ if (UNEXPECTED(result)) {
+ ZVAL_NULL(result);
+ }
+ }
+ OBJ_RELEASE(Z_OBJ(obj));
+}
+
/* Utility Functions for Extensions */
static void zend_extension_statement_handler(const zend_extension *extension, zend_op_array *op_array)
{
@@ -1311,14 +1443,14 @@ num_index:
if (retval == NULL) {
switch (type) {
case BP_VAR_R:
- zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, hval);
+ zend_error(E_NOTICE,"Undefined offset: " ZEND_LONG_FMT, hval);
/* break missing intentionally */
case BP_VAR_UNSET:
case BP_VAR_IS:
retval = &EG(uninitialized_zval);
break;
case BP_VAR_RW:
- zend_error(E_NOTICE,"Undefined offset: " ZEND_ULONG_FMT, hval);
+ zend_error(E_NOTICE,"Undefined offset: " ZEND_LONG_FMT, hval);
/* break missing intentionally */
case BP_VAR_W:
retval = zend_hash_index_add_new(ht, hval, &EG(uninitialized_zval));
@@ -1458,8 +1590,8 @@ static zend_always_inline void zend_fetch_dimension_address(zval *result, zval *
{
zval *retval;
-try_again:
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+try_array:
SEPARATE_ARRAY(container);
fetch_from_array:
if (dim == NULL) {
@@ -1472,7 +1604,14 @@ fetch_from_array:
retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type);
}
ZVAL_INDIRECT(result, retval);
- } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ return;
+ } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto try_array;
+ }
+ }
+ if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
if (type != BP_VAR_UNSET && UNEXPECTED(Z_STRLEN_P(container) == 0)) {
zval_ptr_dtor_nogc(container);
convert_to_array:
@@ -1534,9 +1673,6 @@ convert_to_array:
/* for read-mode only */
ZVAL_NULL(result);
}
- } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
- container = Z_REFVAL_P(container);
- goto try_again;
} else {
if (type == BP_VAR_UNSET) {
zend_error(E_WARNING, "Cannot unset offset in a non-array variable");
@@ -1567,11 +1703,18 @@ static zend_always_inline void zend_fetch_dimension_address_read(zval *result, z
{
zval *retval;
-try_again:
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+try_array:
retval = zend_fetch_dimension_address_inner(Z_ARRVAL_P(container), dim, dim_type, type);
ZVAL_COPY(result, retval);
- } else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ return;
+ } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto try_array;
+ }
+ }
+ if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) {
zend_long offset;
try_string_offset:
@@ -1637,9 +1780,6 @@ try_string_offset:
ZVAL_NULL(result);
}
}
- } else if (EXPECTED(Z_TYPE_P(container) == IS_REFERENCE)) {
- container = Z_REFVAL_P(container);
- goto try_again;
} else {
ZVAL_NULL(result);
}
@@ -1742,21 +1882,17 @@ static inline zend_brk_cont_element* zend_brk_cont(int nest_levels, int array_of
do {
ZEND_ASSERT(array_offset != -1);
jmp_to = &op_array->brk_cont_array[array_offset];
- if (nest_levels>1) {
+ if (nest_levels > 1 && jmp_to->start >= 0) {
zend_op *brk_opline = &op_array->opcodes[jmp_to->brk];
if (brk_opline->opcode == ZEND_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
- }
+ zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
} else if (brk_opline->opcode == ZEND_FE_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval *var = EX_VAR(brk_opline->op1.var);
- 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);
+ zval *var = EX_VAR(brk_opline->op1.var);
+ 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);
}
}
array_offset = jmp_to->parent;
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index 706d913f72..9687a556af 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -176,8 +176,10 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
if (finally_op_num) {
zval *fast_call = ZEND_CALL_VAR(ex, ex->func->op_array.opcodes[finally_op_end].op1.var);
- Z_OBJ_P(fast_call) = NULL;
+ Z_OBJ_P(fast_call) = EG(exception);
+ EG(exception) = NULL;
fast_call->u2.lineno = (uint32_t)-1;
+
ex->opline = &ex->func->op_array.opcodes[finally_op_num];
generator->flags |= ZEND_GENERATOR_FORCED_CLOSE;
zend_generator_resume(generator);
@@ -817,7 +819,10 @@ ZEND_METHOD(Generator, current)
root = zend_generator_get_current(generator);
if (Z_TYPE(root->value) != IS_UNDEF) {
- RETURN_ZVAL_FAST(&root->value);
+ zval *value = &root->value;
+
+ ZVAL_DEREF(value);
+ ZVAL_COPY(return_value, value);
}
}
/* }}} */
@@ -838,7 +843,10 @@ ZEND_METHOD(Generator, key)
root = zend_generator_get_current(generator);
if (Z_TYPE(root->key) != IS_UNDEF) {
- RETURN_ZVAL_FAST(&root->key);
+ zval *key = &root->key;
+
+ ZVAL_DEREF(key);
+ ZVAL_COPY(return_value, key);
}
}
/* }}} */
@@ -892,7 +900,10 @@ ZEND_METHOD(Generator, send)
root = zend_generator_get_current(generator);
if (Z_TYPE(root->value) != IS_UNDEF) {
- RETURN_ZVAL_FAST(&root->value);
+ zval *value = &root->value;
+
+ ZVAL_DEREF(value);
+ ZVAL_COPY(return_value, value);
}
}
/* }}} */
@@ -923,7 +934,10 @@ ZEND_METHOD(Generator, throw)
root = zend_generator_get_current(generator);
if (Z_TYPE(root->value) != IS_UNDEF) {
- RETURN_ZVAL_FAST(&root->value);
+ zval *value = &root->value;
+
+ ZVAL_DEREF(value);
+ ZVAL_COPY(return_value, value);
}
} else {
/* If the generator is already closed throw the exception in the
@@ -1021,7 +1035,10 @@ static void zend_generator_iterator_get_key(zend_object_iterator *iterator, zval
root = zend_generator_get_current(generator);
if (Z_TYPE(root->key) != IS_UNDEF) {
- ZVAL_ZVAL(key, &root->key, 1, 0);
+ zval *zv = &root->key;
+
+ ZVAL_DEREF(zv);
+ ZVAL_COPY(key, zv);
} else {
ZVAL_NULL(key);
}
diff --git a/Zend/zend_globals.h b/Zend/zend_globals.h
index 326955a103..28487a2a4a 100644
--- a/Zend/zend_globals.h
+++ b/Zend/zend_globals.h
@@ -249,6 +249,12 @@ struct _zend_ini_scanner_globals {
int scanner_mode;
};
+typedef enum {
+ ON_TOKEN,
+ ON_FEEDBACK,
+ ON_STOP
+} zend_php_scanner_event;
+
struct _zend_php_scanner_globals {
zend_file_handle *yy_in;
zend_file_handle *yy_out;
@@ -278,6 +284,9 @@ struct _zend_php_scanner_globals {
/* initial string length after scanning to first variable */
int scanned_string_len;
+
+ /* hooks */
+ void (* on_event)(zend_php_scanner_event event, int token, int line);
};
#endif /* ZEND_GLOBALS_H */
diff --git a/Zend/zend_hash.c b/Zend/zend_hash.c
index 75bcb2142d..05426412fe 100644
--- a/Zend/zend_hash.c
+++ b/Zend/zend_hash.c
@@ -28,7 +28,7 @@
# define HT_ASSERT(c) ZEND_ASSERT(c)
#else
# define HT_ASSERT(c)
-#endif
+#endif
#if ZEND_DEBUG
/*
@@ -71,7 +71,7 @@ static void _zend_is_inconsistent(const HashTable *ht, const char *file, int lin
#define HASH_PROTECT_RECURSION(ht) \
if ((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION) { \
- if ((ht)->u.flags >= (3 << 8)) { \
+ if (((ht)->u.flags & ZEND_HASH_APPLY_COUNT_MASK) >= (3 << 8)) { \
zend_error_noreturn(E_ERROR, "Nesting level too deep - recursive dependency?");\
} \
ZEND_HASH_INC_APPLY_COUNT(ht); \
@@ -125,13 +125,13 @@ static void zend_always_inline zend_hash_real_init_ex(HashTable *ht, int packed)
HT_ASSERT(GC_REFCOUNT(ht) == 1);
ZEND_ASSERT(!((ht)->u.flags & HASH_FLAG_INITIALIZED));
if (packed) {
- (ht)->u.flags |= HASH_FLAG_INITIALIZED | HASH_FLAG_PACKED;
HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
+ (ht)->u.flags |= HASH_FLAG_INITIALIZED | HASH_FLAG_PACKED;
HT_HASH_RESET_PACKED(ht);
} else {
- (ht)->u.flags |= HASH_FLAG_INITIALIZED;
(ht)->nTableMask = -(ht)->nTableSize;
HT_SET_DATA_ADDR(ht, pemalloc(HT_SIZE(ht), (ht)->u.flags & HASH_FLAG_PERSISTENT));
+ (ht)->u.flags |= HASH_FLAG_INITIALIZED;
HT_HASH_RESET(ht);
}
}
@@ -219,7 +219,7 @@ ZEND_API void ZEND_FASTCALL zend_hash_to_packed(HashTable *ht)
ZEND_API void ZEND_FASTCALL _zend_hash_init_ex(HashTable *ht, uint32_t nSize, dtor_func_t pDestructor, zend_bool persistent, zend_bool bApplyProtection ZEND_FILE_LINE_DC)
{
- _zend_hash_init(ht, nSize, pDestructor, persistent ZEND_FILE_LINE_CC);
+ _zend_hash_init(ht, nSize, pDestructor, persistent ZEND_FILE_LINE_RELAY_CC);
if (!bApplyProtection) {
ht->u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
}
@@ -567,7 +567,7 @@ ZEND_API zval* ZEND_FASTCALL _zend_hash_add_new(HashTable *ht, zend_string *key,
ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add_or_update(HashTable *ht, const char *str, size_t len, zval *pData, uint32_t flag ZEND_FILE_LINE_DC)
{
zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
- zval *ret = _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_CC);
+ zval *ret = _zend_hash_add_or_update_i(ht, key, pData, flag ZEND_FILE_LINE_RELAY_CC);
zend_string_release(key);
return ret;
}
@@ -575,7 +575,7 @@ ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add_or_update(HashTable *ht, const c
ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
{
zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
- zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_CC);
+ zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE ZEND_FILE_LINE_RELAY_CC);
zend_string_release(key);
return ret;
}
@@ -583,7 +583,7 @@ ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update(HashTable *ht, const char *st
ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update_ind(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
{
zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
- zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_CC);
+ zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_UPDATE | HASH_UPDATE_INDIRECT ZEND_FILE_LINE_RELAY_CC);
zend_string_release(key);
return ret;
}
@@ -591,7 +591,7 @@ ZEND_API zval* ZEND_FASTCALL _zend_hash_str_update_ind(HashTable *ht, const char
ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
{
zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
- zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_CC);
+ zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD ZEND_FILE_LINE_RELAY_CC);
zend_string_release(key);
return ret;
}
@@ -599,14 +599,13 @@ ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add(HashTable *ht, const char *str,
ZEND_API zval* ZEND_FASTCALL _zend_hash_str_add_new(HashTable *ht, const char *str, size_t len, zval *pData ZEND_FILE_LINE_DC)
{
zend_string *key = zend_string_init(str, len, ht->u.flags & HASH_FLAG_PERSISTENT);
- zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_CC);
- zend_string_release(key);
+ zval *ret = _zend_hash_add_or_update_i(ht, key, pData, HASH_ADD_NEW ZEND_FILE_LINE_RELAY_CC);
+ zend_string_delref(key);
return ret;
}
ZEND_API zval* ZEND_FASTCALL zend_hash_index_add_empty_element(HashTable *ht, zend_ulong h)
{
-
zval dummy;
ZVAL_NULL(&dummy);
@@ -615,7 +614,6 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_index_add_empty_element(HashTable *ht, ze
ZEND_API zval* ZEND_FASTCALL zend_hash_add_empty_element(HashTable *ht, zend_string *key)
{
-
zval dummy;
ZVAL_NULL(&dummy);
@@ -624,7 +622,6 @@ ZEND_API zval* ZEND_FASTCALL zend_hash_add_empty_element(HashTable *ht, zend_str
ZEND_API zval* ZEND_FASTCALL zend_hash_str_add_empty_element(HashTable *ht, const char *str, size_t len)
{
-
zval dummy;
ZVAL_NULL(&dummy);
@@ -1698,7 +1695,7 @@ ZEND_API HashTable* ZEND_FASTCALL zend_array_dup(HashTable *source)
target->pDestructor = source->pDestructor;
if (source->nNumUsed == 0) {
- target->u.flags = (source->u.flags & ~(HASH_FLAG_INITIALIZED|HASH_FLAG_PERSISTENT)) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS;
+ target->u.flags = (source->u.flags & ~(HASH_FLAG_INITIALIZED|HASH_FLAG_PACKED|HASH_FLAG_PERSISTENT)) | HASH_FLAG_APPLY_PROTECTION | HASH_FLAG_STATIC_KEYS;
target->nTableMask = HT_MIN_MASK;
target->nNumUsed = 0;
target->nNumOfElements = 0;
diff --git a/Zend/zend_hash.h b/Zend/zend_hash.h
index dcac9c355c..e55ee9e61f 100644
--- a/Zend/zend_hash.h
+++ b/Zend/zend_hash.h
@@ -589,6 +589,15 @@ static zend_always_inline void *zend_hash_index_add_ptr(HashTable *ht, zend_ulon
return zv ? Z_PTR_P(zv) : NULL;
}
+static zend_always_inline void *zend_hash_index_add_new_ptr(HashTable *ht, zend_ulong h, void *pData)
+{
+ zval tmp, *zv;
+
+ ZVAL_PTR(&tmp, pData);
+ zv = zend_hash_index_add_new(ht, h, &tmp);
+ return zv ? Z_PTR_P(zv) : NULL;
+}
+
static zend_always_inline void *zend_hash_index_update_ptr(HashTable *ht, zend_ulong h, void *pData)
{
zval tmp, *zv;
@@ -845,8 +854,9 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht,
#define ZEND_HASH_APPLY_PROTECTION(ht) \
((ht)->u.flags & HASH_FLAG_APPLY_PROTECTION)
-#define ZEND_HASH_APPLY_SHIFT 8
-#define ZEND_HASH_GET_APPLY_COUNT(ht) ((ht)->u.flags >> ZEND_HASH_APPLY_SHIFT)
+#define ZEND_HASH_APPLY_SHIFT 8
+#define ZEND_HASH_APPLY_COUNT_MASK 0xff00
+#define ZEND_HASH_GET_APPLY_COUNT(ht) (((ht)->u.flags & ZEND_HASH_APPLY_COUNT_MASK) >> ZEND_HASH_APPLY_SHIFT)
#define ZEND_HASH_INC_APPLY_COUNT(ht) ((ht)->u.flags += (1 << ZEND_HASH_APPLY_SHIFT))
#define ZEND_HASH_DEC_APPLY_COUNT(ht) ((ht)->u.flags -= (1 << ZEND_HASH_APPLY_SHIFT))
@@ -877,7 +887,7 @@ static zend_always_inline void *zend_hash_get_current_data_ptr_ex(HashTable *ht,
__fill_ht->nInternalPointer = 0; \
} while (0)
-static zend_always_inline void _zend_hash_append(HashTable *ht, zend_string *key, zval *zv)
+static zend_always_inline zval *_zend_hash_append(HashTable *ht, zend_string *key, zval *zv)
{
uint32_t idx = ht->nNumUsed++;
uint32_t nIndex;
@@ -896,9 +906,10 @@ static zend_always_inline void _zend_hash_append(HashTable *ht, zend_string *key
HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
ht->nNumUsed = idx + 1;
ht->nNumOfElements++;
+ return &p->val;
}
-static zend_always_inline void _zend_hash_append_ptr(HashTable *ht, zend_string *key, void *ptr)
+static zend_always_inline zval *_zend_hash_append_ptr(HashTable *ht, zend_string *key, void *ptr)
{
uint32_t idx = ht->nNumUsed++;
uint32_t nIndex;
@@ -917,6 +928,7 @@ static zend_always_inline void _zend_hash_append_ptr(HashTable *ht, zend_string
HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(idx);
ht->nNumUsed = idx + 1;
ht->nNumOfElements++;
+ return &p->val;
}
static zend_always_inline void _zend_hash_append_ind(HashTable *ht, zend_string *key, zval *ptr)
diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c
index f32c55aaef..608af74353 100644
--- a/Zend/zend_inheritance.c
+++ b/Zend/zend_inheritance.c
@@ -1451,7 +1451,7 @@ static void zend_do_traits_property_binding(zend_class_entry *ce) /* {{{ */
* then check whether the property is already there
*/
flags = property_info->flags;
- if ((flags & ZEND_ACC_PPP_MASK) == ZEND_ACC_PUBLIC) {
+ if (flags & ZEND_ACC_PUBLIC) {
prop_name = zend_string_copy(property_info->name);
} else {
const char *pname;
diff --git a/Zend/zend_ini_scanner.c b/Zend/zend_ini_scanner.c
index 990a3733cd..6eb1ff716e 100644
--- a/Zend/zend_ini_scanner.c
+++ b/Zend/zend_ini_scanner.c
@@ -1937,7 +1937,7 @@ end_raw_value_chars:
}
/* Eat leading and trailing double quotes */
- if (yytext[0] == '"' && yytext[yyleng - 1] == '"') {
+ if (yyleng > 1 && yytext[0] == '"' && yytext[yyleng - 1] == '"') {
SCNG(yy_text)++;
yyleng = yyleng - 2;
} else if (sc) {
diff --git a/Zend/zend_ini_scanner.l b/Zend/zend_ini_scanner.l
index c82d79383f..8cc7266ebb 100644
--- a/Zend/zend_ini_scanner.l
+++ b/Zend/zend_ini_scanner.l
@@ -524,7 +524,7 @@ end_raw_value_chars:
}
/* Eat leading and trailing double quotes */
- if (yytext[0] == '"' && yytext[yyleng - 1] == '"') {
+ if (yyleng > 1 && yytext[0] == '"' && yytext[yyleng - 1] == '"') {
SCNG(yy_text)++;
yyleng = yyleng - 2;
} else if (sc) {
diff --git a/Zend/zend_language_parser.y b/Zend/zend_language_parser.y
index 2541c9f571..9612324eac 100644
--- a/Zend/zend_language_parser.y
+++ b/Zend/zend_language_parser.y
@@ -21,20 +21,13 @@
/* $Id$ */
-/*
- * LALR shift/reduce conflicts and how they are resolved:
- *
- * - 2 shift/reduce conflicts due to the dangling elseif/else ambiguity. Solved by shift.
- *
- */
-
-
#include "zend_compile.h"
#include "zend.h"
#include "zend_list.h"
#include "zend_globals.h"
#include "zend_API.h"
#include "zend_constants.h"
+#include "zend_language_scanner.h"
#define YYSIZE_T size_t
#define yytnamerr zend_yytnamerr
@@ -51,7 +44,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%}
%pure_parser
-%expect 2
+%expect 0
%code requires {
}
@@ -87,6 +80,7 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%right T_POW
%right '['
%nonassoc T_NEW T_CLONE
+%left T_NOELSE
%left T_ELSEIF
%left T_ELSE
%left T_ENDIF
@@ -243,8 +237,8 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%type <ast> absolute_trait_method_reference trait_method_reference property echo_expr
%type <ast> new_expr anonymous_class class_name class_name_reference simple_variable
%type <ast> internal_functions_in_yacc
-%type <ast> exit_expr scalar backticks_expr lexical_var function_call member_name
-%type <ast> variable_class_name dereferencable_scalar class_name_scalar constant dereferencable
+%type <ast> exit_expr scalar backticks_expr lexical_var function_call member_name property_name
+%type <ast> variable_class_name dereferencable_scalar constant dereferencable
%type <ast> callable_expr callable_variable static_member new_variable
%type <ast> assignment_list_element array_pair encaps_var encaps_var_offset isset_variables
%type <ast> top_statement_list use_declarations const_list inner_statement_list if_stmt
@@ -252,13 +246,14 @@ static YYSIZE_T zend_yytnamerr(char*, const char*);
%type <ast> echo_expr_list unset_variables catch_list parameter_list class_statement_list
%type <ast> implements_list case_list if_stmt_without_else
%type <ast> non_empty_parameter_list argument_list non_empty_argument_list property_list
-%type <ast> class_const_list name_list trait_adaptations method_body non_empty_for_exprs
+%type <ast> class_const_list class_const_decl name_list trait_adaptations method_body non_empty_for_exprs
%type <ast> ctor_arguments alt_if_stmt_without_else trait_adaptation_list lexical_vars
%type <ast> lexical_var_list encaps_list array_pair_list non_empty_array_pair_list
%type <ast> assignment_list isset_variable type return_type
+%type <ast> identifier
%type <num> returns_ref function is_reference is_variadic variable_modifiers
-%type <num> method_modifiers trait_modifiers non_empty_member_modifiers member_modifier
+%type <num> method_modifiers non_empty_member_modifiers member_modifier
%type <num> class_modifiers class_modifier use_type
%type <str> backup_doc_comment
@@ -269,6 +264,29 @@ start:
top_statement_list { CG(ast) = $1; }
;
+reserved_non_modifiers:
+ T_INCLUDE | T_INCLUDE_ONCE | T_EVAL | T_REQUIRE | T_REQUIRE_ONCE | T_LOGICAL_OR | T_LOGICAL_XOR | T_LOGICAL_AND
+ | T_INSTANCEOF | T_NEW | T_CLONE | T_EXIT | T_IF | T_ELSEIF | T_ELSE | T_ENDIF | T_ECHO | T_DO | T_WHILE | T_ENDWHILE
+ | T_FOR | T_ENDFOR | T_FOREACH | T_ENDFOREACH | T_DECLARE | T_ENDDECLARE | T_AS | T_TRY | T_CATCH | T_FINALLY
+ | T_THROW | T_USE | T_INSTEADOF | T_GLOBAL | T_VAR | T_UNSET | T_ISSET | T_EMPTY | T_CONTINUE | T_GOTO
+ | T_FUNCTION | T_CONST | T_RETURN | T_PRINT | T_YIELD | T_LIST | T_SWITCH | T_ENDSWITCH | T_CASE | T_DEFAULT | T_BREAK
+ | T_ARRAY | T_CALLABLE | T_EXTENDS | T_IMPLEMENTS | T_NAMESPACE | T_TRAIT | T_INTERFACE | T_CLASS
+;
+
+semi_reserved:
+ reserved_non_modifiers
+ | T_STATIC | T_ABSTRACT | T_FINAL | T_PRIVATE | T_PROTECTED | T_PUBLIC
+;
+
+identifier:
+ T_STRING { $$ = $1; }
+ | semi_reserved {
+ zval zv;
+ zend_lex_tstring(&zv);
+ $$ = zend_ast_create_zval(&zv);
+ }
+;
+
top_statement_list:
top_statement_list top_statement { $$ = zend_ast_list_add($1, $2); }
| /* empty */ { $$ = zend_ast_create_list(0, ZEND_AST_STMT_LIST); }
@@ -561,7 +579,7 @@ if_stmt_without_else:
;
if_stmt:
- if_stmt_without_else { $$ = $1; }
+ if_stmt_without_else %prec T_NOELSE { $$ = $1; }
| if_stmt_without_else T_ELSE statement
{ $$ = zend_ast_list_add($1, zend_ast_create(ZEND_AST_IF_ELEM, NULL, $3)); }
;
@@ -673,7 +691,7 @@ class_statement:
{ $$ = $2; RESET_DOC_COMMENT(); }
| T_USE name_list trait_adaptations
{ $$ = zend_ast_create(ZEND_AST_USE_TRAIT, $2, $3); }
- | method_modifiers function returns_ref T_STRING '(' parameter_list ')'
+ | method_modifiers function returns_ref identifier '(' parameter_list ')'
return_type backup_doc_comment method_body
{ $$ = zend_ast_create_decl(ZEND_AST_METHOD, $3 | $1, $2, $9,
zend_ast_get_str($4), $6, NULL, $10, $8); }
@@ -708,28 +726,27 @@ trait_precedence:
;
trait_alias:
- trait_method_reference T_AS trait_modifiers T_STRING
+ trait_method_reference T_AS T_STRING
+ { $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, 0, $1, $3); }
+ | trait_method_reference T_AS reserved_non_modifiers
+ { zval zv; zend_lex_tstring(&zv); $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, 0, $1, zend_ast_create_zval(&zv)); }
+ | trait_method_reference T_AS member_modifier identifier
{ $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, $3, $1, $4); }
- | trait_method_reference T_AS member_modifier
+ | trait_method_reference T_AS member_modifier %prec '+'
{ $$ = zend_ast_create_ex(ZEND_AST_TRAIT_ALIAS, $3, $1, NULL); }
;
trait_method_reference:
- T_STRING
+ identifier
{ $$ = zend_ast_create(ZEND_AST_METHOD_REFERENCE, NULL, $1); }
| absolute_trait_method_reference { $$ = $1; }
;
absolute_trait_method_reference:
- name T_PAAMAYIM_NEKUDOTAYIM T_STRING
+ name T_PAAMAYIM_NEKUDOTAYIM identifier
{ $$ = zend_ast_create(ZEND_AST_METHOD_REFERENCE, $1, $3); }
;
-trait_modifiers:
- /* empty */ { $$ = 0; }
- | member_modifier { $$ = $1; }
-;
-
method_body:
';' /* abstract method */ { $$ = NULL; }
| '{' inner_statement_list '}' { $$ = $2; }
@@ -773,8 +790,12 @@ property:
;
class_const_list:
- class_const_list ',' const_decl { $$ = zend_ast_list_add($1, $3); }
- | const_decl { $$ = zend_ast_create_list(1, ZEND_AST_CLASS_CONST_DECL, $1); }
+ class_const_list ',' class_const_decl { $$ = zend_ast_list_add($1, $3); }
+ | class_const_decl { $$ = zend_ast_create_list(1, ZEND_AST_CLASS_CONST_DECL, $1); }
+;
+
+class_const_decl:
+ identifier '=' expr { $$ = zend_ast_create(ZEND_AST_CONST_ELEM, $1, $3); }
;
const_decl:
@@ -1028,15 +1049,14 @@ scalar:
| '"' encaps_list '"' { $$ = $2; }
| T_START_HEREDOC encaps_list T_END_HEREDOC { $$ = $2; }
| dereferencable_scalar { $$ = $1; }
- | class_name_scalar { $$ = $1; }
| constant { $$ = $1; }
;
constant:
name { $$ = zend_ast_create(ZEND_AST_CONST, $1); }
- | class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING
+ | class_name T_PAAMAYIM_NEKUDOTAYIM identifier
{ $$ = zend_ast_create(ZEND_AST_CLASS_CONST, $1, $3); }
- | variable_class_name T_PAAMAYIM_NEKUDOTAYIM T_STRING
+ | variable_class_name T_PAAMAYIM_NEKUDOTAYIM identifier
{ $$ = zend_ast_create(ZEND_AST_CLASS_CONST, $1, $3); }
;
@@ -1080,7 +1100,7 @@ callable_variable:
{ $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
| dereferencable '{' expr '}'
{ $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
- | dereferencable T_OBJECT_OPERATOR member_name argument_list
+ | dereferencable T_OBJECT_OPERATOR property_name argument_list
{ $$ = zend_ast_create(ZEND_AST_METHOD_CALL, $1, $3, $4); }
| function_call { $$ = $1; }
;
@@ -1090,7 +1110,7 @@ variable:
{ $$ = $1; }
| static_member
{ $$ = $1; }
- | dereferencable T_OBJECT_OPERATOR member_name
+ | dereferencable T_OBJECT_OPERATOR property_name
{ $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); }
;
@@ -1114,7 +1134,7 @@ new_variable:
{ $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
| new_variable '{' expr '}'
{ $$ = zend_ast_create(ZEND_AST_DIM, $1, $3); }
- | new_variable T_OBJECT_OPERATOR member_name
+ | new_variable T_OBJECT_OPERATOR property_name
{ $$ = zend_ast_create(ZEND_AST_PROP, $1, $3); }
| class_name T_PAAMAYIM_NEKUDOTAYIM simple_variable
{ $$ = zend_ast_create(ZEND_AST_STATIC_PROP, $1, $3); }
@@ -1123,7 +1143,13 @@ new_variable:
;
member_name:
- T_STRING { $$ = $1; }
+ identifier { $$ = $1; }
+ | '{' expr '}' { $$ = $2; }
+ | simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
+;
+
+property_name:
+ T_STRING { $$ = $1; }
| '{' expr '}' { $$ = $2; }
| simple_variable { $$ = zend_ast_create(ZEND_AST_VAR, $1); }
;
@@ -1226,11 +1252,6 @@ isset_variable:
expr { $$ = zend_ast_create(ZEND_AST_ISSET, $1); }
;
-class_name_scalar:
- class_name T_PAAMAYIM_NEKUDOTAYIM T_CLASS
- { $$ = zend_ast_create(ZEND_AST_RESOLVE_CLASS_NAME, $1); }
-;
-
%%
/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
diff --git a/Zend/zend_language_scanner.c b/Zend/zend_language_scanner.c
index e3b2de1a79..6813cf4db2 100644
--- a/Zend/zend_language_scanner.c
+++ b/Zend/zend_language_scanner.c
@@ -195,6 +195,7 @@ void shutdown_scanner(void)
zend_stack_destroy(&SCNG(state_stack));
zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1);
zend_ptr_stack_destroy(&SCNG(heredoc_label_stack));
+ SCNG(on_event) = NULL;
}
ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state)
@@ -225,6 +226,8 @@ ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state)
lex_state->output_filter = SCNG(output_filter);
lex_state->script_encoding = SCNG(script_encoding);
+ lex_state->on_event = SCNG(on_event);
+
lex_state->ast = CG(ast);
lex_state->ast_arena = CG(ast_arena);
}
@@ -262,6 +265,8 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state)
SCNG(output_filter) = lex_state->output_filter;
SCNG(script_encoding) = lex_state->script_encoding;
+ SCNG(on_event) = lex_state->on_event;
+
CG(ast) = lex_state->ast;
CG(ast_arena) = lex_state->ast_arena;
@@ -278,6 +283,13 @@ ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle)
}
}
+ZEND_API void zend_lex_tstring(zval *zv)
+{
+ if (SCNG(on_event)) SCNG(on_event)(ON_FEEDBACK, T_STRING, 0);
+
+ ZVAL_STRINGL(zv, (char*)SCNG(yy_text), SCNG(yy_leng));
+}
+
#define BOM_UTF32_BE "\x00\x00\xfe\xff"
#define BOM_UTF32_LE "\xff\xfe\x00\x00"
#define BOM_UTF16_BE "\xfe\xff"
@@ -1085,14 +1097,25 @@ static int zend_scan_escape_string(zval *zendlval, char *str, int len, char quot
return SUCCESS;
}
+static zend_always_inline int emit_token(int token, int token_line)
+{
+ if(SCNG(on_event)) SCNG(on_event)(ON_TOKEN, token, token_line);
+
+ return token;
+}
+
+#define RETURN_TOKEN(token) return emit_token(token, start_line);
int lex_scan(zval *zendlval)
{
+
+int start_line = CG(zend_lineno);
+
restart:
SCNG(yy_text) = YYCURSOR;
-#line 1096 "Zend/zend_language_scanner.c"
+#line 1119 "Zend/zend_language_scanner.c"
{
YYCTYPE yych;
unsigned int yyaccept = 0;
@@ -1146,10 +1169,10 @@ yyc_INITIAL:
yy3:
YYDEBUG(3, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1784 "Zend/zend_language_scanner.l"
+#line 1807 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
inline_char_handler:
@@ -1189,9 +1212,9 @@ inline_char_handler:
ZVAL_STRINGL(zendlval, yytext, yyleng);
}
HANDLE_NEWLINES(yytext, yyleng);
- return T_INLINE_HTML;
+ RETURN_TOKEN(T_INLINE_HTML);
}
-#line 1195 "Zend/zend_language_scanner.c"
+#line 1218 "Zend/zend_language_scanner.c"
yy4:
YYDEBUG(4, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1209,27 +1232,27 @@ yy5:
yy6:
YYDEBUG(6, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1775 "Zend/zend_language_scanner.l"
+#line 1798 "Zend/zend_language_scanner.l"
{
if (CG(short_tags)) {
BEGIN(ST_IN_SCRIPTING);
- return T_OPEN_TAG;
+ RETURN_TOKEN(T_OPEN_TAG);
} else {
goto inline_char_handler;
}
}
-#line 1222 "Zend/zend_language_scanner.c"
+#line 1245 "Zend/zend_language_scanner.c"
yy7:
YYDEBUG(7, *YYCURSOR);
++YYCURSOR;
YYDEBUG(8, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1762 "Zend/zend_language_scanner.l"
+#line 1785 "Zend/zend_language_scanner.l"
{
BEGIN(ST_IN_SCRIPTING);
- return T_OPEN_TAG_WITH_ECHO;
+ RETURN_TOKEN(T_OPEN_TAG_WITH_ECHO);
}
-#line 1233 "Zend/zend_language_scanner.c"
+#line 1256 "Zend/zend_language_scanner.c"
yy9:
YYDEBUG(9, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1260,13 +1283,13 @@ yy13:
yy14:
YYDEBUG(14, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1768 "Zend/zend_language_scanner.l"
+#line 1791 "Zend/zend_language_scanner.l"
{
HANDLE_NEWLINE(yytext[yyleng-1]);
BEGIN(ST_IN_SCRIPTING);
- return T_OPEN_TAG;
+ RETURN_TOKEN(T_OPEN_TAG);
}
-#line 1270 "Zend/zend_language_scanner.c"
+#line 1293 "Zend/zend_language_scanner.c"
yy15:
YYDEBUG(15, *YYCURSOR);
++YYCURSOR;
@@ -1336,10 +1359,10 @@ yyc_ST_BACKQUOTE:
yy19:
YYDEBUG(19, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2198 "Zend/zend_language_scanner.l"
+#line 2221 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
YYCURSOR++;
@@ -1375,11 +1398,11 @@ yy19:
yyleng = YYCURSOR - SCNG(yy_text);
if (zend_scan_escape_string(zendlval, yytext, yyleng, '`') == FAILURE) {
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
-#line 1383 "Zend/zend_language_scanner.c"
+#line 1406 "Zend/zend_language_scanner.c"
yy20:
YYDEBUG(20, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1390,12 +1413,12 @@ yy21:
++YYCURSOR;
YYDEBUG(22, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2140 "Zend/zend_language_scanner.l"
+#line 2163 "Zend/zend_language_scanner.l"
{
BEGIN(ST_IN_SCRIPTING);
- return '`';
+ RETURN_TOKEN('`');
}
-#line 1399 "Zend/zend_language_scanner.c"
+#line 1422 "Zend/zend_language_scanner.c"
yy23:
YYDEBUG(23, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1405,14 +1428,14 @@ yy24:
++YYCURSOR;
YYDEBUG(25, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2127 "Zend/zend_language_scanner.l"
+#line 2150 "Zend/zend_language_scanner.l"
{
Z_LVAL_P(zendlval) = (zend_long) '{';
yy_push_state(ST_IN_SCRIPTING);
yyless(1);
- return T_CURLY_OPEN;
+ RETURN_TOKEN(T_CURLY_OPEN);
}
-#line 1416 "Zend/zend_language_scanner.c"
+#line 1439 "Zend/zend_language_scanner.c"
yy26:
YYDEBUG(26, *YYCURSOR);
yyaccept = 0;
@@ -1428,23 +1451,23 @@ yy26:
yy28:
YYDEBUG(28, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1849 "Zend/zend_language_scanner.l"
+#line 1872 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
-#line 1437 "Zend/zend_language_scanner.c"
+#line 1460 "Zend/zend_language_scanner.c"
yy29:
YYDEBUG(29, *YYCURSOR);
++YYCURSOR;
YYDEBUG(30, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1570 "Zend/zend_language_scanner.l"
+#line 1593 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME);
- return T_DOLLAR_OPEN_CURLY_BRACES;
+ RETURN_TOKEN(T_DOLLAR_OPEN_CURLY_BRACES);
}
-#line 1448 "Zend/zend_language_scanner.c"
+#line 1471 "Zend/zend_language_scanner.c"
yy31:
YYDEBUG(31, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1458,14 +1481,14 @@ yy33:
++YYCURSOR;
YYDEBUG(34, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1842 "Zend/zend_language_scanner.l"
+#line 1865 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
-#line 1469 "Zend/zend_language_scanner.c"
+#line 1492 "Zend/zend_language_scanner.c"
yy35:
YYDEBUG(35, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1483,14 +1506,14 @@ yy36:
++YYCURSOR;
YYDEBUG(37, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1833 "Zend/zend_language_scanner.l"
+#line 1856 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
-#line 1494 "Zend/zend_language_scanner.c"
+#line 1517 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_DOUBLE_QUOTES:
@@ -1558,7 +1581,7 @@ yy40:
yy41:
YYDEBUG(41, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2146 "Zend/zend_language_scanner.l"
+#line 2169 "Zend/zend_language_scanner.l"
{
if (GET_DOUBLE_QUOTES_SCANNED_LENGTH()) {
YYCURSOR += GET_DOUBLE_QUOTES_SCANNED_LENGTH() - 1;
@@ -1568,7 +1591,7 @@ yy41:
}
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
YYCURSOR++;
@@ -1605,11 +1628,11 @@ double_quotes_scan_done:
yyleng = YYCURSOR - SCNG(yy_text);
if (zend_scan_escape_string(zendlval, yytext, yyleng, '"') == FAILURE) {
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
-#line 1613 "Zend/zend_language_scanner.c"
+#line 1636 "Zend/zend_language_scanner.c"
yy42:
YYDEBUG(42, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1620,12 +1643,12 @@ yy43:
++YYCURSOR;
YYDEBUG(44, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2135 "Zend/zend_language_scanner.l"
+#line 2158 "Zend/zend_language_scanner.l"
{
BEGIN(ST_IN_SCRIPTING);
- return '"';
+ RETURN_TOKEN('"');
}
-#line 1629 "Zend/zend_language_scanner.c"
+#line 1652 "Zend/zend_language_scanner.c"
yy45:
YYDEBUG(45, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1635,14 +1658,14 @@ yy46:
++YYCURSOR;
YYDEBUG(47, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2127 "Zend/zend_language_scanner.l"
+#line 2150 "Zend/zend_language_scanner.l"
{
Z_LVAL_P(zendlval) = (zend_long) '{';
yy_push_state(ST_IN_SCRIPTING);
yyless(1);
- return T_CURLY_OPEN;
+ RETURN_TOKEN(T_CURLY_OPEN);
}
-#line 1646 "Zend/zend_language_scanner.c"
+#line 1669 "Zend/zend_language_scanner.c"
yy48:
YYDEBUG(48, *YYCURSOR);
yyaccept = 0;
@@ -1658,23 +1681,23 @@ yy48:
yy50:
YYDEBUG(50, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1849 "Zend/zend_language_scanner.l"
+#line 1872 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
-#line 1667 "Zend/zend_language_scanner.c"
+#line 1690 "Zend/zend_language_scanner.c"
yy51:
YYDEBUG(51, *YYCURSOR);
++YYCURSOR;
YYDEBUG(52, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1570 "Zend/zend_language_scanner.l"
+#line 1593 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME);
- return T_DOLLAR_OPEN_CURLY_BRACES;
+ RETURN_TOKEN(T_DOLLAR_OPEN_CURLY_BRACES);
}
-#line 1678 "Zend/zend_language_scanner.c"
+#line 1701 "Zend/zend_language_scanner.c"
yy53:
YYDEBUG(53, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1688,14 +1711,14 @@ yy55:
++YYCURSOR;
YYDEBUG(56, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1842 "Zend/zend_language_scanner.l"
+#line 1865 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
-#line 1699 "Zend/zend_language_scanner.c"
+#line 1722 "Zend/zend_language_scanner.c"
yy57:
YYDEBUG(57, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1713,14 +1736,14 @@ yy58:
++YYCURSOR;
YYDEBUG(59, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1833 "Zend/zend_language_scanner.l"
+#line 1856 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
-#line 1724 "Zend/zend_language_scanner.c"
+#line 1747 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_END_HEREDOC:
@@ -1731,7 +1754,7 @@ yyc_ST_END_HEREDOC:
++YYCURSOR;
YYDEBUG(63, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2113 "Zend/zend_language_scanner.l"
+#line 2136 "Zend/zend_language_scanner.l"
{
zend_heredoc_label *heredoc_label = zend_ptr_stack_pop(&SCNG(heredoc_label_stack));
@@ -1742,9 +1765,9 @@ yyc_ST_END_HEREDOC:
efree(heredoc_label);
BEGIN(ST_IN_SCRIPTING);
- return T_END_HEREDOC;
+ RETURN_TOKEN(T_END_HEREDOC);
}
-#line 1748 "Zend/zend_language_scanner.c"
+#line 1771 "Zend/zend_language_scanner.c"
/* *********************************** */
yyc_ST_HEREDOC:
{
@@ -1806,14 +1829,14 @@ yy66:
yy67:
YYDEBUG(67, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2242 "Zend/zend_language_scanner.l"
+#line 2265 "Zend/zend_language_scanner.l"
{
int newline = 0;
zend_heredoc_label *heredoc_label = zend_ptr_stack_top(&SCNG(heredoc_label_stack));
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
YYCURSOR--;
@@ -1877,11 +1900,11 @@ heredoc_scan_done:
yyleng = YYCURSOR - SCNG(yy_text);
if (zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0) == FAILURE) {
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
-#line 1885 "Zend/zend_language_scanner.c"
+#line 1908 "Zend/zend_language_scanner.c"
yy68:
YYDEBUG(68, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1896,14 +1919,14 @@ yy70:
++YYCURSOR;
YYDEBUG(71, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2127 "Zend/zend_language_scanner.l"
+#line 2150 "Zend/zend_language_scanner.l"
{
Z_LVAL_P(zendlval) = (zend_long) '{';
yy_push_state(ST_IN_SCRIPTING);
yyless(1);
- return T_CURLY_OPEN;
+ RETURN_TOKEN(T_CURLY_OPEN);
}
-#line 1907 "Zend/zend_language_scanner.c"
+#line 1930 "Zend/zend_language_scanner.c"
yy72:
YYDEBUG(72, *YYCURSOR);
yyaccept = 0;
@@ -1919,23 +1942,23 @@ yy72:
yy74:
YYDEBUG(74, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1849 "Zend/zend_language_scanner.l"
+#line 1872 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
-#line 1928 "Zend/zend_language_scanner.c"
+#line 1951 "Zend/zend_language_scanner.c"
yy75:
YYDEBUG(75, *YYCURSOR);
++YYCURSOR;
YYDEBUG(76, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1570 "Zend/zend_language_scanner.l"
+#line 1593 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_VARNAME);
- return T_DOLLAR_OPEN_CURLY_BRACES;
+ RETURN_TOKEN(T_DOLLAR_OPEN_CURLY_BRACES);
}
-#line 1939 "Zend/zend_language_scanner.c"
+#line 1962 "Zend/zend_language_scanner.c"
yy77:
YYDEBUG(77, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1949,14 +1972,14 @@ yy79:
++YYCURSOR;
YYDEBUG(80, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1842 "Zend/zend_language_scanner.l"
+#line 1865 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
-#line 1960 "Zend/zend_language_scanner.c"
+#line 1983 "Zend/zend_language_scanner.c"
yy81:
YYDEBUG(81, *YYCURSOR);
yych = *++YYCURSOR;
@@ -1974,14 +1997,14 @@ yy82:
++YYCURSOR;
YYDEBUG(83, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1833 "Zend/zend_language_scanner.l"
+#line 1856 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
-#line 1985 "Zend/zend_language_scanner.c"
+#line 2008 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_IN_SCRIPTING:
@@ -2164,12 +2187,12 @@ yy86:
yy87:
YYDEBUG(87, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1872 "Zend/zend_language_scanner.l"
+#line 1895 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, yytext, yyleng);
- return T_STRING;
+ RETURN_TOKEN(T_STRING);
}
-#line 2173 "Zend/zend_language_scanner.c"
+#line 2196 "Zend/zend_language_scanner.c"
yy88:
YYDEBUG(88, *YYCURSOR);
yych = *++YYCURSOR;
@@ -2401,11 +2424,11 @@ yy101:
yy102:
YYDEBUG(102, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1559 "Zend/zend_language_scanner.l"
+#line 1582 "Zend/zend_language_scanner.l"
{
- return yytext[0];
+ RETURN_TOKEN(yytext[0]);
}
-#line 2409 "Zend/zend_language_scanner.c"
+#line 2432 "Zend/zend_language_scanner.c"
yy103:
YYDEBUG(103, *YYCURSOR);
++YYCURSOR;
@@ -2414,12 +2437,12 @@ yy103:
yy104:
YYDEBUG(104, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1274 "Zend/zend_language_scanner.l"
+#line 1297 "Zend/zend_language_scanner.l"
{
HANDLE_NEWLINES(yytext, yyleng);
- return T_WHITESPACE;
+ RETURN_TOKEN(T_WHITESPACE);
}
-#line 2423 "Zend/zend_language_scanner.c"
+#line 2446 "Zend/zend_language_scanner.c"
yy105:
YYDEBUG(105, *YYCURSOR);
yych = *++YYCURSOR;
@@ -2430,11 +2453,11 @@ yy106:
++YYCURSOR;
YYDEBUG(107, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1299 "Zend/zend_language_scanner.l"
+#line 1322 "Zend/zend_language_scanner.l"
{
- return T_NS_SEPARATOR;
+ RETURN_TOKEN(T_NS_SEPARATOR);
}
-#line 2438 "Zend/zend_language_scanner.c"
+#line 2461 "Zend/zend_language_scanner.c"
yy108:
YYDEBUG(108, *YYCURSOR);
yyaccept = 1;
@@ -2663,26 +2686,26 @@ yy131:
++YYCURSOR;
YYDEBUG(132, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1564 "Zend/zend_language_scanner.l"
+#line 1587 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_IN_SCRIPTING);
- return '{';
+ RETURN_TOKEN('{');
}
-#line 2672 "Zend/zend_language_scanner.c"
+#line 2695 "Zend/zend_language_scanner.c"
yy133:
YYDEBUG(133, *YYCURSOR);
++YYCURSOR;
YYDEBUG(134, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1576 "Zend/zend_language_scanner.l"
+#line 1599 "Zend/zend_language_scanner.l"
{
RESET_DOC_COMMENT();
if (!zend_stack_is_empty(&SCNG(state_stack))) {
yy_pop_state();
}
- return '}';
+ RETURN_TOKEN('}');
}
-#line 2686 "Zend/zend_language_scanner.c"
+#line 2709 "Zend/zend_language_scanner.c"
yy135:
YYDEBUG(135, *YYCURSOR);
yyaccept = 2;
@@ -2710,7 +2733,7 @@ yy135:
yy136:
YYDEBUG(136, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1629 "Zend/zend_language_scanner.l"
+#line 1652 "Zend/zend_language_scanner.l"
{
char *end;
if (yyleng < MAX_LENGTH_OF_LONG - 1) { /* Won't overflow */
@@ -2721,7 +2744,7 @@ yy136:
*/
if (end != yytext + yyleng) {
zend_throw_exception(zend_get_parse_error(), "Invalid numeric literal", E_PARSE);
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
} else {
errno = 0;
@@ -2738,21 +2761,21 @@ yy136:
if (end != yytext + yyleng) {
zend_throw_exception(zend_get_parse_error(),
"Invalid numeric literal", E_PARSE);
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
ZEND_ASSERT(!errno);
- return T_DNUMBER;
+ RETURN_TOKEN(T_DNUMBER);
}
/* Also not an assert for the same reason */
if (end != yytext + yyleng) {
zend_throw_exception(zend_get_parse_error(), "Invalid numeric literal", E_PARSE);
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
}
ZEND_ASSERT(!errno);
- return T_LNUMBER;
+ RETURN_TOKEN(T_LNUMBER);
}
-#line 2756 "Zend/zend_language_scanner.c"
+#line 2779 "Zend/zend_language_scanner.c"
yy137:
YYDEBUG(137, *YYCURSOR);
yyaccept = 2;
@@ -2780,7 +2803,7 @@ yy139:
yy140:
YYDEBUG(140, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1878 "Zend/zend_language_scanner.l"
+#line 1901 "Zend/zend_language_scanner.l"
{
while (YYCURSOR < YYLIMIT) {
switch (*YYCURSOR++) {
@@ -2807,16 +2830,16 @@ yy140:
yyleng = YYCURSOR - SCNG(yy_text);
- return T_COMMENT;
+ RETURN_TOKEN(T_COMMENT);
}
-#line 2813 "Zend/zend_language_scanner.c"
+#line 2836 "Zend/zend_language_scanner.c"
yy141:
YYDEBUG(141, *YYCURSOR);
++YYCURSOR;
yy142:
YYDEBUG(142, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1946 "Zend/zend_language_scanner.l"
+#line 1969 "Zend/zend_language_scanner.l"
{
register char *s, *t;
char *end;
@@ -2839,7 +2862,7 @@ yy142:
* for ' (unrecognized by parser), instead of old flex fallback to "Unexpected character..."
* rule, which continued in ST_IN_SCRIPTING state after the quote */
ZVAL_NULL(zendlval);
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
}
@@ -2882,16 +2905,16 @@ yy142:
SCNG(output_filter)((unsigned char **)&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval));
ZVAL_STRINGL(zendlval, str, sz);
}
- return T_CONSTANT_ENCAPSED_STRING;
+ RETURN_TOKEN(T_CONSTANT_ENCAPSED_STRING);
}
-#line 2888 "Zend/zend_language_scanner.c"
+#line 2911 "Zend/zend_language_scanner.c"
yy143:
YYDEBUG(143, *YYCURSOR);
++YYCURSOR;
yy144:
YYDEBUG(144, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2015 "Zend/zend_language_scanner.l"
+#line 2038 "Zend/zend_language_scanner.l"
{
int bprefix = (yytext[0] != '"') ? 1 : 0;
@@ -2900,9 +2923,9 @@ yy144:
case '"':
yyleng = YYCURSOR - SCNG(yy_text);
if (zend_scan_escape_string(zendlval, yytext+bprefix+1, yyleng-bprefix-2, '"') == FAILURE) {
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
- return T_CONSTANT_ENCAPSED_STRING;
+ RETURN_TOKEN(T_CONSTANT_ENCAPSED_STRING);
case '$':
if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
break;
@@ -2932,35 +2955,35 @@ yy144:
YYCURSOR = SCNG(yy_text) + yyleng;
BEGIN(ST_DOUBLE_QUOTES);
- return '"';
+ RETURN_TOKEN('"');
}
-#line 2938 "Zend/zend_language_scanner.c"
+#line 2961 "Zend/zend_language_scanner.c"
yy145:
YYDEBUG(145, *YYCURSOR);
++YYCURSOR;
YYDEBUG(146, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2107 "Zend/zend_language_scanner.l"
+#line 2130 "Zend/zend_language_scanner.l"
{
BEGIN(ST_BACKQUOTE);
- return '`';
+ RETURN_TOKEN('`');
}
-#line 2949 "Zend/zend_language_scanner.c"
+#line 2972 "Zend/zend_language_scanner.c"
yy147:
YYDEBUG(147, *YYCURSOR);
++YYCURSOR;
YYDEBUG(148, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2375 "Zend/zend_language_scanner.l"
+#line 2398 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
goto restart;
}
-#line 2964 "Zend/zend_language_scanner.c"
+#line 2987 "Zend/zend_language_scanner.c"
yy149:
YYDEBUG(149, *YYCURSOR);
++YYCURSOR;
@@ -2987,16 +3010,16 @@ yy151:
yy153:
YYDEBUG(153, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1720 "Zend/zend_language_scanner.l"
+#line 1743 "Zend/zend_language_scanner.l"
{
const char *end;
ZVAL_DOUBLE(zendlval, zend_strtod(yytext, &end));
/* errno isn't checked since we allow HUGE_VAL/INF overflow */
ZEND_ASSERT(end == yytext + yyleng);
- return T_DNUMBER;
+ RETURN_TOKEN(T_DNUMBER);
}
-#line 3000 "Zend/zend_language_scanner.c"
+#line 3023 "Zend/zend_language_scanner.c"
yy154:
YYDEBUG(154, *YYCURSOR);
yyaccept = 2;
@@ -3092,7 +3115,7 @@ yy163:
}
YYDEBUG(165, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1601 "Zend/zend_language_scanner.l"
+#line 1624 "Zend/zend_language_scanner.l"
{
char *bin = yytext + 2; /* Skip "0b" */
int len = yyleng - 2;
@@ -3112,15 +3135,15 @@ yy163:
ZVAL_LONG(zendlval, ZEND_STRTOL(bin, &end, 2));
ZEND_ASSERT(!errno && end == yytext + yyleng);
}
- return T_LNUMBER;
+ RETURN_TOKEN(T_LNUMBER);
} else {
ZVAL_DOUBLE(zendlval, zend_bin_strtod(bin, (const char **)&end));
/* errno isn't checked since we allow HUGE_VAL/INF overflow */
ZEND_ASSERT(end == yytext + yyleng);
- return T_DNUMBER;
+ RETURN_TOKEN(T_DNUMBER);
}
}
-#line 3124 "Zend/zend_language_scanner.c"
+#line 3147 "Zend/zend_language_scanner.c"
yy166:
YYDEBUG(166, *YYCURSOR);
++YYCURSOR;
@@ -3132,7 +3155,7 @@ yy166:
}
YYDEBUG(168, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1671 "Zend/zend_language_scanner.l"
+#line 1694 "Zend/zend_language_scanner.l"
{
char *hex = yytext + 2; /* Skip "0x" */
int len = yyleng - 2;
@@ -3152,15 +3175,15 @@ yy166:
ZVAL_LONG(zendlval, ZEND_STRTOL(hex, &end, 16));
ZEND_ASSERT(!errno && end == hex + len);
}
- return T_LNUMBER;
+ RETURN_TOKEN(T_LNUMBER);
} else {
ZVAL_DOUBLE(zendlval, zend_hex_strtod(hex, (const char **)&end));
/* errno isn't checked since we allow HUGE_VAL/INF overflow */
ZEND_ASSERT(end == hex + len);
- return T_DNUMBER;
+ RETURN_TOKEN(T_DNUMBER);
}
}
-#line 3164 "Zend/zend_language_scanner.c"
+#line 3187 "Zend/zend_language_scanner.c"
yy169:
YYDEBUG(169, *YYCURSOR);
++YYCURSOR;
@@ -3185,12 +3208,12 @@ yy169:
yy171:
YYDEBUG(171, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1849 "Zend/zend_language_scanner.l"
+#line 1872 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
-#line 3194 "Zend/zend_language_scanner.c"
+#line 3217 "Zend/zend_language_scanner.c"
yy172:
YYDEBUG(172, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3204,11 +3227,11 @@ yy173:
}
YYDEBUG(174, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1547 "Zend/zend_language_scanner.l"
+#line 1570 "Zend/zend_language_scanner.l"
{
- return T_LOGICAL_XOR;
+ RETURN_TOKEN(T_LOGICAL_XOR);
}
-#line 3212 "Zend/zend_language_scanner.c"
+#line 3235 "Zend/zend_language_scanner.c"
yy175:
YYDEBUG(175, *YYCURSOR);
++YYCURSOR;
@@ -3217,71 +3240,71 @@ yy175:
}
YYDEBUG(176, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1539 "Zend/zend_language_scanner.l"
+#line 1562 "Zend/zend_language_scanner.l"
{
- return T_LOGICAL_OR;
+ RETURN_TOKEN(T_LOGICAL_OR);
}
-#line 3225 "Zend/zend_language_scanner.c"
+#line 3248 "Zend/zend_language_scanner.c"
yy177:
YYDEBUG(177, *YYCURSOR);
++YYCURSOR;
YYDEBUG(178, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1527 "Zend/zend_language_scanner.l"
+#line 1550 "Zend/zend_language_scanner.l"
{
- return T_XOR_EQUAL;
+ RETURN_TOKEN(T_XOR_EQUAL);
}
-#line 3235 "Zend/zend_language_scanner.c"
+#line 3258 "Zend/zend_language_scanner.c"
yy179:
YYDEBUG(179, *YYCURSOR);
++YYCURSOR;
YYDEBUG(180, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1531 "Zend/zend_language_scanner.l"
+#line 1554 "Zend/zend_language_scanner.l"
{
- return T_BOOLEAN_OR;
+ RETURN_TOKEN(T_BOOLEAN_OR);
}
-#line 3245 "Zend/zend_language_scanner.c"
+#line 3268 "Zend/zend_language_scanner.c"
yy181:
YYDEBUG(181, *YYCURSOR);
++YYCURSOR;
YYDEBUG(182, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1523 "Zend/zend_language_scanner.l"
+#line 1546 "Zend/zend_language_scanner.l"
{
- return T_OR_EQUAL;
+ RETURN_TOKEN(T_OR_EQUAL);
}
-#line 3255 "Zend/zend_language_scanner.c"
+#line 3278 "Zend/zend_language_scanner.c"
yy183:
YYDEBUG(183, *YYCURSOR);
++YYCURSOR;
YYDEBUG(184, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1535 "Zend/zend_language_scanner.l"
+#line 1558 "Zend/zend_language_scanner.l"
{
- return T_BOOLEAN_AND;
+ RETURN_TOKEN(T_BOOLEAN_AND);
}
-#line 3265 "Zend/zend_language_scanner.c"
+#line 3288 "Zend/zend_language_scanner.c"
yy185:
YYDEBUG(185, *YYCURSOR);
++YYCURSOR;
YYDEBUG(186, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1519 "Zend/zend_language_scanner.l"
+#line 1542 "Zend/zend_language_scanner.l"
{
- return T_AND_EQUAL;
+ RETURN_TOKEN(T_AND_EQUAL);
}
-#line 3275 "Zend/zend_language_scanner.c"
+#line 3298 "Zend/zend_language_scanner.c"
yy187:
YYDEBUG(187, *YYCURSOR);
++YYCURSOR;
YYDEBUG(188, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1507 "Zend/zend_language_scanner.l"
+#line 1530 "Zend/zend_language_scanner.l"
{
- return T_MOD_EQUAL;
+ RETURN_TOKEN(T_MOD_EQUAL);
}
-#line 3285 "Zend/zend_language_scanner.c"
+#line 3308 "Zend/zend_language_scanner.c"
yy189:
YYDEBUG(189, *YYCURSOR);
yyaccept = 4;
@@ -3290,7 +3313,7 @@ yy189:
yy190:
YYDEBUG(190, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1907 "Zend/zend_language_scanner.l"
+#line 1930 "Zend/zend_language_scanner.l"
{
int doc_com;
@@ -3318,12 +3341,12 @@ yy190:
if (doc_com) {
CG(doc_comment) = zend_string_init(yytext, yyleng, 0);
- return T_DOC_COMMENT;
+ RETURN_TOKEN(T_DOC_COMMENT);
}
- return T_COMMENT;
+ RETURN_TOKEN(T_COMMENT);
}
-#line 3327 "Zend/zend_language_scanner.c"
+#line 3350 "Zend/zend_language_scanner.c"
yy191:
YYDEBUG(191, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3333,11 +3356,11 @@ yy192:
++YYCURSOR;
YYDEBUG(193, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1499 "Zend/zend_language_scanner.l"
+#line 1522 "Zend/zend_language_scanner.l"
{
- return T_DIV_EQUAL;
+ RETURN_TOKEN(T_DIV_EQUAL);
}
-#line 3341 "Zend/zend_language_scanner.c"
+#line 3364 "Zend/zend_language_scanner.c"
yy194:
YYDEBUG(194, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3361,62 +3384,62 @@ yy197:
if ((yych = *YYCURSOR) == '=') goto yy201;
YYDEBUG(198, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1491 "Zend/zend_language_scanner.l"
+#line 1514 "Zend/zend_language_scanner.l"
{
- return T_POW;
+ RETURN_TOKEN(T_POW);
}
-#line 3369 "Zend/zend_language_scanner.c"
+#line 3392 "Zend/zend_language_scanner.c"
yy199:
YYDEBUG(199, *YYCURSOR);
++YYCURSOR;
YYDEBUG(200, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1487 "Zend/zend_language_scanner.l"
+#line 1510 "Zend/zend_language_scanner.l"
{
- return T_MUL_EQUAL;
+ RETURN_TOKEN(T_MUL_EQUAL);
}
-#line 3379 "Zend/zend_language_scanner.c"
+#line 3402 "Zend/zend_language_scanner.c"
yy201:
YYDEBUG(201, *YYCURSOR);
++YYCURSOR;
YYDEBUG(202, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1495 "Zend/zend_language_scanner.l"
+#line 1518 "Zend/zend_language_scanner.l"
{
- return T_POW_EQUAL;
+ RETURN_TOKEN(T_POW_EQUAL);
}
-#line 3389 "Zend/zend_language_scanner.c"
+#line 3412 "Zend/zend_language_scanner.c"
yy203:
YYDEBUG(203, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) == '=') goto yy207;
YYDEBUG(204, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1555 "Zend/zend_language_scanner.l"
+#line 1578 "Zend/zend_language_scanner.l"
{
- return T_SR;
+ RETURN_TOKEN(T_SR);
}
-#line 3400 "Zend/zend_language_scanner.c"
+#line 3423 "Zend/zend_language_scanner.c"
yy205:
YYDEBUG(205, *YYCURSOR);
++YYCURSOR;
YYDEBUG(206, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1475 "Zend/zend_language_scanner.l"
+#line 1498 "Zend/zend_language_scanner.l"
{
- return T_IS_GREATER_OR_EQUAL;
+ RETURN_TOKEN(T_IS_GREATER_OR_EQUAL);
}
-#line 3410 "Zend/zend_language_scanner.c"
+#line 3433 "Zend/zend_language_scanner.c"
yy207:
YYDEBUG(207, *YYCURSOR);
++YYCURSOR;
YYDEBUG(208, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1515 "Zend/zend_language_scanner.l"
+#line 1538 "Zend/zend_language_scanner.l"
{
- return T_SR_EQUAL;
+ RETURN_TOKEN(T_SR_EQUAL);
}
-#line 3420 "Zend/zend_language_scanner.c"
+#line 3443 "Zend/zend_language_scanner.c"
yy209:
YYDEBUG(209, *YYCURSOR);
yyaccept = 5;
@@ -3427,53 +3450,53 @@ yy209:
yy210:
YYDEBUG(210, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1551 "Zend/zend_language_scanner.l"
+#line 1574 "Zend/zend_language_scanner.l"
{
- return T_SL;
+ RETURN_TOKEN(T_SL);
}
-#line 3435 "Zend/zend_language_scanner.c"
+#line 3458 "Zend/zend_language_scanner.c"
yy211:
YYDEBUG(211, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) == '>') goto yy215;
YYDEBUG(212, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1471 "Zend/zend_language_scanner.l"
+#line 1494 "Zend/zend_language_scanner.l"
{
- return T_IS_SMALLER_OR_EQUAL;
+ RETURN_TOKEN(T_IS_SMALLER_OR_EQUAL);
}
-#line 3446 "Zend/zend_language_scanner.c"
+#line 3469 "Zend/zend_language_scanner.c"
yy213:
YYDEBUG(213, *YYCURSOR);
++YYCURSOR;
yy214:
YYDEBUG(214, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1463 "Zend/zend_language_scanner.l"
+#line 1486 "Zend/zend_language_scanner.l"
{
- return T_IS_NOT_EQUAL;
+ RETURN_TOKEN(T_IS_NOT_EQUAL);
}
-#line 3457 "Zend/zend_language_scanner.c"
+#line 3480 "Zend/zend_language_scanner.c"
yy215:
YYDEBUG(215, *YYCURSOR);
++YYCURSOR;
YYDEBUG(216, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1467 "Zend/zend_language_scanner.l"
+#line 1490 "Zend/zend_language_scanner.l"
{
- return T_SPACESHIP;
+ RETURN_TOKEN(T_SPACESHIP);
}
-#line 3467 "Zend/zend_language_scanner.c"
+#line 3490 "Zend/zend_language_scanner.c"
yy217:
YYDEBUG(217, *YYCURSOR);
++YYCURSOR;
YYDEBUG(218, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1511 "Zend/zend_language_scanner.l"
+#line 1534 "Zend/zend_language_scanner.l"
{
- return T_SL_EQUAL;
+ RETURN_TOKEN(T_SL_EQUAL);
}
-#line 3477 "Zend/zend_language_scanner.c"
+#line 3500 "Zend/zend_language_scanner.c"
yy219:
YYDEBUG(219, *YYCURSOR);
++YYCURSOR;
@@ -3578,7 +3601,7 @@ yy228:
yy229:
YYDEBUG(229, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2059 "Zend/zend_language_scanner.l"
+#line 2082 "Zend/zend_language_scanner.l"
{
char *s;
int bprefix = (yytext[0] != '<') ? 1 : 0;
@@ -3623,9 +3646,9 @@ yy229:
zend_ptr_stack_push(&SCNG(heredoc_label_stack), (void *) heredoc_label);
- return T_START_HEREDOC;
+ RETURN_TOKEN(T_START_HEREDOC);
}
-#line 3629 "Zend/zend_language_scanner.c"
+#line 3652 "Zend/zend_language_scanner.c"
yy230:
YYDEBUG(230, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3665,31 +3688,31 @@ yy233:
++YYCURSOR;
YYDEBUG(235, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1455 "Zend/zend_language_scanner.l"
+#line 1478 "Zend/zend_language_scanner.l"
{
- return T_IS_NOT_IDENTICAL;
+ RETURN_TOKEN(T_IS_NOT_IDENTICAL);
}
-#line 3673 "Zend/zend_language_scanner.c"
+#line 3696 "Zend/zend_language_scanner.c"
yy236:
YYDEBUG(236, *YYCURSOR);
++YYCURSOR;
YYDEBUG(237, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1479 "Zend/zend_language_scanner.l"
+#line 1502 "Zend/zend_language_scanner.l"
{
- return T_PLUS_EQUAL;
+ RETURN_TOKEN(T_PLUS_EQUAL);
}
-#line 3683 "Zend/zend_language_scanner.c"
+#line 3706 "Zend/zend_language_scanner.c"
yy238:
YYDEBUG(238, *YYCURSOR);
++YYCURSOR;
YYDEBUG(239, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1443 "Zend/zend_language_scanner.l"
+#line 1466 "Zend/zend_language_scanner.l"
{
- return T_INC;
+ RETURN_TOKEN(T_INC);
}
-#line 3693 "Zend/zend_language_scanner.c"
+#line 3716 "Zend/zend_language_scanner.c"
yy240:
YYDEBUG(240, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3708,42 +3731,42 @@ yy242:
}
YYDEBUG(243, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1431 "Zend/zend_language_scanner.l"
+#line 1454 "Zend/zend_language_scanner.l"
{
- return T_LIST;
+ RETURN_TOKEN(T_LIST);
}
-#line 3716 "Zend/zend_language_scanner.c"
+#line 3739 "Zend/zend_language_scanner.c"
yy244:
YYDEBUG(244, *YYCURSOR);
++YYCURSOR;
if ((yych = *YYCURSOR) == '=') goto yy248;
YYDEBUG(245, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1459 "Zend/zend_language_scanner.l"
+#line 1482 "Zend/zend_language_scanner.l"
{
- return T_IS_EQUAL;
+ RETURN_TOKEN(T_IS_EQUAL);
}
-#line 3727 "Zend/zend_language_scanner.c"
+#line 3750 "Zend/zend_language_scanner.c"
yy246:
YYDEBUG(246, *YYCURSOR);
++YYCURSOR;
YYDEBUG(247, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1427 "Zend/zend_language_scanner.l"
+#line 1450 "Zend/zend_language_scanner.l"
{
- return T_DOUBLE_ARROW;
+ RETURN_TOKEN(T_DOUBLE_ARROW);
}
-#line 3737 "Zend/zend_language_scanner.c"
+#line 3760 "Zend/zend_language_scanner.c"
yy248:
YYDEBUG(248, *YYCURSOR);
++YYCURSOR;
YYDEBUG(249, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1451 "Zend/zend_language_scanner.l"
+#line 1474 "Zend/zend_language_scanner.l"
{
- return T_IS_IDENTICAL;
+ RETURN_TOKEN(T_IS_IDENTICAL);
}
-#line 3747 "Zend/zend_language_scanner.c"
+#line 3770 "Zend/zend_language_scanner.c"
yy250:
YYDEBUG(250, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3873,11 +3896,11 @@ yy266:
}
YYDEBUG(269, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1757 "Zend/zend_language_scanner.l"
+#line 1780 "Zend/zend_language_scanner.l"
{
- return T_NS_C;
+ RETURN_TOKEN(T_NS_C);
}
-#line 3881 "Zend/zend_language_scanner.c"
+#line 3904 "Zend/zend_language_scanner.c"
yy270:
YYDEBUG(270, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3897,11 +3920,11 @@ yy271:
}
YYDEBUG(274, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1753 "Zend/zend_language_scanner.l"
+#line 1776 "Zend/zend_language_scanner.l"
{
- return T_DIR;
+ RETURN_TOKEN(T_DIR);
}
-#line 3905 "Zend/zend_language_scanner.c"
+#line 3928 "Zend/zend_language_scanner.c"
yy275:
YYDEBUG(275, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3926,11 +3949,11 @@ yy277:
}
YYDEBUG(280, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1745 "Zend/zend_language_scanner.l"
+#line 1768 "Zend/zend_language_scanner.l"
{
- return T_LINE;
+ RETURN_TOKEN(T_LINE);
}
-#line 3934 "Zend/zend_language_scanner.c"
+#line 3957 "Zend/zend_language_scanner.c"
yy281:
YYDEBUG(281, *YYCURSOR);
yych = *++YYCURSOR;
@@ -3965,11 +3988,11 @@ yy285:
}
YYDEBUG(288, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1741 "Zend/zend_language_scanner.l"
+#line 1764 "Zend/zend_language_scanner.l"
{
- return T_METHOD_C;
+ RETURN_TOKEN(T_METHOD_C);
}
-#line 3973 "Zend/zend_language_scanner.c"
+#line 3996 "Zend/zend_language_scanner.c"
yy289:
YYDEBUG(289, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4020,11 +4043,11 @@ yy296:
}
YYDEBUG(299, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1737 "Zend/zend_language_scanner.l"
+#line 1760 "Zend/zend_language_scanner.l"
{
- return T_FUNC_C;
+ RETURN_TOKEN(T_FUNC_C);
}
-#line 4028 "Zend/zend_language_scanner.c"
+#line 4051 "Zend/zend_language_scanner.c"
yy300:
YYDEBUG(300, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4044,11 +4067,11 @@ yy301:
}
YYDEBUG(304, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1749 "Zend/zend_language_scanner.l"
+#line 1772 "Zend/zend_language_scanner.l"
{
- return T_FILE;
+ RETURN_TOKEN(T_FILE);
}
-#line 4052 "Zend/zend_language_scanner.c"
+#line 4075 "Zend/zend_language_scanner.c"
yy305:
YYDEBUG(305, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4078,11 +4101,11 @@ yy308:
}
YYDEBUG(311, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1733 "Zend/zend_language_scanner.l"
+#line 1756 "Zend/zend_language_scanner.l"
{
- return T_TRAIT_C;
+ RETURN_TOKEN(T_TRAIT_C);
}
-#line 4086 "Zend/zend_language_scanner.c"
+#line 4109 "Zend/zend_language_scanner.c"
yy312:
YYDEBUG(312, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4112,11 +4135,11 @@ yy315:
}
YYDEBUG(318, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1729 "Zend/zend_language_scanner.l"
+#line 1752 "Zend/zend_language_scanner.l"
{
- return T_CLASS_C;
+ RETURN_TOKEN(T_CLASS_C);
}
-#line 4120 "Zend/zend_language_scanner.c"
+#line 4143 "Zend/zend_language_scanner.c"
yy319:
YYDEBUG(319, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4178,11 +4201,11 @@ yy330:
}
YYDEBUG(331, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1395 "Zend/zend_language_scanner.l"
+#line 1418 "Zend/zend_language_scanner.l"
{
- return T_HALT_COMPILER;
+ RETURN_TOKEN(T_HALT_COMPILER);
}
-#line 4186 "Zend/zend_language_scanner.c"
+#line 4209 "Zend/zend_language_scanner.c"
yy332:
YYDEBUG(332, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4202,11 +4225,11 @@ yy334:
}
YYDEBUG(335, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1375 "Zend/zend_language_scanner.l"
+#line 1398 "Zend/zend_language_scanner.l"
{
- return T_USE;
+ RETURN_TOKEN(T_USE);
}
-#line 4210 "Zend/zend_language_scanner.c"
+#line 4233 "Zend/zend_language_scanner.c"
yy336:
YYDEBUG(336, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4225,11 +4248,11 @@ yy338:
}
YYDEBUG(339, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1423 "Zend/zend_language_scanner.l"
+#line 1446 "Zend/zend_language_scanner.l"
{
- return T_UNSET;
+ RETURN_TOKEN(T_UNSET);
}
-#line 4233 "Zend/zend_language_scanner.c"
+#line 4256 "Zend/zend_language_scanner.c"
yy340:
YYDEBUG(340, *YYCURSOR);
++YYCURSOR;
@@ -4401,11 +4424,11 @@ yy355:
++YYCURSOR;
YYDEBUG(357, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1323 "Zend/zend_language_scanner.l"
+#line 1346 "Zend/zend_language_scanner.l"
{
- return T_INT_CAST;
+ RETURN_TOKEN(T_INT_CAST);
}
-#line 4409 "Zend/zend_language_scanner.c"
+#line 4432 "Zend/zend_language_scanner.c"
yy358:
YYDEBUG(358, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4449,11 +4472,11 @@ yy363:
++YYCURSOR;
YYDEBUG(366, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1327 "Zend/zend_language_scanner.l"
+#line 1350 "Zend/zend_language_scanner.l"
{
- return T_DOUBLE_CAST;
+ RETURN_TOKEN(T_DOUBLE_CAST);
}
-#line 4457 "Zend/zend_language_scanner.c"
+#line 4480 "Zend/zend_language_scanner.c"
yy367:
YYDEBUG(367, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4523,11 +4546,11 @@ yy377:
++YYCURSOR;
YYDEBUG(380, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1331 "Zend/zend_language_scanner.l"
+#line 1354 "Zend/zend_language_scanner.l"
{
- return T_STRING_CAST;
+ RETURN_TOKEN(T_STRING_CAST);
}
-#line 4531 "Zend/zend_language_scanner.c"
+#line 4554 "Zend/zend_language_scanner.c"
yy381:
YYDEBUG(381, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4560,11 +4583,11 @@ yy384:
++YYCURSOR;
YYDEBUG(387, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1335 "Zend/zend_language_scanner.l"
+#line 1358 "Zend/zend_language_scanner.l"
{
- return T_ARRAY_CAST;
+ RETURN_TOKEN(T_ARRAY_CAST);
}
-#line 4568 "Zend/zend_language_scanner.c"
+#line 4591 "Zend/zend_language_scanner.c"
yy388:
YYDEBUG(388, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4602,11 +4625,11 @@ yy392:
++YYCURSOR;
YYDEBUG(395, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1339 "Zend/zend_language_scanner.l"
+#line 1362 "Zend/zend_language_scanner.l"
{
- return T_OBJECT_CAST;
+ RETURN_TOKEN(T_OBJECT_CAST);
}
-#line 4610 "Zend/zend_language_scanner.c"
+#line 4633 "Zend/zend_language_scanner.c"
yy396:
YYDEBUG(396, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4647,11 +4670,11 @@ yy401:
++YYCURSOR;
YYDEBUG(403, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1343 "Zend/zend_language_scanner.l"
+#line 1366 "Zend/zend_language_scanner.l"
{
- return T_BOOL_CAST;
+ RETURN_TOKEN(T_BOOL_CAST);
}
-#line 4655 "Zend/zend_language_scanner.c"
+#line 4678 "Zend/zend_language_scanner.c"
yy404:
YYDEBUG(404, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4711,11 +4734,11 @@ yy412:
++YYCURSOR;
YYDEBUG(415, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1347 "Zend/zend_language_scanner.l"
+#line 1370 "Zend/zend_language_scanner.l"
{
- return T_UNSET_CAST;
+ RETURN_TOKEN(T_UNSET_CAST);
}
-#line 4719 "Zend/zend_language_scanner.c"
+#line 4742 "Zend/zend_language_scanner.c"
yy416:
YYDEBUG(416, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4729,11 +4752,11 @@ yy417:
}
YYDEBUG(418, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1319 "Zend/zend_language_scanner.l"
+#line 1342 "Zend/zend_language_scanner.l"
{
- return T_VAR;
+ RETURN_TOKEN(T_VAR);
}
-#line 4737 "Zend/zend_language_scanner.c"
+#line 4760 "Zend/zend_language_scanner.c"
yy419:
YYDEBUG(419, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4753,11 +4776,11 @@ yy421:
}
YYDEBUG(422, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1311 "Zend/zend_language_scanner.l"
+#line 1334 "Zend/zend_language_scanner.l"
{
- return T_NEW;
+ RETURN_TOKEN(T_NEW);
}
-#line 4761 "Zend/zend_language_scanner.c"
+#line 4784 "Zend/zend_language_scanner.c"
yy423:
YYDEBUG(423, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4796,11 +4819,11 @@ yy429:
}
YYDEBUG(430, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1371 "Zend/zend_language_scanner.l"
+#line 1394 "Zend/zend_language_scanner.l"
{
- return T_NAMESPACE;
+ RETURN_TOKEN(T_NAMESPACE);
}
-#line 4804 "Zend/zend_language_scanner.c"
+#line 4827 "Zend/zend_language_scanner.c"
yy431:
YYDEBUG(431, *YYCURSOR);
++YYCURSOR;
@@ -4809,22 +4832,22 @@ yy431:
yy432:
YYDEBUG(432, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1940 "Zend/zend_language_scanner.l"
+#line 1963 "Zend/zend_language_scanner.l"
{
BEGIN(INITIAL);
- return T_CLOSE_TAG; /* implicit ';' at php-end tag */
+ RETURN_TOKEN(T_CLOSE_TAG); /* implicit ';' at php-end tag */
}
-#line 4818 "Zend/zend_language_scanner.c"
+#line 4841 "Zend/zend_language_scanner.c"
yy433:
YYDEBUG(433, *YYCURSOR);
++YYCURSOR;
YYDEBUG(434, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1307 "Zend/zend_language_scanner.l"
+#line 1330 "Zend/zend_language_scanner.l"
{
- return T_COALESCE;
+ RETURN_TOKEN(T_COALESCE);
}
-#line 4828 "Zend/zend_language_scanner.c"
+#line 4851 "Zend/zend_language_scanner.c"
yy435:
YYDEBUG(435, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4855,11 +4878,11 @@ yy439:
++YYCURSOR;
YYDEBUG(440, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1503 "Zend/zend_language_scanner.l"
+#line 1526 "Zend/zend_language_scanner.l"
{
- return T_CONCAT_EQUAL;
+ RETURN_TOKEN(T_CONCAT_EQUAL);
}
-#line 4863 "Zend/zend_language_scanner.c"
+#line 4886 "Zend/zend_language_scanner.c"
yy441:
YYDEBUG(441, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4868,21 +4891,21 @@ yy441:
++YYCURSOR;
YYDEBUG(443, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1303 "Zend/zend_language_scanner.l"
+#line 1326 "Zend/zend_language_scanner.l"
{
- return T_ELLIPSIS;
+ RETURN_TOKEN(T_ELLIPSIS);
}
-#line 4876 "Zend/zend_language_scanner.c"
+#line 4899 "Zend/zend_language_scanner.c"
yy444:
YYDEBUG(444, *YYCURSOR);
++YYCURSOR;
YYDEBUG(445, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1295 "Zend/zend_language_scanner.l"
+#line 1318 "Zend/zend_language_scanner.l"
{
- return T_PAAMAYIM_NEKUDOTAYIM;
+ RETURN_TOKEN(T_PAAMAYIM_NEKUDOTAYIM);
}
-#line 4886 "Zend/zend_language_scanner.c"
+#line 4909 "Zend/zend_language_scanner.c"
yy446:
YYDEBUG(446, *YYCURSOR);
++YYCURSOR;
@@ -4904,32 +4927,32 @@ yy448:
++YYCURSOR;
YYDEBUG(449, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1483 "Zend/zend_language_scanner.l"
+#line 1506 "Zend/zend_language_scanner.l"
{
- return T_MINUS_EQUAL;
+ RETURN_TOKEN(T_MINUS_EQUAL);
}
-#line 4912 "Zend/zend_language_scanner.c"
+#line 4935 "Zend/zend_language_scanner.c"
yy450:
YYDEBUG(450, *YYCURSOR);
++YYCURSOR;
YYDEBUG(451, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1447 "Zend/zend_language_scanner.l"
+#line 1470 "Zend/zend_language_scanner.l"
{
- return T_DEC;
+ RETURN_TOKEN(T_DEC);
}
-#line 4922 "Zend/zend_language_scanner.c"
+#line 4945 "Zend/zend_language_scanner.c"
yy452:
YYDEBUG(452, *YYCURSOR);
++YYCURSOR;
YYDEBUG(453, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1269 "Zend/zend_language_scanner.l"
+#line 1292 "Zend/zend_language_scanner.l"
{
yy_push_state(ST_LOOKING_FOR_PROPERTY);
- return T_OBJECT_OPERATOR;
+ RETURN_TOKEN(T_OBJECT_OPERATOR);
}
-#line 4933 "Zend/zend_language_scanner.c"
+#line 4956 "Zend/zend_language_scanner.c"
yy454:
YYDEBUG(454, *YYCURSOR);
yych = *++YYCURSOR;
@@ -4974,11 +4997,11 @@ yy459:
}
YYDEBUG(460, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1419 "Zend/zend_language_scanner.l"
+#line 1442 "Zend/zend_language_scanner.l"
{
- return T_PUBLIC;
+ RETURN_TOKEN(T_PUBLIC);
}
-#line 4982 "Zend/zend_language_scanner.c"
+#line 5005 "Zend/zend_language_scanner.c"
yy461:
YYDEBUG(461, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5033,11 +5056,11 @@ yy468:
}
YYDEBUG(469, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1415 "Zend/zend_language_scanner.l"
+#line 1438 "Zend/zend_language_scanner.l"
{
- return T_PROTECTED;
+ RETURN_TOKEN(T_PROTECTED);
}
-#line 5041 "Zend/zend_language_scanner.c"
+#line 5064 "Zend/zend_language_scanner.c"
yy470:
YYDEBUG(470, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5067,11 +5090,11 @@ yy474:
}
YYDEBUG(475, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1411 "Zend/zend_language_scanner.l"
+#line 1434 "Zend/zend_language_scanner.l"
{
- return T_PRIVATE;
+ RETURN_TOKEN(T_PRIVATE);
}
-#line 5075 "Zend/zend_language_scanner.c"
+#line 5098 "Zend/zend_language_scanner.c"
yy476:
YYDEBUG(476, *YYCURSOR);
++YYCURSOR;
@@ -5080,11 +5103,11 @@ yy476:
}
YYDEBUG(477, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1245 "Zend/zend_language_scanner.l"
+#line 1268 "Zend/zend_language_scanner.l"
{
- return T_PRINT;
+ RETURN_TOKEN(T_PRINT);
}
-#line 5088 "Zend/zend_language_scanner.c"
+#line 5111 "Zend/zend_language_scanner.c"
yy478:
YYDEBUG(478, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5109,11 +5132,11 @@ yy481:
}
YYDEBUG(482, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1237 "Zend/zend_language_scanner.l"
+#line 1260 "Zend/zend_language_scanner.l"
{
- return T_GOTO;
+ RETURN_TOKEN(T_GOTO);
}
-#line 5117 "Zend/zend_language_scanner.c"
+#line 5140 "Zend/zend_language_scanner.c"
yy483:
YYDEBUG(483, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5137,11 +5160,11 @@ yy486:
}
YYDEBUG(487, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1383 "Zend/zend_language_scanner.l"
+#line 1406 "Zend/zend_language_scanner.l"
{
- return T_GLOBAL;
+ RETURN_TOKEN(T_GLOBAL);
}
-#line 5145 "Zend/zend_language_scanner.c"
+#line 5168 "Zend/zend_language_scanner.c"
yy488:
YYDEBUG(488, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5178,11 +5201,11 @@ yy494:
}
YYDEBUG(495, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1229 "Zend/zend_language_scanner.l"
+#line 1252 "Zend/zend_language_scanner.l"
{
- return T_BREAK;
+ RETURN_TOKEN(T_BREAK);
}
-#line 5186 "Zend/zend_language_scanner.c"
+#line 5209 "Zend/zend_language_scanner.c"
yy496:
YYDEBUG(496, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5222,11 +5245,11 @@ yy502:
}
YYDEBUG(503, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1213 "Zend/zend_language_scanner.l"
+#line 1236 "Zend/zend_language_scanner.l"
{
- return T_SWITCH;
+ RETURN_TOKEN(T_SWITCH);
}
-#line 5230 "Zend/zend_language_scanner.c"
+#line 5253 "Zend/zend_language_scanner.c"
yy504:
YYDEBUG(504, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5250,11 +5273,11 @@ yy507:
}
YYDEBUG(508, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1399 "Zend/zend_language_scanner.l"
+#line 1422 "Zend/zend_language_scanner.l"
{
- return T_STATIC;
+ RETURN_TOKEN(T_STATIC);
}
-#line 5258 "Zend/zend_language_scanner.c"
+#line 5281 "Zend/zend_language_scanner.c"
yy509:
YYDEBUG(509, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5281,11 +5304,11 @@ yy512:
}
YYDEBUG(513, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1209 "Zend/zend_language_scanner.l"
+#line 1232 "Zend/zend_language_scanner.l"
{
- return T_AS;
+ RETURN_TOKEN(T_AS);
}
-#line 5289 "Zend/zend_language_scanner.c"
+#line 5312 "Zend/zend_language_scanner.c"
yy514:
YYDEBUG(514, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5304,11 +5327,11 @@ yy516:
}
YYDEBUG(517, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1435 "Zend/zend_language_scanner.l"
+#line 1458 "Zend/zend_language_scanner.l"
{
- return T_ARRAY;
+ RETURN_TOKEN(T_ARRAY);
}
-#line 5312 "Zend/zend_language_scanner.c"
+#line 5335 "Zend/zend_language_scanner.c"
yy518:
YYDEBUG(518, *YYCURSOR);
++YYCURSOR;
@@ -5317,11 +5340,11 @@ yy518:
}
YYDEBUG(519, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1543 "Zend/zend_language_scanner.l"
+#line 1566 "Zend/zend_language_scanner.l"
{
- return T_LOGICAL_AND;
+ RETURN_TOKEN(T_LOGICAL_AND);
}
-#line 5325 "Zend/zend_language_scanner.c"
+#line 5348 "Zend/zend_language_scanner.c"
yy520:
YYDEBUG(520, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5355,11 +5378,11 @@ yy525:
}
YYDEBUG(526, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1403 "Zend/zend_language_scanner.l"
+#line 1426 "Zend/zend_language_scanner.l"
{
- return T_ABSTRACT;
+ RETURN_TOKEN(T_ABSTRACT);
}
-#line 5363 "Zend/zend_language_scanner.c"
+#line 5386 "Zend/zend_language_scanner.c"
yy527:
YYDEBUG(527, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5383,11 +5406,11 @@ yy530:
}
YYDEBUG(531, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1169 "Zend/zend_language_scanner.l"
+#line 1192 "Zend/zend_language_scanner.l"
{
- return T_WHILE;
+ RETURN_TOKEN(T_WHILE);
}
-#line 5391 "Zend/zend_language_scanner.c"
+#line 5414 "Zend/zend_language_scanner.c"
yy532:
YYDEBUG(532, *YYCURSOR);
++YYCURSOR;
@@ -5396,11 +5419,11 @@ yy532:
}
YYDEBUG(533, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1153 "Zend/zend_language_scanner.l"
+#line 1176 "Zend/zend_language_scanner.l"
{
- return T_IF;
+ RETURN_TOKEN(T_IF);
}
-#line 5404 "Zend/zend_language_scanner.c"
+#line 5427 "Zend/zend_language_scanner.c"
yy534:
YYDEBUG(534, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5452,11 +5475,11 @@ yy539:
}
YYDEBUG(540, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1387 "Zend/zend_language_scanner.l"
+#line 1410 "Zend/zend_language_scanner.l"
{
- return T_ISSET;
+ RETURN_TOKEN(T_ISSET);
}
-#line 5460 "Zend/zend_language_scanner.c"
+#line 5483 "Zend/zend_language_scanner.c"
yy541:
YYDEBUG(541, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5510,11 +5533,11 @@ yy547:
yy548:
YYDEBUG(548, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1355 "Zend/zend_language_scanner.l"
+#line 1378 "Zend/zend_language_scanner.l"
{
- return T_INCLUDE;
+ RETURN_TOKEN(T_INCLUDE);
}
-#line 5518 "Zend/zend_language_scanner.c"
+#line 5541 "Zend/zend_language_scanner.c"
yy549:
YYDEBUG(549, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5543,11 +5566,11 @@ yy553:
}
YYDEBUG(554, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1359 "Zend/zend_language_scanner.l"
+#line 1382 "Zend/zend_language_scanner.l"
{
- return T_INCLUDE_ONCE;
+ RETURN_TOKEN(T_INCLUDE_ONCE);
}
-#line 5551 "Zend/zend_language_scanner.c"
+#line 5574 "Zend/zend_language_scanner.c"
yy555:
YYDEBUG(555, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5581,11 +5604,11 @@ yy560:
}
YYDEBUG(561, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1253 "Zend/zend_language_scanner.l"
+#line 1276 "Zend/zend_language_scanner.l"
{
- return T_INTERFACE;
+ RETURN_TOKEN(T_INTERFACE);
}
-#line 5589 "Zend/zend_language_scanner.c"
+#line 5612 "Zend/zend_language_scanner.c"
yy562:
YYDEBUG(562, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5635,11 +5658,11 @@ yy568:
}
YYDEBUG(569, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1379 "Zend/zend_language_scanner.l"
+#line 1402 "Zend/zend_language_scanner.l"
{
- return T_INSTEADOF;
+ RETURN_TOKEN(T_INSTEADOF);
}
-#line 5643 "Zend/zend_language_scanner.c"
+#line 5666 "Zend/zend_language_scanner.c"
yy570:
YYDEBUG(570, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5668,11 +5691,11 @@ yy574:
}
YYDEBUG(575, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1205 "Zend/zend_language_scanner.l"
+#line 1228 "Zend/zend_language_scanner.l"
{
- return T_INSTANCEOF;
+ RETURN_TOKEN(T_INSTANCEOF);
}
-#line 5676 "Zend/zend_language_scanner.c"
+#line 5699 "Zend/zend_language_scanner.c"
yy576:
YYDEBUG(576, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5716,11 +5739,11 @@ yy583:
}
YYDEBUG(584, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1265 "Zend/zend_language_scanner.l"
+#line 1288 "Zend/zend_language_scanner.l"
{
- return T_IMPLEMENTS;
+ RETURN_TOKEN(T_IMPLEMENTS);
}
-#line 5724 "Zend/zend_language_scanner.c"
+#line 5747 "Zend/zend_language_scanner.c"
yy585:
YYDEBUG(585, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5748,11 +5771,11 @@ yy586:
}
YYDEBUG(588, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1137 "Zend/zend_language_scanner.l"
+#line 1160 "Zend/zend_language_scanner.l"
{
- return T_TRY;
+ RETURN_TOKEN(T_TRY);
}
-#line 5756 "Zend/zend_language_scanner.c"
+#line 5779 "Zend/zend_language_scanner.c"
yy589:
YYDEBUG(589, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5771,11 +5794,11 @@ yy591:
}
YYDEBUG(592, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1257 "Zend/zend_language_scanner.l"
+#line 1280 "Zend/zend_language_scanner.l"
{
- return T_TRAIT;
+ RETURN_TOKEN(T_TRAIT);
}
-#line 5779 "Zend/zend_language_scanner.c"
+#line 5802 "Zend/zend_language_scanner.c"
yy593:
YYDEBUG(593, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5794,11 +5817,11 @@ yy595:
}
YYDEBUG(596, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1149 "Zend/zend_language_scanner.l"
+#line 1172 "Zend/zend_language_scanner.l"
{
- return T_THROW;
+ RETURN_TOKEN(T_THROW);
}
-#line 5802 "Zend/zend_language_scanner.c"
+#line 5825 "Zend/zend_language_scanner.c"
yy597:
YYDEBUG(597, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5831,11 +5854,11 @@ yy600:
yy601:
YYDEBUG(601, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1133 "Zend/zend_language_scanner.l"
+#line 1156 "Zend/zend_language_scanner.l"
{
- return T_YIELD;
+ RETURN_TOKEN(T_YIELD);
}
-#line 5839 "Zend/zend_language_scanner.c"
+#line 5862 "Zend/zend_language_scanner.c"
yy602:
YYDEBUG(602, *YYCURSOR);
++YYCURSOR;
@@ -5877,11 +5900,11 @@ yy607:
++YYCURSOR;
YYDEBUG(608, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1129 "Zend/zend_language_scanner.l"
+#line 1152 "Zend/zend_language_scanner.l"
{
- return T_YIELD_FROM;
+ RETURN_TOKEN(T_YIELD_FROM);
}
-#line 5885 "Zend/zend_language_scanner.c"
+#line 5908 "Zend/zend_language_scanner.c"
yy609:
YYDEBUG(609, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5942,11 +5965,11 @@ yy615:
yy616:
YYDEBUG(616, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1363 "Zend/zend_language_scanner.l"
+#line 1386 "Zend/zend_language_scanner.l"
{
- return T_REQUIRE;
+ RETURN_TOKEN(T_REQUIRE);
}
-#line 5950 "Zend/zend_language_scanner.c"
+#line 5973 "Zend/zend_language_scanner.c"
yy617:
YYDEBUG(617, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5975,11 +5998,11 @@ yy621:
}
YYDEBUG(622, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1367 "Zend/zend_language_scanner.l"
+#line 1390 "Zend/zend_language_scanner.l"
{
- return T_REQUIRE_ONCE;
+ RETURN_TOKEN(T_REQUIRE_ONCE);
}
-#line 5983 "Zend/zend_language_scanner.c"
+#line 6006 "Zend/zend_language_scanner.c"
yy623:
YYDEBUG(623, *YYCURSOR);
yych = *++YYCURSOR;
@@ -5998,11 +6021,11 @@ yy625:
}
YYDEBUG(626, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1125 "Zend/zend_language_scanner.l"
+#line 1148 "Zend/zend_language_scanner.l"
{
- return T_RETURN;
+ RETURN_TOKEN(T_RETURN);
}
-#line 6006 "Zend/zend_language_scanner.c"
+#line 6029 "Zend/zend_language_scanner.c"
yy627:
YYDEBUG(627, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6092,11 +6115,11 @@ yy636:
}
YYDEBUG(637, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1233 "Zend/zend_language_scanner.l"
+#line 1256 "Zend/zend_language_scanner.l"
{
- return T_CONTINUE;
+ RETURN_TOKEN(T_CONTINUE);
}
-#line 6100 "Zend/zend_language_scanner.c"
+#line 6123 "Zend/zend_language_scanner.c"
yy638:
YYDEBUG(638, *YYCURSOR);
++YYCURSOR;
@@ -6105,11 +6128,11 @@ yy638:
}
YYDEBUG(639, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1121 "Zend/zend_language_scanner.l"
+#line 1144 "Zend/zend_language_scanner.l"
{
- return T_CONST;
+ RETURN_TOKEN(T_CONST);
}
-#line 6113 "Zend/zend_language_scanner.c"
+#line 6136 "Zend/zend_language_scanner.c"
yy640:
YYDEBUG(640, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6134,11 +6157,11 @@ yy643:
}
YYDEBUG(644, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1315 "Zend/zend_language_scanner.l"
+#line 1338 "Zend/zend_language_scanner.l"
{
- return T_CLONE;
+ RETURN_TOKEN(T_CLONE);
}
-#line 6142 "Zend/zend_language_scanner.c"
+#line 6165 "Zend/zend_language_scanner.c"
yy645:
YYDEBUG(645, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6152,11 +6175,11 @@ yy646:
}
YYDEBUG(647, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1249 "Zend/zend_language_scanner.l"
+#line 1272 "Zend/zend_language_scanner.l"
{
- return T_CLASS;
+ RETURN_TOKEN(T_CLASS);
}
-#line 6160 "Zend/zend_language_scanner.c"
+#line 6183 "Zend/zend_language_scanner.c"
yy648:
YYDEBUG(648, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6202,11 +6225,11 @@ yy655:
}
YYDEBUG(656, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1439 "Zend/zend_language_scanner.l"
+#line 1462 "Zend/zend_language_scanner.l"
{
- return T_CALLABLE;
+ RETURN_TOKEN(T_CALLABLE);
}
-#line 6210 "Zend/zend_language_scanner.c"
+#line 6233 "Zend/zend_language_scanner.c"
yy657:
YYDEBUG(657, *YYCURSOR);
++YYCURSOR;
@@ -6215,11 +6238,11 @@ yy657:
}
YYDEBUG(658, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1221 "Zend/zend_language_scanner.l"
+#line 1244 "Zend/zend_language_scanner.l"
{
- return T_CASE;
+ RETURN_TOKEN(T_CASE);
}
-#line 6223 "Zend/zend_language_scanner.c"
+#line 6246 "Zend/zend_language_scanner.c"
yy659:
YYDEBUG(659, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6233,11 +6256,11 @@ yy660:
}
YYDEBUG(661, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1141 "Zend/zend_language_scanner.l"
+#line 1164 "Zend/zend_language_scanner.l"
{
- return T_CATCH;
+ RETURN_TOKEN(T_CATCH);
}
-#line 6241 "Zend/zend_language_scanner.c"
+#line 6264 "Zend/zend_language_scanner.c"
yy662:
YYDEBUG(662, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6288,11 +6311,11 @@ yy670:
}
YYDEBUG(671, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1117 "Zend/zend_language_scanner.l"
+#line 1140 "Zend/zend_language_scanner.l"
{
- return T_FUNCTION;
+ RETURN_TOKEN(T_FUNCTION);
}
-#line 6296 "Zend/zend_language_scanner.c"
+#line 6319 "Zend/zend_language_scanner.c"
yy672:
YYDEBUG(672, *YYCURSOR);
++YYCURSOR;
@@ -6316,11 +6339,11 @@ yy672:
yy673:
YYDEBUG(673, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1181 "Zend/zend_language_scanner.l"
+#line 1204 "Zend/zend_language_scanner.l"
{
- return T_FOR;
+ RETURN_TOKEN(T_FOR);
}
-#line 6324 "Zend/zend_language_scanner.c"
+#line 6347 "Zend/zend_language_scanner.c"
yy674:
YYDEBUG(674, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6344,11 +6367,11 @@ yy677:
}
YYDEBUG(678, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1189 "Zend/zend_language_scanner.l"
+#line 1212 "Zend/zend_language_scanner.l"
{
- return T_FOREACH;
+ RETURN_TOKEN(T_FOREACH);
}
-#line 6352 "Zend/zend_language_scanner.c"
+#line 6375 "Zend/zend_language_scanner.c"
yy679:
YYDEBUG(679, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6382,11 +6405,11 @@ yy681:
yy682:
YYDEBUG(682, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1407 "Zend/zend_language_scanner.l"
+#line 1430 "Zend/zend_language_scanner.l"
{
- return T_FINAL;
+ RETURN_TOKEN(T_FINAL);
}
-#line 6390 "Zend/zend_language_scanner.c"
+#line 6413 "Zend/zend_language_scanner.c"
yy683:
YYDEBUG(683, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6400,11 +6423,11 @@ yy684:
}
YYDEBUG(685, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1145 "Zend/zend_language_scanner.l"
+#line 1168 "Zend/zend_language_scanner.l"
{
- return T_FINALLY;
+ RETURN_TOKEN(T_FINALLY);
}
-#line 6408 "Zend/zend_language_scanner.c"
+#line 6431 "Zend/zend_language_scanner.c"
yy686:
YYDEBUG(686, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6435,11 +6458,11 @@ yy688:
}
YYDEBUG(689, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1177 "Zend/zend_language_scanner.l"
+#line 1200 "Zend/zend_language_scanner.l"
{
- return T_DO;
+ RETURN_TOKEN(T_DO);
}
-#line 6443 "Zend/zend_language_scanner.c"
+#line 6466 "Zend/zend_language_scanner.c"
yy690:
YYDEBUG(690, *YYCURSOR);
++YYCURSOR;
@@ -6448,11 +6471,11 @@ yy690:
}
YYDEBUG(691, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1113 "Zend/zend_language_scanner.l"
+#line 1136 "Zend/zend_language_scanner.l"
{
- return T_EXIT;
+ RETURN_TOKEN(T_EXIT);
}
-#line 6456 "Zend/zend_language_scanner.c"
+#line 6479 "Zend/zend_language_scanner.c"
yy692:
YYDEBUG(692, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6487,11 +6510,11 @@ yy697:
}
YYDEBUG(698, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1225 "Zend/zend_language_scanner.l"
+#line 1248 "Zend/zend_language_scanner.l"
{
- return T_DEFAULT;
+ RETURN_TOKEN(T_DEFAULT);
}
-#line 6495 "Zend/zend_language_scanner.c"
+#line 6518 "Zend/zend_language_scanner.c"
yy699:
YYDEBUG(699, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6515,11 +6538,11 @@ yy702:
}
YYDEBUG(703, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1197 "Zend/zend_language_scanner.l"
+#line 1220 "Zend/zend_language_scanner.l"
{
- return T_DECLARE;
+ RETURN_TOKEN(T_DECLARE);
}
-#line 6523 "Zend/zend_language_scanner.c"
+#line 6546 "Zend/zend_language_scanner.c"
yy704:
YYDEBUG(704, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6599,11 +6622,11 @@ yy715:
}
YYDEBUG(716, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1261 "Zend/zend_language_scanner.l"
+#line 1284 "Zend/zend_language_scanner.l"
{
- return T_EXTENDS;
+ RETURN_TOKEN(T_EXTENDS);
}
-#line 6607 "Zend/zend_language_scanner.c"
+#line 6630 "Zend/zend_language_scanner.c"
yy717:
YYDEBUG(717, *YYCURSOR);
++YYCURSOR;
@@ -6612,11 +6635,11 @@ yy717:
}
YYDEBUG(718, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1109 "Zend/zend_language_scanner.l"
+#line 1132 "Zend/zend_language_scanner.l"
{
- return T_EXIT;
+ RETURN_TOKEN(T_EXIT);
}
-#line 6620 "Zend/zend_language_scanner.c"
+#line 6643 "Zend/zend_language_scanner.c"
yy719:
YYDEBUG(719, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6630,11 +6653,11 @@ yy720:
}
YYDEBUG(721, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1351 "Zend/zend_language_scanner.l"
+#line 1374 "Zend/zend_language_scanner.l"
{
- return T_EVAL;
+ RETURN_TOKEN(T_EVAL);
}
-#line 6638 "Zend/zend_language_scanner.c"
+#line 6661 "Zend/zend_language_scanner.c"
yy722:
YYDEBUG(722, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6704,11 +6727,11 @@ yy731:
}
YYDEBUG(732, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1173 "Zend/zend_language_scanner.l"
+#line 1196 "Zend/zend_language_scanner.l"
{
- return T_ENDWHILE;
+ RETURN_TOKEN(T_ENDWHILE);
}
-#line 6712 "Zend/zend_language_scanner.c"
+#line 6735 "Zend/zend_language_scanner.c"
yy733:
YYDEBUG(733, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6737,11 +6760,11 @@ yy737:
}
YYDEBUG(738, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1217 "Zend/zend_language_scanner.l"
+#line 1240 "Zend/zend_language_scanner.l"
{
- return T_ENDSWITCH;
+ RETURN_TOKEN(T_ENDSWITCH);
}
-#line 6745 "Zend/zend_language_scanner.c"
+#line 6768 "Zend/zend_language_scanner.c"
yy739:
YYDEBUG(739, *YYCURSOR);
++YYCURSOR;
@@ -6750,11 +6773,11 @@ yy739:
}
YYDEBUG(740, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1161 "Zend/zend_language_scanner.l"
+#line 1184 "Zend/zend_language_scanner.l"
{
- return T_ENDIF;
+ RETURN_TOKEN(T_ENDIF);
}
-#line 6758 "Zend/zend_language_scanner.c"
+#line 6781 "Zend/zend_language_scanner.c"
yy741:
YYDEBUG(741, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6783,11 +6806,11 @@ yy742:
yy743:
YYDEBUG(743, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1185 "Zend/zend_language_scanner.l"
+#line 1208 "Zend/zend_language_scanner.l"
{
- return T_ENDFOR;
+ RETURN_TOKEN(T_ENDFOR);
}
-#line 6791 "Zend/zend_language_scanner.c"
+#line 6814 "Zend/zend_language_scanner.c"
yy744:
YYDEBUG(744, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6811,11 +6834,11 @@ yy747:
}
YYDEBUG(748, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1193 "Zend/zend_language_scanner.l"
+#line 1216 "Zend/zend_language_scanner.l"
{
- return T_ENDFOREACH;
+ RETURN_TOKEN(T_ENDFOREACH);
}
-#line 6819 "Zend/zend_language_scanner.c"
+#line 6842 "Zend/zend_language_scanner.c"
yy749:
YYDEBUG(749, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6849,11 +6872,11 @@ yy754:
}
YYDEBUG(755, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1201 "Zend/zend_language_scanner.l"
+#line 1224 "Zend/zend_language_scanner.l"
{
- return T_ENDDECLARE;
+ RETURN_TOKEN(T_ENDDECLARE);
}
-#line 6857 "Zend/zend_language_scanner.c"
+#line 6880 "Zend/zend_language_scanner.c"
yy756:
YYDEBUG(756, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6872,11 +6895,11 @@ yy758:
}
YYDEBUG(759, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1391 "Zend/zend_language_scanner.l"
+#line 1414 "Zend/zend_language_scanner.l"
{
- return T_EMPTY;
+ RETURN_TOKEN(T_EMPTY);
}
-#line 6880 "Zend/zend_language_scanner.c"
+#line 6903 "Zend/zend_language_scanner.c"
yy760:
YYDEBUG(760, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6905,11 +6928,11 @@ yy761:
yy762:
YYDEBUG(762, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1165 "Zend/zend_language_scanner.l"
+#line 1188 "Zend/zend_language_scanner.l"
{
- return T_ELSE;
+ RETURN_TOKEN(T_ELSE);
}
-#line 6913 "Zend/zend_language_scanner.c"
+#line 6936 "Zend/zend_language_scanner.c"
yy763:
YYDEBUG(763, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6923,11 +6946,11 @@ yy764:
}
YYDEBUG(765, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1157 "Zend/zend_language_scanner.l"
+#line 1180 "Zend/zend_language_scanner.l"
{
- return T_ELSEIF;
+ RETURN_TOKEN(T_ELSEIF);
}
-#line 6931 "Zend/zend_language_scanner.c"
+#line 6954 "Zend/zend_language_scanner.c"
yy766:
YYDEBUG(766, *YYCURSOR);
yych = *++YYCURSOR;
@@ -6941,11 +6964,11 @@ yy767:
}
YYDEBUG(768, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1241 "Zend/zend_language_scanner.l"
+#line 1264 "Zend/zend_language_scanner.l"
{
- return T_ECHO;
+ RETURN_TOKEN(T_ECHO);
}
-#line 6949 "Zend/zend_language_scanner.c"
+#line 6972 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_LOOKING_FOR_PROPERTY:
@@ -7018,12 +7041,12 @@ yy771:
yy772:
YYDEBUG(772, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1274 "Zend/zend_language_scanner.l"
+#line 1297 "Zend/zend_language_scanner.l"
{
HANDLE_NEWLINES(yytext, yyleng);
- return T_WHITESPACE;
+ RETURN_TOKEN(T_WHITESPACE);
}
-#line 7027 "Zend/zend_language_scanner.c"
+#line 7050 "Zend/zend_language_scanner.c"
yy773:
YYDEBUG(773, *YYCURSOR);
++YYCURSOR;
@@ -7031,13 +7054,13 @@ yy773:
yy774:
YYDEBUG(774, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1289 "Zend/zend_language_scanner.l"
+#line 1312 "Zend/zend_language_scanner.l"
{
yyless(0);
yy_pop_state();
goto restart;
}
-#line 7041 "Zend/zend_language_scanner.c"
+#line 7064 "Zend/zend_language_scanner.c"
yy775:
YYDEBUG(775, *YYCURSOR);
++YYCURSOR;
@@ -7046,13 +7069,13 @@ yy775:
yy776:
YYDEBUG(776, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1283 "Zend/zend_language_scanner.l"
+#line 1306 "Zend/zend_language_scanner.l"
{
yy_pop_state();
zend_copy_value(zendlval, yytext, yyleng);
- return T_STRING;
+ RETURN_TOKEN(T_STRING);
}
-#line 7056 "Zend/zend_language_scanner.c"
+#line 7079 "Zend/zend_language_scanner.c"
yy777:
YYDEBUG(777, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7073,11 +7096,11 @@ yy780:
++YYCURSOR;
YYDEBUG(781, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1279 "Zend/zend_language_scanner.l"
+#line 1302 "Zend/zend_language_scanner.l"
{
- return T_OBJECT_OPERATOR;
+ RETURN_TOKEN(T_OBJECT_OPERATOR);
}
-#line 7081 "Zend/zend_language_scanner.c"
+#line 7104 "Zend/zend_language_scanner.c"
yy782:
YYDEBUG(782, *YYCURSOR);
++YYCURSOR;
@@ -7162,14 +7185,14 @@ yy786:
yy787:
YYDEBUG(787, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1594 "Zend/zend_language_scanner.l"
+#line 1617 "Zend/zend_language_scanner.l"
{
yyless(0);
yy_pop_state();
yy_push_state(ST_IN_SCRIPTING);
goto restart;
}
-#line 7173 "Zend/zend_language_scanner.c"
+#line 7196 "Zend/zend_language_scanner.c"
yy788:
YYDEBUG(788, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7194,15 +7217,15 @@ yy792:
++YYCURSOR;
YYDEBUG(793, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1585 "Zend/zend_language_scanner.l"
+#line 1608 "Zend/zend_language_scanner.l"
{
yyless(yyleng - 1);
zend_copy_value(zendlval, yytext, yyleng);
yy_pop_state();
yy_push_state(ST_IN_SCRIPTING);
- return T_STRING_VARNAME;
+ RETURN_TOKEN(T_STRING_VARNAME);
}
-#line 7206 "Zend/zend_language_scanner.c"
+#line 7229 "Zend/zend_language_scanner.c"
}
/* *********************************** */
yyc_ST_NOWDOC:
@@ -7213,14 +7236,14 @@ yyc_ST_NOWDOC:
++YYCURSOR;
YYDEBUG(797, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2318 "Zend/zend_language_scanner.l"
+#line 2341 "Zend/zend_language_scanner.l"
{
int newline = 0;
zend_heredoc_label *heredoc_label = zend_ptr_stack_top(&SCNG(heredoc_label_stack));
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
YYCURSOR--;
@@ -7267,9 +7290,9 @@ nowdoc_scan_done:
zend_copy_value(zendlval, yytext, yyleng - newline);
HANDLE_NEWLINES(yytext, yyleng - newline);
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
-#line 7273 "Zend/zend_language_scanner.c"
+#line 7296 "Zend/zend_language_scanner.c"
/* *********************************** */
yyc_ST_VAR_OFFSET:
{
@@ -7376,7 +7399,7 @@ yy800:
yy801:
YYDEBUG(801, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1699 "Zend/zend_language_scanner.l"
+#line 1722 "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;
@@ -7390,9 +7413,9 @@ yy801:
string:
ZVAL_STRINGL(zendlval, yytext, yyleng);
}
- return T_NUM_STRING;
+ RETURN_TOKEN(T_NUM_STRING);
}
-#line 7396 "Zend/zend_language_scanner.c"
+#line 7419 "Zend/zend_language_scanner.c"
yy802:
YYDEBUG(802, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7412,23 +7435,23 @@ yy803:
yy804:
YYDEBUG(804, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1859 "Zend/zend_language_scanner.l"
+#line 1882 "Zend/zend_language_scanner.l"
{
/* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */
- return yytext[0];
+ RETURN_TOKEN(yytext[0]);
}
-#line 7421 "Zend/zend_language_scanner.c"
+#line 7444 "Zend/zend_language_scanner.c"
yy805:
YYDEBUG(805, *YYCURSOR);
++YYCURSOR;
YYDEBUG(806, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1854 "Zend/zend_language_scanner.l"
+#line 1877 "Zend/zend_language_scanner.l"
{
yy_pop_state();
- return ']';
+ RETURN_TOKEN(']');
}
-#line 7432 "Zend/zend_language_scanner.c"
+#line 7455 "Zend/zend_language_scanner.c"
yy807:
YYDEBUG(807, *YYCURSOR);
yych = *++YYCURSOR;
@@ -7438,15 +7461,15 @@ yy808:
++YYCURSOR;
YYDEBUG(809, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1864 "Zend/zend_language_scanner.l"
+#line 1887 "Zend/zend_language_scanner.l"
{
/* Invalid rule to return a more explicit parse error with proper line number */
yyless(0);
yy_pop_state();
ZVAL_NULL(zendlval);
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
-#line 7450 "Zend/zend_language_scanner.c"
+#line 7473 "Zend/zend_language_scanner.c"
yy810:
YYDEBUG(810, *YYCURSOR);
++YYCURSOR;
@@ -7455,27 +7478,27 @@ yy810:
yy811:
YYDEBUG(811, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1872 "Zend/zend_language_scanner.l"
+#line 1895 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, yytext, yyleng);
- return T_STRING;
+ RETURN_TOKEN(T_STRING);
}
-#line 7464 "Zend/zend_language_scanner.c"
+#line 7487 "Zend/zend_language_scanner.c"
yy812:
YYDEBUG(812, *YYCURSOR);
++YYCURSOR;
YYDEBUG(813, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 2375 "Zend/zend_language_scanner.l"
+#line 2398 "Zend/zend_language_scanner.l"
{
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
goto restart;
}
-#line 7479 "Zend/zend_language_scanner.c"
+#line 7502 "Zend/zend_language_scanner.c"
yy814:
YYDEBUG(814, *YYCURSOR);
++YYCURSOR;
@@ -7511,12 +7534,12 @@ yy816:
yy818:
YYDEBUG(818, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1849 "Zend/zend_language_scanner.l"
+#line 1872 "Zend/zend_language_scanner.l"
{
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
-#line 7520 "Zend/zend_language_scanner.c"
+#line 7543 "Zend/zend_language_scanner.c"
yy819:
YYDEBUG(819, *YYCURSOR);
++YYCURSOR;
@@ -7556,12 +7579,12 @@ yy824:
yy826:
YYDEBUG(826, *YYCURSOR);
yyleng = YYCURSOR - SCNG(yy_text);
-#line 1715 "Zend/zend_language_scanner.l"
+#line 1738 "Zend/zend_language_scanner.l"
{ /* Offset must be treated as a string */
ZVAL_STRINGL(zendlval, yytext, yyleng);
- return T_NUM_STRING;
+ RETURN_TOKEN(T_NUM_STRING);
}
-#line 7565 "Zend/zend_language_scanner.c"
+#line 7588 "Zend/zend_language_scanner.c"
yy827:
YYDEBUG(827, *YYCURSOR);
++YYCURSOR;
@@ -7584,6 +7607,6 @@ yy829:
goto yy826;
}
}
-#line 2384 "Zend/zend_language_scanner.l"
+#line 2407 "Zend/zend_language_scanner.l"
}
diff --git a/Zend/zend_language_scanner.h b/Zend/zend_language_scanner.h
index c82b3069c5..3b75ff8cc4 100644
--- a/Zend/zend_language_scanner.h
+++ b/Zend/zend_language_scanner.h
@@ -50,6 +50,9 @@ typedef struct _zend_lex_state {
zend_encoding_filter output_filter;
const zend_encoding *script_encoding;
+ /* hooks */
+ void (* on_event)(zend_php_scanner_event event, int token, int line);
+
zend_ast *ast;
zend_arena *ast_arena;
} zend_lex_state;
@@ -66,6 +69,7 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state);
ZEND_API int zend_prepare_string_for_scanning(zval *str, char *filename);
ZEND_API void zend_multibyte_yyinput_again(zend_encoding_filter old_input_filter, const zend_encoding *old_encoding);
ZEND_API int zend_multibyte_set_filter(const zend_encoding *onetime_encoding);
+ZEND_API void zend_lex_tstring(zval *zv);
END_EXTERN_C()
diff --git a/Zend/zend_language_scanner.l b/Zend/zend_language_scanner.l
index 1204287ad9..01c489cbe4 100644
--- a/Zend/zend_language_scanner.l
+++ b/Zend/zend_language_scanner.l
@@ -193,6 +193,7 @@ void shutdown_scanner(void)
zend_stack_destroy(&SCNG(state_stack));
zend_ptr_stack_clean(&SCNG(heredoc_label_stack), (void (*)(void *)) &heredoc_label_dtor, 1);
zend_ptr_stack_destroy(&SCNG(heredoc_label_stack));
+ SCNG(on_event) = NULL;
}
ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state)
@@ -223,6 +224,8 @@ ZEND_API void zend_save_lexical_state(zend_lex_state *lex_state)
lex_state->output_filter = SCNG(output_filter);
lex_state->script_encoding = SCNG(script_encoding);
+ lex_state->on_event = SCNG(on_event);
+
lex_state->ast = CG(ast);
lex_state->ast_arena = CG(ast_arena);
}
@@ -260,6 +263,8 @@ ZEND_API void zend_restore_lexical_state(zend_lex_state *lex_state)
SCNG(output_filter) = lex_state->output_filter;
SCNG(script_encoding) = lex_state->script_encoding;
+ SCNG(on_event) = lex_state->on_event;
+
CG(ast) = lex_state->ast;
CG(ast_arena) = lex_state->ast_arena;
@@ -276,6 +281,13 @@ ZEND_API void zend_destroy_file_handle(zend_file_handle *file_handle)
}
}
+ZEND_API void zend_lex_tstring(zval *zv)
+{
+ if (SCNG(on_event)) SCNG(on_event)(ON_FEEDBACK, T_STRING, 0);
+
+ ZVAL_STRINGL(zv, (char*)SCNG(yy_text), SCNG(yy_leng));
+}
+
#define BOM_UTF32_BE "\x00\x00\xfe\xff"
#define BOM_UTF32_LE "\xff\xfe\x00\x00"
#define BOM_UTF16_BE "\xfe\xff"
@@ -1083,9 +1095,20 @@ static int zend_scan_escape_string(zval *zendlval, char *str, int len, char quot
return SUCCESS;
}
+static zend_always_inline int emit_token(int token, int token_line)
+{
+ if(SCNG(on_event)) SCNG(on_event)(ON_TOKEN, token, token_line);
+
+ return token;
+}
+
+#define RETURN_TOKEN(token) return emit_token(token, start_line);
int lex_scan(zval *zendlval)
{
+
+int start_line = CG(zend_lineno);
+
restart:
SCNG(yy_text) = YYCURSOR;
@@ -1107,183 +1130,183 @@ NEWLINE ("\r"|"\n"|"\r\n")
<!*> := yyleng = YYCURSOR - SCNG(yy_text);
<ST_IN_SCRIPTING>"exit" {
- return T_EXIT;
+ RETURN_TOKEN(T_EXIT);
}
<ST_IN_SCRIPTING>"die" {
- return T_EXIT;
+ RETURN_TOKEN(T_EXIT);
}
<ST_IN_SCRIPTING>"function" {
- return T_FUNCTION;
+ RETURN_TOKEN(T_FUNCTION);
}
<ST_IN_SCRIPTING>"const" {
- return T_CONST;
+ RETURN_TOKEN(T_CONST);
}
<ST_IN_SCRIPTING>"return" {
- return T_RETURN;
+ RETURN_TOKEN(T_RETURN);
}
<ST_IN_SCRIPTING>"yield"{WHITESPACE}"from" {
- return T_YIELD_FROM;
+ RETURN_TOKEN(T_YIELD_FROM);
}
<ST_IN_SCRIPTING>"yield" {
- return T_YIELD;
+ RETURN_TOKEN(T_YIELD);
}
<ST_IN_SCRIPTING>"try" {
- return T_TRY;
+ RETURN_TOKEN(T_TRY);
}
<ST_IN_SCRIPTING>"catch" {
- return T_CATCH;
+ RETURN_TOKEN(T_CATCH);
}
<ST_IN_SCRIPTING>"finally" {
- return T_FINALLY;
+ RETURN_TOKEN(T_FINALLY);
}
<ST_IN_SCRIPTING>"throw" {
- return T_THROW;
+ RETURN_TOKEN(T_THROW);
}
<ST_IN_SCRIPTING>"if" {
- return T_IF;
+ RETURN_TOKEN(T_IF);
}
<ST_IN_SCRIPTING>"elseif" {
- return T_ELSEIF;
+ RETURN_TOKEN(T_ELSEIF);
}
<ST_IN_SCRIPTING>"endif" {
- return T_ENDIF;
+ RETURN_TOKEN(T_ENDIF);
}
<ST_IN_SCRIPTING>"else" {
- return T_ELSE;
+ RETURN_TOKEN(T_ELSE);
}
<ST_IN_SCRIPTING>"while" {
- return T_WHILE;
+ RETURN_TOKEN(T_WHILE);
}
<ST_IN_SCRIPTING>"endwhile" {
- return T_ENDWHILE;
+ RETURN_TOKEN(T_ENDWHILE);
}
<ST_IN_SCRIPTING>"do" {
- return T_DO;
+ RETURN_TOKEN(T_DO);
}
<ST_IN_SCRIPTING>"for" {
- return T_FOR;
+ RETURN_TOKEN(T_FOR);
}
<ST_IN_SCRIPTING>"endfor" {
- return T_ENDFOR;
+ RETURN_TOKEN(T_ENDFOR);
}
<ST_IN_SCRIPTING>"foreach" {
- return T_FOREACH;
+ RETURN_TOKEN(T_FOREACH);
}
<ST_IN_SCRIPTING>"endforeach" {
- return T_ENDFOREACH;
+ RETURN_TOKEN(T_ENDFOREACH);
}
<ST_IN_SCRIPTING>"declare" {
- return T_DECLARE;
+ RETURN_TOKEN(T_DECLARE);
}
<ST_IN_SCRIPTING>"enddeclare" {
- return T_ENDDECLARE;
+ RETURN_TOKEN(T_ENDDECLARE);
}
<ST_IN_SCRIPTING>"instanceof" {
- return T_INSTANCEOF;
+ RETURN_TOKEN(T_INSTANCEOF);
}
<ST_IN_SCRIPTING>"as" {
- return T_AS;
+ RETURN_TOKEN(T_AS);
}
<ST_IN_SCRIPTING>"switch" {
- return T_SWITCH;
+ RETURN_TOKEN(T_SWITCH);
}
<ST_IN_SCRIPTING>"endswitch" {
- return T_ENDSWITCH;
+ RETURN_TOKEN(T_ENDSWITCH);
}
<ST_IN_SCRIPTING>"case" {
- return T_CASE;
+ RETURN_TOKEN(T_CASE);
}
<ST_IN_SCRIPTING>"default" {
- return T_DEFAULT;
+ RETURN_TOKEN(T_DEFAULT);
}
<ST_IN_SCRIPTING>"break" {
- return T_BREAK;
+ RETURN_TOKEN(T_BREAK);
}
<ST_IN_SCRIPTING>"continue" {
- return T_CONTINUE;
+ RETURN_TOKEN(T_CONTINUE);
}
<ST_IN_SCRIPTING>"goto" {
- return T_GOTO;
+ RETURN_TOKEN(T_GOTO);
}
<ST_IN_SCRIPTING>"echo" {
- return T_ECHO;
+ RETURN_TOKEN(T_ECHO);
}
<ST_IN_SCRIPTING>"print" {
- return T_PRINT;
+ RETURN_TOKEN(T_PRINT);
}
<ST_IN_SCRIPTING>"class" {
- return T_CLASS;
+ RETURN_TOKEN(T_CLASS);
}
<ST_IN_SCRIPTING>"interface" {
- return T_INTERFACE;
+ RETURN_TOKEN(T_INTERFACE);
}
<ST_IN_SCRIPTING>"trait" {
- return T_TRAIT;
+ RETURN_TOKEN(T_TRAIT);
}
<ST_IN_SCRIPTING>"extends" {
- return T_EXTENDS;
+ RETURN_TOKEN(T_EXTENDS);
}
<ST_IN_SCRIPTING>"implements" {
- return T_IMPLEMENTS;
+ RETURN_TOKEN(T_IMPLEMENTS);
}
<ST_IN_SCRIPTING>"->" {
yy_push_state(ST_LOOKING_FOR_PROPERTY);
- return T_OBJECT_OPERATOR;
+ RETURN_TOKEN(T_OBJECT_OPERATOR);
}
<ST_IN_SCRIPTING,ST_LOOKING_FOR_PROPERTY>{WHITESPACE}+ {
HANDLE_NEWLINES(yytext, yyleng);
- return T_WHITESPACE;
+ RETURN_TOKEN(T_WHITESPACE);
}
<ST_LOOKING_FOR_PROPERTY>"->" {
- return T_OBJECT_OPERATOR;
+ RETURN_TOKEN(T_OBJECT_OPERATOR);
}
<ST_LOOKING_FOR_PROPERTY>{LABEL} {
yy_pop_state();
zend_copy_value(zendlval, yytext, yyleng);
- return T_STRING;
+ RETURN_TOKEN(T_STRING);
}
<ST_LOOKING_FOR_PROPERTY>{ANY_CHAR} {
@@ -1293,283 +1316,283 @@ NEWLINE ("\r"|"\n"|"\r\n")
}
<ST_IN_SCRIPTING>"::" {
- return T_PAAMAYIM_NEKUDOTAYIM;
+ RETURN_TOKEN(T_PAAMAYIM_NEKUDOTAYIM);
}
<ST_IN_SCRIPTING>"\\" {
- return T_NS_SEPARATOR;
+ RETURN_TOKEN(T_NS_SEPARATOR);
}
<ST_IN_SCRIPTING>"..." {
- return T_ELLIPSIS;
+ RETURN_TOKEN(T_ELLIPSIS);
}
<ST_IN_SCRIPTING>"??" {
- return T_COALESCE;
+ RETURN_TOKEN(T_COALESCE);
}
<ST_IN_SCRIPTING>"new" {
- return T_NEW;
+ RETURN_TOKEN(T_NEW);
}
<ST_IN_SCRIPTING>"clone" {
- return T_CLONE;
+ RETURN_TOKEN(T_CLONE);
}
<ST_IN_SCRIPTING>"var" {
- return T_VAR;
+ RETURN_TOKEN(T_VAR);
}
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("int"|"integer"){TABS_AND_SPACES}")" {
- return T_INT_CAST;
+ RETURN_TOKEN(T_INT_CAST);
}
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("real"|"double"|"float"){TABS_AND_SPACES}")" {
- return T_DOUBLE_CAST;
+ RETURN_TOKEN(T_DOUBLE_CAST);
}
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("string"|"binary"){TABS_AND_SPACES}")" {
- return T_STRING_CAST;
+ RETURN_TOKEN(T_STRING_CAST);
}
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"array"{TABS_AND_SPACES}")" {
- return T_ARRAY_CAST;
+ RETURN_TOKEN(T_ARRAY_CAST);
}
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}"object"{TABS_AND_SPACES}")" {
- return T_OBJECT_CAST;
+ RETURN_TOKEN(T_OBJECT_CAST);
}
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("bool"|"boolean"){TABS_AND_SPACES}")" {
- return T_BOOL_CAST;
+ RETURN_TOKEN(T_BOOL_CAST);
}
<ST_IN_SCRIPTING>"("{TABS_AND_SPACES}("unset"){TABS_AND_SPACES}")" {
- return T_UNSET_CAST;
+ RETURN_TOKEN(T_UNSET_CAST);
}
<ST_IN_SCRIPTING>"eval" {
- return T_EVAL;
+ RETURN_TOKEN(T_EVAL);
}
<ST_IN_SCRIPTING>"include" {
- return T_INCLUDE;
+ RETURN_TOKEN(T_INCLUDE);
}
<ST_IN_SCRIPTING>"include_once" {
- return T_INCLUDE_ONCE;
+ RETURN_TOKEN(T_INCLUDE_ONCE);
}
<ST_IN_SCRIPTING>"require" {
- return T_REQUIRE;
+ RETURN_TOKEN(T_REQUIRE);
}
<ST_IN_SCRIPTING>"require_once" {
- return T_REQUIRE_ONCE;
+ RETURN_TOKEN(T_REQUIRE_ONCE);
}
<ST_IN_SCRIPTING>"namespace" {
- return T_NAMESPACE;
+ RETURN_TOKEN(T_NAMESPACE);
}
<ST_IN_SCRIPTING>"use" {
- return T_USE;
+ RETURN_TOKEN(T_USE);
}
<ST_IN_SCRIPTING>"insteadof" {
- return T_INSTEADOF;
+ RETURN_TOKEN(T_INSTEADOF);
}
<ST_IN_SCRIPTING>"global" {
- return T_GLOBAL;
+ RETURN_TOKEN(T_GLOBAL);
}
<ST_IN_SCRIPTING>"isset" {
- return T_ISSET;
+ RETURN_TOKEN(T_ISSET);
}
<ST_IN_SCRIPTING>"empty" {
- return T_EMPTY;
+ RETURN_TOKEN(T_EMPTY);
}
<ST_IN_SCRIPTING>"__halt_compiler" {
- return T_HALT_COMPILER;
+ RETURN_TOKEN(T_HALT_COMPILER);
}
<ST_IN_SCRIPTING>"static" {
- return T_STATIC;
+ RETURN_TOKEN(T_STATIC);
}
<ST_IN_SCRIPTING>"abstract" {
- return T_ABSTRACT;
+ RETURN_TOKEN(T_ABSTRACT);
}
<ST_IN_SCRIPTING>"final" {
- return T_FINAL;
+ RETURN_TOKEN(T_FINAL);
}
<ST_IN_SCRIPTING>"private" {
- return T_PRIVATE;
+ RETURN_TOKEN(T_PRIVATE);
}
<ST_IN_SCRIPTING>"protected" {
- return T_PROTECTED;
+ RETURN_TOKEN(T_PROTECTED);
}
<ST_IN_SCRIPTING>"public" {
- return T_PUBLIC;
+ RETURN_TOKEN(T_PUBLIC);
}
<ST_IN_SCRIPTING>"unset" {
- return T_UNSET;
+ RETURN_TOKEN(T_UNSET);
}
<ST_IN_SCRIPTING>"=>" {
- return T_DOUBLE_ARROW;
+ RETURN_TOKEN(T_DOUBLE_ARROW);
}
<ST_IN_SCRIPTING>"list" {
- return T_LIST;
+ RETURN_TOKEN(T_LIST);
}
<ST_IN_SCRIPTING>"array" {
- return T_ARRAY;
+ RETURN_TOKEN(T_ARRAY);
}
<ST_IN_SCRIPTING>"callable" {
- return T_CALLABLE;
+ RETURN_TOKEN(T_CALLABLE);
}
<ST_IN_SCRIPTING>"++" {
- return T_INC;
+ RETURN_TOKEN(T_INC);
}
<ST_IN_SCRIPTING>"--" {
- return T_DEC;
+ RETURN_TOKEN(T_DEC);
}
<ST_IN_SCRIPTING>"===" {
- return T_IS_IDENTICAL;
+ RETURN_TOKEN(T_IS_IDENTICAL);
}
<ST_IN_SCRIPTING>"!==" {
- return T_IS_NOT_IDENTICAL;
+ RETURN_TOKEN(T_IS_NOT_IDENTICAL);
}
<ST_IN_SCRIPTING>"==" {
- return T_IS_EQUAL;
+ RETURN_TOKEN(T_IS_EQUAL);
}
<ST_IN_SCRIPTING>"!="|"<>" {
- return T_IS_NOT_EQUAL;
+ RETURN_TOKEN(T_IS_NOT_EQUAL);
}
<ST_IN_SCRIPTING>"<=>" {
- return T_SPACESHIP;
+ RETURN_TOKEN(T_SPACESHIP);
}
<ST_IN_SCRIPTING>"<=" {
- return T_IS_SMALLER_OR_EQUAL;
+ RETURN_TOKEN(T_IS_SMALLER_OR_EQUAL);
}
<ST_IN_SCRIPTING>">=" {
- return T_IS_GREATER_OR_EQUAL;
+ RETURN_TOKEN(T_IS_GREATER_OR_EQUAL);
}
<ST_IN_SCRIPTING>"+=" {
- return T_PLUS_EQUAL;
+ RETURN_TOKEN(T_PLUS_EQUAL);
}
<ST_IN_SCRIPTING>"-=" {
- return T_MINUS_EQUAL;
+ RETURN_TOKEN(T_MINUS_EQUAL);
}
<ST_IN_SCRIPTING>"*=" {
- return T_MUL_EQUAL;
+ RETURN_TOKEN(T_MUL_EQUAL);
}
<ST_IN_SCRIPTING>"*\*" {
- return T_POW;
+ RETURN_TOKEN(T_POW);
}
<ST_IN_SCRIPTING>"*\*=" {
- return T_POW_EQUAL;
+ RETURN_TOKEN(T_POW_EQUAL);
}
<ST_IN_SCRIPTING>"/=" {
- return T_DIV_EQUAL;
+ RETURN_TOKEN(T_DIV_EQUAL);
}
<ST_IN_SCRIPTING>".=" {
- return T_CONCAT_EQUAL;
+ RETURN_TOKEN(T_CONCAT_EQUAL);
}
<ST_IN_SCRIPTING>"%=" {
- return T_MOD_EQUAL;
+ RETURN_TOKEN(T_MOD_EQUAL);
}
<ST_IN_SCRIPTING>"<<=" {
- return T_SL_EQUAL;
+ RETURN_TOKEN(T_SL_EQUAL);
}
<ST_IN_SCRIPTING>">>=" {
- return T_SR_EQUAL;
+ RETURN_TOKEN(T_SR_EQUAL);
}
<ST_IN_SCRIPTING>"&=" {
- return T_AND_EQUAL;
+ RETURN_TOKEN(T_AND_EQUAL);
}
<ST_IN_SCRIPTING>"|=" {
- return T_OR_EQUAL;
+ RETURN_TOKEN(T_OR_EQUAL);
}
<ST_IN_SCRIPTING>"^=" {
- return T_XOR_EQUAL;
+ RETURN_TOKEN(T_XOR_EQUAL);
}
<ST_IN_SCRIPTING>"||" {
- return T_BOOLEAN_OR;
+ RETURN_TOKEN(T_BOOLEAN_OR);
}
<ST_IN_SCRIPTING>"&&" {
- return T_BOOLEAN_AND;
+ RETURN_TOKEN(T_BOOLEAN_AND);
}
<ST_IN_SCRIPTING>"OR" {
- return T_LOGICAL_OR;
+ RETURN_TOKEN(T_LOGICAL_OR);
}
<ST_IN_SCRIPTING>"AND" {
- return T_LOGICAL_AND;
+ RETURN_TOKEN(T_LOGICAL_AND);
}
<ST_IN_SCRIPTING>"XOR" {
- return T_LOGICAL_XOR;
+ RETURN_TOKEN(T_LOGICAL_XOR);
}
<ST_IN_SCRIPTING>"<<" {
- return T_SL;
+ RETURN_TOKEN(T_SL);
}
<ST_IN_SCRIPTING>">>" {
- return T_SR;
+ RETURN_TOKEN(T_SR);
}
<ST_IN_SCRIPTING>{TOKENS} {
- return yytext[0];
+ RETURN_TOKEN(yytext[0]);
}
<ST_IN_SCRIPTING>"{" {
yy_push_state(ST_IN_SCRIPTING);
- return '{';
+ RETURN_TOKEN('{');
}
<ST_DOUBLE_QUOTES,ST_BACKQUOTE,ST_HEREDOC>"${" {
yy_push_state(ST_LOOKING_FOR_VARNAME);
- return T_DOLLAR_OPEN_CURLY_BRACES;
+ RETURN_TOKEN(T_DOLLAR_OPEN_CURLY_BRACES);
}
@@ -1578,7 +1601,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
if (!zend_stack_is_empty(&SCNG(state_stack))) {
yy_pop_state();
}
- return '}';
+ RETURN_TOKEN('}');
}
@@ -1587,7 +1610,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
zend_copy_value(zendlval, yytext, yyleng);
yy_pop_state();
yy_push_state(ST_IN_SCRIPTING);
- return T_STRING_VARNAME;
+ RETURN_TOKEN(T_STRING_VARNAME);
}
@@ -1617,12 +1640,12 @@ NEWLINE ("\r"|"\n"|"\r\n")
ZVAL_LONG(zendlval, ZEND_STRTOL(bin, &end, 2));
ZEND_ASSERT(!errno && end == yytext + yyleng);
}
- return T_LNUMBER;
+ RETURN_TOKEN(T_LNUMBER);
} else {
ZVAL_DOUBLE(zendlval, zend_bin_strtod(bin, (const char **)&end));
/* errno isn't checked since we allow HUGE_VAL/INF overflow */
ZEND_ASSERT(end == yytext + yyleng);
- return T_DNUMBER;
+ RETURN_TOKEN(T_DNUMBER);
}
}
@@ -1636,7 +1659,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
*/
if (end != yytext + yyleng) {
zend_throw_exception(zend_get_parse_error(), "Invalid numeric literal", E_PARSE);
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
} else {
errno = 0;
@@ -1653,19 +1676,19 @@ NEWLINE ("\r"|"\n"|"\r\n")
if (end != yytext + yyleng) {
zend_throw_exception(zend_get_parse_error(),
"Invalid numeric literal", E_PARSE);
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
ZEND_ASSERT(!errno);
- return T_DNUMBER;
+ RETURN_TOKEN(T_DNUMBER);
}
/* Also not an assert for the same reason */
if (end != yytext + yyleng) {
zend_throw_exception(zend_get_parse_error(), "Invalid numeric literal", E_PARSE);
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
}
ZEND_ASSERT(!errno);
- return T_LNUMBER;
+ RETURN_TOKEN(T_LNUMBER);
}
<ST_IN_SCRIPTING>{HNUM} {
@@ -1687,12 +1710,12 @@ NEWLINE ("\r"|"\n"|"\r\n")
ZVAL_LONG(zendlval, ZEND_STRTOL(hex, &end, 16));
ZEND_ASSERT(!errno && end == hex + len);
}
- return T_LNUMBER;
+ RETURN_TOKEN(T_LNUMBER);
} else {
ZVAL_DOUBLE(zendlval, zend_hex_strtod(hex, (const char **)&end));
/* errno isn't checked since we allow HUGE_VAL/INF overflow */
ZEND_ASSERT(end == hex + len);
- return T_DNUMBER;
+ RETURN_TOKEN(T_DNUMBER);
}
}
@@ -1709,12 +1732,12 @@ NEWLINE ("\r"|"\n"|"\r\n")
string:
ZVAL_STRINGL(zendlval, yytext, yyleng);
}
- return T_NUM_STRING;
+ RETURN_TOKEN(T_NUM_STRING);
}
<ST_VAR_OFFSET>{LNUM}|{HNUM}|{BNUM} { /* Offset must be treated as a string */
ZVAL_STRINGL(zendlval, yytext, yyleng);
- return T_NUM_STRING;
+ RETURN_TOKEN(T_NUM_STRING);
}
<ST_IN_SCRIPTING>{DNUM}|{EXPONENT_DNUM} {
@@ -1723,59 +1746,59 @@ string:
ZVAL_DOUBLE(zendlval, zend_strtod(yytext, &end));
/* errno isn't checked since we allow HUGE_VAL/INF overflow */
ZEND_ASSERT(end == yytext + yyleng);
- return T_DNUMBER;
+ RETURN_TOKEN(T_DNUMBER);
}
<ST_IN_SCRIPTING>"__CLASS__" {
- return T_CLASS_C;
+ RETURN_TOKEN(T_CLASS_C);
}
<ST_IN_SCRIPTING>"__TRAIT__" {
- return T_TRAIT_C;
+ RETURN_TOKEN(T_TRAIT_C);
}
<ST_IN_SCRIPTING>"__FUNCTION__" {
- return T_FUNC_C;
+ RETURN_TOKEN(T_FUNC_C);
}
<ST_IN_SCRIPTING>"__METHOD__" {
- return T_METHOD_C;
+ RETURN_TOKEN(T_METHOD_C);
}
<ST_IN_SCRIPTING>"__LINE__" {
- return T_LINE;
+ RETURN_TOKEN(T_LINE);
}
<ST_IN_SCRIPTING>"__FILE__" {
- return T_FILE;
+ RETURN_TOKEN(T_FILE);
}
<ST_IN_SCRIPTING>"__DIR__" {
- return T_DIR;
+ RETURN_TOKEN(T_DIR);
}
<ST_IN_SCRIPTING>"__NAMESPACE__" {
- return T_NS_C;
+ RETURN_TOKEN(T_NS_C);
}
<INITIAL>"<?=" {
BEGIN(ST_IN_SCRIPTING);
- return T_OPEN_TAG_WITH_ECHO;
+ RETURN_TOKEN(T_OPEN_TAG_WITH_ECHO);
}
<INITIAL>"<?php"([ \t]|{NEWLINE}) {
HANDLE_NEWLINE(yytext[yyleng-1]);
BEGIN(ST_IN_SCRIPTING);
- return T_OPEN_TAG;
+ RETURN_TOKEN(T_OPEN_TAG);
}
<INITIAL>"<?" {
if (CG(short_tags)) {
BEGIN(ST_IN_SCRIPTING);
- return T_OPEN_TAG;
+ RETURN_TOKEN(T_OPEN_TAG);
} else {
goto inline_char_handler;
}
@@ -1783,7 +1806,7 @@ string:
<INITIAL>{ANY_CHAR} {
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
inline_char_handler:
@@ -1823,7 +1846,7 @@ inline_char_handler:
ZVAL_STRINGL(zendlval, yytext, yyleng);
}
HANDLE_NEWLINES(yytext, yyleng);
- return T_INLINE_HTML;
+ RETURN_TOKEN(T_INLINE_HTML);
}
@@ -1834,7 +1857,7 @@ inline_char_handler:
yyless(yyleng - 3);
yy_push_state(ST_LOOKING_FOR_PROPERTY);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
/* A [ always designates a variable offset, regardless of what follows
@@ -1843,22 +1866,22 @@ inline_char_handler:
yyless(yyleng - 1);
yy_push_state(ST_VAR_OFFSET);
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
<ST_IN_SCRIPTING,ST_DOUBLE_QUOTES,ST_HEREDOC,ST_BACKQUOTE,ST_VAR_OFFSET>"$"{LABEL} {
zend_copy_value(zendlval, (yytext+1), (yyleng-1));
- return T_VARIABLE;
+ RETURN_TOKEN(T_VARIABLE);
}
<ST_VAR_OFFSET>"]" {
yy_pop_state();
- return ']';
+ RETURN_TOKEN(']');
}
<ST_VAR_OFFSET>{TOKENS}|[{}"`] {
/* Only '[' can be valid, but returning other tokens will allow a more explicit parse error */
- return yytext[0];
+ RETURN_TOKEN(yytext[0]);
}
<ST_VAR_OFFSET>[ \n\r\t\\'#] {
@@ -1866,12 +1889,12 @@ inline_char_handler:
yyless(0);
yy_pop_state();
ZVAL_NULL(zendlval);
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
<ST_IN_SCRIPTING,ST_VAR_OFFSET>{LABEL} {
zend_copy_value(zendlval, yytext, yyleng);
- return T_STRING;
+ RETURN_TOKEN(T_STRING);
}
@@ -1901,7 +1924,7 @@ inline_char_handler:
yyleng = YYCURSOR - SCNG(yy_text);
- return T_COMMENT;
+ RETURN_TOKEN(T_COMMENT);
}
<ST_IN_SCRIPTING>"/*"|"/**"{WHITESPACE} {
@@ -1931,15 +1954,15 @@ inline_char_handler:
if (doc_com) {
CG(doc_comment) = zend_string_init(yytext, yyleng, 0);
- return T_DOC_COMMENT;
+ RETURN_TOKEN(T_DOC_COMMENT);
}
- return T_COMMENT;
+ RETURN_TOKEN(T_COMMENT);
}
<ST_IN_SCRIPTING>"?>"{NEWLINE}? {
BEGIN(INITIAL);
- return T_CLOSE_TAG; /* implicit ';' at php-end tag */
+ RETURN_TOKEN(T_CLOSE_TAG); /* implicit ';' at php-end tag */
}
@@ -1965,7 +1988,7 @@ inline_char_handler:
* for ' (unrecognized by parser), instead of old flex fallback to "Unexpected character..."
* rule, which continued in ST_IN_SCRIPTING state after the quote */
ZVAL_NULL(zendlval);
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
}
@@ -2008,7 +2031,7 @@ inline_char_handler:
SCNG(output_filter)((unsigned char **)&str, &sz, (unsigned char *)s, (size_t)Z_STRLEN_P(zendlval));
ZVAL_STRINGL(zendlval, str, sz);
}
- return T_CONSTANT_ENCAPSED_STRING;
+ RETURN_TOKEN(T_CONSTANT_ENCAPSED_STRING);
}
@@ -2020,9 +2043,9 @@ inline_char_handler:
case '"':
yyleng = YYCURSOR - SCNG(yy_text);
if (zend_scan_escape_string(zendlval, yytext+bprefix+1, yyleng-bprefix-2, '"') == FAILURE) {
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
- return T_CONSTANT_ENCAPSED_STRING;
+ RETURN_TOKEN(T_CONSTANT_ENCAPSED_STRING);
case '$':
if (IS_LABEL_START(*YYCURSOR) || *YYCURSOR == '{') {
break;
@@ -2052,7 +2075,7 @@ inline_char_handler:
YYCURSOR = SCNG(yy_text) + yyleng;
BEGIN(ST_DOUBLE_QUOTES);
- return '"';
+ RETURN_TOKEN('"');
}
@@ -2100,13 +2123,13 @@ inline_char_handler:
zend_ptr_stack_push(&SCNG(heredoc_label_stack), (void *) heredoc_label);
- return T_START_HEREDOC;
+ RETURN_TOKEN(T_START_HEREDOC);
}
<ST_IN_SCRIPTING>[`] {
BEGIN(ST_BACKQUOTE);
- return '`';
+ RETURN_TOKEN('`');
}
@@ -2120,7 +2143,7 @@ inline_char_handler:
efree(heredoc_label);
BEGIN(ST_IN_SCRIPTING);
- return T_END_HEREDOC;
+ RETURN_TOKEN(T_END_HEREDOC);
}
@@ -2128,18 +2151,18 @@ inline_char_handler:
Z_LVAL_P(zendlval) = (zend_long) '{';
yy_push_state(ST_IN_SCRIPTING);
yyless(1);
- return T_CURLY_OPEN;
+ RETURN_TOKEN(T_CURLY_OPEN);
}
<ST_DOUBLE_QUOTES>["] {
BEGIN(ST_IN_SCRIPTING);
- return '"';
+ RETURN_TOKEN('"');
}
<ST_BACKQUOTE>[`] {
BEGIN(ST_IN_SCRIPTING);
- return '`';
+ RETURN_TOKEN('`');
}
@@ -2152,7 +2175,7 @@ inline_char_handler:
}
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
YYCURSOR++;
@@ -2189,15 +2212,15 @@ double_quotes_scan_done:
yyleng = YYCURSOR - SCNG(yy_text);
if (zend_scan_escape_string(zendlval, yytext, yyleng, '"') == FAILURE) {
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
<ST_BACKQUOTE>{ANY_CHAR} {
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
if (yytext[0] == '\\' && YYCURSOR < YYLIMIT) {
YYCURSOR++;
@@ -2233,9 +2256,9 @@ double_quotes_scan_done:
yyleng = YYCURSOR - SCNG(yy_text);
if (zend_scan_escape_string(zendlval, yytext, yyleng, '`') == FAILURE) {
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
@@ -2245,7 +2268,7 @@ double_quotes_scan_done:
zend_heredoc_label *heredoc_label = zend_ptr_stack_top(&SCNG(heredoc_label_stack));
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
YYCURSOR--;
@@ -2309,9 +2332,9 @@ heredoc_scan_done:
yyleng = YYCURSOR - SCNG(yy_text);
if (zend_scan_escape_string(zendlval, yytext, yyleng - newline, 0) == FAILURE) {
- return T_ERROR;
+ RETURN_TOKEN(T_ERROR);
}
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
@@ -2321,7 +2344,7 @@ heredoc_scan_done:
zend_heredoc_label *heredoc_label = zend_ptr_stack_top(&SCNG(heredoc_label_stack));
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
YYCURSOR--;
@@ -2368,13 +2391,13 @@ nowdoc_scan_done:
zend_copy_value(zendlval, yytext, yyleng - newline);
HANDLE_NEWLINES(yytext, yyleng - newline);
- return T_ENCAPSED_AND_WHITESPACE;
+ RETURN_TOKEN(T_ENCAPSED_AND_WHITESPACE);
}
<ST_IN_SCRIPTING,ST_VAR_OFFSET>{ANY_CHAR} {
if (YYCURSOR > YYLIMIT) {
- return 0;
+ RETURN_TOKEN(END);
}
zend_error(E_COMPILE_WARNING,"Unexpected character in input: '%c' (ASCII=%d) state=%d", yytext[0], yytext[0], YYSTATE);
diff --git a/Zend/zend_long.h b/Zend/zend_long.h
index 1acd2cfb08..4c81105438 100644
--- a/Zend/zend_long.h
+++ b/Zend/zend_long.h
@@ -25,7 +25,7 @@
#include "main/php_stdint.h"
/* This is the heart of the whole int64 enablement in zval. */
-#if defined(__X86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)
+#if defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)
# define ZEND_ENABLE_ZVAL_LONG64 1
#endif
diff --git a/Zend/zend_object_handlers.c b/Zend/zend_object_handlers.c
index 363ea139d6..74ae382df4 100644
--- a/Zend/zend_object_handlers.c
+++ b/Zend/zend_object_handlers.c
@@ -265,15 +265,14 @@ static void zend_std_call_issetter(zval *object, zval *member, zval *retval) /*
static zend_always_inline int zend_verify_property_access(zend_property_info *property_info, zend_class_entry *ce) /* {{{ */
{
- switch (property_info->flags & ZEND_ACC_PPP_MASK) {
- case ZEND_ACC_PUBLIC:
- return 1;
- case ZEND_ACC_PROTECTED:
- return zend_check_protected(property_info->ce, EG(scope));
- case ZEND_ACC_PRIVATE:
- return (ce == EG(scope) || property_info->ce == EG(scope));
+ if (property_info->flags & ZEND_ACC_PUBLIC) {
+ return 1;
+ } else if (property_info->flags & ZEND_ACC_PRIVATE) {
+ return (ce == EG(scope) || property_info->ce == EG(scope));
+ } else {
+ ZEND_ASSERT(property_info->flags & ZEND_ACC_PROTECTED);
+ return zend_check_protected(property_info->ce, EG(scope));
}
- return 0;
}
/* }}} */
@@ -673,7 +672,7 @@ write_std_property:
if (Z_REFCOUNTED_P(value)) {
if (Z_ISREF_P(value)) {
/* if we assign referenced variable, we should separate it */
- ZVAL_DUP(&tmp, Z_REFVAL_P(value));
+ ZVAL_COPY(&tmp, Z_REFVAL_P(value));
value = &tmp;
} else {
Z_ADDREF_P(value);
@@ -1256,8 +1255,10 @@ ZEND_API zval *zend_std_get_static_property(zend_class_entry *ce, zend_string *p
goto undeclared_property;
}
- if (UNEXPECTED(zend_update_class_constants(ce)) != SUCCESS) {
- return NULL;
+ if (UNEXPECTED(!(ce->ce_flags & ZEND_ACC_CONSTANTS_UPDATED))) {
+ if (UNEXPECTED(zend_update_class_constants(ce)) != SUCCESS) {
+ return NULL;
+ }
}
ret = CE_STATIC_MEMBERS(ce) + property_info->offset;
diff --git a/Zend/zend_objects.c b/Zend/zend_objects.c
index 2826c322a9..9007661f03 100644
--- a/Zend/zend_objects.c
+++ b/Zend/zend_objects.c
@@ -164,7 +164,8 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o
dst++;
} while (src != end);
}
- if (old_object->properties) {
+ if (old_object->properties &&
+ EXPECTED(zend_hash_num_elements(old_object->properties))) {
zval *prop, new_prop;
zend_ulong num_key;
zend_string *key;
@@ -172,6 +173,9 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o
if (!new_object->properties) {
ALLOC_HASHTABLE(new_object->properties);
zend_hash_init(new_object->properties, zend_hash_num_elements(old_object->properties), NULL, ZVAL_PTR_DTOR, 0);
+ zend_hash_real_init(new_object->properties, 0);
+ } else {
+ zend_hash_extend(new_object->properties, new_object->properties->nNumUsed + zend_hash_num_elements(old_object->properties), 0);
}
ZEND_HASH_FOREACH_KEY_VAL(old_object->properties, num_key, key, prop) {
@@ -181,8 +185,8 @@ ZEND_API void zend_objects_clone_members(zend_object *new_object, zend_object *o
ZVAL_COPY_VALUE(&new_prop, prop);
zval_add_ref(&new_prop);
}
- if (key) {
- zend_hash_add_new(new_object->properties, key, &new_prop);
+ if (EXPECTED(key)) {
+ _zend_hash_append(new_object->properties, key, &new_prop);
} else {
zend_hash_index_add_new(new_object->properties, num_key, &new_prop);
}
diff --git a/Zend/zend_opcode.c b/Zend/zend_opcode.c
index f24fc9f193..abb91b1ee3 100644
--- a/Zend/zend_opcode.c
+++ b/Zend/zend_opcode.c
@@ -180,6 +180,7 @@ ZEND_API void zend_cleanup_internal_class_data(zend_class_entry *ce)
#else
ce->static_members_table = NULL;
#endif
+ ce->ce_flags &= ~ZEND_ACC_CONSTANTS_UPDATED;
while (p != end) {
i_zval_ptr_dtor(p ZEND_FILE_LINE_CC);
p++;
@@ -409,6 +410,10 @@ ZEND_API void destroy_op_array(zend_op_array *op_array)
}
if (arg_info[i].class_name) {
zend_string_release(arg_info[i].class_name);
+
+ if (arg_info[i].lower_class_name) {
+ zend_string_release(arg_info[i].lower_class_name);
+ }
}
}
efree(arg_info);
@@ -666,6 +671,20 @@ static void zend_resolve_finally_ret(zend_op_array *op_array, uint32_t op_num)
}
}
+static uint32_t zend_get_brk_cont_target(const zend_op_array *op_array, const zend_op *opline) {
+ int nest_levels = opline->op2.num;
+ int array_offset = opline->op1.num;
+ zend_brk_cont_element *jmp_to;
+ do {
+ jmp_to = &op_array->brk_cont_array[array_offset];
+ if (nest_levels > 1) {
+ array_offset = jmp_to->parent;
+ }
+ } while (--nest_levels > 0);
+
+ return opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont;
+}
+
static void zend_resolve_finally_calls(zend_op_array *op_array)
{
uint32_t i, j;
@@ -681,22 +700,8 @@ static void zend_resolve_finally_calls(zend_op_array *op_array)
break;
case ZEND_BRK:
case ZEND_CONT:
- {
- int nest_levels, array_offset;
- zend_brk_cont_element *jmp_to;
-
- nest_levels = Z_LVAL(op_array->literals[opline->op2.constant]);
- if ((array_offset = opline->op1.opline_num) != -1) {
- do {
- jmp_to = &op_array->brk_cont_array[array_offset];
- if (nest_levels > 1) {
- array_offset = jmp_to->parent;
- }
- } while (--nest_levels > 0);
- zend_resolve_finally_call(op_array, i, opline->opcode == ZEND_BRK ? jmp_to->brk : jmp_to->cont);
- break;
- }
- }
+ zend_resolve_finally_call(op_array, i, zend_get_brk_cont_target(op_array, opline));
+ break;
case ZEND_GOTO:
if (Z_TYPE_P(CT_CONSTANT_EX(op_array, opline->op2.constant)) != IS_LONG) {
uint32_t num = opline->op2.constant;
@@ -774,6 +779,16 @@ ZEND_API int pass_two(zend_op_array *op_array)
case ZEND_DECLARE_INHERITED_CLASS_DELAYED:
opline->extended_value = (uint32_t)(zend_intptr_t)ZEND_CALL_VAR_NUM(NULL, op_array->last_var + opline->extended_value);
break;
+ case ZEND_BRK:
+ case ZEND_CONT:
+ {
+ uint32_t jmp_target = zend_get_brk_cont_target(op_array, opline);
+ opline->opcode = ZEND_JMP;
+ opline->op1.opline_num = jmp_target;
+ opline->op2.num = 0;
+ ZEND_PASS_TWO_UPDATE_JMP_TARGET(op_array, opline, opline->op1);
+ }
+ break;
case ZEND_GOTO:
if (Z_TYPE_P(RT_CONSTANT(op_array, opline->op2)) != IS_LONG) {
zend_resolve_goto_label(op_array, opline, 1);
diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c
index e384031ddb..a6172179f5 100644
--- a/Zend/zend_operators.c
+++ b/Zend/zend_operators.c
@@ -209,7 +209,7 @@ try_again:
(op) = &(holder); \
break; \
case IS_OBJECT: \
- ZVAL_DUP(&(holder), op); \
+ ZVAL_COPY(&(holder), op); \
convert_to_long_base(&(holder), 10); \
if (Z_TYPE(holder) == IS_LONG) { \
(op) = &(holder); \
@@ -312,7 +312,7 @@ ZEND_API void ZEND_FASTCALL convert_to_long_base(zval *op, int base) /* {{{ */
break;
case IS_ARRAY:
tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
- zval_dtor(op);
+ zval_ptr_dtor(op);
ZVAL_LONG(op, tmp);
break;
case IS_OBJECT:
@@ -369,7 +369,7 @@ ZEND_API void ZEND_FASTCALL convert_to_double(zval *op) /* {{{ */
break;
case IS_ARRAY:
tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
- zval_dtor(op);
+ zval_ptr_dtor(op);
ZVAL_DOUBLE(op, tmp);
break;
case IS_OBJECT:
@@ -408,7 +408,7 @@ ZEND_API void ZEND_FASTCALL convert_to_null(zval *op) /* {{{ */
}
}
- zval_dtor(op);
+ zval_ptr_dtor(op);
ZVAL_NULL(op);
}
/* }}} */
@@ -452,7 +452,7 @@ ZEND_API void ZEND_FASTCALL convert_to_boolean(zval *op) /* {{{ */
break;
case IS_ARRAY:
tmp = (zend_hash_num_elements(Z_ARRVAL_P(op))?1:0);
- zval_dtor(op);
+ zval_ptr_dtor(op);
ZVAL_BOOL(op, tmp);
break;
case IS_OBJECT:
@@ -516,7 +516,7 @@ ZEND_API void ZEND_FASTCALL _convert_to_string(zval *op ZEND_FILE_LINE_DC) /* {{
}
case IS_ARRAY:
zend_error(E_NOTICE, "Array to string conversion");
- zval_dtor(op);
+ zval_ptr_dtor(op);
ZVAL_NEW_STR(op, zend_string_init("Array", sizeof("Array")-1, 0));
break;
case IS_OBJECT: {
@@ -603,14 +603,10 @@ ZEND_API void ZEND_FASTCALL convert_to_object(zval *op) /* {{{ */
switch (Z_TYPE_P(op)) {
case IS_ARRAY:
{
- HashTable *properties = emalloc(sizeof(HashTable));
- zend_array *arr = Z_ARR_P(op);
-
- memcpy(properties, Z_ARRVAL_P(op), sizeof(HashTable));
- object_and_properties_init(op, zend_standard_class_def, properties);
- if (--GC_REFCOUNT(arr) == 0) {
- efree_size(arr, sizeof(zend_array));
- }
+ zval tmp;
+ ZVAL_COPY_VALUE(&tmp, op);
+ SEPARATE_ARRAY(&tmp);
+ object_and_properties_init(op, zend_standard_class_def, Z_ARR(tmp));
break;
}
case IS_OBJECT:
@@ -1249,11 +1245,20 @@ try_again:
case IS_STRING: {
size_t i;
- ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(op1), 0));
- for (i = 0; i < Z_STRLEN_P(op1); i++) {
- Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i];
+ if (Z_STRLEN_P(op1) == 1) {
+ zend_uchar not = (zend_uchar) ~*Z_STRVAL_P(op1);
+ if (CG(one_char_string)[not]) {
+ ZVAL_INTERNED_STR(result, CG(one_char_string)[not]);
+ } else {
+ ZVAL_NEW_STR(result, zend_string_init((char *) &not, 1, 0));
+ }
+ } else {
+ ZVAL_NEW_STR(result, zend_string_alloc(Z_STRLEN_P(op1), 0));
+ for (i = 0; i < Z_STRLEN_P(op1); i++) {
+ Z_STRVAL_P(result)[i] = ~Z_STRVAL_P(op1)[i];
+ }
+ Z_STRVAL_P(result)[i] = 0;
}
- Z_STRVAL_P(result)[i] = 0;
return SUCCESS;
}
case IS_REFERENCE:
@@ -1280,12 +1285,21 @@ ZEND_API int ZEND_FASTCALL bitwise_or_function(zval *result, zval *op1, zval *op
ZVAL_DEREF(op1);
ZVAL_DEREF(op2);
- if (Z_TYPE_P(op1) == IS_STRING && Z_TYPE_P(op2) == IS_STRING) {
+ if (Z_TYPE_P(op1) == IS_STRING && EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
zval *longer, *shorter;
zend_string *str;
size_t i;
- if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
+ if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
+ if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
+ zend_uchar or = (zend_uchar) (*Z_STRVAL_P(op1) | *Z_STRVAL_P(op2));
+ if (CG(one_char_string)[or]) {
+ ZVAL_INTERNED_STR(result, CG(one_char_string)[or]);
+ } else {
+ ZVAL_NEW_STR(result, zend_string_init((char *) &or, 1, 0));
+ }
+ return SUCCESS;
+ }
longer = op1;
shorter = op2;
} else {
@@ -1343,7 +1357,16 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o
zend_string *str;
size_t i;
- if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
+ if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
+ if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
+ zend_uchar and = (zend_uchar) (*Z_STRVAL_P(op1) & *Z_STRVAL_P(op2));
+ if (CG(one_char_string)[and]) {
+ ZVAL_INTERNED_STR(result, CG(one_char_string)[and]);
+ } else {
+ ZVAL_NEW_STR(result, zend_string_init((char *) &and, 1, 0));
+ }
+ return SUCCESS;
+ }
longer = op1;
shorter = op2;
} else {
@@ -1364,7 +1387,7 @@ ZEND_API int ZEND_FASTCALL bitwise_and_function(zval *result, zval *op1, zval *o
}
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
- ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_or_function);
+ ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_AND, bitwise_and_function);
op1_lval = _zval_get_long_func(op1);
} else {
op1_lval = Z_LVAL_P(op1);
@@ -1401,7 +1424,16 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o
zend_string *str;
size_t i;
- if (Z_STRLEN_P(op1) >= Z_STRLEN_P(op2)) {
+ if (EXPECTED(Z_STRLEN_P(op1) >= Z_STRLEN_P(op2))) {
+ if (EXPECTED(Z_STRLEN_P(op1) == Z_STRLEN_P(op2)) && Z_STRLEN_P(op1) == 1) {
+ zend_uchar xor = (zend_uchar) (*Z_STRVAL_P(op1) ^ *Z_STRVAL_P(op2));
+ if (CG(one_char_string)[xor]) {
+ ZVAL_INTERNED_STR(result, CG(one_char_string)[xor]);
+ } else {
+ ZVAL_NEW_STR(result, zend_string_init((char *) &xor, 1, 0));
+ }
+ return SUCCESS;
+ }
longer = op1;
shorter = op2;
} else {
@@ -1422,7 +1454,7 @@ ZEND_API int ZEND_FASTCALL bitwise_xor_function(zval *result, zval *op1, zval *o
}
if (UNEXPECTED(Z_TYPE_P(op1) != IS_LONG)) {
- ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_or_function);
+ ZEND_TRY_BINARY_OP1_OBJECT_OPERATION(ZEND_BW_XOR, bitwise_xor_function);
op1_lval = _zval_get_long_func(op1);
} else {
op1_lval = Z_LVAL_P(op1);
diff --git a/Zend/zend_operators.h b/Zend/zend_operators.h
index c026f23415..17d1bcffb4 100644
--- a/Zend/zend_operators.h
+++ b/Zend/zend_operators.h
@@ -364,7 +364,6 @@ ZEND_API void ZEND_FASTCALL zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_D
#define convert_to_ex_master(pzv, lower_type, upper_type) \
if (Z_TYPE_P(pzv)!=upper_type) { \
- SEPARATE_ZVAL_IF_NOT_REF(pzv); \
convert_to_##lower_type(pzv); \
}
@@ -400,7 +399,6 @@ ZEND_API void ZEND_FASTCALL zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_D
#define convert_to_explicit_type_ex(pzv, str_type) \
if (Z_TYPE_P(pzv) != str_type) { \
- SEPARATE_ZVAL_IF_NOT_REF(pzv); \
convert_to_explicit_type(pzv, str_type); \
}
@@ -414,7 +412,6 @@ ZEND_API void ZEND_FASTCALL zend_locale_sprintf_double(zval *op ZEND_FILE_LINE_D
#define convert_scalar_to_number_ex(pzv) \
if (Z_TYPE_P(pzv)!=IS_LONG && Z_TYPE_P(pzv)!=IS_DOUBLE) { \
- SEPARATE_ZVAL_IF_NOT_REF(pzv); \
convert_scalar_to_number(pzv); \
}
diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h
index eca9c83f89..65455ee10f 100644
--- a/Zend/zend_portability.h
+++ b/Zend/zend_portability.h
@@ -240,6 +240,7 @@ char *alloca();
#if (defined(__GNUC__) && __GNUC__ >= 3 && !defined(__INTEL_COMPILER) && !defined(DARWIN) && !defined(__hpux) && !defined(_AIX) && !defined(__osf__))
# define HAVE_NORETURN_ALIAS
+# define HAVE_ATTRIBUTE_WEAK
#endif
#if ZEND_DEBUG
diff --git a/Zend/zend_types.h b/Zend/zend_types.h
index d66da1eade..63565182ce 100644
--- a/Zend/zend_types.h
+++ b/Zend/zend_types.h
@@ -229,13 +229,13 @@ struct _zend_array {
HT_HASH_EX((ht)->arData, idx)
#define HT_HASH_SIZE(ht) \
- ((-(int32_t)(ht)->nTableMask) * sizeof(uint32_t))
+ (((size_t)(uint32_t)-(int32_t)(ht)->nTableMask) * sizeof(uint32_t))
#define HT_DATA_SIZE(ht) \
- ((ht)->nTableSize * sizeof(Bucket))
+ ((size_t)(ht)->nTableSize * sizeof(Bucket))
#define HT_SIZE(ht) \
(HT_HASH_SIZE(ht) + HT_DATA_SIZE(ht))
#define HT_USED_SIZE(ht) \
- (HT_HASH_SIZE(ht) + ((ht)->nNumUsed * sizeof(Bucket)))
+ (HT_HASH_SIZE(ht) + ((size_t)(ht)->nNumUsed * sizeof(Bucket)))
#define HT_HASH_RESET(ht) \
memset(&HT_HASH(ht, (ht)->nTableMask), HT_INVALID_IDX, HT_HASH_SIZE(ht))
#define HT_HASH_RESET_PACKED(ht) do { \
@@ -802,7 +802,7 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) {
return --GC_REFCOUNT(Z_COUNTED_P(pz));
}
-#if SIZEOF_ZEND_LONG == 4
+#if SIZEOF_SIZE_T == 4
# define ZVAL_COPY_VALUE_EX(z, v, gc, t) \
do { \
uint32_t _w2 = v->value.ww.w2; \
@@ -810,14 +810,14 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) {
z->value.ww.w2 = _w2; \
Z_TYPE_INFO_P(z) = t; \
} while (0)
-#elif SIZEOF_ZEND_LONG == 8
+#elif SIZEOF_SIZE_T == 8
# define ZVAL_COPY_VALUE_EX(z, v, gc, t) \
do { \
Z_COUNTED_P(z) = gc; \
Z_TYPE_INFO_P(z) = t; \
} while (0)
#else
-# error "Unknbown SIZEOF_ZEND_LONG"
+# error "Unknown SIZEOF_SIZE_T"
#endif
#define ZVAL_COPY_VALUE(z, v) \
@@ -890,11 +890,12 @@ static zend_always_inline uint32_t zval_delref_p(zval* pz) {
#define SEPARATE_ARRAY(zv) do { \
zval *_zv = (zv); \
- if (Z_REFCOUNT_P(_zv) > 1) { \
+ zend_array *_arr = Z_ARR_P(_zv); \
+ if (GC_REFCOUNT(_arr) > 1) { \
if (!Z_IMMUTABLE_P(_zv)) { \
- Z_DELREF_P(_zv); \
+ GC_REFCOUNT(_arr)--; \
} \
- zval_copy_ctor_func(_zv); \
+ ZVAL_ARR(_zv, zend_array_dup(_arr)); \
} \
} while (0)
diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c
index 28cc7f6eed..cc3fff4416 100644
--- a/Zend/zend_virtual_cwd.c
+++ b/Zend/zend_virtual_cwd.c
@@ -54,10 +54,6 @@
# endif
#endif
-#ifndef S_IFLNK
-# define S_IFLNK 0120000
-#endif
-
#ifdef NETWARE
#include <fsio.h>
#endif
@@ -89,14 +85,6 @@ cwd_state main_cwd_state; /* True global */
#include <direct.h>
#endif
-#ifndef S_ISDIR
-#define S_ISDIR(mode) ((mode) & _S_IFDIR)
-#endif
-
-#ifndef S_ISREG
-#define S_ISREG(mode) ((mode) & _S_IFREG)
-#endif
-
#ifdef TSRM_WIN32
#include <tchar.h>
#define tsrm_strtok_r(a,b,c) _tcstok((a),(b))
@@ -237,6 +225,10 @@ CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len){
typedef BOOL (WINAPI *gfpnh_func)(HANDLE, LPTSTR, DWORD, DWORD);
gfpnh_func pGetFinalPathNameByHandle;
+ if (!target_len) {
+ return -1;
+ }
+
kernel32 = LoadLibrary("kernel32.dll");
if (kernel32) {
@@ -260,8 +252,14 @@ CWD_API int php_sys_readlink(const char *link, char *target, size_t target_len){
return -1;
}
- dwRet = pGetFinalPathNameByHandle(hFile, target, MAXPATHLEN, VOLUME_NAME_DOS);
- if(dwRet >= MAXPATHLEN || dwRet == 0) {
+ /* Despite MSDN has documented it won't to, the length returned by
+ GetFinalPathNameByHandleA includes the length of the
+ null terminator. This behavior is at least reproducible
+ with VS2012 and earlier, and seems not to be fixed till
+ now. Thus, correcting target_len so it's suddenly don't
+ overflown. */
+ dwRet = pGetFinalPathNameByHandle(hFile, target, target_len - 1, VOLUME_NAME_DOS);
+ if(dwRet >= target_len || dwRet >= MAXPATHLEN || dwRet == 0) {
return -1;
}
@@ -555,6 +553,11 @@ CWD_API char *virtual_getcwd_ex(size_t *length) /* {{{ */
return retval;
}
#endif
+ if (!state->cwd) {
+ *length = 0;
+ return NULL;
+ }
+
*length = state->cwd_length;
return estrdup(state->cwd);
}
@@ -576,6 +579,9 @@ CWD_API char *virtual_getcwd(char *buf, size_t size) /* {{{ */
errno = ERANGE; /* Is this OK? */
return NULL;
}
+ if (!cwd) {
+ return NULL;
+ }
memcpy(buf, cwd, length+1);
efree(cwd);
return buf;
diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h
index d7d1067828..019888757f 100644
--- a/Zend/zend_virtual_cwd.h
+++ b/Zend/zend_virtual_cwd.h
@@ -337,4 +337,33 @@ CWD_API realpath_cache_bucket** realpath_cache_get_buckets(void);
#endif
+/* Global stat declarations */
+#ifndef _S_IFDIR
+#define _S_IFDIR S_IFDIR
+#endif
+
+#ifndef _S_IFREG
+#define _S_IFREG S_IFREG
+#endif
+
+#ifndef S_IFLNK
+# define S_IFLNK 0120000
+#endif
+
+#ifndef S_ISDIR
+#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
+#endif
+
+#ifndef S_ISREG
+#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
+#endif
+
+#ifndef S_ISLNK
+#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK)
+#endif
+
+#ifndef S_IXROOT
+#define S_IXROOT ( S_IXUSR | S_IXGRP | S_IXOTH )
+#endif
+
#endif /* VIRTUAL_CWD_H */
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 5d6b128cb3..0fe820a20f 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -164,11 +164,12 @@ ZEND_VM_HANDLER(4, ZEND_DIV, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- fast_div_function(EX_VAR(opline->result.var),
- GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R));
+ op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ fast_div_function(EX_VAR(opline->result.var), op1, op2);
FREE_OP1();
FREE_OP2();
CHECK_EXCEPTION();
@@ -218,11 +219,12 @@ ZEND_VM_HANDLER(6, ZEND_SL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_left_function(EX_VAR(opline->result.var),
- GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R));
+ op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ shift_left_function(EX_VAR(opline->result.var), op1, op2);
FREE_OP1();
FREE_OP2();
CHECK_EXCEPTION();
@@ -233,11 +235,12 @@ ZEND_VM_HANDLER(7, ZEND_SR, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_right_function(EX_VAR(opline->result.var),
- GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R));
+ op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ shift_right_function(EX_VAR(opline->result.var), op1, op2);
FREE_OP1();
FREE_OP2();
CHECK_EXCEPTION();
@@ -248,12 +251,58 @@ ZEND_VM_HANDLER(8, ZEND_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- concat_function(EX_VAR(opline->result.var),
- GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R));
- FREE_OP1();
+ op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
+
+ do {
+ if ((OP1_TYPE == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
+ (OP2_TYPE == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
+ zend_string *op1_str = Z_STR_P(op1);
+ zend_string *op2_str = Z_STR_P(op2);
+ zend_string *str;
+
+ if (OP1_TYPE != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
+ FREE_OP1();
+ break;
+ }
+ }
+ if (OP2_TYPE != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
+ FREE_OP1();
+ break;
+ }
+ }
+ if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_CV &&
+ !IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ size_t len = op1_str->len;
+
+ str = zend_string_realloc(op1_str, len + op2_str->len, 0);
+ memcpy(str->val + len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ break;
+ } else {
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ }
+ } else {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ concat_function(EX_VAR(opline->result.var), op1, op2);
+ }
+ FREE_OP1();
+ } while (0);
FREE_OP2();
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -263,12 +312,13 @@ ZEND_VM_HANDLER(15, ZEND_IS_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R),
- GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R));
+ op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
+ result = fast_is_identical_function(op1, op2);
FREE_OP1();
FREE_OP2();
ZEND_VM_SMART_BRANCH(result, (OP1_TYPE|OP2_TYPE) & (IS_VAR|IS_TMP_VAR));
@@ -283,12 +333,13 @@ ZEND_VM_HANDLER(16, ZEND_IS_NOT_IDENTICAL, CONST|TMP|VAR|CV, CONST|TMP|VAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R),
- GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R));
+ op1 = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR_DEREF(BP_VAR_R);
+ result = fast_is_not_identical_function(op1, op2);
FREE_OP1();
FREE_OP2();
ZEND_VM_SMART_BRANCH(result, (OP1_TYPE|OP2_TYPE) & (IS_VAR|IS_TMP_VAR));
@@ -310,18 +361,18 @@ ZEND_VM_HANDLER(17, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -353,10 +404,10 @@ ZEND_VM_HANDLER(17, ZEND_IS_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
} while (0);
SAVE_OPLINE();
- if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -379,18 +430,18 @@ ZEND_VM_HANDLER(18, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -422,10 +473,10 @@ ZEND_VM_HANDLER(18, ZEND_IS_NOT_EQUAL, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
} while (0);
SAVE_OPLINE();
- if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -543,12 +594,12 @@ ZEND_VM_HANDLER(170, ZEND_SPACESHIP, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = EX_VAR(opline->result.var);
+ zval *op1, *op2;
SAVE_OPLINE();
- compare_function(result,
- GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R));
+ op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ compare_function(EX_VAR(opline->result.var), op1, op2);
FREE_OP1();
FREE_OP2();
CHECK_EXCEPTION();
@@ -559,11 +610,12 @@ ZEND_VM_HANDLER(9, ZEND_BW_OR, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_or_function(EX_VAR(opline->result.var),
- GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R));
+ op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ bitwise_or_function(EX_VAR(opline->result.var), op1, op2);
FREE_OP1();
FREE_OP2();
CHECK_EXCEPTION();
@@ -574,11 +626,12 @@ ZEND_VM_HANDLER(10, ZEND_BW_AND, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_and_function(EX_VAR(opline->result.var),
- GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R));
+ op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ bitwise_and_function(EX_VAR(opline->result.var), op1, op2);
FREE_OP1();
FREE_OP2();
CHECK_EXCEPTION();
@@ -589,11 +642,12 @@ ZEND_VM_HANDLER(11, ZEND_BW_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_xor_function(EX_VAR(opline->result.var),
- GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R));
+ op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ bitwise_xor_function(EX_VAR(opline->result.var), op1, op2);
FREE_OP1();
FREE_OP2();
CHECK_EXCEPTION();
@@ -604,11 +658,12 @@ ZEND_VM_HANDLER(14, ZEND_BOOL_XOR, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- boolean_xor_function(EX_VAR(opline->result.var),
- GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R));
+ op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ boolean_xor_function(EX_VAR(opline->result.var), op1, op2);
FREE_OP1();
FREE_OP2();
CHECK_EXCEPTION();
@@ -678,7 +733,6 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
FREE_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -708,42 +762,7 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_obj_helper, VAR|UNUSED|CV, CONST|TMPVAR|
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval *z;
- zval rv, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- if (Z_OBJ_HT(obj)->read_property &&
- (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- zptr = z;
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- binary_op(z, z, value);
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- zval_ptr_dtor(zptr);
- } else {
- zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
- OBJ_RELEASE(Z_OBJ(obj));
+ zend_assign_op_overloaded_property(object, property, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), value, binary_op, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -775,7 +794,6 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_dim_helper, VAR|UNUSED|CV, CONST|TMPVAR|
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
FREE_UNFETCHED_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -846,7 +864,6 @@ ZEND_VM_HELPER_EX(zend_binary_assign_op_helper, VAR|CV, CONST|TMPVAR|CV, binary_
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
FREE_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -1091,7 +1108,7 @@ ZEND_VM_HANDLER(33, ZEND_ASSIGN_BW_XOR, VAR|UNUSED|CV, CONST|TMPVAR|UNUSED|CV)
#endif
}
-ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, incdec_t incdec_op)
+ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, int inc)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -1113,7 +1130,6 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C
if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
FREE_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -1134,51 +1150,27 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- SEPARATE_ZVAL_NOREF(zptr);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
+ }
+ } else {
+ ZVAL_DEREF(zptr);
+ SEPARATE_ZVAL_NOREF(zptr);
- incdec_op(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
+ }
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval rv;
-
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- incdec_op(z);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(z);
- } else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
+ zend_pre_incdec_overloaded_property(object, property, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -1190,15 +1182,15 @@ ZEND_VM_HELPER_EX(zend_pre_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|C
ZEND_VM_HANDLER(132, ZEND_PRE_INC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
{
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_pre_incdec_property_helper, incdec_op, increment_function);
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_pre_incdec_property_helper, inc, 1);
}
ZEND_VM_HANDLER(133, ZEND_PRE_DEC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
{
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_pre_incdec_property_helper, incdec_op, decrement_function);
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_pre_incdec_property_helper, inc, 0);
}
-ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, incdec_t incdec_op)
+ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|CV, int inc)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -1220,7 +1212,6 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|
if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
FREE_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -1239,44 +1230,25 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
- zval_opt_copy_ctor(zptr);
- incdec_op(zptr);
- } else {
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval rv, obj;
- zval *z;
- zval z_copy;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
}
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- ZVAL_DUP(EX_VAR(opline->result.var), z);
- ZVAL_DUP(&z_copy, z);
- incdec_op(&z_copy);
- if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
- Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(&z_copy);
- zval_ptr_dtor(z);
} else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- ZVAL_NULL(EX_VAR(opline->result.var));
+ ZVAL_DEREF(zptr);
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ zval_opt_copy_ctor(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
}
+ } else {
+ zend_post_incdec_overloaded_property(object, property, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, EX_VAR(opline->result.var));
}
} while (0);
@@ -1288,12 +1260,12 @@ ZEND_VM_HELPER_EX(zend_post_incdec_property_helper, VAR|UNUSED|CV, CONST|TMPVAR|
ZEND_VM_HANDLER(134, ZEND_POST_INC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
{
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_post_incdec_property_helper, incdec_op, increment_function);
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_post_incdec_property_helper, inc, 1);
}
ZEND_VM_HANDLER(135, ZEND_POST_DEC_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
{
- ZEND_VM_DISPATCH_TO_HELPER_EX(zend_post_incdec_property_helper, incdec_op, decrement_function);
+ ZEND_VM_DISPATCH_TO_HELPER_EX(zend_post_incdec_property_helper, inc, 0);
}
ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY)
@@ -1307,7 +1279,6 @@ ZEND_VM_HANDLER(34, ZEND_PRE_INC, VAR|CV, ANY)
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -1355,7 +1326,6 @@ ZEND_VM_HANDLER(35, ZEND_PRE_DEC, VAR|CV, ANY)
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -1403,7 +1373,6 @@ ZEND_VM_HANDLER(36, ZEND_POST_INC, VAR|CV, ANY)
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -1444,7 +1413,6 @@ ZEND_VM_HANDLER(37, ZEND_POST_DEC, VAR|CV, ANY)
if (OP1_TYPE == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -1481,7 +1449,7 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMPVAR|CV, ANY)
zval *z;
SAVE_OPLINE();
- z = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ z = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
if (Z_TYPE_P(z) == IS_STRING) {
zend_string *str = Z_STR_P(z);
@@ -1494,6 +1462,8 @@ ZEND_VM_HANDLER(40, ZEND_ECHO, CONST|TMPVAR|CV, ANY)
if (str->len != 0) {
zend_write(str->val, str->len);
+ } else if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(z, BP_VAR_R);
}
zend_string_release(str);
}
@@ -1513,7 +1483,7 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
HashTable *target_symbol_table;
SAVE_OPLINE();
- varname = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ varname = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP1_TYPE == IS_CONST) {
name = Z_STR_P(varname);
@@ -1521,6 +1491,9 @@ ZEND_VM_HELPER_EX(zend_fetch_var_address_helper, CONST|TMPVAR|CV, UNUSED|CONST|V
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);
}
@@ -1714,7 +1687,6 @@ ZEND_VM_HANDLER(84, ZEND_FETCH_DIM_W, VAR|CV, CONST|TMPVAR|UNUSED|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
@@ -1738,7 +1710,6 @@ ZEND_VM_HANDLER(87, ZEND_FETCH_DIM_RW, VAR|CV, CONST|TMPVAR|UNUSED|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
@@ -1785,7 +1756,6 @@ ZEND_VM_HANDLER(93, ZEND_FETCH_DIM_FUNC_ARG, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUS
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
@@ -1822,7 +1792,6 @@ ZEND_VM_HANDLER(96, ZEND_FETCH_DIM_UNSET, VAR|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, GET_OP2_ZVAL_PTR(BP_VAR_R), OP2_TYPE);
@@ -1854,7 +1823,8 @@ ZEND_VM_HANDLER(82, ZEND_FETCH_OBJ_R, CONST|TMP|VAR|UNUSED|CV, CONST|TMPVAR|CV)
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (OP1_TYPE == IS_CONST ||
+ (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -1927,7 +1897,6 @@ ZEND_VM_HANDLER(85, ZEND_FETCH_OBJ_W, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -1960,7 +1929,6 @@ ZEND_VM_HANDLER(88, ZEND_FETCH_OBJ_RW, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
@@ -1992,7 +1960,8 @@ ZEND_VM_HANDLER(91, ZEND_FETCH_OBJ_IS, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR|CV)
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (OP1_TYPE == IS_CONST ||
+ (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -2074,7 +2043,6 @@ ZEND_VM_HANDLER(94, ZEND_FETCH_OBJ_FUNC_ARG, CONST|TMP|VAR|UNUSED|CV, CONST|TMPV
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -2110,7 +2078,6 @@ ZEND_VM_HANDLER(97, ZEND_FETCH_OBJ_UNSET, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, OP1_TYPE, property, OP2_TYPE, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
@@ -2130,7 +2097,7 @@ ZEND_VM_HANDLER(98, ZEND_FETCH_LIST, CONST|TMPVAR|CV, CONST)
zval *container;
SAVE_OPLINE();
- container = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ container = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
ZEND_VM_C_LABEL(try_fetch_list):
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -2142,7 +2109,8 @@ ZEND_VM_C_LABEL(try_fetch_list):
} else {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
- } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
+ } else if (OP1_TYPE != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
zval *result = EX_VAR(opline->result.var);
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
@@ -2154,10 +2122,13 @@ ZEND_VM_C_LABEL(try_fetch_list):
} else {
ZVAL_NULL(result);
}
- } else if (Z_TYPE_P(container) == IS_REFERENCE) {
+ } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(container) == IS_REFERENCE) {
container = Z_REFVAL_P(container);
ZEND_VM_C_GOTO(try_fetch_list);
} else {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(container, BP_VAR_R);
+ }
ZVAL_NULL(EX_VAR(opline->result.var));
}
CHECK_EXCEPTION();
@@ -2185,7 +2156,6 @@ ZEND_VM_HANDLER(136, ZEND_ASSIGN_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, OP1_TYPE, property_name, OP2_TYPE, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
@@ -2214,11 +2184,9 @@ ZEND_VM_HANDLER(147, ZEND_ASSIGN_DIM, VAR|CV, CONST|TMPVAR|UNUSED|CV)
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
FREE_UNFETCHED_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
-ZEND_VM_C_LABEL(try_assign_dim):
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
ZEND_VM_C_LABEL(try_assign_dim_array):
if (OP2_TYPE == IS_UNUSED) {
@@ -2246,53 +2214,58 @@ ZEND_VM_C_LABEL(try_assign_dim_array):
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
}
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
- zend_free_op free_op2;
- zval *property_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ } else {
+ if (EXPECTED(Z_ISREF_P(object_ptr))) {
+ object_ptr = Z_REFVAL_P(object_ptr);
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
+ ZEND_VM_C_GOTO(try_assign_dim_array);
+ }
+ }
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
+ zend_free_op free_op2;
+ zval *property_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
- zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
- FREE_OP2();
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
- if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
- if (OP2_TYPE == IS_UNUSED) {
- zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
- FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- FREE_OP1_VAR_PTR();
- HANDLE_EXCEPTION();
- } else {
- zend_long offset;
+ zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
+ FREE_OP2();
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
+ if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+ if (OP2_TYPE == IS_UNUSED) {
+ zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
+ FREE_OP1_VAR_PTR();
+ HANDLE_EXCEPTION();
+ } else {
+ zend_long offset;
- dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
- offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
- FREE_OP2();
- value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
- FREE_OP(free_op_data1);
+ dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
+ FREE_OP2();
+ value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
+ FREE_OP(free_op_data1);
+ }
+ } else {
+ zval_ptr_dtor_nogc(object_ptr);
+ZEND_VM_C_LABEL(assign_dim_convert_to_array):
+ ZVAL_NEW_ARR(object_ptr);
+ zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
+ ZEND_VM_C_GOTO(try_assign_dim_array);
}
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
+ if (OP1_TYPE == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) {
+ ZEND_VM_C_GOTO(assign_dim_clean);
+ }
+ ZEND_VM_C_GOTO(assign_dim_convert_to_array);
} else {
- zval_ptr_dtor_nogc(object_ptr);
-ZEND_VM_C_LABEL(assign_dim_convert_to_array):
- ZVAL_NEW_ARR(object_ptr);
- zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
- ZEND_VM_C_GOTO(try_assign_dim_array);
- }
- } else if (EXPECTED(Z_ISREF_P(object_ptr))) {
- object_ptr = Z_REFVAL_P(object_ptr);
- ZEND_VM_C_GOTO(try_assign_dim);
- } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
- if (UNEXPECTED(object_ptr == &EG(error_zval))) {
- ZEND_VM_C_GOTO(assign_dim_clean);
- }
- ZEND_VM_C_GOTO(assign_dim_convert_to_array);
- } else {
- zend_error(E_WARNING, "Cannot use a scalar value as an array");
+ zend_error(E_WARNING, "Cannot use a scalar value as an array");
ZEND_VM_C_LABEL(assign_dim_clean):
- dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
- FREE_OP2();
- value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- FREE_OP(free_op_data1);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
+ dim = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ FREE_OP2();
+ value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ FREE_OP(free_op_data1);
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
}
}
FREE_OP1_VAR_PTR();
@@ -2343,7 +2316,6 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
if (OP2_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
- FREE_OP2_VAR_PTR();
FREE_UNFETCHED_OP1();
HANDLE_EXCEPTION();
}
@@ -2366,7 +2338,6 @@ ZEND_VM_HANDLER(39, ZEND_ASSIGN_REF, VAR|CV, VAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(variable_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
FREE_OP2_VAR_PTR();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
if (OP1_TYPE == IS_VAR &&
@@ -2735,28 +2706,60 @@ ZEND_VM_HANDLER(53, ZEND_FAST_CONCAT, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
zend_string *op1_str, *op2_str, *str;
SAVE_OPLINE();
- op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
- op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ op1 = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP1_TYPE == IS_CONST) {
op1_str = Z_STR_P(op1);
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ op1_str = zend_string_copy(Z_STR_P(op1));
} else {
- op1_str = zval_get_string(op1);
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ op1_str = _zval_get_string_func(op1);
}
+ op2 = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP2_TYPE == IS_CONST) {
op2_str = Z_STR_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ op2_str = zend_string_copy(Z_STR_P(op2));
} else {
- op2_str = zval_get_string(op2);
- }
- str = zend_string_alloc(op1_str->len + op2_str->len, 0);
- memcpy(str->val, op1_str->val, op1_str->len);
- memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
- ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- if (OP1_TYPE != IS_CONST) {
- zend_string_release(op1_str);
- }
- if (OP2_TYPE != IS_CONST) {
- zend_string_release(op2_str);
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ op2_str = _zval_get_string_func(op2);
}
+ do {
+ if (OP1_TYPE != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ if (OP2_TYPE == IS_CONST) {
+ zend_string_addref(op2_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op2_str);
+ zend_string_release(op1_str);
+ break;
+ }
+ }
+ if (OP2_TYPE != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ if (OP1_TYPE == IS_CONST) {
+ zend_string_addref(op1_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op1_str);
+ zend_string_release(op2_str);
+ break;
+ }
+ }
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ if (OP1_TYPE != IS_CONST) {
+ zend_string_release(op1_str);
+ }
+ if (OP2_TYPE != IS_CONST) {
+ zend_string_release(op2_str);
+ }
+ } while (0);
FREE_OP1();
FREE_OP2();
CHECK_EXCEPTION();
@@ -2776,11 +2779,22 @@ ZEND_VM_HANDLER(54, ZEND_ROPE_INIT, UNUSED, CONST|TMPVAR|CV)
var = GET_OP2_ZVAL_PTR(BP_VAR_R);
rope[0] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
- var = GET_OP2_ZVAL_PTR(BP_VAR_R);
- rope[0] = zval_get_string(var);
- FREE_OP2();
- CHECK_EXCEPTION();
+ var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if (OP2_TYPE == IS_CV) {
+ rope[0] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[0] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[0] = _zval_get_string_func(var);
+ FREE_OP2();
+ CHECK_EXCEPTION();
+ }
}
ZEND_VM_NEXT_OPCODE();
}
@@ -2798,11 +2812,22 @@ ZEND_VM_HANDLER(55, ZEND_ROPE_ADD, TMP, CONST|TMPVAR|CV)
var = GET_OP2_ZVAL_PTR(BP_VAR_R);
rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
- var = GET_OP2_ZVAL_PTR(BP_VAR_R);
- rope[opline->extended_value] = zval_get_string(var);
- FREE_OP2();
- CHECK_EXCEPTION();
+ var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if (OP2_TYPE == IS_CV) {
+ rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[opline->extended_value] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[opline->extended_value] = _zval_get_string_func(var);
+ FREE_OP2();
+ CHECK_EXCEPTION();
+ }
}
ZEND_VM_NEXT_OPCODE();
}
@@ -2822,11 +2847,22 @@ ZEND_VM_HANDLER(56, ZEND_ROPE_END, TMP, CONST|TMPVAR|CV)
var = GET_OP2_ZVAL_PTR(BP_VAR_R);
rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
- var = GET_OP2_ZVAL_PTR(BP_VAR_R);
- rope[opline->extended_value] = zval_get_string(var);
- FREE_OP2();
- CHECK_EXCEPTION();
+ var = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if (OP2_TYPE == IS_CV) {
+ rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[opline->extended_value] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[opline->extended_value] = _zval_get_string_func(var);
+ FREE_OP2();
+ CHECK_EXCEPTION();
+ }
}
for (i = 0; i <= opline->extended_value; i++) {
len += rope[i]->len;
@@ -2858,7 +2894,7 @@ ZEND_VM_HANDLER(109, ZEND_FETCH_CLASS, ANY, CONST|TMPVAR|UNUSED|CV)
ZEND_VM_NEXT_OPCODE();
} else {
zend_free_op free_op2;
- zval *class_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zval *class_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
ZEND_VM_C_LABEL(try_class_name):
if (OP2_TYPE == IS_CONST) {
@@ -2876,6 +2912,9 @@ ZEND_VM_C_LABEL(try_class_name):
class_name = Z_REFVAL_P(class_name);
ZEND_VM_C_GOTO(try_class_name);
} else {
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(class_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -2902,7 +2941,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
SAVE_OPLINE();
- function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP2_TYPE != IS_CONST &&
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
@@ -2913,6 +2952,9 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
break;
}
}
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -2923,7 +2965,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
} while (0);
}
- object = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
+ object = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context");
@@ -2933,13 +2975,16 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
if (OP1_TYPE != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (OP1_TYPE == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if ((OP1_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -2986,7 +3031,8 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR)) {
+ } else if (OP1_TYPE & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -3044,9 +3090,12 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
} else if (OP2_TYPE != IS_UNUSED) {
zend_free_op free_op2;
- function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP2_TYPE != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -3174,7 +3223,7 @@ ZEND_VM_HANDLER(128, ZEND_INIT_DYNAMIC_CALL, ANY, CONST|TMPVAR|CV)
uint32_t call_info = ZEND_CALL_NESTED_FUNCTION;
SAVE_OPLINE();
- function_name = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
ZEND_VM_C_LABEL(try_function_name):
if (OP2_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
@@ -3354,6 +3403,9 @@ ZEND_VM_C_LABEL(try_function_name):
function_name = Z_REFVAL_P(function_name);
ZEND_VM_C_GOTO(try_function_name);
} else {
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -3908,6 +3960,10 @@ ZEND_VM_HANDLER(124, ZEND_VERIFY_RETURN_TYPE, CONST|TMP|VAR|UNUSED|CV, UNUSED)
}
}
zend_verify_return_type(EX(func), retval_ptr);
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ FREE_OP1();
+ }
#endif
}
CHECK_EXCEPTION();
@@ -3924,15 +3980,14 @@ ZEND_VM_HANDLER(62, ZEND_RETURN, CONST|TMP|VAR|CV, ANY)
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) {
SAVE_OPLINE();
retval_ptr = GET_OP1_UNDEF_CV(retval_ptr, BP_VAR_R);
- CHECK_EXCEPTION();
- }
-
- if (!EX(return_value)) {
+ if (EX(return_value)) {
+ ZVAL_NULL(EX(return_value));
+ }
+ } else if (!EX(return_value)) {
if (OP1_TYPE == IS_VAR || OP1_TYPE == IS_TMP_VAR ) {
if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) {
SAVE_OPLINE();
zval_dtor_func_for_ptr(Z_COUNTED_P(free_op1));
- CHECK_EXCEPTION();
}
}
} else {
@@ -3998,7 +4053,6 @@ ZEND_VM_HANDLER(111, ZEND_RETURN_BY_REF, CONST|TMP|VAR|CV, ANY)
if (OP1_TYPE == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot return string offsets by reference");
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -4080,7 +4134,7 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY)
zend_free_op free_op1;
SAVE_OPLINE();
- value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
do {
if (OP1_TYPE == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
@@ -4090,6 +4144,9 @@ ZEND_VM_HANDLER(108, ZEND_THROW, CONST|TMP|VAR|CV, ANY)
break;
}
}
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -4297,7 +4354,6 @@ ZEND_VM_HANDLER(67, ZEND_SEND_REF, VAR|CV, ANY)
if (OP1_TYPE == IS_VAR && UNEXPECTED(varptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Only variables can be passed by reference");
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
@@ -4376,71 +4432,67 @@ ZEND_VM_HANDLER(165, ZEND_SEND_UNPACK, ANY, ANY)
int arg_num;
SAVE_OPLINE();
- args = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ args = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1;
ZEND_VM_C_LABEL(send_again):
- switch (Z_TYPE_P(args)) {
- case IS_ARRAY: {
- HashTable *ht = Z_ARRVAL_P(args);
- zval *arg, *top;
- zend_string *name;
-
- zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht));
-
- if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
- uint32_t i;
- int separate = 0;
-
- /* check if any of arguments are going to be passed by reference */
- for (i = 0; i < zend_hash_num_elements(ht); i++) {
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) {
- separate = 1;
- break;
- }
- }
- if (separate) {
- zval_copy_ctor(args);
- ht = Z_ARRVAL_P(args);
+ if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) {
+ HashTable *ht = Z_ARRVAL_P(args);
+ zval *arg, *top;
+ zend_string *name;
+
+ zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht));
+
+ if (OP1_TYPE != IS_CONST && OP1_TYPE != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
+ uint32_t i;
+ int separate = 0;
+
+ /* check if any of arguments are going to be passed by reference */
+ for (i = 0; i < zend_hash_num_elements(ht); i++) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) {
+ separate = 1;
+ break;
}
}
+ if (separate) {
+ zval_copy_ctor(args);
+ ht = Z_ARRVAL_P(args);
+ }
+ }
- ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
- if (name) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unpack array with string keys");
- FREE_OP1();
- HANDLE_EXCEPTION();
- }
+ ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
+ if (name) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unpack array with string keys");
+ FREE_OP1();
+ HANDLE_EXCEPTION();
+ }
- top = ZEND_CALL_ARG(EX(call), arg_num);
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
- if (!Z_IMMUTABLE_P(args)) {
- ZVAL_MAKE_REF(arg);
- Z_ADDREF_P(arg);
- ZVAL_REF(top, Z_REF_P(arg));
- } else {
- ZVAL_DUP(top, arg);
- }
- } else if (Z_ISREF_P(arg)) {
- ZVAL_COPY(top, Z_REFVAL_P(arg));
+ top = ZEND_CALL_ARG(EX(call), arg_num);
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
+ if (!Z_IMMUTABLE_P(args)) {
+ ZVAL_MAKE_REF(arg);
+ Z_ADDREF_P(arg);
+ ZVAL_REF(top, Z_REF_P(arg));
} else {
- ZVAL_COPY(top, arg);
+ ZVAL_DUP(top, arg);
}
+ } else if (Z_ISREF_P(arg)) {
+ ZVAL_COPY(top, Z_REFVAL_P(arg));
+ } else {
+ ZVAL_COPY(top, arg);
+ }
- ZEND_CALL_NUM_ARGS(EX(call))++;
- arg_num++;
- } ZEND_HASH_FOREACH_END();
+ ZEND_CALL_NUM_ARGS(EX(call))++;
+ arg_num++;
+ } ZEND_HASH_FOREACH_END();
- break;
- }
- case IS_OBJECT: {
- zend_class_entry *ce = Z_OBJCE_P(args);
- zend_object_iterator *iter;
+ } else if (EXPECTED(Z_TYPE_P(args) == IS_OBJECT)) {
+ zend_class_entry *ce = Z_OBJCE_P(args);
+ zend_object_iterator *iter;
- if (!ce || !ce->get_iterator) {
- zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
- break;
- }
+ if (!ce || !ce->get_iterator) {
+ zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
+ } else {
iter = ce->get_iterator(ce, args, 0);
if (UNEXPECTED(!iter)) {
@@ -4518,14 +4570,15 @@ ZEND_VM_C_LABEL(send_again):
ZEND_VM_C_LABEL(unpack_iter_dtor):
zend_iterator_dtor(iter);
- break;
}
- case IS_REFERENCE:
- args = Z_REFVAL_P(args);
- ZEND_VM_C_GOTO(send_again);
- break;
- default:
- zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
+ } else if (EXPECTED(Z_ISREF_P(args))) {
+ args = Z_REFVAL_P(args);
+ ZEND_VM_C_GOTO(send_again);
+ } else {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(args) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(args, BP_VAR_R);
+ }
+ zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
}
FREE_OP1();
@@ -4817,31 +4870,8 @@ ZEND_VM_HANDLER(52, ZEND_BOOL, CONST|TMPVAR|CV, ANY)
ZEND_VM_NEXT_OPCODE();
}
-ZEND_VM_HANDLER(50, ZEND_BRK, ANY, CONST)
-{
- USE_OPLINE
- zend_brk_cont_element *el;
-
- SAVE_OPLINE();
- el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
- &EX(func)->op_array, execute_data);
- ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
-}
-
-ZEND_VM_HANDLER(51, ZEND_CONT, ANY, CONST)
-{
- USE_OPLINE
- zend_brk_cont_element *el;
-
- SAVE_OPLINE();
- el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
- &EX(func)->op_array, execute_data);
- ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
-}
-
ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
{
- zend_op *brk_opline;
USE_OPLINE
zend_brk_cont_element *el;
@@ -4849,14 +4879,12 @@ ZEND_VM_HANDLER(100, ZEND_GOTO, ANY, CONST)
el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->extended_value,
&EX(func)->op_array, execute_data);
- brk_opline = EX(func)->op_array.opcodes + el->brk;
+ if (el->start >= 0) {
+ zend_op *brk_opline = EX(func)->op_array.opcodes + el->brk;
- if (brk_opline->opcode == ZEND_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ if (brk_opline->opcode == ZEND_FREE) {
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
- }
- } else if (brk_opline->opcode == ZEND_FE_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ } else if (brk_opline->opcode == ZEND_FE_FREE) {
zval *var = EX_VAR(brk_opline->op1.var);
if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
zend_hash_iterator_del(Z_FE_ITER_P(var));
@@ -4878,18 +4906,18 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -4920,10 +4948,10 @@ ZEND_VM_HANDLER(48, ZEND_CASE, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
} while (0);
SAVE_OPLINE();
- if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -4999,7 +5027,7 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY)
zend_object_clone_obj_t clone_call;
SAVE_OPLINE();
- obj = GET_OP1_OBJ_ZVAL_PTR(BP_VAR_R);
+ obj = GET_OP1_OBJ_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP1_TYPE == IS_UNUSED && UNEXPECTED(Z_OBJ_P(obj) == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context");
@@ -5014,7 +5042,10 @@ ZEND_VM_HANDLER(110, ZEND_CLONE, CONST|TMPVAR|UNUSED|CV, ANY)
if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
break;
}
- }
+ }
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(obj, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -5075,7 +5106,6 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
SAVE_OPLINE();
if (OP1_TYPE == IS_UNUSED) {
zend_constant *c;
- zval *retval;
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
@@ -5101,67 +5131,80 @@ ZEND_VM_HANDLER(99, ZEND_FETCH_CONSTANT, VAR|CONST|UNUSED, CONST)
} else {
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
}
- retval = EX_VAR(opline->result.var);
- ZVAL_COPY_VALUE(retval, &c->value);
- if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval)) {
- zval_copy_ctor_func(retval);
- } else {
- Z_ADDREF_P(retval);
- }
+#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;
- if (OP1_TYPE == IS_CONST) {
- if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- ZVAL_DEREF(value);
- ZVAL_DUP(EX_VAR(opline->result.var), value);
- ZEND_VM_C_GOTO(constant_fetch_end);
- } else if (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(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if (OP1_TYPE == IS_CONST) {
+ if (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)));
+#endif
+ break;
+ } else if (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(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ if (UNEXPECTED(ce == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
+ HANDLE_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
- if (UNEXPECTED(ce == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
- 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;
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
- }
- } 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);
- ZVAL_DUP(EX_VAR(opline->result.var), value);
- ZEND_VM_C_GOTO(constant_fetch_end);
}
- }
- 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 (OP1_TYPE == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
+ 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 {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ }
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ HANDLE_EXCEPTION();
}
+ } while (0);
+#ifdef ZTS
+ if (ce->type == ZEND_INTERNAL_CLASS) {
ZVAL_DUP(EX_VAR(opline->result.var), value);
} else {
- zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
}
+#else
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+#endif
}
-ZEND_VM_C_LABEL(constant_fetch_end):
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -5173,11 +5216,10 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSE
SAVE_OPLINE();
if ((OP1_TYPE == IS_VAR || OP1_TYPE == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
if (OP1_TYPE == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
- FREE_OP1_VAR_PTR();
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -5187,11 +5229,11 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSE
} else {
expr_ptr = GET_OP1_ZVAL_PTR(BP_VAR_R);
if (OP1_TYPE == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (OP1_TYPE == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (OP1_TYPE == IS_CV) {
@@ -5217,48 +5259,46 @@ ZEND_VM_HANDLER(72, ZEND_ADD_ARRAY_ELEMENT, CONST|TMP|VAR|CV, CONST|TMPVAR|UNUSE
if (OP2_TYPE != IS_UNUSED) {
zend_free_op free_op2;
- zval *offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ zval *offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
zend_string *str;
zend_ulong hval;
ZEND_VM_C_LABEL(add_again):
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- ZEND_VM_C_GOTO(num_index);
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-ZEND_VM_C_LABEL(num_index):
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (OP2_TYPE != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- ZEND_VM_C_GOTO(num_index);
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (OP2_TYPE != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ ZEND_VM_C_GOTO(num_index);
}
+ }
ZEND_VM_C_LABEL(str_index):
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- ZEND_VM_C_GOTO(str_index);
- case IS_FALSE:
- hval = 0;
- ZEND_VM_C_GOTO(num_index);
- case IS_TRUE:
- hval = 1;
- ZEND_VM_C_GOTO(num_index);
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- ZEND_VM_C_GOTO(add_again);
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+ZEND_VM_C_LABEL(num_index):
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ ZEND_VM_C_GOTO(add_again);
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ ZEND_VM_C_GOTO(str_index);
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ ZEND_VM_C_GOTO(num_index);
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ ZEND_VM_C_GOTO(num_index);
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ ZEND_VM_C_GOTO(num_index);
+ } else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ ZEND_VM_C_GOTO(str_index);
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
FREE_OP2();
} else {
@@ -5392,8 +5432,7 @@ ZEND_VM_HANDLER(21, ZEND_CAST, CONST|TMP|VAR|CV, ANY)
}
}
} else {
- ZVAL_COPY_VALUE(result, expr);
- zval_opt_copy_ctor(result);
+ ZVAL_COPY(result, expr);
convert_to_object(result);
}
}
@@ -5414,10 +5453,13 @@ ZEND_VM_HANDLER(73, ZEND_INCLUDE_OR_EVAL, CONST|TMPVAR|CV, ANY)
zend_bool failure_retval=0;
SAVE_OPLINE();
- inc_filename = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ inc_filename = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
ZVAL_UNDEF(&tmp_inc_filename);
if (Z_TYPE_P(inc_filename) != IS_STRING) {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(inc_filename) == IS_UNDEF)) {
+ inc_filename = GET_OP1_UNDEF_CV(inc_filename, BP_VAR_R);
+ }
ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename));
inc_filename = &tmp_inc_filename;
}
@@ -5560,10 +5602,13 @@ ZEND_VM_HANDLER(74, ZEND_UNSET_VAR, CONST|TMPVAR|CV, UNUSED|CONST|VAR)
ZEND_VM_NEXT_OPCODE();
}
- varname = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ 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;
}
@@ -5616,6 +5661,7 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMPVAR|CV)
zval *container;
zval *offset;
zend_ulong hval;
+ zend_string *key;
SAVE_OPLINE();
container = GET_OP1_OBJ_ZVAL_PTR_PTR(BP_VAR_UNSET);
@@ -5627,72 +5673,81 @@ ZEND_VM_HANDLER(75, ZEND_UNSET_DIM, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
FREE_UNFETCHED_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
- offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
-ZEND_VM_C_LABEL(unset_dim_again):
- if (OP1_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht;
+ do {
+ if (OP1_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ HashTable *ht;
+ZEND_VM_C_LABEL(unset_dim_array):
+ SEPARATE_ARRAY(container);
+ ht = Z_ARRVAL_P(container);
ZEND_VM_C_LABEL(offset_again):
- SEPARATE_ARRAY(container);
- ht = Z_ARRVAL_P(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- zend_hash_index_del(ht, hval);
- break;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-ZEND_VM_C_LABEL(num_index_dim):
- zend_hash_index_del(ht, hval);
- break;
- case IS_STRING:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ key = Z_STR_P(offset);
if (OP2_TYPE != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
+ if (ZEND_HANDLE_NUMERIC(key, hval)) {
ZEND_VM_C_GOTO(num_index_dim);
}
}
+ZEND_VM_C_LABEL(str_index_dim):
if (ht == &EG(symbol_table)) {
- zend_delete_global_variable(Z_STR_P(offset));
+ zend_delete_global_variable(key);
} else {
- zend_hash_del(ht, Z_STR_P(offset));
+ zend_hash_del(ht, key);
}
- break;
- case IS_NULL:
- zend_hash_del(ht, STR_EMPTY_ALLOC());
- break;
- case IS_FALSE:
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+ZEND_VM_C_LABEL(num_index_dim):
+ zend_hash_index_del(ht, hval);
+ } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ ZEND_VM_C_GOTO(offset_again);
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ ZEND_VM_C_GOTO(num_index_dim);
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ key = STR_EMPTY_ALLOC();
+ ZEND_VM_C_GOTO(str_index_dim);
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
hval = 0;
ZEND_VM_C_GOTO(num_index_dim);
- case IS_TRUE:
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
hval = 1;
ZEND_VM_C_GOTO(num_index_dim);
- case IS_RESOURCE:
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
hval = Z_RES_HANDLE_P(offset);
ZEND_VM_C_GOTO(num_index_dim);
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- ZEND_VM_C_GOTO(offset_again);
- break;
- default:
+ } else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ key = STR_EMPTY_ALLOC();
+ ZEND_VM_C_GOTO(str_index_dim);
+ } else {
zend_error(E_WARNING, "Illegal offset type in unset");
- break;
+ }
+ break;
+ } else if (OP1_TYPE != IS_UNUSED && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ ZEND_VM_C_GOTO(unset_dim_array);
+ }
}
- } else if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
- } else {
- Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
}
- } else if (OP1_TYPE != IS_UNUSED && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- ZEND_VM_C_GOTO(unset_dim_again);
- } else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- }
+ if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
+ } else {
+ Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ }
+ } else if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
+ }
+ } while (0);
+
FREE_OP2();
FREE_OP1_VAR_PTR();
CHECK_EXCEPTION();
@@ -5716,7 +5771,6 @@ ZEND_VM_HANDLER(76, ZEND_UNSET_OBJ, VAR|UNUSED|CV, CONST|TMPVAR|CV)
if (OP1_TYPE == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
FREE_UNFETCHED_OP2();
- FREE_OP1_VAR_PTR();
HANDLE_EXCEPTION();
}
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
@@ -6520,14 +6574,15 @@ ZEND_VM_HANDLER(115, ZEND_ISSET_ISEMPTY_DIM_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|T
HANDLE_EXCEPTION();
}
- offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ offset = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
-ZEND_VM_C_LABEL(isset_dim_obj_again):
if (OP1_TYPE != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+ZEND_VM_C_LABEL(isset_dim_obj_array):
+ ht = Z_ARRVAL_P(container);
ZEND_VM_C_LABEL(isset_again):
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -6542,31 +6597,31 @@ ZEND_VM_C_LABEL(str_index_prop):
hval = Z_LVAL_P(offset);
ZEND_VM_C_LABEL(num_index_prop):
value = zend_hash_index_find(ht, hval);
+ } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ ZEND_VM_C_GOTO(isset_again);
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ ZEND_VM_C_GOTO(num_index_prop);
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ ZEND_VM_C_GOTO(str_index_prop);
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ ZEND_VM_C_GOTO(num_index_prop);
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ ZEND_VM_C_GOTO(num_index_prop);
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ ZEND_VM_C_GOTO(num_index_prop);
+ } else if (OP2_TYPE == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ ZEND_VM_C_GOTO(str_index_prop);
} else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- ZEND_VM_C_GOTO(num_index_prop);
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- ZEND_VM_C_GOTO(str_index_prop);
- case IS_FALSE:
- hval = 0;
- ZEND_VM_C_GOTO(num_index_prop);
- case IS_TRUE:
- hval = 1;
- ZEND_VM_C_GOTO(num_index_prop);
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- ZEND_VM_C_GOTO(num_index_prop);
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- ZEND_VM_C_GOTO(isset_again);
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ ZEND_VM_C_GOTO(isset_not_found);
}
if (opline->extended_value & ZEND_ISSET) {
@@ -6576,50 +6631,61 @@ ZEND_VM_C_LABEL(num_index_prop):
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if (OP1_TYPE == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ ZEND_VM_C_GOTO(isset_dim_obj_exit);
+ } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ ZEND_VM_C_GOTO(isset_dim_obj_array);
+ }
+ }
+
+ if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if (OP1_TYPE == IS_UNUSED ||
+ (OP1_TYPE != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ ZEND_VM_C_GOTO(isset_not_found);
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+ZEND_VM_C_LABEL(isset_str_offset):
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ ZEND_VM_C_GOTO(isset_not_found);
+ }
+ } else {
if (OP2_TYPE & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
- }
- }
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
+ lval = zval_get_long(offset);
+ ZEND_VM_C_GOTO(isset_str_offset);
}
+ ZEND_VM_C_GOTO(isset_not_found);
}
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- ZEND_VM_C_GOTO(isset_dim_obj_again);
} else {
+ZEND_VM_C_LABEL(isset_not_found):
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+ZEND_VM_C_LABEL(isset_dim_obj_exit):
FREE_OP2();
FREE_OP1();
ZEND_VM_SMART_BRANCH(result, 1);
@@ -6647,7 +6713,8 @@ ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|
offset = GET_OP2_ZVAL_PTR(BP_VAR_R);
- if (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (OP1_TYPE == IS_CONST ||
+ (OP1_TYPE != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -6662,10 +6729,9 @@ ZEND_VM_HANDLER(148, ZEND_ISSET_ISEMPTY_PROP_OBJ, CONST|TMPVAR|UNUSED|CV, CONST|
ZEND_VM_C_LABEL(isset_no_object):
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((OP2_TYPE == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
FREE_OP2();
@@ -7000,7 +7066,7 @@ ZEND_VM_HANDLER(138, ZEND_INSTANCEOF, TMPVAR|CV, CONST|VAR)
zend_bool result;
SAVE_OPLINE();
- expr = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ expr = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
ZEND_VM_C_LABEL(try_instanceof):
if (Z_TYPE_P(expr) == IS_OBJECT) {
@@ -7027,6 +7093,9 @@ ZEND_VM_C_LABEL(try_instanceof):
expr = Z_REFVAL_P(expr);
ZEND_VM_C_GOTO(try_instanceof);
} else {
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(expr) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(expr, BP_VAR_R);
+ }
result = 0;
}
FREE_OP1();
@@ -7265,17 +7334,13 @@ ZEND_VM_HANDLER(149, ZEND_HANDLE_EXCEPTION, ANY, ANY)
zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
if (brk_opline->opcode == ZEND_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
- }
+ zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
} else if (brk_opline->opcode == ZEND_FE_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval *var = EX_VAR(brk_opline->op1.var);
- 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);
+ zval *var = EX_VAR(brk_opline->op1.var);
+ 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_END_SILENCE) {
/* restore previous error_reporting value */
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
@@ -7446,7 +7511,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
FREE_UNFETCHED_OP2();
FREE_UNFETCHED_OP1();
@@ -7463,7 +7528,7 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
if (OP1_TYPE != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (OP1_TYPE == IS_CONST || OP1_TYPE == IS_TMP_VAR) {
@@ -7473,11 +7538,10 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
value = GET_OP1_ZVAL_PTR(BP_VAR_R);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (OP1_TYPE != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (OP1_TYPE != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = GET_OP1_ZVAL_PTR_PTR(BP_VAR_W);
@@ -7485,7 +7549,6 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
if (OP1_TYPE == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
FREE_UNFETCHED_OP2();
- FREE_OP1();
HANDLE_EXCEPTION();
}
@@ -7508,11 +7571,14 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
/* Consts, temporary variables and references need copying */
if (OP1_TYPE == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (OP1_TYPE == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((OP1_TYPE == IS_CV || OP1_TYPE == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
FREE_OP1_IF_VAR();
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -7533,11 +7599,14 @@ ZEND_VM_HANDLER(160, ZEND_YIELD, CONST|TMP|VAR|CV|UNUSED, CONST|TMP|VAR|CV|UNUSE
/* Consts, temporary variables and references need copying */
if (OP2_TYPE == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (OP2_TYPE == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((OP2_TYPE == IS_VAR || OP2_TYPE == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((OP2_TYPE & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
FREE_OP2_IF_VAR();
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -7742,11 +7811,12 @@ ZEND_VM_HANDLER(166, ZEND_POW, CONST|TMPVAR|CV, CONST|TMPVAR|CV)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- pow_function(EX_VAR(opline->result.var),
- GET_OP1_ZVAL_PTR(BP_VAR_R),
- GET_OP2_ZVAL_PTR(BP_VAR_R));
+ op1 = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ op2 = GET_OP2_ZVAL_PTR(BP_VAR_R);
+ pow_function(EX_VAR(opline->result.var), op1, op2);
FREE_OP1();
FREE_OP2();
CHECK_EXCEPTION();
@@ -7846,13 +7916,16 @@ ZEND_VM_HANDLER(121, ZEND_STRLEN, CONST|TMPVAR|CV, ANY)
zend_free_op free_op1;
SAVE_OPLINE();
- value = GET_OP1_ZVAL_PTR(BP_VAR_R);
+ value = GET_OP1_ZVAL_PTR_UNDEF(BP_VAR_R);
ZEND_VM_C_LABEL(try_strlen):
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
} else {
zend_bool strict;
+ if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ value = GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ }
if ((OP1_TYPE & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
ZEND_VM_C_GOTO(try_strlen);
@@ -7890,7 +7963,7 @@ ZEND_VM_HANDLER(123, ZEND_TYPE_CHECK, CONST|TMP|VAR|CV, ANY)
SAVE_OPLINE();
value = GET_OP1_ZVAL_PTR_DEREF(BP_VAR_R);
if (EXPECTED(Z_TYPE_P(value) == opline->extended_value)) {
- if (UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
+ if (OP1_TYPE != IS_CONST && UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
zend_class_entry *ce = Z_OBJCE_P(value);
if (UNEXPECTED(ce->name->len != sizeof("__PHP_Incomplete_Class") - 1) ||
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index e98f9dbf15..1ab12b7779 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -926,71 +926,67 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_UNPACK_SPEC_HANDLER(ZEND_
int arg_num;
SAVE_OPLINE();
- args = get_zval_ptr(opline->op1_type, opline->op1, execute_data, &free_op1, BP_VAR_R);
+ args = get_zval_ptr_undef(opline->op1_type, opline->op1, execute_data, &free_op1, BP_VAR_R);
arg_num = ZEND_CALL_NUM_ARGS(EX(call)) + 1;
send_again:
- switch (Z_TYPE_P(args)) {
- case IS_ARRAY: {
- HashTable *ht = Z_ARRVAL_P(args);
- zval *arg, *top;
- zend_string *name;
-
- zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht));
-
- if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
- uint32_t i;
- int separate = 0;
-
- /* check if any of arguments are going to be passed by reference */
- for (i = 0; i < zend_hash_num_elements(ht); i++) {
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) {
- separate = 1;
- break;
- }
- }
- if (separate) {
- zval_copy_ctor(args);
- ht = Z_ARRVAL_P(args);
+ if (EXPECTED(Z_TYPE_P(args) == IS_ARRAY)) {
+ HashTable *ht = Z_ARRVAL_P(args);
+ zval *arg, *top;
+ zend_string *name;
+
+ zend_vm_stack_extend_call_frame(&EX(call), arg_num - 1, zend_hash_num_elements(ht));
+
+ if (opline->op1_type != IS_CONST && opline->op1_type != IS_TMP_VAR && Z_IMMUTABLE_P(args)) {
+ uint32_t i;
+ int separate = 0;
+
+ /* check if any of arguments are going to be passed by reference */
+ for (i = 0; i < zend_hash_num_elements(ht); i++) {
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num + i)) {
+ separate = 1;
+ break;
}
}
+ if (separate) {
+ zval_copy_ctor(args);
+ ht = Z_ARRVAL_P(args);
+ }
+ }
- ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
- if (name) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unpack array with string keys");
- FREE_OP(free_op1);
- HANDLE_EXCEPTION();
- }
+ ZEND_HASH_FOREACH_STR_KEY_VAL(ht, name, arg) {
+ if (name) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unpack array with string keys");
+ FREE_OP(free_op1);
+ HANDLE_EXCEPTION();
+ }
- top = ZEND_CALL_ARG(EX(call), arg_num);
- if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
- if (!Z_IMMUTABLE_P(args)) {
- ZVAL_MAKE_REF(arg);
- Z_ADDREF_P(arg);
- ZVAL_REF(top, Z_REF_P(arg));
- } else {
- ZVAL_DUP(top, arg);
- }
- } else if (Z_ISREF_P(arg)) {
- ZVAL_COPY(top, Z_REFVAL_P(arg));
+ top = ZEND_CALL_ARG(EX(call), arg_num);
+ if (ARG_SHOULD_BE_SENT_BY_REF(EX(call)->func, arg_num)) {
+ if (!Z_IMMUTABLE_P(args)) {
+ ZVAL_MAKE_REF(arg);
+ Z_ADDREF_P(arg);
+ ZVAL_REF(top, Z_REF_P(arg));
} else {
- ZVAL_COPY(top, arg);
+ ZVAL_DUP(top, arg);
}
+ } else if (Z_ISREF_P(arg)) {
+ ZVAL_COPY(top, Z_REFVAL_P(arg));
+ } else {
+ ZVAL_COPY(top, arg);
+ }
- ZEND_CALL_NUM_ARGS(EX(call))++;
- arg_num++;
- } ZEND_HASH_FOREACH_END();
+ ZEND_CALL_NUM_ARGS(EX(call))++;
+ arg_num++;
+ } ZEND_HASH_FOREACH_END();
- break;
- }
- case IS_OBJECT: {
- zend_class_entry *ce = Z_OBJCE_P(args);
- zend_object_iterator *iter;
+ } else if (EXPECTED(Z_TYPE_P(args) == IS_OBJECT)) {
+ zend_class_entry *ce = Z_OBJCE_P(args);
+ zend_object_iterator *iter;
- if (!ce || !ce->get_iterator) {
- zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
- break;
- }
+ if (!ce || !ce->get_iterator) {
+ zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
+ } else {
iter = ce->get_iterator(ce, args, 0);
if (UNEXPECTED(!iter)) {
@@ -1068,14 +1064,15 @@ send_again:
unpack_iter_dtor:
zend_iterator_dtor(iter);
- break;
}
- case IS_REFERENCE:
- args = Z_REFVAL_P(args);
- goto send_again;
- break;
- default:
- zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
+ } else if (EXPECTED(Z_ISREF_P(args))) {
+ args = Z_REFVAL_P(args);
+ goto send_again;
+ } else {
+ if (opline->op1_type == IS_CV && UNEXPECTED(Z_TYPE_P(args) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(args, BP_VAR_R);
+ }
+ zend_error(E_WARNING, "Only arrays and Traversables can be unpacked");
}
FREE_OP(free_op1);
@@ -1615,17 +1612,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_HANDLE_EXCEPTION_SPEC_HANDLER(
zend_op *brk_opline = &EX(func)->op_array.opcodes[EX(func)->op_array.brk_cont_array[i].brk];
if (brk_opline->opcode == ZEND_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
- }
+ zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
} else if (brk_opline->opcode == ZEND_FE_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
- zval *var = EX_VAR(brk_opline->op1.var);
- 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);
+ zval *var = EX_VAR(brk_opline->op1.var);
+ 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_END_SILENCE) {
/* restore previous error_reporting value */
if (!EG(error_reporting) && Z_LVAL_P(EX_VAR(brk_opline->op1.var)) != 0) {
@@ -2004,6 +1997,9 @@ try_class_name:
class_name = Z_REFVAL_P(class_name);
goto try_class_name;
} else {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(class_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -2236,6 +2232,9 @@ try_function_name:
function_name = Z_REFVAL_P(function_name);
goto try_function_name;
} else {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -2352,31 +2351,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RECV_INIT_SPEC_CONST_HANDLER(Z
ZEND_VM_NEXT_OPCODE();
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BRK_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
- zend_brk_cont_element *el;
-
- SAVE_OPLINE();
- el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
- &EX(func)->op_array, execute_data);
- ZEND_VM_JMP(EX(func)->op_array.opcodes + el->brk);
-}
-
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONT_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
-{
- USE_OPLINE
- zend_brk_cont_element *el;
-
- SAVE_OPLINE();
- el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->op1.opline_num,
- &EX(func)->op_array, execute_data);
- ZEND_VM_JMP(EX(func)->op_array.opcodes + el->cont);
-}
-
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- zend_op *brk_opline;
USE_OPLINE
zend_brk_cont_element *el;
@@ -2384,14 +2360,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_GOTO_SPEC_CONST_HANDLER(ZEND_O
el = zend_brk_cont(Z_LVAL_P(EX_CONSTANT(opline->op2)), opline->extended_value,
&EX(func)->op_array, execute_data);
- brk_opline = EX(func)->op_array.opcodes + el->brk;
+ if (el->start >= 0) {
+ zend_op *brk_opline = EX(func)->op_array.opcodes + el->brk;
- if (brk_opline->opcode == ZEND_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ if (brk_opline->opcode == ZEND_FREE) {
zval_ptr_dtor_nogc(EX_VAR(brk_opline->op1.var));
- }
- } else if (brk_opline->opcode == ZEND_FE_FREE) {
- if (!(brk_opline->extended_value & EXT_TYPE_FREE_ON_RETURN)) {
+ } else if (brk_opline->opcode == ZEND_FE_FREE) {
zval *var = EX_VAR(brk_opline->op1.var);
if (Z_TYPE_P(var) != IS_ARRAY && Z_FE_ITER_P(var) != (uint32_t)-1) {
zend_hash_iterator_del(Z_FE_ITER_P(var));
@@ -2461,6 +2435,9 @@ try_class_name:
class_name = Z_REFVAL_P(class_name);
goto try_class_name;
} else {
+ if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(class_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -2486,7 +2463,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CLASS_SPEC_CV_HANDLER(ZE
ZEND_VM_NEXT_OPCODE();
} else {
- zval *class_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ zval *class_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
try_class_name:
if (IS_CV == IS_CONST) {
@@ -2504,6 +2481,9 @@ try_class_name:
class_name = Z_REFVAL_P(class_name);
goto try_class_name;
} else {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(class_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -2528,7 +2508,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_DYNAMIC_CALL_SPEC_CV_HAND
uint32_t call_info = ZEND_CALL_NESTED_FUNCTION;
SAVE_OPLINE();
- function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
try_function_name:
if (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
@@ -2708,6 +2688,9 @@ try_function_name:
function_name = Z_REFVAL_P(function_name);
goto try_function_name;
} else {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -2756,6 +2739,9 @@ try_class_name:
class_name = Z_REFVAL_P(class_name);
goto try_class_name;
} else {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(class_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(class_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -2961,6 +2947,9 @@ try_function_name:
function_name = Z_REFVAL_P(function_name);
goto try_function_name;
} else {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -3035,6 +3024,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CONST_HANDLER(ZEND_O
if (str->len != 0) {
zend_write(str->val, str->len);
+ } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(z, BP_VAR_R);
}
zend_string_release(str);
}
@@ -3252,15 +3243,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CONST_HANDLER(ZEND
if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) {
SAVE_OPLINE();
retval_ptr = GET_OP1_UNDEF_CV(retval_ptr, BP_VAR_R);
- CHECK_EXCEPTION();
- }
-
- if (!EX(return_value)) {
+ if (EX(return_value)) {
+ ZVAL_NULL(EX(return_value));
+ }
+ } else if (!EX(return_value)) {
if (IS_CONST == IS_VAR || IS_CONST == IS_TMP_VAR ) {
if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) {
SAVE_OPLINE();
zval_dtor_func_for_ptr(Z_COUNTED_P(free_op1));
- CHECK_EXCEPTION();
}
}
} else {
@@ -3326,7 +3316,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CONST_HANDL
if (IS_CONST == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot return string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -3417,6 +3406,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CONST_HANDLER(ZEND_
break;
}
}
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -3589,7 +3581,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CONST_HANDLER(ZEND_
if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
break;
}
- }
+ }
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(obj, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -3735,8 +3730,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CONST_HANDLER(ZEND_O
}
}
} else {
- ZVAL_COPY_VALUE(result, expr);
- zval_opt_copy_ctor(result);
+ ZVAL_COPY(result, expr);
convert_to_object(result);
}
}
@@ -3760,6 +3754,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CONST_HAN
ZVAL_UNDEF(&tmp_inc_filename);
if (Z_TYPE_P(inc_filename) != IS_STRING) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(inc_filename) == IS_UNDEF)) {
+ inc_filename = GET_OP1_UNDEF_CV(inc_filename, BP_VAR_R);
+ }
ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename));
inc_filename = &tmp_inc_filename;
}
@@ -4382,6 +4379,9 @@ try_strlen:
} else {
zend_bool strict;
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ value = GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ }
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
goto try_strlen;
@@ -4419,7 +4419,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CONST_HANDLER(
SAVE_OPLINE();
value = EX_CONSTANT(opline->op1);
if (EXPECTED(Z_TYPE_P(value) == opline->extended_value)) {
- if (UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
+ if (IS_CONST != IS_CONST && UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
zend_class_entry *ce = Z_OBJCE_P(value);
if (UNEXPECTED(ce->name->len != sizeof("__PHP_Incomplete_Class") - 1) ||
@@ -4605,11 +4605,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CONST_HANDLER(Z
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- fast_div_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+ fast_div_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -4659,11 +4660,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CONST_HANDLER(ZE
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_left_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+ shift_left_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -4674,11 +4676,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_CONST_HANDLER(ZE
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_right_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+ shift_right_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -4689,12 +4692,58 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CONST_HANDLE
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- concat_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+
+ do {
+ if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
+ (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
+ zend_string *op1_str = Z_STR_P(op1);
+ zend_string *op2_str = Z_STR_P(op2);
+ zend_string *str;
+
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
+
+ break;
+ }
+ }
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
+
+ break;
+ }
+ }
+ if (IS_CONST != IS_CONST && IS_CONST != IS_CV &&
+ !IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ size_t len = op1_str->len;
+
+ str = zend_string_realloc(op1_str, len + op2_str->len, 0);
+ memcpy(str->val + len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ break;
+ } else {
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ }
+ } else {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ concat_function(EX_VAR(opline->result.var), op1, op2);
+ }
+ } while (0);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -4704,12 +4753,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CONST_
{
USE_OPLINE
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+ result = fast_is_identical_function(op1, op2);
ZEND_VM_SMART_BRANCH(result, (IS_CONST|IS_CONST) & (IS_VAR|IS_TMP_VAR));
@@ -4724,12 +4774,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CO
{
USE_OPLINE
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+ result = fast_is_not_identical_function(op1, op2);
ZEND_VM_SMART_BRANCH(result, (IS_CONST|IS_CONST) & (IS_VAR|IS_TMP_VAR));
@@ -4751,18 +4802,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CONST_HAND
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -4794,10 +4845,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CONST_HAND
} while (0);
SAVE_OPLINE();
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -4820,18 +4871,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -4863,10 +4914,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CONST_
} while (0);
SAVE_OPLINE();
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -4984,12 +5035,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CONST_HAN
{
USE_OPLINE
- zval *result = EX_VAR(opline->result.var);
+ zval *op1, *op2;
SAVE_OPLINE();
- compare_function(result,
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+ compare_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -5000,11 +5051,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CONST_HANDLER
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_or_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+ bitwise_or_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -5015,11 +5067,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CONST_HANDLE
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_and_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+ bitwise_and_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -5030,11 +5083,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CONST_HANDLE
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_xor_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+ bitwise_xor_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -5045,11 +5099,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CONST_HAND
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- boolean_xor_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+ boolean_xor_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -5074,6 +5129,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
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);
}
@@ -5289,7 +5347,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
@@ -5333,7 +5390,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CONST_H
offset = EX_CONSTANT(opline->op2);
- if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST ||
+ (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -5405,7 +5463,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CONST_
offset = EX_CONSTANT(opline->op2);
- if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST ||
+ (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -5486,7 +5545,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -5521,7 +5579,8 @@ try_fetch_list:
} else {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
- } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
+ } else if (IS_CONST != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
zval *result = EX_VAR(opline->result.var);
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
@@ -5533,10 +5592,13 @@ try_fetch_list:
} else {
ZVAL_NULL(result);
}
- } else if (Z_TYPE_P(container) == IS_REFERENCE) {
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_TYPE_P(container) == IS_REFERENCE) {
container = Z_REFVAL_P(container);
goto try_fetch_list;
} else {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(container, BP_VAR_R);
+ }
ZVAL_NULL(EX_VAR(opline->result.var));
}
CHECK_EXCEPTION();
@@ -5552,27 +5614,59 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CONST_H
SAVE_OPLINE();
op1 = EX_CONSTANT(opline->op1);
- op2 = EX_CONSTANT(opline->op2);
if (IS_CONST == IS_CONST) {
op1_str = Z_STR_P(op1);
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ op1_str = zend_string_copy(Z_STR_P(op1));
} else {
- op1_str = zval_get_string(op1);
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ op1_str = _zval_get_string_func(op1);
}
+ op2 = EX_CONSTANT(opline->op2);
if (IS_CONST == IS_CONST) {
op2_str = Z_STR_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ op2_str = zend_string_copy(Z_STR_P(op2));
} else {
- op2_str = zval_get_string(op2);
- }
- str = zend_string_alloc(op1_str->len + op2_str->len, 0);
- memcpy(str->val, op1_str->val, op1_str->len);
- memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
- ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- if (IS_CONST != IS_CONST) {
- zend_string_release(op1_str);
- }
- if (IS_CONST != IS_CONST) {
- zend_string_release(op2_str);
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ op2_str = _zval_get_string_func(op2);
}
+ do {
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ if (IS_CONST == IS_CONST) {
+ zend_string_addref(op2_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op2_str);
+ zend_string_release(op1_str);
+ break;
+ }
+ }
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ if (IS_CONST == IS_CONST) {
+ zend_string_addref(op1_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op1_str);
+ zend_string_release(op2_str);
+ break;
+ }
+ }
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ if (IS_CONST != IS_CONST) {
+ zend_string_release(op1_str);
+ }
+ if (IS_CONST != IS_CONST) {
+ zend_string_release(op2_str);
+ }
+ } while (0);
CHECK_EXCEPTION();
@@ -5604,6 +5698,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CO
break;
}
}
+ 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();
}
@@ -5624,13 +5721,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CO
if (IS_CONST != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -5677,7 +5777,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CO
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if (IS_CONST & (IS_VAR|IS_TMP_VAR)) {
+ } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -5736,6 +5837,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
function_name = EX_CONSTANT(opline->op2);
if (IS_CONST != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -5889,18 +5993,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CONST_HANDLER(
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -5931,10 +6035,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CONST_HANDLER(
} while (0);
SAVE_OPLINE();
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -5952,7 +6056,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONS
SAVE_OPLINE();
if (IS_CONST == IS_UNUSED) {
zend_constant *c;
- zval *retval;
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
@@ -5978,67 +6081,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_CONST_CONS
} else {
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
}
- retval = EX_VAR(opline->result.var);
- ZVAL_COPY_VALUE(retval, &c->value);
- if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval)) {
- zval_copy_ctor_func(retval);
- } else {
- Z_ADDREF_P(retval);
- }
+#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;
- if (IS_CONST == IS_CONST) {
- if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- ZVAL_DEREF(value);
- ZVAL_DUP(EX_VAR(opline->result.var), value);
- goto constant_fetch_end;
- } else if (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(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if (IS_CONST == IS_CONST) {
+ if (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)));
+#endif
+ break;
+ } else if (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(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ if (UNEXPECTED(ce == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
+ HANDLE_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
- if (UNEXPECTED(ce == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
- 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;
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
- }
- } 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);
- ZVAL_DUP(EX_VAR(opline->result.var), value);
- goto constant_fetch_end;
}
- }
- 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 (IS_CONST == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
+ 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 {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ }
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ HANDLE_EXCEPTION();
}
+ } while (0);
+#ifdef ZTS
+ if (ce->type == ZEND_INTERNAL_CLASS) {
ZVAL_DUP(EX_VAR(opline->result.var), value);
} else {
- zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
}
+#else
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+#endif
}
-constant_fetch_end:
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -6050,11 +6166,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C
SAVE_OPLINE();
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -6064,11 +6179,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C
} else {
expr_ptr = EX_CONSTANT(opline->op1);
if (IS_CONST == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_CONST == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_CONST == IS_CV) {
@@ -6099,43 +6214,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_CONST != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CONST != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -6210,6 +6323,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_CONST_HAN
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;
}
@@ -6380,12 +6496,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CON
offset = EX_CONSTANT(opline->op2);
-isset_dim_obj_again:
if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -6400,31 +6517,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -6434,50 +6551,62 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if (IS_CONST == IS_UNUSED ||
+ (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if (IS_CONST & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
- }
- }
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
+
ZEND_VM_SMART_BRANCH(result, 1);
ZVAL_BOOL(EX_VAR(opline->result.var), result);
@@ -6504,7 +6633,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CO
offset = EX_CONSTANT(opline->op2);
- if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST ||
+ (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -6519,10 +6649,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CO
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
@@ -6576,7 +6705,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
@@ -6593,7 +6722,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER
if (IS_CONST != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -6603,11 +6732,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER
value = EX_CONSTANT(opline->op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_CONST != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -6615,7 +6743,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER
if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -6637,11 +6764,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER
/* Consts, temporary variables and references need copying */
if (IS_CONST == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -6662,11 +6792,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CONST_HANDLER
/* Consts, temporary variables and references need copying */
if (IS_CONST == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -6710,11 +6843,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CONST_HANDLER(Z
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- pow_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- EX_CONSTANT(opline->op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = EX_CONSTANT(opline->op2);
+ pow_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -6725,12 +6859,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_TMP_HA
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_CONST|IS_TMP_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -6745,12 +6880,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_TM
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_CONST|IS_TMP_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -6768,7 +6904,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
@@ -6785,7 +6921,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z
if (IS_CONST != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -6795,11 +6931,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z
value = EX_CONSTANT(opline->op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_CONST != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -6807,7 +6942,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z
if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
@@ -6829,11 +6963,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_CONST == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -6854,11 +6991,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_TMP_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_TMP_VAR == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_TMP_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -6902,12 +7042,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_VAR_HA
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_CONST|IS_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -6922,12 +7063,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_VA
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_CONST|IS_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -6956,6 +7098,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
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);
}
@@ -7156,6 +7301,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_VAR_HANDL
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;
}
@@ -7313,7 +7461,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
@@ -7330,7 +7478,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z
if (IS_CONST != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -7340,11 +7488,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z
value = EX_CONSTANT(opline->op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_CONST != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -7352,7 +7499,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z
if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
@@ -7374,11 +7520,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_CONST == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -7399,11 +7548,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_VAR_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_VAR == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
zval_ptr_dtor_nogc(free_op2);
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -7461,6 +7613,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
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);
}
@@ -7646,7 +7801,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
@@ -7715,6 +7869,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
function_name = NULL;
if (IS_UNUSED != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
+ if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -7844,6 +8001,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CONST_
}
}
zend_verify_return_type(EX(func), retval_ptr);
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+
+ }
#endif
}
CHECK_EXCEPTION();
@@ -7858,11 +8019,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U
SAVE_OPLINE();
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -7872,11 +8032,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U
} else {
expr_ptr = EX_CONSTANT(opline->op1);
if (IS_CONST == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_CONST == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_CONST == IS_CV) {
@@ -7907,43 +8067,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_U
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_UNUSED != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_UNUSED != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -8018,6 +8176,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CONST_UNUSED_HA
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;
}
@@ -8198,7 +8359,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
@@ -8215,7 +8376,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE
if (IS_CONST != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -8225,11 +8386,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE
value = EX_CONSTANT(opline->op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_CONST != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -8237,7 +8397,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE
if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -8259,11 +8418,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE
/* Consts, temporary variables and references need copying */
if (IS_CONST == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -8284,11 +8446,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_UNUSED_HANDLE
/* Consts, temporary variables and references need copying */
if (IS_UNUSED == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_UNUSED == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -8467,11 +8632,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_CV_HANDLER(ZEND
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- fast_div_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ fast_div_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -8521,11 +8687,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_CV_HANDLER(ZEND_
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_left_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ shift_left_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -8536,11 +8703,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_CV_HANDLER(ZEND_
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_right_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ shift_right_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -8551,12 +8719,58 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_CV_HANDLER(Z
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- concat_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
+
+ do {
+ if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
+ (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
+ zend_string *op1_str = Z_STR_P(op1);
+ zend_string *op2_str = Z_STR_P(op2);
+ zend_string *str;
+
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
+
+ break;
+ }
+ }
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
+
+ break;
+ }
+ }
+ if (IS_CONST != IS_CONST && IS_CONST != IS_CV &&
+ !IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ size_t len = op1_str->len;
+
+ str = zend_string_realloc(op1_str, len + op2_str->len, 0);
+ memcpy(str->val + len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ break;
+ } else {
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ }
+ } else {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ concat_function(EX_VAR(opline->result.var), op1, op2);
+ }
+ } while (0);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -8566,12 +8780,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CONST_CV_HAN
{
USE_OPLINE
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var);
+ result = fast_is_identical_function(op1, op2);
ZEND_VM_SMART_BRANCH(result, (IS_CONST|IS_CV) & (IS_VAR|IS_TMP_VAR));
@@ -8586,12 +8801,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CONST_CV
{
USE_OPLINE
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var);
+ result = fast_is_not_identical_function(op1, op2);
ZEND_VM_SMART_BRANCH(result, (IS_CONST|IS_CV) & (IS_VAR|IS_TMP_VAR));
@@ -8613,18 +8829,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -8656,10 +8872,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_CV_HANDLER
} while (0);
SAVE_OPLINE();
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -8682,18 +8898,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HAN
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -8725,10 +8941,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_CV_HAN
} while (0);
SAVE_OPLINE();
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -8846,12 +9062,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_CV_HANDLE
{
USE_OPLINE
- zval *result = EX_VAR(opline->result.var);
+ zval *op1, *op2;
SAVE_OPLINE();
- compare_function(result,
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ compare_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -8862,11 +9078,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_CV_HANDLER(ZE
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_or_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ bitwise_or_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -8877,11 +9094,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_CV_HANDLER(Z
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_and_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ bitwise_and_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -8892,11 +9110,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_CV_HANDLER(Z
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_xor_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ bitwise_xor_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -8907,11 +9126,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_CV_HANDLER
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- boolean_xor_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ boolean_xor_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -8967,7 +9187,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
@@ -9011,7 +9230,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_CV_HAND
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST ||
+ (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -9083,7 +9303,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_CV_HAN
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST ||
+ (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -9164,7 +9385,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -9189,27 +9409,59 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_CV_HAND
SAVE_OPLINE();
op1 = EX_CONSTANT(opline->op1);
- op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
if (IS_CONST == IS_CONST) {
op1_str = Z_STR_P(op1);
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ op1_str = zend_string_copy(Z_STR_P(op1));
} else {
- op1_str = zval_get_string(op1);
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ op1_str = _zval_get_string_func(op1);
}
+ op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
if (IS_CV == IS_CONST) {
op2_str = Z_STR_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ op2_str = zend_string_copy(Z_STR_P(op2));
} else {
- op2_str = zval_get_string(op2);
- }
- str = zend_string_alloc(op1_str->len + op2_str->len, 0);
- memcpy(str->val, op1_str->val, op1_str->len);
- memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
- ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- if (IS_CONST != IS_CONST) {
- zend_string_release(op1_str);
- }
- if (IS_CV != IS_CONST) {
- zend_string_release(op2_str);
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ op2_str = _zval_get_string_func(op2);
}
+ do {
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ if (IS_CV == IS_CONST) {
+ zend_string_addref(op2_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op2_str);
+ zend_string_release(op1_str);
+ break;
+ }
+ }
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ if (IS_CONST == IS_CONST) {
+ zend_string_addref(op1_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op1_str);
+ zend_string_release(op2_str);
+ break;
+ }
+ }
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ if (IS_CONST != IS_CONST) {
+ zend_string_release(op1_str);
+ }
+ if (IS_CV != IS_CONST) {
+ zend_string_release(op2_str);
+ }
+ } while (0);
CHECK_EXCEPTION();
@@ -9230,7 +9482,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV
SAVE_OPLINE();
- function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
if (IS_CV != IS_CONST &&
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
@@ -9241,6 +9493,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV
break;
}
}
+ 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();
}
@@ -9261,13 +9516,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV
if (IS_CONST != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -9314,7 +9572,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if (IS_CONST & (IS_VAR|IS_TMP_VAR)) {
+ } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -9370,9 +9629,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
} else if (IS_CV != IS_UNUSED) {
- function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ 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();
}
@@ -9577,18 +9839,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEN
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -9619,10 +9881,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_CV_HANDLER(ZEN
} while (0);
SAVE_OPLINE();
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -9641,11 +9903,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C
SAVE_OPLINE();
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -9655,11 +9916,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C
} else {
expr_ptr = EX_CONSTANT(opline->op1);
if (IS_CONST == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_CONST == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_CONST == IS_CV) {
@@ -9685,48 +9946,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_C
if (IS_CV != IS_UNUSED) {
- zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ zval *offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
zend_string *str;
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_CV != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CV != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -9785,14 +10044,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CON
HANDLE_EXCEPTION();
}
- offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
-isset_dim_obj_again:
if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -9807,31 +10067,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -9841,50 +10101,62 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if (IS_CONST == IS_UNUSED ||
+ (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if (IS_CV & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
- }
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
+
ZEND_VM_SMART_BRANCH(result, 1);
ZVAL_BOOL(EX_VAR(opline->result.var), result);
@@ -9911,7 +10183,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CO
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST ||
+ (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -9926,10 +10199,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CO
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
@@ -9946,7 +10218,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
@@ -9963,7 +10235,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE
if (IS_CONST != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CONST == IS_CONST || IS_CONST == IS_TMP_VAR) {
@@ -9973,11 +10245,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE
value = EX_CONSTANT(opline->op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_CONST != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -9985,7 +10256,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE
if (IS_CONST == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -10007,11 +10277,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE
/* Consts, temporary variables and references need copying */
if (IS_CONST == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_CONST == IS_CV || IS_CONST == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -10032,11 +10305,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CONST_CV_HANDLER(ZE
/* Consts, temporary variables and references need copying */
if (IS_CV == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -10080,11 +10356,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_CV_HANDLER(ZEND
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- pow_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ pow_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -10230,11 +10507,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CONST_TMPVAR_HANDLER(
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- fast_div_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ fast_div_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -10284,11 +10562,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CONST_TMPVAR_HANDLER(Z
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_left_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ shift_left_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -10299,11 +10578,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CONST_TMPVAR_HANDLER(Z
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_right_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ shift_right_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -10314,12 +10594,58 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CONST_TMPVAR_HANDL
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- concat_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+
+ do {
+ if ((IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
+ ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
+ zend_string *op1_str = Z_STR_P(op1);
+ zend_string *op2_str = Z_STR_P(op2);
+ zend_string *str;
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
+
+ break;
+ }
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
+
+ break;
+ }
+ }
+ if (IS_CONST != IS_CONST && IS_CONST != IS_CV &&
+ !IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ size_t len = op1_str->len;
+
+ str = zend_string_realloc(op1_str, len + op2_str->len, 0);
+ memcpy(str->val + len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ break;
+ } else {
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ }
+ } else {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ concat_function(EX_VAR(opline->result.var), op1, op2);
+ }
+
+ } while (0);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -10336,18 +10662,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_TMPVAR_HAN
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -10379,10 +10705,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CONST_TMPVAR_HAN
} while (0);
SAVE_OPLINE();
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -10405,18 +10731,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_TMPVAR
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -10448,10 +10774,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CONST_TMPVAR
} while (0);
SAVE_OPLINE();
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -10569,12 +10895,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CONST_TMPVAR_HA
{
USE_OPLINE
zend_free_op free_op2;
- zval *result = EX_VAR(opline->result.var);
+ zval *op1, *op2;
SAVE_OPLINE();
- compare_function(result,
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ compare_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -10585,11 +10911,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CONST_TMPVAR_HANDLE
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_or_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ bitwise_or_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -10600,11 +10927,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CONST_TMPVAR_HANDL
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_and_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ bitwise_and_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -10615,11 +10943,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CONST_TMPVAR_HANDL
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_xor_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ bitwise_xor_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -10630,11 +10959,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CONST_TMPVAR_HAN
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- boolean_xor_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ boolean_xor_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -10690,7 +11020,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CONST_
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
@@ -10734,7 +11063,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CONST_TMPVAR_
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST ||
+ (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -10807,7 +11137,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CONST_TMPVAR
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST ||
+ (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -10889,7 +11220,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CONST_
if (IS_CONST == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CONST, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -10914,27 +11244,59 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CONST_TMPVAR_
SAVE_OPLINE();
op1 = EX_CONSTANT(opline->op1);
- op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
if (IS_CONST == IS_CONST) {
op1_str = Z_STR_P(op1);
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ op1_str = zend_string_copy(Z_STR_P(op1));
} else {
- op1_str = zval_get_string(op1);
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ op1_str = _zval_get_string_func(op1);
}
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
op2_str = Z_STR_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ op2_str = zend_string_copy(Z_STR_P(op2));
} else {
- op2_str = zval_get_string(op2);
- }
- str = zend_string_alloc(op1_str->len + op2_str->len, 0);
- memcpy(str->val, op1_str->val, op1_str->len);
- memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
- ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- if (IS_CONST != IS_CONST) {
- zend_string_release(op1_str);
- }
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- zend_string_release(op2_str);
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ op2_str = _zval_get_string_func(op2);
}
+ do {
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+ zend_string_addref(op2_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op2_str);
+ zend_string_release(op1_str);
+ break;
+ }
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ if (IS_CONST == IS_CONST) {
+ zend_string_addref(op1_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op1_str);
+ zend_string_release(op2_str);
+ break;
+ }
+ }
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ if (IS_CONST != IS_CONST) {
+ zend_string_release(op1_str);
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ zend_string_release(op2_str);
+ }
+ } while (0);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -10966,6 +11328,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TM
break;
}
}
+ 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();
}
@@ -10986,13 +11351,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TM
if (IS_CONST != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -11039,7 +11407,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TM
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if (IS_CONST & (IS_VAR|IS_TMP_VAR)) {
+ } else if (IS_CONST & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -11099,6 +11468,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -11253,18 +11625,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -11295,10 +11667,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CONST_TMPVAR_HANDLER
} while (0);
SAVE_OPLINE();
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -11317,11 +11689,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T
SAVE_OPLINE();
if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
if (IS_CONST == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -11331,11 +11702,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T
} else {
expr_ptr = EX_CONSTANT(opline->op1);
if (IS_CONST == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_CONST == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_CONST == IS_CV) {
@@ -11366,43 +11737,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CONST_T
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
zval_ptr_dtor_nogc(free_op2);
} else {
@@ -11463,12 +11832,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CON
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
-isset_dim_obj_again:
if (IS_CONST != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -11483,31 +11853,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -11517,50 +11887,61 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if (IS_CONST == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if (IS_CONST == IS_UNUSED ||
+ (IS_CONST != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
- }
- }
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, 1);
@@ -11588,7 +11969,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CO
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CONST == IS_CONST ||
+ (IS_CONST != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -11603,10 +11985,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CO
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
zval_ptr_dtor_nogc(free_op2);
@@ -11621,11 +12002,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CONST_TMPVAR_HANDLER(
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- pow_function(EX_VAR(opline->result.var),
- EX_CONSTANT(opline->op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = EX_CONSTANT(opline->op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ pow_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -11642,15 +12024,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_TMP_HANDLER(ZEND_O
if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) {
SAVE_OPLINE();
retval_ptr = GET_OP1_UNDEF_CV(retval_ptr, BP_VAR_R);
- CHECK_EXCEPTION();
- }
-
- if (!EX(return_value)) {
+ if (EX(return_value)) {
+ ZVAL_NULL(EX(return_value));
+ }
+ } else if (!EX(return_value)) {
if (IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_TMP_VAR ) {
if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) {
SAVE_OPLINE();
zval_dtor_func_for_ptr(Z_COUNTED_P(free_op1));
- CHECK_EXCEPTION();
}
}
} else {
@@ -11716,7 +12097,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_TMP_HANDLER
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot return string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -11807,6 +12187,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_TMP_HANDLER(ZEND_OP
break;
}
}
+ if (IS_TMP_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -11966,8 +12349,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_TMP_HANDLER(ZEND_OPC
}
}
} else {
- ZVAL_COPY_VALUE(result, expr);
- zval_opt_copy_ctor(result);
+ ZVAL_COPY(result, expr);
convert_to_object(result);
}
}
@@ -12467,7 +12849,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_TMP_HANDLER(ZE
SAVE_OPLINE();
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
if (EXPECTED(Z_TYPE_P(value) == opline->extended_value)) {
- if (UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
+ if (IS_TMP_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
zend_class_entry *ce = Z_OBJCE_P(value);
if (UNEXPECTED(ce->name->len != sizeof("__PHP_Incomplete_Class") - 1) ||
@@ -12498,12 +12880,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CONST_HA
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
ZEND_VM_SMART_BRANCH(result, (IS_TMP_VAR|IS_CONST) & (IS_VAR|IS_TMP_VAR));
@@ -12518,12 +12901,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CONS
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
ZEND_VM_SMART_BRANCH(result, (IS_TMP_VAR|IS_CONST) & (IS_VAR|IS_TMP_VAR));
@@ -12553,7 +12937,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CO
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
@@ -12597,7 +12980,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CONST_HAN
offset = EX_CONSTANT(opline->op2);
- if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_TMP_VAR == IS_CONST ||
+ (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -12678,7 +13062,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CO
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -12707,11 +13090,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CONST_HANDLE
var = EX_CONSTANT(opline->op2);
rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
var = EX_CONSTANT(opline->op2);
- rope[opline->extended_value] = zval_get_string(var);
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if (IS_CONST == IS_CV) {
+ rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[opline->extended_value] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[opline->extended_value] = _zval_get_string_func(var);
- CHECK_EXCEPTION();
+ CHECK_EXCEPTION();
+ }
}
ZEND_VM_NEXT_OPCODE();
}
@@ -12731,11 +13125,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CONST_HANDLE
var = EX_CONSTANT(opline->op2);
rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
var = EX_CONSTANT(opline->op2);
- rope[opline->extended_value] = zval_get_string(var);
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if (IS_CONST == IS_CV) {
+ rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[opline->extended_value] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[opline->extended_value] = _zval_get_string_func(var);
- CHECK_EXCEPTION();
+ CHECK_EXCEPTION();
+ }
}
for (i = 0; i <= opline->extended_value; i++) {
len += rope[i]->len;
@@ -12761,11 +13166,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON
SAVE_OPLINE();
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -12775,11 +13179,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON
} else {
expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
if (IS_TMP_VAR == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_TMP_VAR == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_TMP_VAR == IS_CV) {
@@ -12810,43 +13214,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CON
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_CONST != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CONST != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -12894,7 +13296,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -12911,7 +13313,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z
if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -12921,11 +13323,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_TMP_VAR != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_TMP_VAR != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -12933,7 +13334,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
- zval_ptr_dtor_nogc(free_op1);
HANDLE_EXCEPTION();
}
@@ -12955,11 +13355,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_TMP_VAR == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_TMP_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -12980,11 +13383,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CONST_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_CONST == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -13028,12 +13434,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_TMP_HAND
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_TMP_VAR|IS_TMP_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -13048,12 +13455,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_TMP_
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_TMP_VAR|IS_TMP_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -13071,7 +13479,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -13088,7 +13496,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN
if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -13098,11 +13506,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_TMP_VAR != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_TMP_VAR != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -13110,7 +13517,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- zval_ptr_dtor_nogc(free_op1);
HANDLE_EXCEPTION();
}
@@ -13132,11 +13538,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN
/* Consts, temporary variables and references need copying */
if (IS_TMP_VAR == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_TMP_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -13157,11 +13566,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_TMP_HANDLER(ZEN
/* Consts, temporary variables and references need copying */
if (IS_TMP_VAR == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_TMP_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -13205,12 +13617,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_VAR_HAND
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -13225,12 +13638,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_VAR_
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -13248,7 +13662,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -13265,7 +13679,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN
if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -13275,11 +13689,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_TMP_VAR != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_TMP_VAR != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -13287,7 +13700,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- zval_ptr_dtor_nogc(free_op1);
HANDLE_EXCEPTION();
}
@@ -13309,11 +13721,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN
/* Consts, temporary variables and references need copying */
if (IS_TMP_VAR == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_TMP_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -13334,11 +13749,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_VAR_HANDLER(ZEN
/* Consts, temporary variables and references need copying */
if (IS_VAR == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
zval_ptr_dtor_nogc(free_op2);
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -13397,7 +13815,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_UN
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
@@ -13465,6 +13882,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_TMP_UN
}
}
zend_verify_return_type(EX(func), retval_ptr);
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zval_ptr_dtor_nogc(free_op1);
+ }
#endif
}
CHECK_EXCEPTION();
@@ -13479,11 +13900,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU
SAVE_OPLINE();
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -13493,11 +13913,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU
} else {
expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
if (IS_TMP_VAR == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_TMP_VAR == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_TMP_VAR == IS_CV) {
@@ -13528,43 +13948,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_UNU
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_UNUSED != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_UNUSED != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -13612,7 +14030,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -13629,7 +14047,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(
if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -13639,11 +14057,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_TMP_VAR != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_TMP_VAR != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -13651,7 +14068,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
- zval_ptr_dtor_nogc(free_op1);
HANDLE_EXCEPTION();
}
@@ -13673,11 +14089,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(
/* Consts, temporary variables and references need copying */
if (IS_TMP_VAR == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_TMP_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -13698,11 +14117,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_UNUSED_HANDLER(
/* Consts, temporary variables and references need copying */
if (IS_UNUSED == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_UNUSED == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -13746,12 +14168,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_TMP_CV_HANDL
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
ZEND_VM_SMART_BRANCH(result, (IS_TMP_VAR|IS_CV) & (IS_VAR|IS_TMP_VAR));
@@ -13766,12 +14189,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_TMP_CV_H
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
ZEND_VM_SMART_BRANCH(result, (IS_TMP_VAR|IS_CV) & (IS_VAR|IS_TMP_VAR));
@@ -13801,7 +14225,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_CV
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
@@ -13845,7 +14268,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_CV_HANDLE
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_TMP_VAR == IS_CONST ||
+ (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -13926,7 +14350,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_CV
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -13955,11 +14378,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_CV_HANDLER(Z
var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
- var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- rope[opline->extended_value] = zval_get_string(var);
+ var = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if (IS_CV == IS_CV) {
+ rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[opline->extended_value] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[opline->extended_value] = _zval_get_string_func(var);
- CHECK_EXCEPTION();
+ CHECK_EXCEPTION();
+ }
}
ZEND_VM_NEXT_OPCODE();
}
@@ -13979,11 +14413,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_CV_HANDLER(Z
var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
- var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- rope[opline->extended_value] = zval_get_string(var);
+ var = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if (IS_CV == IS_CV) {
+ rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[opline->extended_value] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[opline->extended_value] = _zval_get_string_func(var);
- CHECK_EXCEPTION();
+ CHECK_EXCEPTION();
+ }
}
for (i = 0; i <= opline->extended_value; i++) {
len += rope[i]->len;
@@ -14009,11 +14454,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_
SAVE_OPLINE();
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -14023,11 +14467,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_
} else {
expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
if (IS_TMP_VAR == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_TMP_VAR == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_TMP_VAR == IS_CV) {
@@ -14053,48 +14497,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_CV_
if (IS_CV != IS_UNUSED) {
- zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ zval *offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
zend_string *str;
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_CV != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CV != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -14142,7 +14584,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -14159,7 +14601,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND
if (IS_TMP_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_TMP_VAR == IS_CONST || IS_TMP_VAR == IS_TMP_VAR) {
@@ -14169,11 +14611,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND
value = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_TMP_VAR != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_TMP_VAR != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -14181,7 +14622,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
- zval_ptr_dtor_nogc(free_op1);
HANDLE_EXCEPTION();
}
@@ -14203,11 +14643,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND
/* Consts, temporary variables and references need copying */
if (IS_TMP_VAR == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_TMP_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_TMP_VAR == IS_CV || IS_TMP_VAR == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -14228,11 +14671,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_TMP_CV_HANDLER(ZEND
/* Consts, temporary variables and references need copying */
if (IS_CV == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -14291,7 +14737,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_TMP_TM
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
@@ -14335,7 +14780,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_TMP_TMPVAR_HA
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_TMP_VAR == IS_CONST ||
+ (IS_TMP_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -14417,7 +14863,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_TMP_TM
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_TMP_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -14446,11 +14891,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_ADD_SPEC_TMP_TMPVAR_HANDL
var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- rope[opline->extended_value] = zval_get_string(var);
- zval_ptr_dtor_nogc(free_op2);
- CHECK_EXCEPTION();
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
+ rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[opline->extended_value] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[opline->extended_value] = _zval_get_string_func(var);
+ zval_ptr_dtor_nogc(free_op2);
+ CHECK_EXCEPTION();
+ }
}
ZEND_VM_NEXT_OPCODE();
}
@@ -14470,11 +14926,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_END_SPEC_TMP_TMPVAR_HANDL
var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- rope[opline->extended_value] = zval_get_string(var);
- zval_ptr_dtor_nogc(free_op2);
- CHECK_EXCEPTION();
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
+ rope[opline->extended_value] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[opline->extended_value] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[opline->extended_value] = _zval_get_string_func(var);
+ zval_ptr_dtor_nogc(free_op2);
+ CHECK_EXCEPTION();
+ }
}
for (i = 0; i <= opline->extended_value; i++) {
len += rope[i]->len;
@@ -14500,11 +14967,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP
SAVE_OPLINE();
if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = NULL;
if (IS_TMP_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -14514,11 +14980,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP
} else {
expr_ptr = _get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1);
if (IS_TMP_VAR == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_TMP_VAR == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_TMP_VAR == IS_CV) {
@@ -14549,43 +15015,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_TMP_TMP
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
zval_ptr_dtor_nogc(free_op2);
} else {
@@ -14637,7 +15101,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_VAR_HANDLER(ZEND_
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -14685,7 +15148,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_VAR_HANDLER(ZEND_
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -14733,7 +15195,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_VAR_HANDLER(ZEND
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -14774,7 +15235,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_VAR_HANDLER(ZEND
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -14814,15 +15274,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_VAR_HANDLER(ZEND_O
if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) {
SAVE_OPLINE();
retval_ptr = GET_OP1_UNDEF_CV(retval_ptr, BP_VAR_R);
- CHECK_EXCEPTION();
- }
-
- if (!EX(return_value)) {
+ if (EX(return_value)) {
+ ZVAL_NULL(EX(return_value));
+ }
+ } else if (!EX(return_value)) {
if (IS_VAR == IS_VAR || IS_VAR == IS_TMP_VAR ) {
if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) {
SAVE_OPLINE();
zval_dtor_func_for_ptr(Z_COUNTED_P(free_op1));
- CHECK_EXCEPTION();
}
}
} else {
@@ -14888,7 +15347,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_VAR_HANDLER
if (IS_VAR == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot return string offsets by reference");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -14980,6 +15438,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_VAR_HANDLER(ZEND_OP
break;
}
}
+ if (IS_VAR == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -15089,7 +15550,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_VAR_HANDLER(ZEND
if (IS_VAR == IS_VAR && UNEXPECTED(varptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Only variables can be passed by reference");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -15365,8 +15825,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_VAR_HANDLER(ZEND_OPC
}
}
} else {
- ZVAL_COPY_VALUE(result, expr);
- zval_opt_copy_ctor(result);
+ ZVAL_COPY(result, expr);
convert_to_object(result);
}
}
@@ -16238,7 +16697,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_VAR_HANDLER(ZE
SAVE_OPLINE();
value = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
if (EXPECTED(Z_TYPE_P(value) == opline->extended_value)) {
- if (UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
+ if (IS_VAR != IS_CONST && UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
zend_class_entry *ce = Z_OBJCE_P(value);
if (UNEXPECTED(ce->name->len != sizeof("__PHP_Incomplete_Class") - 1) ||
@@ -16269,12 +16728,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CONST_HA
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
ZEND_VM_SMART_BRANCH(result, (IS_VAR|IS_CONST) & (IS_VAR|IS_TMP_VAR));
@@ -16289,12 +16749,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CONS
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
ZEND_VM_SMART_BRANCH(result, (IS_VAR|IS_CONST) & (IS_VAR|IS_TMP_VAR));
@@ -16330,7 +16791,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -16360,42 +16820,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval *z;
- zval rv, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- if (Z_OBJ_HT(obj)->read_property &&
- (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- zptr = z;
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- binary_op(z, z, value);
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- zval_ptr_dtor(zptr);
- } else {
- zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
- OBJ_RELEASE(Z_OBJ(obj));
+ zend_assign_op_overloaded_property(object, property, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), value, binary_op, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -16427,7 +16852,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -16497,7 +16921,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_V
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -16741,7 +17164,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_CONST_H
#endif
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CONST(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op1;
@@ -16763,7 +17186,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -16784,51 +17206,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- SEPARATE_ZVAL_NOREF(zptr);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
+ }
+ } else {
+ ZVAL_DEREF(zptr);
+ SEPARATE_ZVAL_NOREF(zptr);
- incdec_op(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
+ }
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval rv;
-
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- incdec_op(z);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(z);
- } else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
+ zend_pre_incdec_overloaded_property(object, property, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -16839,15 +17237,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_VAR_CONST(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_VAR_CONST(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_VAR_CONST(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_VAR_CONST(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CONST(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op1;
@@ -16869,7 +17267,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -16888,44 +17285,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
- zval_opt_copy_ctor(zptr);
- incdec_op(zptr);
- } else {
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval rv, obj;
- zval *z;
- zval z_copy;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
}
- ZVAL_DUP(EX_VAR(opline->result.var), z);
- ZVAL_DUP(&z_copy, z);
- incdec_op(&z_copy);
- if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
- Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(&z_copy);
- zval_ptr_dtor(z);
} else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- ZVAL_NULL(EX_VAR(opline->result.var));
+ ZVAL_DEREF(zptr);
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ zval_opt_copy_ctor(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
}
+ } else {
+ zend_post_incdec_overloaded_property(object, property, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, EX_VAR(opline->result.var));
}
} while (0);
@@ -16936,12 +17314,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_VAR_CONST(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_VAR_CONST(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_VAR_CONST(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_VAR_CONST(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -16955,7 +17333,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CONST_HAN
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
@@ -16979,7 +17356,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CONST_HA
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
@@ -17011,7 +17387,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CO
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
@@ -17048,7 +17423,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CONST
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
@@ -17080,7 +17454,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CONST_HAN
offset = EX_CONSTANT(opline->op2);
- if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_VAR == IS_CONST ||
+ (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -17152,7 +17527,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CONST_HAN
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -17185,7 +17559,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CONST_HA
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
@@ -17226,7 +17599,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CO
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -17262,7 +17634,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CONST
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
@@ -17296,7 +17667,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CONST_HAND
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
@@ -17325,11 +17695,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CONST_HAND
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
-try_assign_dim:
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
try_assign_dim_array:
if (IS_CONST == IS_UNUSED) {
@@ -17357,53 +17725,58 @@ try_assign_dim_array:
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
}
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
+ } else {
+ if (EXPECTED(Z_ISREF_P(object_ptr))) {
+ object_ptr = Z_REFVAL_P(object_ptr);
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
+ goto try_assign_dim_array;
+ }
+ }
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
- zval *property_name = EX_CONSTANT(opline->op2);
+ zval *property_name = EX_CONSTANT(opline->op2);
- zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
+ zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
- if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
- if (IS_CONST == IS_UNUSED) {
- zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
- FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
- HANDLE_EXCEPTION();
- } else {
- zend_long offset;
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
+ if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+ if (IS_CONST == IS_UNUSED) {
+ zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
+ if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
+ HANDLE_EXCEPTION();
+ } else {
+ zend_long offset;
- dim = EX_CONSTANT(opline->op2);
- offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
+ dim = EX_CONSTANT(opline->op2);
+ offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
- value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
- FREE_OP(free_op_data1);
+ value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
+ FREE_OP(free_op_data1);
+ }
+ } else {
+ zval_ptr_dtor_nogc(object_ptr);
+assign_dim_convert_to_array:
+ ZVAL_NEW_ARR(object_ptr);
+ zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
+ goto try_assign_dim_array;
}
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) {
+ goto assign_dim_clean;
+ }
+ goto assign_dim_convert_to_array;
} else {
- zval_ptr_dtor_nogc(object_ptr);
-assign_dim_convert_to_array:
- ZVAL_NEW_ARR(object_ptr);
- zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
- goto try_assign_dim_array;
- }
- } else if (EXPECTED(Z_ISREF_P(object_ptr))) {
- object_ptr = Z_REFVAL_P(object_ptr);
- goto try_assign_dim;
- } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
- if (UNEXPECTED(object_ptr == &EG(error_zval))) {
- goto assign_dim_clean;
- }
- goto assign_dim_convert_to_array;
- } else {
- zend_error(E_WARNING, "Cannot use a scalar value as an array");
+ zend_error(E_WARNING, "Cannot use a scalar value as an array");
assign_dim_clean:
- dim = EX_CONSTANT(opline->op2);
+ dim = EX_CONSTANT(opline->op2);
- value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- FREE_OP(free_op_data1);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
+ value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ FREE_OP(free_op_data1);
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
}
}
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
@@ -17486,6 +17859,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
function_name = EX_CONSTANT(opline->op2);
if (IS_CONST != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -17579,7 +17955,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_
SAVE_OPLINE();
if (IS_VAR == IS_UNUSED) {
zend_constant *c;
- zval *retval;
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
@@ -17605,67 +17980,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_VAR_CONST_
} else {
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
}
- retval = EX_VAR(opline->result.var);
- ZVAL_COPY_VALUE(retval, &c->value);
- if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval)) {
- zval_copy_ctor_func(retval);
- } else {
- Z_ADDREF_P(retval);
- }
+#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;
- if (IS_VAR == IS_CONST) {
- if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- ZVAL_DEREF(value);
- ZVAL_DUP(EX_VAR(opline->result.var), value);
- goto constant_fetch_end;
- } else if (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(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if (IS_VAR == IS_CONST) {
+ if (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)));
+#endif
+ break;
+ } else if (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(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ if (UNEXPECTED(ce == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
+ HANDLE_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
- if (UNEXPECTED(ce == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
- 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;
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
- } 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);
- ZVAL_DUP(EX_VAR(opline->result.var), value);
- goto constant_fetch_end;
- }
- }
- 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 (IS_VAR == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
+ 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 {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ }
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ HANDLE_EXCEPTION();
}
+ } while (0);
+#ifdef ZTS
+ if (ce->type == ZEND_INTERNAL_CLASS) {
ZVAL_DUP(EX_VAR(opline->result.var), value);
} else {
- zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
}
+#else
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+#endif
}
-constant_fetch_end:
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -17677,11 +18065,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON
SAVE_OPLINE();
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -17691,11 +18078,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON
} else {
expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
if (IS_VAR == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_VAR == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_VAR == IS_CV) {
@@ -17726,43 +18113,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CON
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_CONST != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CONST != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -17810,6 +18195,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDL
zval *container;
zval *offset;
zend_ulong hval;
+ zend_string *key;
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -17821,72 +18207,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CONST_HANDL
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
offset = EX_CONSTANT(opline->op2);
-unset_dim_again:
- if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht;
+ do {
+ if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ HashTable *ht;
+unset_dim_array:
+ SEPARATE_ARRAY(container);
+ ht = Z_ARRVAL_P(container);
offset_again:
- SEPARATE_ARRAY(container);
- ht = Z_ARRVAL_P(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- zend_hash_index_del(ht, hval);
- break;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index_dim:
- zend_hash_index_del(ht, hval);
- break;
- case IS_STRING:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ key = Z_STR_P(offset);
if (IS_CONST != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
+ if (ZEND_HANDLE_NUMERIC(key, hval)) {
goto num_index_dim;
}
}
+str_index_dim:
if (ht == &EG(symbol_table)) {
- zend_delete_global_variable(Z_STR_P(offset));
+ zend_delete_global_variable(key);
} else {
- zend_hash_del(ht, Z_STR_P(offset));
+ zend_hash_del(ht, key);
}
- break;
- case IS_NULL:
- zend_hash_del(ht, STR_EMPTY_ALLOC());
- break;
- case IS_FALSE:
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_dim:
+ zend_hash_index_del(ht, hval);
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto offset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
hval = 0;
goto num_index_dim;
- case IS_TRUE:
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
hval = 1;
goto num_index_dim;
- case IS_RESOURCE:
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
hval = Z_RES_HANDLE_P(offset);
goto num_index_dim;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto offset_again;
- break;
- default:
+ } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else {
zend_error(E_WARNING, "Illegal offset type in unset");
- break;
+ }
+ break;
+ } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto unset_dim_array;
+ }
}
- } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
- } else {
- Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
}
- } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto unset_dim_again;
- } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- }
+ if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
+ } else {
+ Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ }
+ } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
+ }
+ } while (0);
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
CHECK_EXCEPTION();
@@ -17910,7 +18304,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CONST_HANDL
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
offset = EX_CONSTANT(opline->op2);
@@ -17945,7 +18338,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -17962,7 +18355,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z
if (IS_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -17972,11 +18365,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_VAR != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_VAR != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -17984,7 +18376,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
- zval_ptr_dtor_nogc(free_op1);
HANDLE_EXCEPTION();
}
@@ -18007,11 +18398,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_VAR == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
zval_ptr_dtor_nogc(free_op1);
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -18032,11 +18426,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CONST_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_CONST == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -18085,12 +18482,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_TMP_HAND
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_VAR|IS_TMP_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -18105,12 +18503,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_TMP_
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_VAR|IS_TMP_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -18157,7 +18556,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -18174,7 +18573,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN
if (IS_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -18184,11 +18583,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_VAR != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_VAR != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -18196,7 +18594,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- zval_ptr_dtor_nogc(free_op1);
HANDLE_EXCEPTION();
}
@@ -18219,11 +18616,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN
/* Consts, temporary variables and references need copying */
if (IS_VAR == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
zval_ptr_dtor_nogc(free_op1);
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -18244,11 +18644,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_TMP_HANDLER(ZEN
/* Consts, temporary variables and references need copying */
if (IS_TMP_VAR == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_TMP_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -18292,12 +18695,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_VAR_HAND
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -18312,12 +18716,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_VAR_
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -18369,7 +18774,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
- if (free_op2) {zval_ptr_dtor_nogc(free_op2);};
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
HANDLE_EXCEPTION();
}
@@ -18392,7 +18796,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_VAR_HANDLE
if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
if (free_op2) {zval_ptr_dtor_nogc(free_op2);};
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
if (IS_VAR == IS_VAR &&
@@ -18428,7 +18831,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -18445,7 +18848,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN
if (IS_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -18455,11 +18858,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_VAR != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_VAR != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -18467,7 +18869,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- zval_ptr_dtor_nogc(free_op1);
HANDLE_EXCEPTION();
}
@@ -18490,11 +18891,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN
/* Consts, temporary variables and references need copying */
if (IS_VAR == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
zval_ptr_dtor_nogc(free_op1);
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -18515,11 +18919,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_VAR_HANDLER(ZEN
/* Consts, temporary variables and references need copying */
if (IS_VAR == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
zval_ptr_dtor_nogc(free_op2);
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -18578,7 +18985,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -18865,7 +19271,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_UNUSED_HA
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
@@ -18889,7 +19294,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_UNUSED_H
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
@@ -18921,7 +19325,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_UN
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
@@ -18963,11 +19366,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_UNUSED_HAN
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
-try_assign_dim:
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
try_assign_dim_array:
if (IS_UNUSED == IS_UNUSED) {
@@ -18995,53 +19396,58 @@ try_assign_dim_array:
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
}
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
+ } else {
+ if (EXPECTED(Z_ISREF_P(object_ptr))) {
+ object_ptr = Z_REFVAL_P(object_ptr);
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
+ goto try_assign_dim_array;
+ }
+ }
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
- zval *property_name = NULL;
+ zval *property_name = NULL;
- zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
+ zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
- if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
- if (IS_UNUSED == IS_UNUSED) {
- zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
- FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
- HANDLE_EXCEPTION();
- } else {
- zend_long offset;
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
+ if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+ if (IS_UNUSED == IS_UNUSED) {
+ zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
+ if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
+ HANDLE_EXCEPTION();
+ } else {
+ zend_long offset;
- dim = NULL;
- offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
+ dim = NULL;
+ offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
- value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
- FREE_OP(free_op_data1);
+ value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
+ FREE_OP(free_op_data1);
+ }
+ } else {
+ zval_ptr_dtor_nogc(object_ptr);
+assign_dim_convert_to_array:
+ ZVAL_NEW_ARR(object_ptr);
+ zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
+ goto try_assign_dim_array;
+ }
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) {
+ goto assign_dim_clean;
}
+ goto assign_dim_convert_to_array;
} else {
- zval_ptr_dtor_nogc(object_ptr);
-assign_dim_convert_to_array:
- ZVAL_NEW_ARR(object_ptr);
- zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
- goto try_assign_dim_array;
- }
- } else if (EXPECTED(Z_ISREF_P(object_ptr))) {
- object_ptr = Z_REFVAL_P(object_ptr);
- goto try_assign_dim;
- } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
- if (UNEXPECTED(object_ptr == &EG(error_zval))) {
- goto assign_dim_clean;
- }
- goto assign_dim_convert_to_array;
- } else {
- zend_error(E_WARNING, "Cannot use a scalar value as an array");
+ zend_error(E_WARNING, "Cannot use a scalar value as an array");
assign_dim_clean:
- dim = NULL;
+ dim = NULL;
- value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- FREE_OP(free_op_data1);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
+ value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ FREE_OP(free_op_data1);
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
}
}
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
@@ -19095,6 +19501,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
function_name = NULL;
if (IS_UNUSED != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
+ if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -19224,6 +19633,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_VAR_UN
}
}
zend_verify_return_type(EX(func), retval_ptr);
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ zval_ptr_dtor_nogc(free_op1);
+ }
#endif
}
CHECK_EXCEPTION();
@@ -19238,11 +19651,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU
SAVE_OPLINE();
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -19252,11 +19664,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU
} else {
expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
if (IS_VAR == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_VAR == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_VAR == IS_CV) {
@@ -19287,43 +19699,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_UNU
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_UNUSED != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_UNUSED != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -19388,7 +19798,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -19405,7 +19815,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(
if (IS_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -19415,11 +19825,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_VAR != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_VAR != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -19427,7 +19836,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
- zval_ptr_dtor_nogc(free_op1);
HANDLE_EXCEPTION();
}
@@ -19450,11 +19858,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(
/* Consts, temporary variables and references need copying */
if (IS_VAR == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
zval_ptr_dtor_nogc(free_op1);
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -19475,11 +19886,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_UNUSED_HANDLER(
/* Consts, temporary variables and references need copying */
if (IS_UNUSED == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_UNUSED == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -19523,12 +19937,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_VAR_CV_HANDL
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
ZEND_VM_SMART_BRANCH(result, (IS_VAR|IS_CV) & (IS_VAR|IS_TMP_VAR));
@@ -19543,12 +19958,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_VAR_CV_H
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_var_deref(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op1);
ZEND_VM_SMART_BRANCH(result, (IS_VAR|IS_CV) & (IS_VAR|IS_TMP_VAR));
@@ -19584,7 +20000,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -19614,42 +20029,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval *z;
- zval rv, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- if (Z_OBJ_HT(obj)->read_property &&
- (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- zptr = z;
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- binary_op(z, z, value);
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- zval_ptr_dtor(zptr);
- } else {
- zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
- OBJ_RELEASE(Z_OBJ(obj));
+ zend_assign_op_overloaded_property(object, property, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), value, binary_op, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -19681,7 +20061,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -19751,7 +20130,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_V
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -19995,7 +20373,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_CV_HAND
#endif
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_CV(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op1;
@@ -20017,7 +20395,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -20038,51 +20415,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- SEPARATE_ZVAL_NOREF(zptr);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
+ }
+ } else {
+ ZVAL_DEREF(zptr);
+ SEPARATE_ZVAL_NOREF(zptr);
- incdec_op(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
+ }
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval rv;
-
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- incdec_op(z);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(z);
- } else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
+ zend_pre_incdec_overloaded_property(object, property, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -20093,15 +20446,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_VAR_CV(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_VAR_CV(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_VAR_CV(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_VAR_CV(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_CV(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op1;
@@ -20123,7 +20476,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -20142,44 +20494,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
- zval_opt_copy_ctor(zptr);
- incdec_op(zptr);
- } else {
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval rv, obj;
- zval *z;
- zval z_copy;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
}
- ZVAL_DUP(EX_VAR(opline->result.var), z);
- ZVAL_DUP(&z_copy, z);
- incdec_op(&z_copy);
- if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
- Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(&z_copy);
- zval_ptr_dtor(z);
} else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- ZVAL_NULL(EX_VAR(opline->result.var));
+ ZVAL_DEREF(zptr);
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ zval_opt_copy_ctor(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
}
+ } else {
+ zend_post_incdec_overloaded_property(object, property, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, EX_VAR(opline->result.var));
}
} while (0);
@@ -20190,12 +20523,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_VAR_CV(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_VAR_CV(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_VAR_CV(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_VAR_CV(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -20209,7 +20542,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_CV_HANDLE
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
@@ -20233,7 +20565,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_CV_HANDL
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
@@ -20265,7 +20596,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_CV
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
@@ -20302,7 +20632,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_CV_HA
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
@@ -20334,7 +20663,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_CV_HANDLE
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_VAR == IS_CONST ||
+ (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -20406,7 +20736,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_CV_HANDLE
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -20439,7 +20768,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_CV_HANDL
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
@@ -20480,7 +20808,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_CV
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -20516,7 +20843,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_CV_HA
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
@@ -20550,7 +20876,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_CV_HANDLER
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
@@ -20579,11 +20904,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_CV_HANDLER
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
-try_assign_dim:
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
try_assign_dim_array:
if (IS_CV == IS_UNUSED) {
@@ -20611,53 +20934,58 @@ try_assign_dim_array:
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
}
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
+ } else {
+ if (EXPECTED(Z_ISREF_P(object_ptr))) {
+ object_ptr = Z_REFVAL_P(object_ptr);
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
+ goto try_assign_dim_array;
+ }
+ }
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
- zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
+ zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
- if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
- if (IS_CV == IS_UNUSED) {
- zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
- FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
- HANDLE_EXCEPTION();
- } else {
- zend_long offset;
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
+ if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+ if (IS_CV == IS_UNUSED) {
+ zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
+ if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
+ HANDLE_EXCEPTION();
+ } else {
+ zend_long offset;
- dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
+ dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
- value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
- FREE_OP(free_op_data1);
+ value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
+ FREE_OP(free_op_data1);
+ }
+ } else {
+ zval_ptr_dtor_nogc(object_ptr);
+assign_dim_convert_to_array:
+ ZVAL_NEW_ARR(object_ptr);
+ zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
+ goto try_assign_dim_array;
+ }
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) {
+ goto assign_dim_clean;
}
+ goto assign_dim_convert_to_array;
} else {
- zval_ptr_dtor_nogc(object_ptr);
-assign_dim_convert_to_array:
- ZVAL_NEW_ARR(object_ptr);
- zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
- goto try_assign_dim_array;
- }
- } else if (EXPECTED(Z_ISREF_P(object_ptr))) {
- object_ptr = Z_REFVAL_P(object_ptr);
- goto try_assign_dim;
- } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
- if (UNEXPECTED(object_ptr == &EG(error_zval))) {
- goto assign_dim_clean;
- }
- goto assign_dim_convert_to_array;
- } else {
- zend_error(E_WARNING, "Cannot use a scalar value as an array");
+ zend_error(E_WARNING, "Cannot use a scalar value as an array");
assign_dim_clean:
- dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- FREE_OP(free_op_data1);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
+ value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ FREE_OP(free_op_data1);
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
}
}
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
@@ -20708,7 +21036,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
-
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
HANDLE_EXCEPTION();
}
@@ -20731,7 +21058,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_VAR_CV_HANDLER
if (IS_VAR == IS_VAR && UNEXPECTED(variable_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
if (IS_VAR == IS_VAR &&
@@ -20800,9 +21126,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
} else if (IS_CV != IS_UNUSED) {
- function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ 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();
}
@@ -20897,11 +21226,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_
SAVE_OPLINE();
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -20911,11 +21239,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_
} else {
expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
if (IS_VAR == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_VAR == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_VAR == IS_CV) {
@@ -20941,48 +21269,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_CV_
if (IS_CV != IS_UNUSED) {
- zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ zval *offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
zend_string *str;
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_CV != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CV != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -21030,6 +21356,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(
zval *container;
zval *offset;
zend_ulong hval;
+ zend_string *key;
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -21041,72 +21368,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_CV_HANDLER(
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
- offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
-unset_dim_again:
- if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht;
+ do {
+ if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ HashTable *ht;
+unset_dim_array:
+ SEPARATE_ARRAY(container);
+ ht = Z_ARRVAL_P(container);
offset_again:
- SEPARATE_ARRAY(container);
- ht = Z_ARRVAL_P(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- zend_hash_index_del(ht, hval);
- break;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index_dim:
- zend_hash_index_del(ht, hval);
- break;
- case IS_STRING:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ key = Z_STR_P(offset);
if (IS_CV != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
+ if (ZEND_HANDLE_NUMERIC(key, hval)) {
goto num_index_dim;
}
}
+str_index_dim:
if (ht == &EG(symbol_table)) {
- zend_delete_global_variable(Z_STR_P(offset));
+ zend_delete_global_variable(key);
} else {
- zend_hash_del(ht, Z_STR_P(offset));
+ zend_hash_del(ht, key);
}
- break;
- case IS_NULL:
- zend_hash_del(ht, STR_EMPTY_ALLOC());
- break;
- case IS_FALSE:
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_dim:
+ zend_hash_index_del(ht, hval);
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto offset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
hval = 0;
goto num_index_dim;
- case IS_TRUE:
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
hval = 1;
goto num_index_dim;
- case IS_RESOURCE:
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
hval = Z_RES_HANDLE_P(offset);
goto num_index_dim;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto offset_again;
- break;
- default:
+ } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else {
zend_error(E_WARNING, "Illegal offset type in unset");
- break;
+ }
+ break;
+ } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto unset_dim_array;
+ }
}
- } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
- } else {
- Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
}
- } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto unset_dim_again;
- } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- }
+ if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
+ } else {
+ Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ }
+ } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
+ }
+ } while (0);
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
CHECK_EXCEPTION();
@@ -21130,7 +21465,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_CV_HANDLER(
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
@@ -21165,7 +21499,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op1.var));
@@ -21182,7 +21516,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND
if (IS_VAR != IS_UNUSED) {
zend_free_op free_op1;
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_VAR == IS_CONST || IS_VAR == IS_TMP_VAR) {
@@ -21192,11 +21526,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND
value = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_VAR != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_VAR != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -21204,7 +21537,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
- zval_ptr_dtor_nogc(free_op1);
HANDLE_EXCEPTION();
}
@@ -21227,11 +21559,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND
/* Consts, temporary variables and references need copying */
if (IS_VAR == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_VAR == IS_CV || IS_VAR == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
zval_ptr_dtor_nogc(free_op1);
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -21252,11 +21587,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_VAR_CV_HANDLER(ZEND
/* Consts, temporary variables and references need copying */
if (IS_CV == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -21326,7 +21664,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
zval_ptr_dtor_nogc(free_op2);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -21356,42 +21693,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval *z;
- zval rv, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- if (Z_OBJ_HT(obj)->read_property &&
- (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- zptr = z;
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- binary_op(z, z, value);
- Z_OBJ_HT(obj)->write_property(&obj, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- zval_ptr_dtor(zptr);
- } else {
- zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
- OBJ_RELEASE(Z_OBJ(obj));
+ zend_assign_op_overloaded_property(object, property, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), value, binary_op, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -21423,7 +21725,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -21494,7 +21795,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_V
if (IS_VAR == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
zval_ptr_dtor_nogc(free_op2);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -21739,7 +22039,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_VAR_TMPVAR_
#endif
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -21761,7 +22061,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
zval_ptr_dtor_nogc(free_op2);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -21782,51 +22081,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- SEPARATE_ZVAL_NOREF(zptr);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
+ }
+ } else {
+ ZVAL_DEREF(zptr);
+ SEPARATE_ZVAL_NOREF(zptr);
- incdec_op(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
+ }
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval rv;
-
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- incdec_op(z);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- Z_OBJ_HT(obj)->write_property(&obj, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(z);
- } else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
+ zend_pre_incdec_overloaded_property(object, property, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -21838,15 +22113,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_VAR_TMPVAR(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op1, free_op2;
@@ -21868,7 +22143,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
zval_ptr_dtor_nogc(free_op2);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -21887,44 +22161,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
- zval_opt_copy_ctor(zptr);
- incdec_op(zptr);
- } else {
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval rv, obj;
- zval *z;
- zval z_copy;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
}
- ZVAL_DUP(EX_VAR(opline->result.var), z);
- ZVAL_DUP(&z_copy, z);
- incdec_op(&z_copy);
- if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
- Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(&z_copy);
- zval_ptr_dtor(z);
} else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- ZVAL_NULL(EX_VAR(opline->result.var));
+ ZVAL_DEREF(zptr);
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ zval_opt_copy_ctor(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
}
+ } else {
+ zend_post_incdec_overloaded_property(object, property, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, EX_VAR(opline->result.var));
}
} while (0);
@@ -21936,12 +22191,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_VAR_TMPVAR(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -21955,7 +22210,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_VAR_TMPVAR_HA
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
@@ -21979,7 +22233,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_VAR_TMPVAR_H
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
@@ -22011,7 +22264,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_VAR_TM
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
@@ -22048,7 +22300,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_VAR_TMPVA
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
@@ -22080,7 +22331,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_VAR_TMPVAR_HA
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_VAR == IS_CONST ||
+ (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -22153,7 +22405,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_VAR_TMPVAR_HA
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
@@ -22186,7 +22437,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_VAR_TMPVAR_H
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
@@ -22227,7 +22477,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_VAR_TM
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -22263,7 +22512,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_VAR_TMPVA
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_VAR, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
@@ -22297,7 +22545,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_VAR_TMPVAR_HAN
if (IS_VAR == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
zval_ptr_dtor_nogc(free_op2);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_VAR, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
@@ -22326,11 +22573,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_VAR_TMPVAR_HAN
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
-try_assign_dim:
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
try_assign_dim_array:
if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
@@ -22358,53 +22603,58 @@ try_assign_dim_array:
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
}
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
- zend_free_op free_op2;
- zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ } else {
+ if (EXPECTED(Z_ISREF_P(object_ptr))) {
+ object_ptr = Z_REFVAL_P(object_ptr);
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
+ goto try_assign_dim_array;
+ }
+ }
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
+ zend_free_op free_op2;
+ zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
- zval_ptr_dtor_nogc(free_op2);
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
- if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
- if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
- zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
- FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
- HANDLE_EXCEPTION();
- } else {
- zend_long offset;
+ zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
+ zval_ptr_dtor_nogc(free_op2);
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
+ if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
+ zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
+ if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
+ HANDLE_EXCEPTION();
+ } else {
+ zend_long offset;
- dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
- zval_ptr_dtor_nogc(free_op2);
- value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
- FREE_OP(free_op_data1);
+ dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
+ zval_ptr_dtor_nogc(free_op2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
+ FREE_OP(free_op_data1);
+ }
+ } else {
+ zval_ptr_dtor_nogc(object_ptr);
+assign_dim_convert_to_array:
+ ZVAL_NEW_ARR(object_ptr);
+ zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
+ goto try_assign_dim_array;
}
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
+ if (IS_VAR == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) {
+ goto assign_dim_clean;
+ }
+ goto assign_dim_convert_to_array;
} else {
- zval_ptr_dtor_nogc(object_ptr);
-assign_dim_convert_to_array:
- ZVAL_NEW_ARR(object_ptr);
- zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
- goto try_assign_dim_array;
- }
- } else if (EXPECTED(Z_ISREF_P(object_ptr))) {
- object_ptr = Z_REFVAL_P(object_ptr);
- goto try_assign_dim;
- } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
- if (UNEXPECTED(object_ptr == &EG(error_zval))) {
- goto assign_dim_clean;
- }
- goto assign_dim_convert_to_array;
- } else {
- zend_error(E_WARNING, "Cannot use a scalar value as an array");
+ zend_error(E_WARNING, "Cannot use a scalar value as an array");
assign_dim_clean:
- dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- zval_ptr_dtor_nogc(free_op2);
- value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- FREE_OP(free_op_data1);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
+ dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ zval_ptr_dtor_nogc(free_op2);
+ value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ FREE_OP(free_op_data1);
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
}
}
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
@@ -22458,6 +22708,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -22552,11 +22805,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP
SAVE_OPLINE();
if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
if (IS_VAR == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -22566,11 +22818,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP
} else {
expr_ptr = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
if (IS_VAR == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_VAR == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_VAR == IS_CV) {
@@ -22601,43 +22853,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_VAR_TMP
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
zval_ptr_dtor_nogc(free_op2);
} else {
@@ -22685,6 +22935,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HAND
zval *container;
zval *offset;
zend_ulong hval;
+ zend_string *key;
SAVE_OPLINE();
container = _get_zval_ptr_ptr_var(opline->op1.var, execute_data, &free_op1);
@@ -22696,72 +22947,81 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_VAR_TMPVAR_HAND
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
-unset_dim_again:
- if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht;
+ do {
+ if (IS_VAR != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ HashTable *ht;
+unset_dim_array:
+ SEPARATE_ARRAY(container);
+ ht = Z_ARRVAL_P(container);
offset_again:
- SEPARATE_ARRAY(container);
- ht = Z_ARRVAL_P(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- zend_hash_index_del(ht, hval);
- break;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index_dim:
- zend_hash_index_del(ht, hval);
- break;
- case IS_STRING:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ key = Z_STR_P(offset);
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
+ if (ZEND_HANDLE_NUMERIC(key, hval)) {
goto num_index_dim;
}
}
+str_index_dim:
if (ht == &EG(symbol_table)) {
- zend_delete_global_variable(Z_STR_P(offset));
+ zend_delete_global_variable(key);
} else {
- zend_hash_del(ht, Z_STR_P(offset));
+ zend_hash_del(ht, key);
}
- break;
- case IS_NULL:
- zend_hash_del(ht, STR_EMPTY_ALLOC());
- break;
- case IS_FALSE:
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_dim:
+ zend_hash_index_del(ht, hval);
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto offset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
hval = 0;
goto num_index_dim;
- case IS_TRUE:
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
hval = 1;
goto num_index_dim;
- case IS_RESOURCE:
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
hval = Z_RES_HANDLE_P(offset);
goto num_index_dim;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto offset_again;
- break;
- default:
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else {
zend_error(E_WARNING, "Illegal offset type in unset");
- break;
+ }
+ break;
+ } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto unset_dim_array;
+ }
}
- } else if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
- } else {
- Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
}
- } else if (IS_VAR != IS_UNUSED && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto unset_dim_again;
- } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- }
+ if (IS_VAR == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
+ } else {
+ Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ }
+ } else if (IS_VAR != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
+ }
+ } while (0);
+
zval_ptr_dtor_nogc(free_op2);
if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
CHECK_EXCEPTION();
@@ -22785,7 +23045,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_VAR_TMPVAR_HAND
if (IS_VAR == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
- if (free_op1) {zval_ptr_dtor_nogc(free_op1);};
HANDLE_EXCEPTION();
}
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
@@ -22844,7 +23103,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_UNUSED_HANDLER(ZEND
if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
break;
}
- }
+ }
+ if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(obj, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -22954,7 +23216,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
@@ -22984,42 +23245,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval *z;
- zval rv, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- if (Z_OBJ_HT(obj)->read_property &&
- (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- zptr = z;
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- binary_op(z, z, value);
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- zval_ptr_dtor(zptr);
- } else {
- zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
- OBJ_RELEASE(Z_OBJ(obj));
+ zend_assign_op_overloaded_property(object, property, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), value, binary_op, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -23051,7 +23277,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
@@ -23327,7 +23552,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CONS
#endif
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
@@ -23349,7 +23574,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -23370,51 +23594,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- SEPARATE_ZVAL_NOREF(zptr);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
+ }
+ } else {
+ ZVAL_DEREF(zptr);
+ SEPARATE_ZVAL_NOREF(zptr);
- incdec_op(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
+ }
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval rv;
-
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- incdec_op(z);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(z);
- } else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
+ zend_pre_incdec_overloaded_property(object, property, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -23425,15 +23625,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_UNUSED_CONST(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CONST(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
@@ -23455,7 +23655,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -23474,44 +23673,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
- zval_opt_copy_ctor(zptr);
- incdec_op(zptr);
- } else {
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval rv, obj;
- zval *z;
- zval z_copy;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
}
- ZVAL_DUP(EX_VAR(opline->result.var), z);
- ZVAL_DUP(&z_copy, z);
- incdec_op(&z_copy);
- if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
- Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(&z_copy);
- zval_ptr_dtor(z);
} else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- ZVAL_NULL(EX_VAR(opline->result.var));
+ ZVAL_DEREF(zptr);
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ zval_opt_copy_ctor(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
}
+ } else {
+ zend_post_incdec_overloaded_property(object, property, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, EX_VAR(opline->result.var));
}
} while (0);
@@ -23522,12 +23702,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_UNUSED_CONST(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -23549,7 +23729,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CONST_
offset = EX_CONSTANT(opline->op2);
- if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST ||
+ (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -23621,7 +23802,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CONST_
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
@@ -23654,7 +23834,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CONST
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
@@ -23686,7 +23865,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CONST
offset = EX_CONSTANT(opline->op2);
- if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST ||
+ (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -23767,7 +23947,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -23803,7 +23982,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CO
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
@@ -23837,7 +24015,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CONST_H
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
@@ -23862,11 +24039,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CONST_HA
var = EX_CONSTANT(opline->op2);
rope[0] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
var = EX_CONSTANT(opline->op2);
- rope[0] = zval_get_string(var);
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if (IS_CONST == IS_CV) {
+ rope[0] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[0] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[0] = _zval_get_string_func(var);
- CHECK_EXCEPTION();
+ CHECK_EXCEPTION();
+ }
}
ZEND_VM_NEXT_OPCODE();
}
@@ -23896,6 +24084,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
break;
}
}
+ 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();
}
@@ -23916,13 +24107,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
if (IS_UNUSED != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -23969,7 +24163,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) {
+ } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -23991,7 +24186,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON
SAVE_OPLINE();
if (IS_UNUSED == IS_UNUSED) {
zend_constant *c;
- zval *retval;
if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
c = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
@@ -24017,67 +24211,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_CONSTANT_SPEC_UNUSED_CON
} else {
CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), c);
}
- retval = EX_VAR(opline->result.var);
- ZVAL_COPY_VALUE(retval, &c->value);
- if (Z_OPT_COPYABLE_P(retval) || Z_OPT_REFCOUNTED_P(retval)) {
- if (Z_OPT_COPYABLE_P(retval)) {
- zval_copy_ctor_func(retval);
- } else {
- Z_ADDREF_P(retval);
- }
+#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;
- if (IS_UNUSED == IS_CONST) {
- if (CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)))) {
- value = CACHED_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)));
- ZVAL_DEREF(value);
- ZVAL_DUP(EX_VAR(opline->result.var), value);
- goto constant_fetch_end;
- } else if (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(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if (IS_UNUSED == IS_CONST) {
+ if (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)));
+#endif
+ break;
+ } else if (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(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
+ if (UNEXPECTED(ce == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
+ HANDLE_EXCEPTION();
+ }
+ CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
- if (UNEXPECTED(ce == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Class '%s' not found", Z_STRVAL_P(EX_CONSTANT(opline->op1)));
- 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;
}
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op1)), ce);
}
- } 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);
- ZVAL_DUP(EX_VAR(opline->result.var), value);
- goto constant_fetch_end;
- }
- }
- 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 (IS_UNUSED == IS_CONST) {
- CACHE_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), value);
+ 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 {
+ CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ }
} else {
- CACHE_POLYMORPHIC_PTR(Z_CACHE_SLOT_P(EX_CONSTANT(opline->op2)), ce, value);
+ zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ HANDLE_EXCEPTION();
}
+ } while (0);
+#ifdef ZTS
+ if (ce->type == ZEND_INTERNAL_CLASS) {
ZVAL_DUP(EX_VAR(opline->result.var), value);
} else {
- zend_error(E_EXCEPTION | E_ERROR, "Undefined class constant '%s'", Z_STRVAL_P(EX_CONSTANT(opline->op2)));
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
}
+#else
+ ZVAL_COPY(EX_VAR(opline->result.var), value);
+#endif
}
-constant_fetch_end:
- CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
}
@@ -24119,6 +24326,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HA
zval *container;
zval *offset;
zend_ulong hval;
+ zend_string *key;
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(execute_data);
@@ -24130,72 +24338,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CONST_HA
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
-
HANDLE_EXCEPTION();
}
offset = EX_CONSTANT(opline->op2);
-unset_dim_again:
- if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht;
+ do {
+ if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ HashTable *ht;
+unset_dim_array:
+ SEPARATE_ARRAY(container);
+ ht = Z_ARRVAL_P(container);
offset_again:
- SEPARATE_ARRAY(container);
- ht = Z_ARRVAL_P(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- zend_hash_index_del(ht, hval);
- break;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index_dim:
- zend_hash_index_del(ht, hval);
- break;
- case IS_STRING:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ key = Z_STR_P(offset);
if (IS_CONST != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
+ if (ZEND_HANDLE_NUMERIC(key, hval)) {
goto num_index_dim;
}
}
+str_index_dim:
if (ht == &EG(symbol_table)) {
- zend_delete_global_variable(Z_STR_P(offset));
+ zend_delete_global_variable(key);
} else {
- zend_hash_del(ht, Z_STR_P(offset));
+ zend_hash_del(ht, key);
}
- break;
- case IS_NULL:
- zend_hash_del(ht, STR_EMPTY_ALLOC());
- break;
- case IS_FALSE:
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_dim:
+ zend_hash_index_del(ht, hval);
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto offset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
hval = 0;
goto num_index_dim;
- case IS_TRUE:
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
hval = 1;
goto num_index_dim;
- case IS_RESOURCE:
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
hval = Z_RES_HANDLE_P(offset);
goto num_index_dim;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto offset_again;
- break;
- default:
+ } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else {
zend_error(E_WARNING, "Illegal offset type in unset");
- break;
+ }
+ break;
+ } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto unset_dim_array;
+ }
}
- } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
- } else {
- Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
}
- } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto unset_dim_again;
- } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- }
+ if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
+ } else {
+ Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ }
+ } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
+ }
+ } while (0);
CHECK_EXCEPTION();
@@ -24219,7 +24435,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CONST_HA
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
-
HANDLE_EXCEPTION();
}
offset = EX_CONSTANT(opline->op2);
@@ -24267,12 +24482,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNU
offset = EX_CONSTANT(opline->op2);
-isset_dim_obj_again:
if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -24287,31 +24503,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -24321,50 +24537,62 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if (IS_UNUSED == IS_UNUSED ||
+ (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if (IS_CONST & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
- }
- }
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
+
ZEND_VM_SMART_BRANCH(result, 1);
ZVAL_BOOL(EX_VAR(opline->result.var), result);
@@ -24391,7 +24619,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN
offset = EX_CONSTANT(opline->op2);
- if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST ||
+ (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -24406,10 +24635,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
@@ -24426,7 +24654,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
@@ -24443,7 +24671,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE
if (IS_UNUSED != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -24453,11 +24681,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE
value = NULL;
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_UNUSED != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_UNUSED != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -24465,7 +24692,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE
if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -24487,11 +24713,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE
/* Consts, temporary variables and references need copying */
if (IS_UNUSED == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_UNUSED == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -24512,11 +24741,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE
/* Consts, temporary variables and references need copying */
if (IS_CONST == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -24563,7 +24795,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
@@ -24580,7 +24812,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(
if (IS_UNUSED != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -24590,11 +24822,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(
value = NULL;
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_UNUSED != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_UNUSED != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -24602,7 +24833,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(
if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
@@ -24624,11 +24854,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(
/* Consts, temporary variables and references need copying */
if (IS_UNUSED == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_UNUSED == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -24649,11 +24882,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(
/* Consts, temporary variables and references need copying */
if (IS_TMP_VAR == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_TMP_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -24700,7 +24936,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
@@ -24717,7 +24953,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(
if (IS_UNUSED != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -24727,11 +24963,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(
value = NULL;
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_UNUSED != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_UNUSED != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -24739,7 +24974,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(
if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
@@ -24761,11 +24995,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(
/* Consts, temporary variables and references need copying */
if (IS_UNUSED == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_UNUSED == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -24786,11 +25023,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(
/* Consts, temporary variables and references need copying */
if (IS_VAR == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
zval_ptr_dtor_nogc(free_op2);
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -24849,7 +25089,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
@@ -25168,6 +25407,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_UNUSED
}
}
zend_verify_return_type(EX(func), retval_ptr);
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+
+ }
#endif
}
CHECK_EXCEPTION();
@@ -25212,7 +25455,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
@@ -25229,7 +25472,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL
if (IS_UNUSED != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -25239,11 +25482,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL
value = NULL;
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_UNUSED != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_UNUSED != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -25251,7 +25493,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL
if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -25273,11 +25514,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL
/* Consts, temporary variables and references need copying */
if (IS_UNUSED == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_UNUSED == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -25298,11 +25542,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL
/* Consts, temporary variables and references need copying */
if (IS_UNUSED == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_UNUSED == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -25367,7 +25614,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
@@ -25397,42 +25643,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval *z;
- zval rv, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- if (Z_OBJ_HT(obj)->read_property &&
- (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- zptr = z;
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- binary_op(z, z, value);
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- zval_ptr_dtor(zptr);
- } else {
- zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
- OBJ_RELEASE(Z_OBJ(obj));
+ zend_assign_op_overloaded_property(object, property, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), value, binary_op, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -25464,7 +25675,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
@@ -25740,7 +25950,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_CV_H
#endif
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_CV(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
@@ -25762,7 +25972,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -25783,51 +25992,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- SEPARATE_ZVAL_NOREF(zptr);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
+ }
+ } else {
+ ZVAL_DEREF(zptr);
+ SEPARATE_ZVAL_NOREF(zptr);
- incdec_op(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
+ }
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval rv;
-
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- incdec_op(z);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(z);
- } else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
+ zend_pre_incdec_overloaded_property(object, property, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -25838,15 +26023,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_UNUSED_CV(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_UNUSED_CV(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_UNUSED_CV(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_UNUSED_CV(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_CV(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
@@ -25868,7 +26053,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -25887,44 +26071,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
- zval_opt_copy_ctor(zptr);
- incdec_op(zptr);
- } else {
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval rv, obj;
- zval *z;
- zval z_copy;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
}
- ZVAL_DUP(EX_VAR(opline->result.var), z);
- ZVAL_DUP(&z_copy, z);
- incdec_op(&z_copy);
- if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
- Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(&z_copy);
- zval_ptr_dtor(z);
} else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- ZVAL_NULL(EX_VAR(opline->result.var));
+ ZVAL_DEREF(zptr);
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ zval_opt_copy_ctor(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
}
+ } else {
+ zend_post_incdec_overloaded_property(object, property, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, EX_VAR(opline->result.var));
}
} while (0);
@@ -25935,12 +26100,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_UNUSED_CV(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_UNUSED_CV(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_UNUSED_CV(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_UNUSED_CV(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -25962,7 +26127,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_CV_HAN
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST ||
+ (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -26034,7 +26200,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_CV_HAN
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
@@ -26067,7 +26232,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_CV_HA
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
@@ -26099,7 +26263,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_CV_HA
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST ||
+ (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -26180,7 +26345,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -26216,7 +26380,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_CV
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
@@ -26250,7 +26413,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_CV_HAND
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
@@ -26275,11 +26437,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_CV_HANDL
var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
rope[0] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
- var = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- rope[0] = zval_get_string(var);
+ var = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if (IS_CV == IS_CV) {
+ rope[0] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[0] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[0] = _zval_get_string_func(var);
- CHECK_EXCEPTION();
+ CHECK_EXCEPTION();
+ }
}
ZEND_VM_NEXT_OPCODE();
}
@@ -26298,7 +26471,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
SAVE_OPLINE();
- function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
if (IS_CV != IS_CONST &&
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
@@ -26309,6 +26482,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
break;
}
}
+ 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();
}
@@ -26329,13 +26505,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
if (IS_UNUSED != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -26382,7 +26561,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) {
+ } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -26435,6 +26615,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDL
zval *container;
zval *offset;
zend_ulong hval;
+ zend_string *key;
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(execute_data);
@@ -26446,72 +26627,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_CV_HANDL
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
-
HANDLE_EXCEPTION();
}
- offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
-unset_dim_again:
- if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht;
+ do {
+ if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ HashTable *ht;
+unset_dim_array:
+ SEPARATE_ARRAY(container);
+ ht = Z_ARRVAL_P(container);
offset_again:
- SEPARATE_ARRAY(container);
- ht = Z_ARRVAL_P(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- zend_hash_index_del(ht, hval);
- break;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index_dim:
- zend_hash_index_del(ht, hval);
- break;
- case IS_STRING:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ key = Z_STR_P(offset);
if (IS_CV != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
+ if (ZEND_HANDLE_NUMERIC(key, hval)) {
goto num_index_dim;
}
}
+str_index_dim:
if (ht == &EG(symbol_table)) {
- zend_delete_global_variable(Z_STR_P(offset));
+ zend_delete_global_variable(key);
} else {
- zend_hash_del(ht, Z_STR_P(offset));
+ zend_hash_del(ht, key);
}
- break;
- case IS_NULL:
- zend_hash_del(ht, STR_EMPTY_ALLOC());
- break;
- case IS_FALSE:
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_dim:
+ zend_hash_index_del(ht, hval);
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto offset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
hval = 0;
goto num_index_dim;
- case IS_TRUE:
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
hval = 1;
goto num_index_dim;
- case IS_RESOURCE:
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
hval = Z_RES_HANDLE_P(offset);
goto num_index_dim;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto offset_again;
- break;
- default:
+ } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else {
zend_error(E_WARNING, "Illegal offset type in unset");
- break;
+ }
+ break;
+ } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto unset_dim_array;
+ }
}
- } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
- } else {
- Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
}
- } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto unset_dim_again;
- } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- }
+ if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
+ } else {
+ Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ }
+ } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
+ }
+ } while (0);
CHECK_EXCEPTION();
@@ -26535,7 +26724,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_CV_HANDL
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
-
HANDLE_EXCEPTION();
}
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
@@ -26581,14 +26769,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNU
HANDLE_EXCEPTION();
}
- offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
-isset_dim_obj_again:
if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -26603,31 +26792,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -26637,50 +26826,62 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if (IS_UNUSED == IS_UNUSED ||
+ (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if (IS_CV & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
- }
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
+
ZEND_VM_SMART_BRANCH(result, 1);
ZVAL_BOOL(EX_VAR(opline->result.var), result);
@@ -26707,7 +26908,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST ||
+ (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -26722,10 +26924,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
@@ -26742,7 +26943,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
@@ -26759,7 +26960,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z
if (IS_UNUSED != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_UNUSED == IS_CONST || IS_UNUSED == IS_TMP_VAR) {
@@ -26769,11 +26970,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z
value = NULL;
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_UNUSED != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_UNUSED != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = NULL;
@@ -26781,7 +26981,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z
if (IS_UNUSED == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -26803,11 +27002,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_UNUSED == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_UNUSED == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_UNUSED == IS_CV || IS_UNUSED == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -26828,11 +27030,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_CV == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -26897,7 +27102,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
@@ -26927,42 +27131,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval *z;
- zval rv, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- if (Z_OBJ_HT(obj)->read_property &&
- (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- zptr = z;
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- binary_op(z, z, value);
- Z_OBJ_HT(obj)->write_property(&obj, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- zval_ptr_dtor(zptr);
- } else {
- zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
- OBJ_RELEASE(Z_OBJ(obj));
+ zend_assign_op_overloaded_property(object, property, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), value, binary_op, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -26994,7 +27163,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
@@ -27271,7 +27439,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_UNUSED_TMPV
#endif
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op2;
@@ -27293,7 +27461,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
@@ -27314,51 +27481,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- SEPARATE_ZVAL_NOREF(zptr);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
+ }
+ } else {
+ ZVAL_DEREF(zptr);
+ SEPARATE_ZVAL_NOREF(zptr);
- incdec_op(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
+ }
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval rv;
-
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- incdec_op(z);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- Z_OBJ_HT(obj)->write_property(&obj, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(z);
- } else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
+ zend_pre_incdec_overloaded_property(object, property, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -27370,15 +27513,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_UNUSED_TMPVAR(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op2;
@@ -27400,7 +27543,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
@@ -27419,44 +27561,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
- zval_opt_copy_ctor(zptr);
- incdec_op(zptr);
- } else {
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval rv, obj;
- zval *z;
- zval z_copy;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
}
- ZVAL_DUP(EX_VAR(opline->result.var), z);
- ZVAL_DUP(&z_copy, z);
- incdec_op(&z_copy);
- if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
- Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(&z_copy);
- zval_ptr_dtor(z);
} else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- ZVAL_NULL(EX_VAR(opline->result.var));
+ ZVAL_DEREF(zptr);
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ zval_opt_copy_ctor(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
}
+ } else {
+ zend_post_incdec_overloaded_property(object, property, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, EX_VAR(opline->result.var));
}
} while (0);
@@ -27468,12 +27591,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_UNUSED_TMPVAR(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -27495,7 +27618,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_UNUSED_TMPVAR
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST ||
+ (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -27568,7 +27692,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_UNUSED_TMPVAR
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
@@ -27601,7 +27724,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_UNUSED_TMPVA
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
@@ -27633,7 +27755,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_UNUSED_TMPVA
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST ||
+ (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -27715,7 +27838,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_UNUSED
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -27751,7 +27873,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_UNUSED_TM
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_UNUSED, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
@@ -27785,7 +27906,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_UNUSED_TMPVAR_
if (IS_UNUSED == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_UNUSED, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
@@ -27810,11 +27930,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ROPE_INIT_SPEC_UNUSED_TMPVAR_H
var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
rope[0] = zend_string_copy(Z_STR_P(var));
} else {
- SAVE_OPLINE();
var = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- rope[0] = zval_get_string(var);
- zval_ptr_dtor_nogc(free_op2);
- CHECK_EXCEPTION();
+ if (EXPECTED(Z_TYPE_P(var) == IS_STRING)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV) {
+ rope[0] = zend_string_copy(Z_STR_P(var));
+ } else {
+ rope[0] = Z_STR_P(var);
+ }
+ } else {
+ SAVE_OPLINE();
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(var) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(var, BP_VAR_R);
+ }
+ rope[0] = _zval_get_string_func(var);
+ zval_ptr_dtor_nogc(free_op2);
+ CHECK_EXCEPTION();
+ }
}
ZEND_VM_NEXT_OPCODE();
}
@@ -27844,6 +27975,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
break;
}
}
+ 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();
}
@@ -27864,13 +27998,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
if (IS_UNUSED != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -27917,7 +28054,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR)) {
+ } else if (IS_UNUSED & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -27971,6 +28109,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_H
zval *container;
zval *offset;
zend_ulong hval;
+ zend_string *key;
SAVE_OPLINE();
container = _get_obj_zval_ptr_unused(execute_data);
@@ -27982,72 +28121,81 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_UNUSED_TMPVAR_H
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
-unset_dim_again:
- if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht;
+ do {
+ if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ HashTable *ht;
+unset_dim_array:
+ SEPARATE_ARRAY(container);
+ ht = Z_ARRVAL_P(container);
offset_again:
- SEPARATE_ARRAY(container);
- ht = Z_ARRVAL_P(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- zend_hash_index_del(ht, hval);
- break;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index_dim:
- zend_hash_index_del(ht, hval);
- break;
- case IS_STRING:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ key = Z_STR_P(offset);
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
+ if (ZEND_HANDLE_NUMERIC(key, hval)) {
goto num_index_dim;
}
}
+str_index_dim:
if (ht == &EG(symbol_table)) {
- zend_delete_global_variable(Z_STR_P(offset));
+ zend_delete_global_variable(key);
} else {
- zend_hash_del(ht, Z_STR_P(offset));
+ zend_hash_del(ht, key);
}
- break;
- case IS_NULL:
- zend_hash_del(ht, STR_EMPTY_ALLOC());
- break;
- case IS_FALSE:
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_dim:
+ zend_hash_index_del(ht, hval);
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto offset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
hval = 0;
goto num_index_dim;
- case IS_TRUE:
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
hval = 1;
goto num_index_dim;
- case IS_RESOURCE:
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
hval = Z_RES_HANDLE_P(offset);
goto num_index_dim;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto offset_again;
- break;
- default:
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else {
zend_error(E_WARNING, "Illegal offset type in unset");
- break;
+ }
+ break;
+ } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto unset_dim_array;
+ }
}
- } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
- } else {
- Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
}
- } else if (IS_UNUSED != IS_UNUSED && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto unset_dim_again;
- } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- }
+ if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
+ } else {
+ Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ }
+ } else if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
+ }
+ } while (0);
+
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -28071,7 +28219,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_UNUSED_TMPVAR_H
if (IS_UNUSED == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
@@ -28120,12 +28267,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_UNU
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
-isset_dim_obj_again:
if (IS_UNUSED != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -28140,31 +28288,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -28174,50 +28322,61 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if (IS_UNUSED == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if (IS_UNUSED == IS_UNUSED ||
+ (IS_UNUSED != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
- }
- }
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, 1);
@@ -28245,7 +28404,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_UNUSED == IS_CONST ||
+ (IS_UNUSED != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -28260,10 +28420,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_UN
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
zval_ptr_dtor_nogc(free_op2);
@@ -28323,7 +28482,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_SPEC_CV_HANDLER(ZEND_O
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -28370,7 +28528,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_SPEC_CV_HANDLER(ZEND_O
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -28417,7 +28574,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_SPEC_CV_HANDLER(ZEND_
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -28457,7 +28613,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_SPEC_CV_HANDLER(ZEND_
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
SAVE_OPLINE();
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -28493,7 +28648,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCO
zval *z;
SAVE_OPLINE();
- z = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ z = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
if (Z_TYPE_P(z) == IS_STRING) {
zend_string *str = Z_STR_P(z);
@@ -28506,6 +28661,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_CV_HANDLER(ZEND_OPCO
if (str->len != 0) {
zend_write(str->val, str->len);
+ } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(z, BP_VAR_R);
}
zend_string_release(str);
}
@@ -28723,15 +28880,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_SPEC_CV_HANDLER(ZEND_OP
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(retval_ptr) == IS_UNDEF)) {
SAVE_OPLINE();
retval_ptr = GET_OP1_UNDEF_CV(retval_ptr, BP_VAR_R);
- CHECK_EXCEPTION();
- }
-
- if (!EX(return_value)) {
+ if (EX(return_value)) {
+ ZVAL_NULL(EX(return_value));
+ }
+ } else if (!EX(return_value)) {
if (IS_CV == IS_VAR || IS_CV == IS_TMP_VAR ) {
if (Z_REFCOUNTED_P(free_op1) && !Z_DELREF_P(free_op1)) {
SAVE_OPLINE();
zval_dtor_func_for_ptr(Z_COUNTED_P(free_op1));
- CHECK_EXCEPTION();
}
}
} else {
@@ -28797,7 +28953,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_RETURN_BY_REF_SPEC_CV_HANDLER(
if (IS_CV == IS_VAR && UNEXPECTED(retval_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot return string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -28878,7 +29033,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPC
SAVE_OPLINE();
- value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ value = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
do {
if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(value) != IS_OBJECT)) {
@@ -28888,6 +29043,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_THROW_SPEC_CV_HANDLER(ZEND_OPC
break;
}
}
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -28997,7 +29155,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SEND_REF_SPEC_CV_HANDLER(ZEND_
if (IS_CV == IS_VAR && UNEXPECTED(varptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Only variables can be passed by reference");
-
HANDLE_EXCEPTION();
}
@@ -29157,7 +29314,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC
zend_object_clone_obj_t clone_call;
SAVE_OPLINE();
- obj = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ obj = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(obj) == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context");
@@ -29172,7 +29329,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_CV_HANDLER(ZEND_OPC
if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
break;
}
- }
+ }
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(obj, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -29318,8 +29478,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CAST_SPEC_CV_HANDLER(ZEND_OPCO
}
}
} else {
- ZVAL_COPY_VALUE(result, expr);
- zval_opt_copy_ctor(result);
+ ZVAL_COPY(result, expr);
convert_to_object(result);
}
}
@@ -29339,10 +29498,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_CV_HANDLE
zend_bool failure_retval=0;
SAVE_OPLINE();
- inc_filename = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ inc_filename = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
ZVAL_UNDEF(&tmp_inc_filename);
if (Z_TYPE_P(inc_filename) != IS_STRING) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(inc_filename) == IS_UNDEF)) {
+ inc_filename = GET_OP1_UNDEF_CV(inc_filename, BP_VAR_R);
+ }
ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename));
inc_filename = &tmp_inc_filename;
}
@@ -29958,13 +30120,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_STRLEN_SPEC_CV_HANDLER(ZEND_OP
SAVE_OPLINE();
- value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ value = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
try_strlen:
if (EXPECTED(Z_TYPE_P(value) == IS_STRING)) {
ZVAL_LONG(EX_VAR(opline->result.var), Z_STRLEN_P(value));
} else {
zend_bool strict;
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ value = GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ }
if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
goto try_strlen;
@@ -30002,7 +30167,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_TYPE_CHECK_SPEC_CV_HANDLER(ZEN
SAVE_OPLINE();
value = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
if (EXPECTED(Z_TYPE_P(value) == opline->extended_value)) {
- if (UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
+ if (IS_CV != IS_CONST && UNEXPECTED(Z_TYPE_P(value) == IS_OBJECT)) {
zend_class_entry *ce = Z_OBJCE_P(value);
if (UNEXPECTED(ce->name->len != sizeof("__PHP_Incomplete_Class") - 1) ||
@@ -30168,11 +30333,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CONST_HANDLER(ZEND
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- fast_div_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+ fast_div_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -30222,11 +30388,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CV_CONST_HANDLER(ZEND_
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_left_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+ shift_left_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -30237,11 +30404,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CV_CONST_HANDLER(ZEND_
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_right_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+ shift_right_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -30252,12 +30420,58 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CONST_HANDLER(Z
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- concat_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+
+ do {
+ if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
+ (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
+ zend_string *op1_str = Z_STR_P(op1);
+ zend_string *op2_str = Z_STR_P(op2);
+ zend_string *str;
+
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
+ break;
+ }
+ }
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
+
+ break;
+ }
+ }
+ if (IS_CV != IS_CONST && IS_CV != IS_CV &&
+ !IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ size_t len = op1_str->len;
+
+ str = zend_string_realloc(op1_str, len + op2_str->len, 0);
+ memcpy(str->val + len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ break;
+ } else {
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ }
+ } else {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ concat_function(EX_VAR(opline->result.var), op1, op2);
+ }
+
+ } while (0);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -30267,12 +30481,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CONST_HAN
{
USE_OPLINE
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+ result = fast_is_identical_function(op1, op2);
ZEND_VM_SMART_BRANCH(result, (IS_CV|IS_CONST) & (IS_VAR|IS_TMP_VAR));
@@ -30287,12 +30502,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CONST
{
USE_OPLINE
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+ result = fast_is_not_identical_function(op1, op2);
ZEND_VM_SMART_BRANCH(result, (IS_CV|IS_CONST) & (IS_VAR|IS_TMP_VAR));
@@ -30314,18 +30530,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -30357,10 +30573,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CONST_HANDLER
} while (0);
SAVE_OPLINE();
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -30383,18 +30599,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HAN
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -30426,10 +30642,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CONST_HAN
} while (0);
SAVE_OPLINE();
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -30547,12 +30763,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CONST_HANDLE
{
USE_OPLINE
- zval *result = EX_VAR(opline->result.var);
+ zval *op1, *op2;
SAVE_OPLINE();
- compare_function(result,
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+ compare_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -30563,11 +30779,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CONST_HANDLER(ZE
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_or_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+ bitwise_or_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -30578,11 +30795,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CONST_HANDLER(Z
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_and_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+ bitwise_and_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -30593,11 +30811,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CONST_HANDLER(Z
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+ bitwise_xor_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -30608,11 +30827,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CONST_HANDLER
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- boolean_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+ boolean_xor_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -30644,7 +30864,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
@@ -30674,42 +30893,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval *z;
- zval rv, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- if (Z_OBJ_HT(obj)->read_property &&
- (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- zptr = z;
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- binary_op(z, z, value);
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- zval_ptr_dtor(zptr);
- } else {
- zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
- OBJ_RELEASE(Z_OBJ(obj));
+ zend_assign_op_overloaded_property(object, property, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), value, binary_op, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -30741,7 +30925,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
@@ -30811,7 +30994,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_C
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -31055,7 +31237,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_CONST_HA
#endif
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CONST(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
@@ -31077,7 +31259,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -31098,51 +31279,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- SEPARATE_ZVAL_NOREF(zptr);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
+ }
+ } else {
+ ZVAL_DEREF(zptr);
+ SEPARATE_ZVAL_NOREF(zptr);
- incdec_op(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
+ }
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval rv;
-
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- incdec_op(z);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(z);
- } else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
+ zend_pre_incdec_overloaded_property(object, property, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -31153,15 +31310,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_CV_CONST(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_CV_CONST(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_CV_CONST(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_CV_CONST(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CONST(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
@@ -31183,7 +31340,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -31202,44 +31358,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
- zval_opt_copy_ctor(zptr);
- incdec_op(zptr);
- } else {
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval rv, obj;
- zval *z;
- zval z_copy;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
}
- ZVAL_DUP(EX_VAR(opline->result.var), z);
- ZVAL_DUP(&z_copy, z);
- incdec_op(&z_copy);
- if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
- Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(&z_copy);
- zval_ptr_dtor(z);
} else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- ZVAL_NULL(EX_VAR(opline->result.var));
+ ZVAL_DEREF(zptr);
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ zval_opt_copy_ctor(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
}
+ } else {
+ zend_post_incdec_overloaded_property(object, property, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, EX_VAR(opline->result.var));
}
} while (0);
@@ -31250,12 +31387,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_CV_CONST(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_CV_CONST(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CONST_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_CV_CONST(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return 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)
@@ -31268,7 +31405,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
HashTable *target_symbol_table;
SAVE_OPLINE();
- varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
if (IS_CV == IS_CONST) {
name = Z_STR_P(varname);
@@ -31276,6 +31413,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
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);
}
@@ -31468,7 +31608,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CONST_HAND
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
@@ -31492,7 +31631,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CONST_HAN
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
@@ -31539,7 +31677,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CON
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
@@ -31576,7 +31713,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CONST_
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, EX_CONSTANT(opline->op2), IS_CONST);
@@ -31608,7 +31744,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CONST_HAND
offset = EX_CONSTANT(opline->op2);
- if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST ||
+ (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -31680,7 +31817,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CONST_HAND
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
@@ -31713,7 +31849,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CONST_HAN
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
@@ -31745,7 +31880,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CONST_HAN
offset = EX_CONSTANT(opline->op2);
- if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST ||
+ (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -31826,7 +31962,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CON
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -31862,7 +31997,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CONST_
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CONST, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
@@ -31882,7 +32016,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_LIST_SPEC_CV_CONST_HANDL
zval *container;
SAVE_OPLINE();
- container = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ container = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
try_fetch_list:
if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
@@ -31894,7 +32028,8 @@ try_fetch_list:
} else {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
- } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
+ } else if (IS_CV != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
zval *result = EX_VAR(opline->result.var);
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
@@ -31906,10 +32041,13 @@ try_fetch_list:
} else {
ZVAL_NULL(result);
}
- } else if (Z_TYPE_P(container) == IS_REFERENCE) {
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_TYPE_P(container) == IS_REFERENCE) {
container = Z_REFVAL_P(container);
goto try_fetch_list;
} else {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(container, BP_VAR_R);
+ }
ZVAL_NULL(EX_VAR(opline->result.var));
}
CHECK_EXCEPTION();
@@ -31937,7 +32075,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CONST_HANDL
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, IS_CONST, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
@@ -31966,11 +32103,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CONST_HANDL
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
-try_assign_dim:
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
try_assign_dim_array:
if (IS_CONST == IS_UNUSED) {
@@ -31998,53 +32133,58 @@ try_assign_dim_array:
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
}
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
+ } else {
+ if (EXPECTED(Z_ISREF_P(object_ptr))) {
+ object_ptr = Z_REFVAL_P(object_ptr);
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
+ goto try_assign_dim_array;
+ }
+ }
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
- zval *property_name = EX_CONSTANT(opline->op2);
+ zval *property_name = EX_CONSTANT(opline->op2);
- zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
+ zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
- if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
- if (IS_CONST == IS_UNUSED) {
- zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
- FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
+ if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+ if (IS_CONST == IS_UNUSED) {
+ zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- HANDLE_EXCEPTION();
- } else {
- zend_long offset;
+ HANDLE_EXCEPTION();
+ } else {
+ zend_long offset;
- dim = EX_CONSTANT(opline->op2);
- offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
+ dim = EX_CONSTANT(opline->op2);
+ offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
- value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
- FREE_OP(free_op_data1);
+ value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
+ FREE_OP(free_op_data1);
+ }
+ } else {
+ zval_ptr_dtor_nogc(object_ptr);
+assign_dim_convert_to_array:
+ ZVAL_NEW_ARR(object_ptr);
+ zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
+ goto try_assign_dim_array;
+ }
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) {
+ goto assign_dim_clean;
}
+ goto assign_dim_convert_to_array;
} else {
- zval_ptr_dtor_nogc(object_ptr);
-assign_dim_convert_to_array:
- ZVAL_NEW_ARR(object_ptr);
- zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
- goto try_assign_dim_array;
- }
- } else if (EXPECTED(Z_ISREF_P(object_ptr))) {
- object_ptr = Z_REFVAL_P(object_ptr);
- goto try_assign_dim;
- } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
- if (UNEXPECTED(object_ptr == &EG(error_zval))) {
- goto assign_dim_clean;
- }
- goto assign_dim_convert_to_array;
- } else {
- zend_error(E_WARNING, "Cannot use a scalar value as an array");
+ zend_error(E_WARNING, "Cannot use a scalar value as an array");
assign_dim_clean:
- dim = EX_CONSTANT(opline->op2);
+ dim = EX_CONSTANT(opline->op2);
- value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- FREE_OP(free_op_data1);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
+ value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ FREE_OP(free_op_data1);
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
}
}
@@ -32091,28 +32231,60 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CONST_HAND
zend_string *op1_str, *op2_str, *str;
SAVE_OPLINE();
- op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
- op2 = EX_CONSTANT(opline->op2);
+ op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
if (IS_CV == IS_CONST) {
op1_str = Z_STR_P(op1);
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ op1_str = zend_string_copy(Z_STR_P(op1));
} else {
- op1_str = zval_get_string(op1);
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ op1_str = _zval_get_string_func(op1);
}
+ op2 = EX_CONSTANT(opline->op2);
if (IS_CONST == IS_CONST) {
op2_str = Z_STR_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ op2_str = zend_string_copy(Z_STR_P(op2));
} else {
- op2_str = zval_get_string(op2);
- }
- str = zend_string_alloc(op1_str->len + op2_str->len, 0);
- memcpy(str->val, op1_str->val, op1_str->len);
- memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
- ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- if (IS_CV != IS_CONST) {
- zend_string_release(op1_str);
- }
- if (IS_CONST != IS_CONST) {
- zend_string_release(op2_str);
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ op2_str = _zval_get_string_func(op2);
}
+ do {
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ if (IS_CONST == IS_CONST) {
+ zend_string_addref(op2_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op2_str);
+ zend_string_release(op1_str);
+ break;
+ }
+ }
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ if (IS_CV == IS_CONST) {
+ zend_string_addref(op1_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op1_str);
+ zend_string_release(op2_str);
+ break;
+ }
+ }
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ if (IS_CV != IS_CONST) {
+ zend_string_release(op1_str);
+ }
+ if (IS_CONST != IS_CONST) {
+ zend_string_release(op2_str);
+ }
+ } while (0);
CHECK_EXCEPTION();
@@ -32144,6 +32316,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST
break;
}
}
+ 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();
}
@@ -32154,7 +32329,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST
} while (0);
}
- object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ object = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context");
@@ -32164,13 +32339,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST
if (IS_CV != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -32217,7 +32395,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if (IS_CV & (IS_VAR|IS_TMP_VAR)) {
+ } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -32243,18 +32422,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEN
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -32285,10 +32464,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CONST_HANDLER(ZEN
} while (0);
SAVE_OPLINE();
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -32307,11 +32486,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS
SAVE_OPLINE();
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -32321,11 +32499,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS
} else {
expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
if (IS_CV == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_CV == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_CV == IS_CV) {
@@ -32356,43 +32534,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CONS
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_CONST != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CONST != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -32463,10 +32639,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_CONST_HANDLE
ZEND_VM_NEXT_OPCODE();
}
- varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ 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;
}
@@ -32519,6 +32698,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLE
zval *container;
zval *offset;
zend_ulong hval;
+ zend_string *key;
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
@@ -32530,72 +32710,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CONST_HANDLE
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
-
HANDLE_EXCEPTION();
}
offset = EX_CONSTANT(opline->op2);
-unset_dim_again:
- if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht;
+ do {
+ if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ HashTable *ht;
+unset_dim_array:
+ SEPARATE_ARRAY(container);
+ ht = Z_ARRVAL_P(container);
offset_again:
- SEPARATE_ARRAY(container);
- ht = Z_ARRVAL_P(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- zend_hash_index_del(ht, hval);
- break;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index_dim:
- zend_hash_index_del(ht, hval);
- break;
- case IS_STRING:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ key = Z_STR_P(offset);
if (IS_CONST != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
+ if (ZEND_HANDLE_NUMERIC(key, hval)) {
goto num_index_dim;
}
}
+str_index_dim:
if (ht == &EG(symbol_table)) {
- zend_delete_global_variable(Z_STR_P(offset));
+ zend_delete_global_variable(key);
} else {
- zend_hash_del(ht, Z_STR_P(offset));
+ zend_hash_del(ht, key);
}
- break;
- case IS_NULL:
- zend_hash_del(ht, STR_EMPTY_ALLOC());
- break;
- case IS_FALSE:
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_dim:
+ zend_hash_index_del(ht, hval);
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto offset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
hval = 0;
goto num_index_dim;
- case IS_TRUE:
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
hval = 1;
goto num_index_dim;
- case IS_RESOURCE:
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
hval = Z_RES_HANDLE_P(offset);
goto num_index_dim;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto offset_again;
- break;
- default:
+ } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else {
zend_error(E_WARNING, "Illegal offset type in unset");
- break;
+ }
+ break;
+ } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto unset_dim_array;
+ }
}
- } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
- } else {
- Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
}
- } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto unset_dim_again;
- } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- }
+ if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
+ } else {
+ Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ }
+ } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
+ }
+ } while (0);
CHECK_EXCEPTION();
@@ -32619,7 +32807,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CONST_HANDLE
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
-
HANDLE_EXCEPTION();
}
offset = EX_CONSTANT(opline->op2);
@@ -32772,12 +32959,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_
offset = EX_CONSTANT(opline->op2);
-isset_dim_obj_again:
if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -32792,31 +32980,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -32826,50 +33014,62 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if (IS_CV == IS_UNUSED ||
+ (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if (IS_CONST & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
- }
- }
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
+
ZEND_VM_SMART_BRANCH(result, 1);
ZVAL_BOOL(EX_VAR(opline->result.var), result);
@@ -32896,7 +33096,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV
offset = EX_CONSTANT(opline->op2);
- if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST ||
+ (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -32911,10 +33112,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
@@ -32932,7 +33132,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_CONST_HANDL
zend_bool result;
SAVE_OPLINE();
- expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ expr = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
try_instanceof:
if (Z_TYPE_P(expr) == IS_OBJECT) {
@@ -32959,6 +33159,9 @@ try_instanceof:
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;
}
@@ -32975,7 +33178,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
@@ -32992,7 +33195,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE
if (IS_CV != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -33002,11 +33205,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_CV != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
@@ -33014,7 +33216,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -33036,11 +33237,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE
/* Consts, temporary variables and references need copying */
if (IS_CV == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -33061,11 +33265,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CONST_HANDLER(ZE
/* Consts, temporary variables and references need copying */
if (IS_CONST == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_CONST == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_CONST == IS_VAR || IS_CONST == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -33109,11 +33316,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CONST_HANDLER(ZEND
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- pow_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = EX_CONSTANT(opline->op2);
+ pow_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -33210,12 +33418,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_TMP_HANDL
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_CV|IS_TMP_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -33230,12 +33439,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_TMP_H
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_CV|IS_TMP_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -33282,7 +33492,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
@@ -33299,7 +33509,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND
if (IS_CV != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -33309,11 +33519,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_CV != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
@@ -33321,7 +33530,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
@@ -33343,11 +33551,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND
/* Consts, temporary variables and references need copying */
if (IS_CV == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -33368,11 +33579,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_TMP_HANDLER(ZEND
/* Consts, temporary variables and references need copying */
if (IS_TMP_VAR == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_TMP_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_TMP_VAR == IS_VAR || IS_TMP_VAR == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_TMP_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -33416,12 +33630,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_VAR_HANDL
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_CV|IS_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -33436,12 +33651,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_VAR_H
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var_deref(opline->op2.var, execute_data, &free_op2);
+ result = fast_is_not_identical_function(op1, op2);
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, (IS_CV|IS_VAR) & (IS_VAR|IS_TMP_VAR));
@@ -33462,7 +33678,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
HashTable *target_symbol_table;
SAVE_OPLINE();
- varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
if (IS_CV == IS_CONST) {
name = Z_STR_P(varname);
@@ -33470,6 +33686,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
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);
}
@@ -33677,7 +33896,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER
if (IS_VAR == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
- if (free_op2) {zval_ptr_dtor_nogc(free_op2);};
HANDLE_EXCEPTION();
}
@@ -33700,7 +33918,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_VAR_HANDLER
if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
if (free_op2) {zval_ptr_dtor_nogc(free_op2);};
-
HANDLE_EXCEPTION();
}
if (IS_CV == IS_VAR &&
@@ -33758,10 +33975,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_VAR_HANDLER(
ZEND_VM_NEXT_OPCODE();
}
- varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ 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;
}
@@ -33920,7 +34140,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INSTANCEOF_SPEC_CV_VAR_HANDLER
zend_bool result;
SAVE_OPLINE();
- expr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ expr = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
try_instanceof:
if (Z_TYPE_P(expr) == IS_OBJECT) {
@@ -33947,6 +34167,9 @@ try_instanceof:
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;
}
@@ -33963,7 +34186,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
@@ -33980,7 +34203,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND
if (IS_CV != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -33990,11 +34213,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_CV != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
@@ -34002,7 +34224,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
@@ -34024,11 +34245,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND
/* Consts, temporary variables and references need copying */
if (IS_CV == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -34049,11 +34273,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_VAR_HANDLER(ZEND
/* Consts, temporary variables and references need copying */
if (IS_VAR == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_VAR == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_VAR == IS_VAR || IS_VAR == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_VAR & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
zval_ptr_dtor_nogc(free_op2);
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -34112,7 +34339,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
@@ -34398,7 +34624,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
HashTable *target_symbol_table;
SAVE_OPLINE();
- varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ varname = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
if (IS_CV == IS_CONST) {
name = Z_STR_P(varname);
@@ -34406,6 +34632,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
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);
}
@@ -34583,7 +34812,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_UNUSED_HAN
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
@@ -34607,7 +34835,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_UNUSED_HA
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
@@ -34639,7 +34866,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_UNU
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, NULL, IS_UNUSED);
@@ -34681,11 +34907,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_UNUSED_HAND
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
-try_assign_dim:
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
try_assign_dim_array:
if (IS_UNUSED == IS_UNUSED) {
@@ -34713,53 +34937,58 @@ try_assign_dim_array:
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
}
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
+ } else {
+ if (EXPECTED(Z_ISREF_P(object_ptr))) {
+ object_ptr = Z_REFVAL_P(object_ptr);
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
+ goto try_assign_dim_array;
+ }
+ }
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
- zval *property_name = NULL;
+ zval *property_name = NULL;
- zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
+ zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
- if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
- if (IS_UNUSED == IS_UNUSED) {
- zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
- FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
+ if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+ if (IS_UNUSED == IS_UNUSED) {
+ zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- HANDLE_EXCEPTION();
- } else {
- zend_long offset;
+ HANDLE_EXCEPTION();
+ } else {
+ zend_long offset;
- dim = NULL;
- offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
+ dim = NULL;
+ offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
- value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
- FREE_OP(free_op_data1);
+ value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
+ FREE_OP(free_op_data1);
+ }
+ } else {
+ zval_ptr_dtor_nogc(object_ptr);
+assign_dim_convert_to_array:
+ ZVAL_NEW_ARR(object_ptr);
+ zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
+ goto try_assign_dim_array;
}
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) {
+ goto assign_dim_clean;
+ }
+ goto assign_dim_convert_to_array;
} else {
- zval_ptr_dtor_nogc(object_ptr);
-assign_dim_convert_to_array:
- ZVAL_NEW_ARR(object_ptr);
- zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
- goto try_assign_dim_array;
- }
- } else if (EXPECTED(Z_ISREF_P(object_ptr))) {
- object_ptr = Z_REFVAL_P(object_ptr);
- goto try_assign_dim;
- } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
- if (UNEXPECTED(object_ptr == &EG(error_zval))) {
- goto assign_dim_clean;
- }
- goto assign_dim_convert_to_array;
- } else {
- zend_error(E_WARNING, "Cannot use a scalar value as an array");
+ zend_error(E_WARNING, "Cannot use a scalar value as an array");
assign_dim_clean:
- dim = NULL;
+ dim = NULL;
- value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- FREE_OP(free_op_data1);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
+ value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ FREE_OP(free_op_data1);
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
}
}
@@ -34812,6 +35041,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_VERIFY_RETURN_TYPE_SPEC_CV_UNU
}
}
zend_verify_return_type(EX(func), retval_ptr);
+
+ if (UNEXPECTED(EG(exception) != NULL)) {
+
+ }
#endif
}
CHECK_EXCEPTION();
@@ -34826,11 +35059,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS
SAVE_OPLINE();
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -34840,11 +35072,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS
} else {
expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
if (IS_CV == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_CV == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_CV == IS_CV) {
@@ -34875,43 +35107,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_UNUS
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_UNUSED != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_UNUSED != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_UNUSED == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -34982,10 +35212,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_CV_UNUSED_HANDL
ZEND_VM_NEXT_OPCODE();
}
- varname = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ 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;
}
@@ -35143,7 +35376,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
@@ -35160,7 +35393,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z
if (IS_CV != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -35170,11 +35403,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_CV != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
@@ -35182,7 +35414,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -35204,11 +35435,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_CV == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -35229,11 +35463,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_UNUSED_HANDLER(Z
/* Consts, temporary variables and references need copying */
if (IS_UNUSED == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_UNUSED == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_UNUSED == IS_VAR || IS_UNUSED == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_UNUSED & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -35412,11 +35649,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_CV_HANDLER(ZEND_OP
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- fast_div_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ fast_div_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -35466,11 +35704,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CV_CV_HANDLER(ZEND_OPC
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_left_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ shift_left_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -35481,11 +35720,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CV_CV_HANDLER(ZEND_OPC
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_right_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ shift_right_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -35496,12 +35736,58 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_CV_HANDLER(ZEND
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- concat_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
+
+ do {
+ if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
+ (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
+ zend_string *op1_str = Z_STR_P(op1);
+ zend_string *op2_str = Z_STR_P(op2);
+ zend_string *str;
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
+
+ break;
+ }
+ }
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
+
+ break;
+ }
+ }
+ if (IS_CV != IS_CONST && IS_CV != IS_CV &&
+ !IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ size_t len = op1_str->len;
+
+ str = zend_string_realloc(op1_str, len + op2_str->len, 0);
+ memcpy(str->val + len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ break;
+ } else {
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ }
+ } else {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ concat_function(EX_VAR(opline->result.var), op1, op2);
+ }
+
+ } while (0);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -35511,12 +35797,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_IDENTICAL_SPEC_CV_CV_HANDLE
{
USE_OPLINE
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_identical_function(
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var);
+ result = fast_is_identical_function(op1, op2);
ZEND_VM_SMART_BRANCH(result, (IS_CV|IS_CV) & (IS_VAR|IS_TMP_VAR));
@@ -35531,12 +35818,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_IDENTICAL_SPEC_CV_CV_HA
{
USE_OPLINE
+ zval *op1, *op2;
int result;
SAVE_OPLINE();
- result = fast_is_not_identical_function(
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_deref_BP_VAR_R(execute_data, opline->op2.var);
+ result = fast_is_not_identical_function(op1, op2);
ZEND_VM_SMART_BRANCH(result, (IS_CV|IS_CV) & (IS_VAR|IS_TMP_VAR));
@@ -35558,18 +35846,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZE
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -35601,10 +35889,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_CV_HANDLER(ZE
} while (0);
SAVE_OPLINE();
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -35627,18 +35915,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLE
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -35670,10 +35958,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_CV_HANDLE
} while (0);
SAVE_OPLINE();
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -35791,12 +36079,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_CV_HANDLER(Z
{
USE_OPLINE
- zval *result = EX_VAR(opline->result.var);
+ zval *op1, *op2;
SAVE_OPLINE();
- compare_function(result,
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ compare_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -35807,11 +36095,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_CV_HANDLER(ZEND_
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_or_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ bitwise_or_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -35822,11 +36111,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_CV_HANDLER(ZEND
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_and_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ bitwise_and_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -35837,11 +36127,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_CV_HANDLER(ZEND
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ bitwise_xor_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -35852,11 +36143,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_CV_HANDLER(ZE
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- boolean_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ boolean_xor_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -35888,7 +36180,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
@@ -35918,42 +36209,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval *z;
- zval rv, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- if (Z_OBJ_HT(obj)->read_property &&
- (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- zptr = z;
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- binary_op(z, z, value);
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- zval_ptr_dtor(zptr);
- } else {
- zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
- OBJ_RELEASE(Z_OBJ(obj));
+ zend_assign_op_overloaded_property(object, property, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), value, binary_op, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -35985,7 +36241,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
@@ -36055,7 +36310,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_C
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -36299,7 +36553,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_CV_HANDL
#endif
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_CV(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
@@ -36321,7 +36575,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -36342,51 +36595,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- SEPARATE_ZVAL_NOREF(zptr);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
+ }
+ } else {
+ ZVAL_DEREF(zptr);
+ SEPARATE_ZVAL_NOREF(zptr);
- incdec_op(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
+ }
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval rv;
-
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- incdec_op(z);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- Z_OBJ_HT(obj)->write_property(&obj, property, z, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(z);
- } else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
+ zend_pre_incdec_overloaded_property(object, property, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -36397,15 +36626,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_CV_CV(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_CV_CV(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_CV_CV(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_CV_CV(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_CV(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
@@ -36427,7 +36656,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
-
HANDLE_EXCEPTION();
}
@@ -36446,44 +36674,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
- zval_opt_copy_ctor(zptr);
- incdec_op(zptr);
- } else {
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval rv, obj;
- zval *z;
- zval z_copy;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
}
- ZVAL_DUP(EX_VAR(opline->result.var), z);
- ZVAL_DUP(&z_copy, z);
- incdec_op(&z_copy);
- if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
- Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(&z_copy);
- zval_ptr_dtor(z);
} else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- ZVAL_NULL(EX_VAR(opline->result.var));
+ ZVAL_DEREF(zptr);
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ zval_opt_copy_ctor(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
}
+ } else {
+ zend_post_incdec_overloaded_property(object, property, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, EX_VAR(opline->result.var));
}
} while (0);
@@ -36494,12 +36703,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_CV_CV(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_CV_CV(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_CV_CV(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_CV_CV(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_CV_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -36528,7 +36737,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_CV_HANDLER
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
@@ -36552,7 +36760,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_CV_HANDLE
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
@@ -36599,7 +36806,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_CV_
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
@@ -36636,7 +36842,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_CV_HAN
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var), IS_CV);
@@ -36668,7 +36873,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_CV_HANDLER
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST ||
+ (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -36740,7 +36946,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_CV_HANDLER
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
@@ -36773,7 +36978,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_CV_HANDLE
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
@@ -36805,7 +37009,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_CV_HANDLE
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST ||
+ (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -36886,7 +37091,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_CV_
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -36922,7 +37126,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_CV_HAN
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, IS_CV, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
@@ -36956,7 +37159,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_CV_HANDLER(
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, IS_CV, (opline+1)->op1_type, (opline+1)->op1, execute_data, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
@@ -36985,11 +37187,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_CV_HANDLER(
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
-
HANDLE_EXCEPTION();
}
-try_assign_dim:
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
try_assign_dim_array:
if (IS_CV == IS_UNUSED) {
@@ -37017,53 +37217,58 @@ try_assign_dim_array:
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
}
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
+ } else {
+ if (EXPECTED(Z_ISREF_P(object_ptr))) {
+ object_ptr = Z_REFVAL_P(object_ptr);
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
+ goto try_assign_dim_array;
+ }
+ }
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
- zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ zval *property_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
+ zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
- if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
- if (IS_CV == IS_UNUSED) {
- zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
- FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
+ if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+ if (IS_CV == IS_UNUSED) {
+ zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- HANDLE_EXCEPTION();
- } else {
- zend_long offset;
+ HANDLE_EXCEPTION();
+ } else {
+ zend_long offset;
- dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
+ dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
- value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
- FREE_OP(free_op_data1);
+ value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
+ FREE_OP(free_op_data1);
+ }
+ } else {
+ zval_ptr_dtor_nogc(object_ptr);
+assign_dim_convert_to_array:
+ ZVAL_NEW_ARR(object_ptr);
+ zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
+ goto try_assign_dim_array;
}
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) {
+ goto assign_dim_clean;
+ }
+ goto assign_dim_convert_to_array;
} else {
- zval_ptr_dtor_nogc(object_ptr);
-assign_dim_convert_to_array:
- ZVAL_NEW_ARR(object_ptr);
- zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
- goto try_assign_dim_array;
- }
- } else if (EXPECTED(Z_ISREF_P(object_ptr))) {
- object_ptr = Z_REFVAL_P(object_ptr);
- goto try_assign_dim;
- } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
- if (UNEXPECTED(object_ptr == &EG(error_zval))) {
- goto assign_dim_clean;
- }
- goto assign_dim_convert_to_array;
- } else {
- zend_error(E_WARNING, "Cannot use a scalar value as an array");
+ zend_error(E_WARNING, "Cannot use a scalar value as an array");
assign_dim_clean:
- dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ dim = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- FREE_OP(free_op_data1);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
+ value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ FREE_OP(free_op_data1);
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
}
}
@@ -37115,7 +37320,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
-
HANDLE_EXCEPTION();
}
if (IS_CV == IS_VAR &&
@@ -37137,7 +37341,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_REF_SPEC_CV_CV_HANDLER(
if (IS_CV == IS_VAR && UNEXPECTED(variable_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets nor overloaded objects");
-
HANDLE_EXCEPTION();
}
if (IS_CV == IS_VAR &&
@@ -37172,28 +37375,60 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_CV_HANDLER
zend_string *op1_str, *op2_str, *str;
SAVE_OPLINE();
- op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
- op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
if (IS_CV == IS_CONST) {
op1_str = Z_STR_P(op1);
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ op1_str = zend_string_copy(Z_STR_P(op1));
} else {
- op1_str = zval_get_string(op1);
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ op1_str = _zval_get_string_func(op1);
}
+ op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
if (IS_CV == IS_CONST) {
op2_str = Z_STR_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ op2_str = zend_string_copy(Z_STR_P(op2));
} else {
- op2_str = zval_get_string(op2);
- }
- str = zend_string_alloc(op1_str->len + op2_str->len, 0);
- memcpy(str->val, op1_str->val, op1_str->len);
- memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
- ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- if (IS_CV != IS_CONST) {
- zend_string_release(op1_str);
- }
- if (IS_CV != IS_CONST) {
- zend_string_release(op2_str);
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ op2_str = _zval_get_string_func(op2);
}
+ do {
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ if (IS_CV == IS_CONST) {
+ zend_string_addref(op2_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op2_str);
+ zend_string_release(op1_str);
+ break;
+ }
+ }
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ if (IS_CV == IS_CONST) {
+ zend_string_addref(op1_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op1_str);
+ zend_string_release(op2_str);
+ break;
+ }
+ }
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ if (IS_CV != IS_CONST) {
+ zend_string_release(op1_str);
+ }
+ if (IS_CV != IS_CONST) {
+ zend_string_release(op2_str);
+ }
+ } while (0);
CHECK_EXCEPTION();
@@ -37214,7 +37449,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
SAVE_OPLINE();
- function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
if (IS_CV != IS_CONST &&
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
@@ -37225,6 +37460,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
break;
}
}
+ 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();
}
@@ -37235,7 +37473,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
} while (0);
}
- object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ object = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context");
@@ -37245,13 +37483,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
if (IS_CV != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -37298,7 +37539,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if (IS_CV & (IS_VAR|IS_TMP_VAR)) {
+ } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -37324,18 +37566,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_O
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -37366,10 +37608,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_CV_HANDLER(ZEND_O
} while (0);
SAVE_OPLINE();
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -37388,11 +37630,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H
SAVE_OPLINE();
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -37402,11 +37643,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H
} else {
expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
if (IS_CV == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_CV == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_CV == IS_CV) {
@@ -37432,48 +37673,46 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_CV_H
if (IS_CV != IS_UNUSED) {
- zval *offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ zval *offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
zend_string *str;
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if (IS_CV != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if (IS_CV != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
} else {
@@ -37521,6 +37760,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(Z
zval *container;
zval *offset;
zend_ulong hval;
+ zend_string *key;
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
@@ -37532,72 +37772,80 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_CV_HANDLER(Z
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
-
HANDLE_EXCEPTION();
}
- offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
-unset_dim_again:
- if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht;
+ do {
+ if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ HashTable *ht;
+unset_dim_array:
+ SEPARATE_ARRAY(container);
+ ht = Z_ARRVAL_P(container);
offset_again:
- SEPARATE_ARRAY(container);
- ht = Z_ARRVAL_P(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- zend_hash_index_del(ht, hval);
- break;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index_dim:
- zend_hash_index_del(ht, hval);
- break;
- case IS_STRING:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ key = Z_STR_P(offset);
if (IS_CV != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
+ if (ZEND_HANDLE_NUMERIC(key, hval)) {
goto num_index_dim;
}
}
+str_index_dim:
if (ht == &EG(symbol_table)) {
- zend_delete_global_variable(Z_STR_P(offset));
+ zend_delete_global_variable(key);
} else {
- zend_hash_del(ht, Z_STR_P(offset));
+ zend_hash_del(ht, key);
}
- break;
- case IS_NULL:
- zend_hash_del(ht, STR_EMPTY_ALLOC());
- break;
- case IS_FALSE:
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_dim:
+ zend_hash_index_del(ht, hval);
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto offset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
hval = 0;
goto num_index_dim;
- case IS_TRUE:
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
hval = 1;
goto num_index_dim;
- case IS_RESOURCE:
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
hval = Z_RES_HANDLE_P(offset);
goto num_index_dim;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto offset_again;
- break;
- default:
+ } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else {
zend_error(E_WARNING, "Illegal offset type in unset");
- break;
+ }
+ break;
+ } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto unset_dim_array;
+ }
}
- } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
- } else {
- Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
}
- } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto unset_dim_again;
- } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- }
+ if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
+ } else {
+ Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ }
+ } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
+ }
+ } while (0);
CHECK_EXCEPTION();
@@ -37621,7 +37869,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_CV_HANDLER(Z
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
-
HANDLE_EXCEPTION();
}
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
@@ -37667,14 +37914,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_
HANDLE_EXCEPTION();
}
- offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
-isset_dim_obj_again:
if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -37689,31 +37937,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -37723,50 +37971,62 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if (IS_CV == IS_UNUSED ||
+ (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if (IS_CV & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
- }
- }
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
+
ZEND_VM_SMART_BRANCH(result, 1);
ZVAL_BOOL(EX_VAR(opline->result.var), result);
@@ -37793,7 +38053,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST ||
+ (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -37808,10 +38069,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
@@ -37828,7 +38088,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_
zend_generator *generator = zend_get_running_generator(execute_data);
SAVE_OPLINE();
- if (generator->flags & ZEND_GENERATOR_FORCED_CLOSE) {
+ if (UNEXPECTED(generator->flags & ZEND_GENERATOR_FORCED_CLOSE)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield from finally in a force-closed generator");
@@ -37845,7 +38105,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_
if (IS_CV != IS_UNUSED) {
- if (EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ if (UNEXPECTED(EX(func)->op_array.fn_flags & ZEND_ACC_RETURN_REFERENCE)) {
/* Constants and temporary variables aren't yieldable by reference,
* but we still allow them with a notice. */
if (IS_CV == IS_CONST || IS_CV == IS_TMP_VAR) {
@@ -37855,11 +38115,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_
value = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
ZVAL_COPY_VALUE(&generator->value, value);
- if (Z_OPT_REFCOUNTED(generator->value)) Z_SET_REFCOUNT(generator->value, 1);
-
- /* Temporary variables don't need ctor copying */
- if (IS_CV != IS_TMP_VAR) {
- zval_opt_copy_ctor(&generator->value);
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
}
} else {
zval *value_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
@@ -37867,7 +38126,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_
if (IS_CV == IS_VAR && UNEXPECTED(value_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot yield string offsets by reference");
-
HANDLE_EXCEPTION();
}
@@ -37889,11 +38147,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_
/* Consts, temporary variables and references need copying */
if (IS_CV == IS_CONST) {
- ZVAL_DUP(&generator->value, value);
+ ZVAL_COPY_VALUE(&generator->value, value);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
+ zval_copy_ctor_func(&generator->value);
+ }
} else if (IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->value, value);
- } else if ((IS_CV == IS_CV || IS_CV == IS_VAR) && Z_ISREF_P(value)) {
- ZVAL_DUP(&generator->value, Z_REFVAL_P(value));
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(value)) {
+ ZVAL_COPY(&generator->value, Z_REFVAL_P(value));
} else {
ZVAL_COPY_VALUE(&generator->value, value);
@@ -37914,11 +38175,14 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_CV_CV_HANDLER(ZEND_
/* Consts, temporary variables and references need copying */
if (IS_CV == IS_CONST) {
- ZVAL_DUP(&generator->key, key);
+ ZVAL_COPY_VALUE(&generator->key, key);
+ if (UNEXPECTED(Z_OPT_COPYABLE(generator->key))) {
+ zval_copy_ctor_func(&generator->key);
+ }
} else if (IS_CV == IS_TMP_VAR) {
ZVAL_COPY_VALUE(&generator->key, key);
- } else if ((IS_CV == IS_VAR || IS_CV == IS_CV) && Z_ISREF_P(key)) {
- ZVAL_DUP(&generator->key, Z_REFVAL_P(key));
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(key)) {
+ ZVAL_COPY(&generator->key, Z_REFVAL_P(key));
} else {
ZVAL_COPY_VALUE(&generator->key, key);
@@ -37962,11 +38226,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_CV_HANDLER(ZEND_OP
{
USE_OPLINE
+ zval *op1, *op2;
SAVE_OPLINE();
- pow_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ pow_function(EX_VAR(opline->result.var), op1, op2);
CHECK_EXCEPTION();
@@ -38117,11 +38382,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_CV_TMPVAR_HANDLER(ZEN
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- fast_div_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ fast_div_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -38171,11 +38437,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_CV_TMPVAR_HANDLER(ZEND
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_left_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ shift_left_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -38186,11 +38453,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_CV_TMPVAR_HANDLER(ZEND
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_right_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ shift_right_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -38201,12 +38469,58 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_CV_TMPVAR_HANDLER(
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- concat_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+
+ do {
+ if ((IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
+ ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
+ zend_string *op1_str = Z_STR_P(op1);
+ zend_string *op2_str = Z_STR_P(op2);
+ zend_string *str;
+
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
+ break;
+ }
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
+
+ break;
+ }
+ }
+ if (IS_CV != IS_CONST && IS_CV != IS_CV &&
+ !IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ size_t len = op1_str->len;
+
+ str = zend_string_realloc(op1_str, len + op2_str->len, 0);
+ memcpy(str->val + len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ break;
+ } else {
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ }
+ } else {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ concat_function(EX_VAR(opline->result.var), op1, op2);
+ }
+
+ } while (0);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -38223,18 +38537,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLE
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -38266,10 +38580,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_CV_TMPVAR_HANDLE
} while (0);
SAVE_OPLINE();
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -38292,18 +38606,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HA
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -38335,10 +38649,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_CV_TMPVAR_HA
} while (0);
SAVE_OPLINE();
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -38456,12 +38770,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_CV_TMPVAR_HANDL
{
USE_OPLINE
zend_free_op free_op2;
- zval *result = EX_VAR(opline->result.var);
+ zval *op1, *op2;
SAVE_OPLINE();
- compare_function(result,
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ compare_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -38472,11 +38786,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_CV_TMPVAR_HANDLER(Z
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_or_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ bitwise_or_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -38487,11 +38802,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_CV_TMPVAR_HANDLER(
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_and_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ bitwise_and_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -38502,11 +38818,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_CV_TMPVAR_HANDLER(
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ bitwise_xor_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -38517,11 +38834,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_CV_TMPVAR_HANDLE
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- boolean_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ boolean_xor_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -38553,7 +38871,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
@@ -38583,42 +38900,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_obj_helper_SP
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval *z;
- zval rv, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- if (Z_OBJ_HT(obj)->read_property &&
- (z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv)) != NULL) {
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
- if (Z_TYPE_P(z) == IS_OBJECT && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- zptr = z;
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- binary_op(z, z, value);
- Z_OBJ_HT(obj)->write_property(&obj, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- zval_ptr_dtor(zptr);
- } else {
- zend_error(E_WARNING, "Attempt to assign property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
- OBJ_RELEASE(Z_OBJ(obj));
+ zend_assign_op_overloaded_property(object, property, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), value, binary_op, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -38650,7 +38932,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_dim_helper_SP
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
@@ -38721,7 +39002,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_binary_assign_op_helper_SPEC_C
if (IS_CV == IS_VAR && UNEXPECTED(var_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use assign-op operators with overloaded objects nor string offsets");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
@@ -38966,7 +39246,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_BW_XOR_SPEC_CV_TMPVAR_H
#endif
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op2;
@@ -38988,7 +39268,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
@@ -39009,51 +39288,27 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- SEPARATE_ZVAL_NOREF(zptr);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
+ }
+ } else {
+ ZVAL_DEREF(zptr);
+ SEPARATE_ZVAL_NOREF(zptr);
- incdec_op(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
+ }
if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
ZVAL_COPY(EX_VAR(opline->result.var), zptr);
}
} else {
- zval rv;
-
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval *z, obj;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
-
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
- }
- ZVAL_DEREF(z);
- SEPARATE_ZVAL_NOREF(z);
- incdec_op(z);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_COPY(EX_VAR(opline->result.var), z);
- }
- Z_OBJ_HT(obj)->write_property(&obj, property, z, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(z);
- } else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
- }
- }
+ zend_pre_incdec_overloaded_property(object, property, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
}
} while (0);
@@ -39065,15 +39320,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_pre_incdec_property_helper_SPE
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_PRE_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_pre_incdec_property_helper_SPEC_CV_TMPVAR(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
-static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMPVAR(incdec_t incdec_op ZEND_OPCODE_HANDLER_ARGS_DC)
+static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SPEC_CV_TMPVAR(int inc ZEND_OPCODE_HANDLER_ARGS_DC)
{
USE_OPLINE
zend_free_op free_op2;
@@ -39095,7 +39350,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot increment/decrement overloaded objects nor string offsets");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
@@ -39114,44 +39368,25 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
if (EXPECTED(Z_OBJ_HT_P(object)->get_property_ptr_ptr)
&& EXPECTED((zptr = Z_OBJ_HT_P(object)->get_property_ptr_ptr(object, property, BP_VAR_RW, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL))) != NULL)) {
- ZVAL_DEREF(zptr);
- ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
- zval_opt_copy_ctor(zptr);
- incdec_op(zptr);
- } else {
- if (Z_OBJ_HT_P(object)->read_property && Z_OBJ_HT_P(object)->write_property) {
- zval rv, obj;
- zval *z;
- zval z_copy;
-
- ZVAL_OBJ(&obj, Z_OBJ_P(object));
- Z_ADDREF(obj);
- z = Z_OBJ_HT(obj)->read_property(&obj, property, BP_VAR_R, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), &rv);
- if (UNEXPECTED(EG(exception))) {
- OBJ_RELEASE(Z_OBJ(obj));
- break;
- }
-
- if (UNEXPECTED(Z_TYPE_P(z) == IS_OBJECT) && Z_OBJ_HT_P(z)->get) {
- zval rv2;
- zval *value = Z_OBJ_HT_P(z)->get(z, &rv2);
- if (z == &rv) {
- zval_ptr_dtor(&rv);
- }
- ZVAL_COPY_VALUE(z, value);
+ if (EXPECTED(Z_TYPE_P(zptr) == IS_LONG)) {
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ if (inc) {
+ fast_long_increment_function(zptr);
+ } else {
+ fast_long_decrement_function(zptr);
}
- ZVAL_DUP(EX_VAR(opline->result.var), z);
- ZVAL_DUP(&z_copy, z);
- incdec_op(&z_copy);
- if (Z_REFCOUNTED_P(z)) Z_ADDREF_P(z);
- Z_OBJ_HT(obj)->write_property(&obj, property, &z_copy, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL));
- OBJ_RELEASE(Z_OBJ(obj));
- zval_ptr_dtor(&z_copy);
- zval_ptr_dtor(z);
} else {
- zend_error(E_WARNING, "Attempt to increment/decrement property of non-object");
- ZVAL_NULL(EX_VAR(opline->result.var));
+ ZVAL_DEREF(zptr);
+ ZVAL_COPY_VALUE(EX_VAR(opline->result.var), zptr);
+ zval_opt_copy_ctor(zptr);
+ if (inc) {
+ increment_function(zptr);
+ } else {
+ decrement_function(zptr);
+ }
}
+ } else {
+ zend_post_incdec_overloaded_property(object, property, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), inc, EX_VAR(opline->result.var));
}
} while (0);
@@ -39163,12 +39398,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_post_incdec_property_helper_SP
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_INC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_CV_TMPVAR(increment_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_CV_TMPVAR(1 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POST_DEC_OBJ_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
{
- return zend_post_incdec_property_helper_SPEC_CV_TMPVAR(decrement_function ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
+ return zend_post_incdec_property_helper_SPEC_CV_TMPVAR(0 ZEND_OPCODE_HANDLER_ARGS_PASSTHRU_CC);
}
static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_R_SPEC_CV_TMPVAR_HANDLER(ZEND_OPCODE_HANDLER_ARGS)
@@ -39197,7 +39432,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_W_SPEC_CV_TMPVAR_HAN
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
@@ -39221,7 +39455,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_RW_SPEC_CV_TMPVAR_HA
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_RW(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
@@ -39268,7 +39501,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_FUNC_ARG_SPEC_CV_TMP
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_W(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
@@ -39305,7 +39537,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_DIM_UNSET_SPEC_CV_TMPVAR
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
zend_fetch_dimension_address_UNSET(EX_VAR(opline->result.var), container, _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2), (IS_TMP_VAR|IS_VAR));
@@ -39337,7 +39568,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_R_SPEC_CV_TMPVAR_HAN
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST ||
+ (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -39410,7 +39642,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_W_SPEC_CV_TMPVAR_HAN
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
@@ -39443,7 +39674,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_RW_SPEC_CV_TMPVAR_HA
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_RW);
@@ -39475,7 +39705,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_CV_TMPVAR_HA
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST ||
+ (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -39557,7 +39788,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_FUNC_ARG_SPEC_CV_TMP
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_W);
@@ -39593,7 +39823,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_UNSET_SPEC_CV_TMPVAR
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an object");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
zend_fetch_property_address(EX_VAR(opline->result.var), container, IS_CV, property, (IS_TMP_VAR|IS_VAR), (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property)) : NULL), BP_VAR_UNSET);
@@ -39627,7 +39856,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_OBJ_SPEC_CV_TMPVAR_HAND
if (IS_CV == IS_VAR && UNEXPECTED(object == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
zval_ptr_dtor_nogc(free_op2);
-
HANDLE_EXCEPTION();
}
zend_assign_to_object(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object, IS_CV, property_name, (IS_TMP_VAR|IS_VAR), (opline+1)->op1_type, (opline+1)->op1, execute_data, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(property_name)) : NULL));
@@ -39656,11 +39884,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ASSIGN_DIM_SPEC_CV_TMPVAR_HAND
zend_error(E_EXCEPTION | E_ERROR, "Cannot use string offset as an array");
FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
-try_assign_dim:
if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
try_assign_dim_array:
if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
@@ -39688,53 +39914,58 @@ try_assign_dim_array:
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
}
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
- zend_free_op free_op2;
- zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ } else {
+ if (EXPECTED(Z_ISREF_P(object_ptr))) {
+ object_ptr = Z_REFVAL_P(object_ptr);
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_ARRAY)) {
+ goto try_assign_dim_array;
+ }
+ }
+ if (EXPECTED(Z_TYPE_P(object_ptr) == IS_OBJECT)) {
+ zend_free_op free_op2;
+ zval *property_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
- zval_ptr_dtor_nogc(free_op2);
- } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
- if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
- if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
- zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
- FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
+ zend_assign_to_object_dim(UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL, object_ptr, property_name, (opline+1)->op1_type, (opline+1)->op1, execute_data);
+ zval_ptr_dtor_nogc(free_op2);
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) == IS_STRING)) {
+ if (EXPECTED(Z_STRLEN_P(object_ptr) != 0)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED) {
+ zend_error(E_EXCEPTION | E_ERROR, "[] operator not supported for strings");
+ FREE_UNFETCHED_OP((opline+1)->op1_type, (opline+1)->op1.var);
- HANDLE_EXCEPTION();
- } else {
- zend_long offset;
+ HANDLE_EXCEPTION();
+ } else {
+ zend_long offset;
- dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
- zval_ptr_dtor_nogc(free_op2);
- value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
- FREE_OP(free_op_data1);
+ dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ offset = zend_fetch_string_offset(object_ptr, dim, BP_VAR_W);
+ zval_ptr_dtor_nogc(free_op2);
+ value = get_zval_ptr_deref((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ zend_assign_to_string_offset(object_ptr, offset, value, (UNEXPECTED(RETURN_VALUE_USED(opline)) ? EX_VAR(opline->result.var) : NULL));
+ FREE_OP(free_op_data1);
+ }
+ } else {
+ zval_ptr_dtor_nogc(object_ptr);
+assign_dim_convert_to_array:
+ ZVAL_NEW_ARR(object_ptr);
+ zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
+ goto try_assign_dim_array;
+ }
+ } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
+ if (IS_CV == IS_VAR && UNEXPECTED(object_ptr == &EG(error_zval))) {
+ goto assign_dim_clean;
}
+ goto assign_dim_convert_to_array;
} else {
- zval_ptr_dtor_nogc(object_ptr);
-assign_dim_convert_to_array:
- ZVAL_NEW_ARR(object_ptr);
- zend_hash_init(Z_ARRVAL_P(object_ptr), 8, NULL, ZVAL_PTR_DTOR, 0);
- goto try_assign_dim_array;
- }
- } else if (EXPECTED(Z_ISREF_P(object_ptr))) {
- object_ptr = Z_REFVAL_P(object_ptr);
- goto try_assign_dim;
- } else if (EXPECTED(Z_TYPE_P(object_ptr) <= IS_FALSE)) {
- if (UNEXPECTED(object_ptr == &EG(error_zval))) {
- goto assign_dim_clean;
- }
- goto assign_dim_convert_to_array;
- } else {
- zend_error(E_WARNING, "Cannot use a scalar value as an array");
+ zend_error(E_WARNING, "Cannot use a scalar value as an array");
assign_dim_clean:
- dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- zval_ptr_dtor_nogc(free_op2);
- value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
- FREE_OP(free_op_data1);
- if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
- ZVAL_NULL(EX_VAR(opline->result.var));
+ dim = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ zval_ptr_dtor_nogc(free_op2);
+ value = get_zval_ptr((opline+1)->op1_type, (opline+1)->op1, execute_data, &free_op_data1, BP_VAR_R);
+ FREE_OP(free_op_data1);
+ if (UNEXPECTED(RETURN_VALUE_USED(opline))) {
+ ZVAL_NULL(EX_VAR(opline->result.var));
+ }
}
}
@@ -39752,28 +39983,60 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_CV_TMPVAR_HAN
zend_string *op1_str, *op2_str, *str;
SAVE_OPLINE();
- op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
- op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ op1 = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
if (IS_CV == IS_CONST) {
op1_str = Z_STR_P(op1);
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ op1_str = zend_string_copy(Z_STR_P(op1));
} else {
- op1_str = zval_get_string(op1);
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ op1_str = _zval_get_string_func(op1);
}
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
op2_str = Z_STR_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ op2_str = zend_string_copy(Z_STR_P(op2));
} else {
- op2_str = zval_get_string(op2);
- }
- str = zend_string_alloc(op1_str->len + op2_str->len, 0);
- memcpy(str->val, op1_str->val, op1_str->len);
- memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
- ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- if (IS_CV != IS_CONST) {
- zend_string_release(op1_str);
- }
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- zend_string_release(op2_str);
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ op2_str = _zval_get_string_func(op2);
}
+ do {
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+ zend_string_addref(op2_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op2_str);
+ zend_string_release(op1_str);
+ break;
+ }
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ if (IS_CV == IS_CONST) {
+ zend_string_addref(op1_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op1_str);
+ zend_string_release(op2_str);
+ break;
+ }
+ }
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ if (IS_CV != IS_CONST) {
+ zend_string_release(op1_str);
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ zend_string_release(op2_str);
+ }
+ } while (0);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -39805,6 +40068,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
break;
}
}
+ 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();
}
@@ -39815,7 +40081,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
} while (0);
}
- object = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ object = _get_zval_ptr_cv_undef(execute_data, opline->op1.var);
if (IS_CV == IS_UNUSED && UNEXPECTED(Z_OBJ_P(object) == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Using $this when not in object context");
@@ -39825,13 +40091,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
if (IS_CV != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -39878,7 +40147,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if (IS_CV & (IS_VAR|IS_TMP_VAR)) {
+ } else if (IS_CV & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -39905,18 +40175,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMPVAR_HANDLER(ZE
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -39947,10 +40217,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_CV_TMPVAR_HANDLER(ZE
} while (0);
SAVE_OPLINE();
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -39969,11 +40239,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV
SAVE_OPLINE();
if ((IS_CV == IS_VAR || IS_CV == IS_CV) &&
- (opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
+ UNEXPECTED(opline->extended_value & ZEND_ARRAY_ELEMENT_REF)) {
expr_ptr = _get_zval_ptr_cv_BP_VAR_W(execute_data, opline->op1.var);
if (IS_CV == IS_VAR && UNEXPECTED(expr_ptr == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot create references to/from string offsets");
-
zend_array_destroy(Z_ARRVAL_P(EX_VAR(opline->result.var)));
HANDLE_EXCEPTION();
}
@@ -39983,11 +40252,11 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV
} else {
expr_ptr = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
if (IS_CV == IS_TMP_VAR) {
- ZVAL_COPY_VALUE(&new_expr, expr_ptr);
- expr_ptr = &new_expr;
+ /* pass */
} else if (IS_CV == IS_CONST) {
- if (!Z_IMMUTABLE_P(expr_ptr)) {
- ZVAL_DUP(&new_expr, expr_ptr);
+ if (UNEXPECTED(Z_OPT_COPYABLE_P(expr_ptr))) {
+ ZVAL_COPY_VALUE(&new_expr, expr_ptr);
+ zval_copy_ctor_func(&new_expr);
expr_ptr = &new_expr;
}
} else if (IS_CV == IS_CV) {
@@ -40018,43 +40287,41 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ADD_ARRAY_ELEMENT_SPEC_CV_TMPV
zend_ulong hval;
add_again:
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index:
- zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
- break;
- case IS_STRING:
- str = Z_STR_P(offset);
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(str, hval)) {
- goto num_index;
- }
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ str = Z_STR_P(offset);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (ZEND_HANDLE_NUMERIC(str, hval)) {
+ goto num_index;
}
+ }
str_index:
- zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
- break;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index;
- case IS_FALSE:
- hval = 0;
- goto num_index;
- case IS_TRUE:
- hval = 1;
- goto num_index;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto add_again;
- break;
- default:
- zend_error(E_WARNING, "Illegal offset type");
- zval_ptr_dtor(expr_ptr);
- /* do nothing */
- break;
+ zend_hash_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), str, expr_ptr);
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index:
+ zend_hash_index_update(Z_ARRVAL_P(EX_VAR(opline->result.var)), hval, expr_ptr);
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto add_again;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index;
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(expr_ptr);
}
zval_ptr_dtor_nogc(free_op2);
} else {
@@ -40102,6 +40369,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDL
zval *container;
zval *offset;
zend_ulong hval;
+ zend_string *key;
SAVE_OPLINE();
container = _get_zval_ptr_cv_BP_VAR_UNSET(execute_data, opline->op1.var);
@@ -40113,72 +40381,81 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_DIM_SPEC_CV_TMPVAR_HANDL
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
-unset_dim_again:
- if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht;
+ do {
+ if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ HashTable *ht;
+unset_dim_array:
+ SEPARATE_ARRAY(container);
+ ht = Z_ARRVAL_P(container);
offset_again:
- SEPARATE_ARRAY(container);
- ht = Z_ARRVAL_P(container);
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- zend_hash_index_del(ht, hval);
- break;
- case IS_LONG:
- hval = Z_LVAL_P(offset);
-num_index_dim:
- zend_hash_index_del(ht, hval);
- break;
- case IS_STRING:
+ if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
+ key = Z_STR_P(offset);
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- if (ZEND_HANDLE_NUMERIC(Z_STR_P(offset), hval)) {
+ if (ZEND_HANDLE_NUMERIC(key, hval)) {
goto num_index_dim;
}
}
+str_index_dim:
if (ht == &EG(symbol_table)) {
- zend_delete_global_variable(Z_STR_P(offset));
+ zend_delete_global_variable(key);
} else {
- zend_hash_del(ht, Z_STR_P(offset));
+ zend_hash_del(ht, key);
}
- break;
- case IS_NULL:
- zend_hash_del(ht, STR_EMPTY_ALLOC());
- break;
- case IS_FALSE:
+ } else if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ hval = Z_LVAL_P(offset);
+num_index_dim:
+ zend_hash_index_del(ht, hval);
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_TYPE_P(offset) == IS_REFERENCE)) {
+ offset = Z_REFVAL_P(offset);
+ goto offset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
hval = 0;
goto num_index_dim;
- case IS_TRUE:
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
hval = 1;
goto num_index_dim;
- case IS_RESOURCE:
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
hval = Z_RES_HANDLE_P(offset);
goto num_index_dim;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto offset_again;
- break;
- default:
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ key = STR_EMPTY_ALLOC();
+ goto str_index_dim;
+ } else {
zend_error(E_WARNING, "Illegal offset type in unset");
- break;
+ }
+ break;
+ } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto unset_dim_array;
+ }
}
- } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
- if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
- } else {
- Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
}
- } else if (IS_CV != IS_UNUSED && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto unset_dim_again;
- } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
- zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
- }
+ if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ if (UNEXPECTED(Z_OBJ_HT_P(container)->unset_dimension == NULL)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot use object as array");
+ } else {
+ Z_OBJ_HT_P(container)->unset_dimension(container, offset);
+ }
+ } else if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) == IS_STRING)) {
+ zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
+ }
+ } while (0);
+
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -40202,7 +40479,6 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_OBJ_SPEC_CV_TMPVAR_HANDL
if (IS_CV == IS_VAR && UNEXPECTED(container == NULL)) {
zend_error(E_EXCEPTION | E_ERROR, "Cannot unset string offsets");
zval_ptr_dtor_nogc(EX_VAR(opline->op2.var));
-
HANDLE_EXCEPTION();
}
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
@@ -40251,12 +40527,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_CV_
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
-isset_dim_obj_again:
if (IS_CV != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -40271,31 +40548,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -40305,50 +40582,61 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if (IS_CV == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if (IS_CV == IS_UNUSED ||
+ (IS_CV != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
- }
- }
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
zval_ptr_dtor_nogc(free_op2);
ZEND_VM_SMART_BRANCH(result, 1);
@@ -40376,7 +40664,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if (IS_CV == IS_CONST ||
+ (IS_CV != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if ((IS_CV & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -40391,10 +40680,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_CV
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
zval_ptr_dtor_nogc(free_op2);
@@ -40409,11 +40697,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_CV_TMPVAR_HANDLER(ZEN
{
USE_OPLINE
zend_free_op free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- pow_function(EX_VAR(opline->result.var),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op1.var);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ pow_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -40483,6 +40772,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ECHO_SPEC_TMPVAR_HANDLER(ZEND_
if (str->len != 0) {
zend_write(str->val, str->len);
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(z) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(z, BP_VAR_R);
}
zend_string_release(str);
}
@@ -40766,7 +41057,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CLONE_SPEC_TMPVAR_HANDLER(ZEND
if (EXPECTED(Z_TYPE_P(obj) == IS_OBJECT)) {
break;
}
- }
+ }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(obj) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(obj, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -40834,6 +41128,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INCLUDE_OR_EVAL_SPEC_TMPVAR_HA
ZVAL_UNDEF(&tmp_inc_filename);
if (Z_TYPE_P(inc_filename) != IS_STRING) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(inc_filename) == IS_UNDEF)) {
+ inc_filename = GET_OP1_UNDEF_CV(inc_filename, BP_VAR_R);
+ }
ZVAL_STR(&tmp_inc_filename, zval_get_string(inc_filename));
inc_filename = &tmp_inc_filename;
}
@@ -40991,6 +41288,9 @@ try_strlen:
} else {
zend_bool strict;
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(value) == IS_UNDEF)) {
+ value = GET_OP1_UNDEF_CV(value, BP_VAR_R);
+ }
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(value) == IS_REFERENCE) {
value = Z_REFVAL_P(value);
goto try_strlen;
@@ -41157,11 +41457,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CONST_HANDLER(
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- fast_div_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ fast_div_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -41211,11 +41512,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVAR_CONST_HANDLER(Z
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_left_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ shift_left_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -41226,11 +41528,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVAR_CONST_HANDLER(Z
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_right_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ shift_right_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -41241,12 +41544,58 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CONST_HANDL
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- concat_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
- zval_ptr_dtor_nogc(free_op1);
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+
+ do {
+ if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
+ (IS_CONST == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
+ zend_string *op1_str = Z_STR_P(op1);
+ zend_string *op2_str = Z_STR_P(op2);
+ zend_string *str;
+
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
+ zval_ptr_dtor_nogc(free_op1);
+ break;
+ }
+ }
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
+ zval_ptr_dtor_nogc(free_op1);
+ break;
+ }
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV &&
+ !IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ size_t len = op1_str->len;
+
+ str = zend_string_realloc(op1_str, len + op2_str->len, 0);
+ memcpy(str->val + len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ break;
+ } else {
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ }
+ } else {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ concat_function(EX_VAR(opline->result.var), op1, op2);
+ }
+ zval_ptr_dtor_nogc(free_op1);
+ } while (0);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -41263,18 +41612,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HAN
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -41306,10 +41655,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CONST_HAN
} while (0);
SAVE_OPLINE();
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -41332,18 +41681,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -41375,10 +41724,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CONST
} while (0);
SAVE_OPLINE();
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -41496,12 +41845,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CONST_HA
{
USE_OPLINE
zend_free_op free_op1;
- zval *result = EX_VAR(opline->result.var);
+ zval *op1, *op2;
SAVE_OPLINE();
- compare_function(result,
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ compare_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -41512,11 +41861,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVAR_CONST_HANDLE
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_or_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ bitwise_or_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -41527,11 +41877,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVAR_CONST_HANDL
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_and_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ bitwise_and_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -41542,11 +41893,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVAR_CONST_HANDL
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ bitwise_xor_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -41557,11 +41909,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CONST_HAN
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- boolean_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ boolean_xor_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -41586,6 +41939,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
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);
}
@@ -41802,7 +42158,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CONST
offset = EX_CONSTANT(opline->op2);
- if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST ||
+ ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -41874,7 +42231,8 @@ try_fetch_list:
} else {
ZVAL_COPY(EX_VAR(opline->result.var), value);
}
- } else if (UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
+ } else if ((IS_TMP_VAR|IS_VAR) != IS_CONST &&
+ UNEXPECTED(Z_TYPE_P(container) == IS_OBJECT) &&
EXPECTED(Z_OBJ_HT_P(container)->read_dimension)) {
zval *result = EX_VAR(opline->result.var);
zval *retval = Z_OBJ_HT_P(container)->read_dimension(container, EX_CONSTANT(opline->op2), BP_VAR_R, result);
@@ -41886,10 +42244,13 @@ try_fetch_list:
} else {
ZVAL_NULL(result);
}
- } else if (Z_TYPE_P(container) == IS_REFERENCE) {
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_TYPE_P(container) == IS_REFERENCE) {
container = Z_REFVAL_P(container);
goto try_fetch_list;
} else {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(container) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(container, BP_VAR_R);
+ }
ZVAL_NULL(EX_VAR(opline->result.var));
}
CHECK_EXCEPTION();
@@ -41905,27 +42266,59 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CONST_
SAVE_OPLINE();
op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
- op2 = EX_CONSTANT(opline->op2);
if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
op1_str = Z_STR_P(op1);
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ op1_str = zend_string_copy(Z_STR_P(op1));
} else {
- op1_str = zval_get_string(op1);
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ op1_str = _zval_get_string_func(op1);
}
+ op2 = EX_CONSTANT(opline->op2);
if (IS_CONST == IS_CONST) {
op2_str = Z_STR_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ op2_str = zend_string_copy(Z_STR_P(op2));
} else {
- op2_str = zval_get_string(op2);
- }
- str = zend_string_alloc(op1_str->len + op2_str->len, 0);
- memcpy(str->val, op1_str->val, op1_str->len);
- memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
- ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- zend_string_release(op1_str);
- }
- if (IS_CONST != IS_CONST) {
- zend_string_release(op2_str);
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ op2_str = _zval_get_string_func(op2);
}
+ do {
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ if (IS_CONST == IS_CONST) {
+ zend_string_addref(op2_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op2_str);
+ zend_string_release(op1_str);
+ break;
+ }
+ }
+ if (IS_CONST != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+ zend_string_addref(op1_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op1_str);
+ zend_string_release(op2_str);
+ break;
+ }
+ }
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ zend_string_release(op1_str);
+ }
+ if (IS_CONST != IS_CONST) {
+ zend_string_release(op2_str);
+ }
+ } while (0);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -41957,6 +42350,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
break;
}
}
+ 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();
}
@@ -41977,13 +42373,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -42030,7 +42429,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) {
+ } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -42057,18 +42457,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -42099,10 +42499,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CONST_HANDLER
} while (0);
SAVE_OPLINE();
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -42147,6 +42547,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_CONST_HA
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;
}
@@ -42318,12 +42721,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP
offset = EX_CONSTANT(opline->op2);
-isset_dim_obj_again:
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -42338,31 +42742,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if ((IS_CONST & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if (IS_CONST == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -42372,50 +42776,62 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED ||
+ ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if (IS_CONST & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
- }
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
+
zval_ptr_dtor_nogc(free_op1);
ZEND_VM_SMART_BRANCH(result, 1);
ZVAL_BOOL(EX_VAR(opline->result.var), result);
@@ -42442,7 +42858,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM
offset = EX_CONSTANT(opline->op2);
- if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST ||
+ ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -42457,10 +42874,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CONST == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
zval_ptr_dtor_nogc(free_op1);
@@ -42505,6 +42921,9 @@ try_instanceof:
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);
@@ -42518,11 +42937,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CONST_HANDLER(
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- pow_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- EX_CONSTANT(opline->op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = EX_CONSTANT(opline->op2);
+ pow_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -42547,6 +42967,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
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);
}
@@ -42748,6 +43171,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_VAR_HAND
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;
}
@@ -42934,6 +43360,9 @@ try_instanceof:
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);
@@ -42961,6 +43390,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL zend_fetch_var_address_helper_SPEC_
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);
}
@@ -43162,6 +43594,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_UNSET_VAR_SPEC_TMPVAR_UNUSED_H
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;
}
@@ -43452,11 +43887,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_CV_HANDLER(ZEN
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- fast_div_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ fast_div_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -43506,11 +43942,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVAR_CV_HANDLER(ZEND
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_left_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ shift_left_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -43521,11 +43958,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVAR_CV_HANDLER(ZEND
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_right_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ shift_right_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -43536,12 +43974,58 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_CV_HANDLER(
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- concat_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
- zval_ptr_dtor_nogc(free_op1);
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
+
+ do {
+ if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
+ (IS_CV == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
+ zend_string *op1_str = Z_STR_P(op1);
+ zend_string *op2_str = Z_STR_P(op2);
+ zend_string *str;
+
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
+ zval_ptr_dtor_nogc(free_op1);
+ break;
+ }
+ }
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
+ zval_ptr_dtor_nogc(free_op1);
+ break;
+ }
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV &&
+ !IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ size_t len = op1_str->len;
+
+ str = zend_string_realloc(op1_str, len + op2_str->len, 0);
+ memcpy(str->val + len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ break;
+ } else {
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ }
+ } else {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ concat_function(EX_VAR(opline->result.var), op1, op2);
+ }
+ zval_ptr_dtor_nogc(free_op1);
+ } while (0);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -43558,18 +44042,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CV_HANDLE
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -43601,10 +44085,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_CV_HANDLE
} while (0);
SAVE_OPLINE();
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -43627,18 +44111,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CV_HA
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -43670,10 +44154,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_CV_HA
} while (0);
SAVE_OPLINE();
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -43791,12 +44275,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_CV_HANDL
{
USE_OPLINE
zend_free_op free_op1;
- zval *result = EX_VAR(opline->result.var);
+ zval *op1, *op2;
SAVE_OPLINE();
- compare_function(result,
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ compare_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -43807,11 +44291,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVAR_CV_HANDLER(Z
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_or_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ bitwise_or_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -43822,11 +44307,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVAR_CV_HANDLER(
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_and_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ bitwise_and_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -43837,11 +44323,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVAR_CV_HANDLER(
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ bitwise_xor_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -43852,11 +44339,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_CV_HANDLE
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- boolean_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ boolean_xor_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -43912,7 +44400,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_CV_HA
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST ||
+ ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -43974,27 +44463,59 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_CV_HAN
SAVE_OPLINE();
op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
- op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
op1_str = Z_STR_P(op1);
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ op1_str = zend_string_copy(Z_STR_P(op1));
} else {
- op1_str = zval_get_string(op1);
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ op1_str = _zval_get_string_func(op1);
}
+ op2 = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
if (IS_CV == IS_CONST) {
op2_str = Z_STR_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ op2_str = zend_string_copy(Z_STR_P(op2));
} else {
- op2_str = zval_get_string(op2);
- }
- str = zend_string_alloc(op1_str->len + op2_str->len, 0);
- memcpy(str->val, op1_str->val, op1_str->len);
- memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
- ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- zend_string_release(op1_str);
- }
- if (IS_CV != IS_CONST) {
- zend_string_release(op2_str);
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ op2_str = _zval_get_string_func(op2);
}
+ do {
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ if (IS_CV == IS_CONST) {
+ zend_string_addref(op2_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op2_str);
+ zend_string_release(op1_str);
+ break;
+ }
+ }
+ if (IS_CV != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+ zend_string_addref(op1_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op1_str);
+ zend_string_release(op2_str);
+ break;
+ }
+ }
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ zend_string_release(op1_str);
+ }
+ if (IS_CV != IS_CONST) {
+ zend_string_release(op2_str);
+ }
+ } while (0);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -44015,7 +44536,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
SAVE_OPLINE();
- function_name = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
if (IS_CV != IS_CONST &&
UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
@@ -44026,6 +44547,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
break;
}
}
+ 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();
}
@@ -44046,13 +44570,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -44099,7 +44626,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) {
+ } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -44126,18 +44654,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZE
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -44168,10 +44696,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_CV_HANDLER(ZE
} while (0);
SAVE_OPLINE();
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -44200,14 +44728,15 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP
HANDLE_EXCEPTION();
}
- offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ offset = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
-isset_dim_obj_again:
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -44222,31 +44751,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if ((IS_CV & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if (IS_CV == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -44256,50 +44785,62 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED ||
+ ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if (IS_CV & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
- }
- }
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
+
zval_ptr_dtor_nogc(free_op1);
ZEND_VM_SMART_BRANCH(result, 1);
ZVAL_BOOL(EX_VAR(opline->result.var), result);
@@ -44326,7 +44867,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM
offset = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
- if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST ||
+ ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -44341,10 +44883,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, ((IS_CV == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
zval_ptr_dtor_nogc(free_op1);
@@ -44358,11 +44899,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_CV_HANDLER(ZEN
{
USE_OPLINE
zend_free_op free_op1;
+ zval *op1, *op2;
SAVE_OPLINE();
- pow_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_cv_BP_VAR_R(execute_data, opline->op2.var);
+ pow_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
CHECK_EXCEPTION();
@@ -44508,11 +45050,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_DIV_SPEC_TMPVAR_TMPVAR_HANDLER
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- fast_div_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ fast_div_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -44562,11 +45105,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SL_SPEC_TMPVAR_TMPVAR_HANDLER(
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_left_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ shift_left_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -44577,11 +45121,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SR_SPEC_TMPVAR_TMPVAR_HANDLER(
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- shift_right_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ shift_right_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -44592,12 +45137,58 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CONCAT_SPEC_TMPVAR_TMPVAR_HAND
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- concat_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
- zval_ptr_dtor_nogc(free_op1);
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+
+ do {
+ if (((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op1) == IS_STRING)) &&
+ ((IS_TMP_VAR|IS_VAR) == IS_CONST || EXPECTED(Z_TYPE_P(op2) == IS_STRING))) {
+ zend_string *op1_str = Z_STR_P(op1);
+ zend_string *op2_str = Z_STR_P(op2);
+ zend_string *str;
+
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op2_str);
+ zval_ptr_dtor_nogc(free_op1);
+ break;
+ }
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ ZVAL_STR_COPY(EX_VAR(opline->result.var), op1_str);
+ zval_ptr_dtor_nogc(free_op1);
+ break;
+ }
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST && (IS_TMP_VAR|IS_VAR) != IS_CV &&
+ !IS_INTERNED(op1_str) && GC_REFCOUNT(op1_str) == 1) {
+ size_t len = op1_str->len;
+
+ str = zend_string_realloc(op1_str, len + op2_str->len, 0);
+ memcpy(str->val + len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ break;
+ } else {
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ }
+ } else {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ concat_function(EX_VAR(opline->result.var), op1, op2);
+ }
+ zval_ptr_dtor_nogc(free_op1);
+ } while (0);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
ZEND_VM_NEXT_OPCODE();
@@ -44614,18 +45205,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HA
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -44657,10 +45248,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_EQUAL_SPEC_TMPVAR_TMPVAR_HA
} while (0);
SAVE_OPLINE();
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -44683,18 +45274,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) != Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) != Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) != Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) != ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -44726,10 +45317,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_IS_NOT_EQUAL_SPEC_TMPVAR_TMPVA
} while (0);
SAVE_OPLINE();
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -44847,12 +45438,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_SPACESHIP_SPEC_TMPVAR_TMPVAR_H
{
USE_OPLINE
zend_free_op free_op1, free_op2;
- zval *result = EX_VAR(opline->result.var);
+ zval *op1, *op2;
SAVE_OPLINE();
- compare_function(result,
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ compare_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -44863,11 +45454,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_OR_SPEC_TMPVAR_TMPVAR_HANDL
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_or_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ bitwise_or_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -44878,11 +45470,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_AND_SPEC_TMPVAR_TMPVAR_HAND
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_and_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ bitwise_and_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -44893,11 +45486,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BW_XOR_SPEC_TMPVAR_TMPVAR_HAND
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- bitwise_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ bitwise_xor_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -44908,11 +45502,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_BOOL_XOR_SPEC_TMPVAR_TMPVAR_HA
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- boolean_xor_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ boolean_xor_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -44968,7 +45563,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FETCH_OBJ_IS_SPEC_TMPVAR_TMPVA
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST ||
+ ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -45031,27 +45627,59 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_FAST_CONCAT_SPEC_TMPVAR_TMPVAR
SAVE_OPLINE();
op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
- op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
op1_str = Z_STR_P(op1);
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_STRING)) {
+ op1_str = zend_string_copy(Z_STR_P(op1));
} else {
- op1_str = zval_get_string(op1);
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(op1, BP_VAR_R);
+ }
+ op1_str = _zval_get_string_func(op1);
}
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
op2_str = Z_STR_P(op2);
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_STRING)) {
+ op2_str = zend_string_copy(Z_STR_P(op2));
} else {
- op2_str = zval_get_string(op2);
- }
- str = zend_string_alloc(op1_str->len + op2_str->len, 0);
- memcpy(str->val, op1_str->val, op1_str->len);
- memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
- ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- zend_string_release(op1_str);
- }
- if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
- zend_string_release(op2_str);
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(op2, BP_VAR_R);
+ }
+ op2_str = _zval_get_string_func(op2);
}
+ do {
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op1_str->len == 0)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+ zend_string_addref(op2_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op2_str);
+ zend_string_release(op1_str);
+ break;
+ }
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ if (UNEXPECTED(op2_str->len == 0)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST) {
+ zend_string_addref(op1_str);
+ }
+ ZVAL_STR(EX_VAR(opline->result.var), op1_str);
+ zend_string_release(op2_str);
+ break;
+ }
+ }
+ str = zend_string_alloc(op1_str->len + op2_str->len, 0);
+ memcpy(str->val, op1_str->val, op1_str->len);
+ memcpy(str->val + op1_str->len, op2_str->val, op2_str->len+1);
+ ZVAL_NEW_STR(EX_VAR(opline->result.var), str);
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ zend_string_release(op1_str);
+ }
+ if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
+ zend_string_release(op2_str);
+ }
+ } while (0);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -45083,6 +45711,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
break;
}
}
+ 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();
}
@@ -45103,13 +45734,16 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED) {
do {
- if (UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST || UNEXPECTED(Z_TYPE_P(object) != IS_OBJECT)) {
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(object))) {
object = Z_REFVAL_P(object);
if (EXPECTED(Z_TYPE_P(object) == IS_OBJECT)) {
break;
}
}
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
+ GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ }
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
}
@@ -45156,7 +45790,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
call_info = ZEND_CALL_NESTED_FUNCTION;
if (UNEXPECTED((fbc->common.fn_flags & ZEND_ACC_STATIC) != 0)) {
obj = NULL;
- } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR)) {
+ } else if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_TMP_VAR|IS_CV)) {
+ /* CV may be changed indirectly (e.g. when it's a reference) */
call_info = ZEND_CALL_NESTED_FUNCTION | ZEND_CALL_RELEASE_THIS;
GC_REFCOUNT(obj)++; /* For $this pointer */
}
@@ -45184,18 +45819,18 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLE
do {
int result;
- if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_LONG)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op1) == IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_LVAL_P(op1) == Z_LVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = ((double)Z_LVAL_P(op1) == Z_DVAL_P(op2));
} else {
break;
}
- } else if (EXPECTED(Z_TYPE_INFO_P(op1) == IS_DOUBLE)) {
- if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_DOUBLE)) {
+ } else if (EXPECTED(Z_TYPE_P(op1) == IS_DOUBLE)) {
+ if (EXPECTED(Z_TYPE_P(op2) == IS_DOUBLE)) {
result = (Z_DVAL_P(op1) == Z_DVAL_P(op2));
- } else if (EXPECTED(Z_TYPE_INFO_P(op2) == IS_LONG)) {
+ } else if (EXPECTED(Z_TYPE_P(op2) == IS_LONG)) {
result = (Z_DVAL_P(op1) == ((double)Z_LVAL_P(op2)));
} else {
break;
@@ -45226,10 +45861,10 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_CASE_SPEC_TMPVAR_TMPVAR_HANDLE
} while (0);
SAVE_OPLINE();
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op1) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op1) == IS_UNDEF)) {
op1 = GET_OP1_UNDEF_CV(op1, BP_VAR_R);
}
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_INFO_P(op2) == IS_UNDEF)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(op2) == IS_UNDEF)) {
op2 = GET_OP2_UNDEF_CV(op2, BP_VAR_R);
}
result = EX_VAR(opline->result.var);
@@ -45260,12 +45895,13 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_DIM_OBJ_SPEC_TMP
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
-isset_dim_obj_again:
if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
- HashTable *ht = Z_ARRVAL_P(container);
+ HashTable *ht;
zval *value;
zend_string *str;
+isset_dim_obj_array:
+ ht = Z_ARRVAL_P(container);
isset_again:
if (EXPECTED(Z_TYPE_P(offset) == IS_STRING)) {
str = Z_STR_P(offset);
@@ -45280,31 +45916,31 @@ str_index_prop:
hval = Z_LVAL_P(offset);
num_index_prop:
value = zend_hash_index_find(ht, hval);
- } else {
- switch (Z_TYPE_P(offset)) {
- case IS_DOUBLE:
- hval = zend_dval_to_lval(Z_DVAL_P(offset));
- goto num_index_prop;
- case IS_NULL:
- str = STR_EMPTY_ALLOC();
- goto str_index_prop;
- case IS_FALSE:
- hval = 0;
- goto num_index_prop;
- case IS_TRUE:
- hval = 1;
- goto num_index_prop;
- case IS_RESOURCE:
- hval = Z_RES_HANDLE_P(offset);
- goto num_index_prop;
- case IS_REFERENCE:
- offset = Z_REFVAL_P(offset);
- goto isset_again;
- default:
- zend_error(E_WARNING, "Illegal offset type in isset or empty");
- value = NULL;
- break;
- }
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && EXPECTED(Z_ISREF_P(offset))) {
+ offset = Z_REFVAL_P(offset);
+ goto isset_again;
+ } else if (Z_TYPE_P(offset) == IS_DOUBLE) {
+ hval = zend_dval_to_lval(Z_DVAL_P(offset));
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_NULL) {
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_FALSE) {
+ hval = 0;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_TRUE) {
+ hval = 1;
+ goto num_index_prop;
+ } else if (Z_TYPE_P(offset) == IS_RESOURCE) {
+ hval = Z_RES_HANDLE_P(offset);
+ goto num_index_prop;
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && Z_TYPE_P(offset) == IS_UNDEF) {
+ GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ str = STR_EMPTY_ALLOC();
+ goto str_index_prop;
+ } else {
+ zend_error(E_WARNING, "Illegal offset type in isset or empty");
+ goto isset_not_found;
}
if (opline->extended_value & ZEND_ISSET) {
@@ -45314,50 +45950,61 @@ num_index_prop:
} else /* if (opline->extended_value & ZEND_ISEMPTY) */ {
result = (value == NULL || !i_zend_is_true(value));
}
- } else if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED || EXPECTED(Z_TYPE_P(container) == IS_OBJECT)) {
+ goto isset_dim_obj_exit;
+ } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
+ container = Z_REFVAL_P(container);
+ if (EXPECTED(Z_TYPE_P(container) == IS_ARRAY)) {
+ goto isset_dim_obj_array;
+ }
+ }
+
+ if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(offset) == IS_UNDEF)) {
+ offset = GET_OP2_UNDEF_CV(offset, BP_VAR_R);
+ }
+
+ if ((IS_TMP_VAR|IS_VAR) == IS_UNUSED ||
+ ((IS_TMP_VAR|IS_VAR) != IS_CONST && EXPECTED(Z_TYPE_P(container) == IS_OBJECT))) {
if (EXPECTED(Z_OBJ_HT_P(container)->has_dimension)) {
- result = Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_dimension(container, offset, (opline->extended_value & ZEND_ISSET) == 0);
} else {
zend_error(E_NOTICE, "Trying to check element of non-array");
- result = 0;
- }
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
+ goto isset_not_found;
}
} else if (EXPECTED(Z_TYPE_P(container) == IS_STRING)) { /* string offsets */
- zval tmp;
+ zend_long lval;
- result = 0;
- if (UNEXPECTED(Z_TYPE_P(offset) != IS_LONG)) {
+ if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
+ lval = Z_LVAL_P(offset);
+isset_str_offset:
+ if (EXPECTED(lval >= 0) && (size_t)lval < Z_STRLEN_P(container)) {
+ if (opline->extended_value & ZEND_ISSET) {
+ result = 1;
+ } else {
+ result = (Z_STRVAL_P(container)[lval] == '0');
+ }
+ } else {
+ goto isset_not_found;
+ }
+ } else {
if ((IS_TMP_VAR|IS_VAR) & (IS_CV|IS_VAR)) {
ZVAL_DEREF(offset);
}
if (Z_TYPE_P(offset) < IS_STRING /* simple scalar types */
|| (Z_TYPE_P(offset) == IS_STRING /* or numeric string */
&& IS_LONG == is_numeric_string(Z_STRVAL_P(offset), Z_STRLEN_P(offset), NULL, NULL, 0))) {
- ZVAL_DUP(&tmp, offset);
- convert_to_long(&tmp);
- offset = &tmp;
- }
- }
- if (EXPECTED(Z_TYPE_P(offset) == IS_LONG)) {
- if (offset->value.lval >= 0 && (size_t)offset->value.lval < Z_STRLEN_P(container)) {
- if ((opline->extended_value & ZEND_ISSET) ||
- Z_STRVAL_P(container)[offset->value.lval] != '0') {
- result = 1;
- }
+ lval = zval_get_long(offset);
+ goto isset_str_offset;
}
+ goto isset_not_found;
}
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
- } else if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
- container = Z_REFVAL_P(container);
- goto isset_dim_obj_again;
} else {
+isset_not_found:
result = ((opline->extended_value & ZEND_ISSET) == 0);
}
+isset_dim_obj_exit:
zval_ptr_dtor_nogc(free_op2);
zval_ptr_dtor_nogc(free_op1);
ZEND_VM_SMART_BRANCH(result, 1);
@@ -45385,7 +46032,8 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM
offset = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
- if ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
+ if ((IS_TMP_VAR|IS_VAR) == IS_CONST ||
+ ((IS_TMP_VAR|IS_VAR) != IS_UNUSED && UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT))) {
if (((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV)) && Z_ISREF_P(container)) {
container = Z_REFVAL_P(container);
if (UNEXPECTED(Z_TYPE_P(container) != IS_OBJECT)) {
@@ -45400,10 +46048,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_ISSET_ISEMPTY_PROP_OBJ_SPEC_TM
isset_no_object:
result = ((opline->extended_value & ZEND_ISSET) == 0);
} else {
- result = Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
- if ((opline->extended_value & ZEND_ISSET) == 0) {
- result = !result;
- }
+ result =
+ ((opline->extended_value & ZEND_ISSET) == 0) ^
+ Z_OBJ_HT_P(container)->has_property(container, offset, (opline->extended_value & ZEND_ISSET) == 0, (((IS_TMP_VAR|IS_VAR) == IS_CONST) ? CACHE_ADDR(Z_CACHE_SLOT_P(offset)) : NULL));
}
zval_ptr_dtor_nogc(free_op2);
@@ -45418,11 +46065,12 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_POW_SPEC_TMPVAR_TMPVAR_HANDLER
{
USE_OPLINE
zend_free_op free_op1, free_op2;
+ zval *op1, *op2;
SAVE_OPLINE();
- pow_function(EX_VAR(opline->result.var),
- _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1),
- _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2));
+ op1 = _get_zval_ptr_var(opline->op1.var, execute_data, &free_op1);
+ op2 = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
+ pow_function(EX_VAR(opline->result.var), op1, op2);
zval_ptr_dtor_nogc(free_op1);
zval_ptr_dtor_nogc(free_op2);
CHECK_EXCEPTION();
@@ -46689,52 +47337,52 @@ void zend_init_opcodes_handlers(void)
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_BRK_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CONST_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
- ZEND_CONT_SPEC_CONST_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
+ ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
ZEND_NULL_HANDLER,
diff --git a/Zend/zend_vm_gen.php b/Zend/zend_vm_gen.php
index 7d49bea509..0b8caadc74 100644
--- a/Zend/zend_vm_gen.php
+++ b/Zend/zend_vm_gen.php
@@ -259,6 +259,26 @@ $op2_get_obj_zval_ptr = array(
"TMPVAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2)",
);
+$op1_get_obj_zval_ptr_undef = array(
+ "ANY" => "get_obj_zval_ptr_undef(opline->op1_type, opline->op1, execute_data, &free_op1, \\1)",
+ "TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1)",
+ "VAR" => "_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1)",
+ "CONST" => "EX_CONSTANT(opline->op1)",
+ "UNUSED" => "_get_obj_zval_ptr_unused(execute_data)",
+ "CV" => "_get_zval_ptr_cv_undef(execute_data, opline->op1.var)",
+ "TMPVAR" => "_get_zval_ptr_var(opline->op1.var, execute_data, &free_op1)",
+);
+
+$op2_get_obj_zval_ptr_undef = array(
+ "ANY" => "get_obj_zval_ptr_undef(opline->op2_type, opline->op2, execute_data, &free_op2, \\1)",
+ "TMP" => "_get_zval_ptr_tmp(opline->op2.var, execute_data, &free_op2)",
+ "VAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2)",
+ "CONST" => "EX_CONSTANT(opline->op2)",
+ "UNUSED" => "_get_obj_zval_ptr_unused(execute_data)",
+ "CV" => "_get_zval_ptr_cv_undef(execute_data, opline->op2.var)",
+ "TMPVAR" => "_get_zval_ptr_var(opline->op2.var, execute_data, &free_op2)",
+);
+
$op1_get_obj_zval_ptr_deref = array(
"ANY" => "get_obj_zval_ptr(opline->op1_type, opline->op1, execute_data, &free_op1, \\1)",
"TMP" => "_get_zval_ptr_tmp(opline->op1.var, execute_data, &free_op1)",
@@ -449,6 +469,7 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
$op1_get_zval_ptr_ptr, $op2_get_zval_ptr_ptr,
$op1_get_zval_ptr_ptr_undef, $op2_get_zval_ptr_ptr_undef,
$op1_get_obj_zval_ptr, $op2_get_obj_zval_ptr,
+ $op1_get_obj_zval_ptr_undef, $op2_get_obj_zval_ptr_undef,
$op1_get_obj_zval_ptr_deref, $op2_get_obj_zval_ptr_deref,
$op1_get_obj_zval_ptr_ptr, $op2_get_obj_zval_ptr_ptr,
$op1_get_obj_zval_ptr_ptr_undef, $op2_get_obj_zval_ptr_ptr_undef,
@@ -475,6 +496,8 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
"/GET_OP2_ZVAL_PTR_PTR_UNDEF\(([^)]*)\)/",
"/GET_OP1_OBJ_ZVAL_PTR\(([^)]*)\)/",
"/GET_OP2_OBJ_ZVAL_PTR\(([^)]*)\)/",
+ "/GET_OP1_OBJ_ZVAL_PTR_UNDEF\(([^)]*)\)/",
+ "/GET_OP2_OBJ_ZVAL_PTR_UNDEF\(([^)]*)\)/",
"/GET_OP1_OBJ_ZVAL_PTR_DEREF\(([^)]*)\)/",
"/GET_OP2_OBJ_ZVAL_PTR_DEREF\(([^)]*)\)/",
"/GET_OP1_OBJ_ZVAL_PTR_PTR\(([^)]*)\)/",
@@ -517,6 +540,8 @@ function gen_code($f, $spec, $kind, $export, $code, $op1, $op2, $name) {
$op2_get_zval_ptr_ptr_undef[$op2],
$op1_get_obj_zval_ptr[$op1],
$op2_get_obj_zval_ptr[$op2],
+ $op1_get_obj_zval_ptr_undef[$op1],
+ $op2_get_obj_zval_ptr_undef[$op2],
$op1_get_obj_zval_ptr_deref[$op1],
$op2_get_obj_zval_ptr_deref[$op2],
$op1_get_obj_zval_ptr_ptr[$op1],
diff --git a/Zend/zend_vm_opcodes.c b/Zend/zend_vm_opcodes.c
index 95b8b859eb..705ab9cd29 100644
--- a/Zend/zend_vm_opcodes.c
+++ b/Zend/zend_vm_opcodes.c
@@ -72,8 +72,8 @@ const char *zend_vm_opcodes_map[173] = {
"ZEND_JMPNZ_EX",
"ZEND_CASE",
NULL,
- "ZEND_BRK",
- "ZEND_CONT",
+ NULL,
+ NULL,
"ZEND_BOOL",
"ZEND_FAST_CONCAT",
"ZEND_ROPE_INIT",
diff --git a/Zend/zend_vm_opcodes.h b/Zend/zend_vm_opcodes.h
index 89a0d3139b..f6de5b1b57 100644
--- a/Zend/zend_vm_opcodes.h
+++ b/Zend/zend_vm_opcodes.h
@@ -82,8 +82,6 @@ END_EXTERN_C()
#define ZEND_JMPZ_EX 46
#define ZEND_JMPNZ_EX 47
#define ZEND_CASE 48
-#define ZEND_BRK 50
-#define ZEND_CONT 51
#define ZEND_BOOL 52
#define ZEND_FAST_CONCAT 53
#define ZEND_ROPE_INIT 54
diff --git a/configure.in b/configure.in
index ffc714ff5f..b70f024252 100644
--- a/configure.in
+++ b/configure.in
@@ -1300,6 +1300,7 @@ PHP_SUBST_OLD(PHP_INSTALLED_SAPIS)
PHP_SUBST(PHP_EXECUTABLE)
+PHP_SUBST(PHP_FASTCGI_OBJS)
PHP_SUBST(PHP_SAPI_OBJS)
PHP_SUBST(PHP_BINARY_OBJS)
PHP_SUBST(PHP_GLOBAL_OBJS)
@@ -1435,10 +1436,10 @@ CC=$old_CC
PHP_CONFIGURE_PART(Generating files)
CXXFLAGS_CLEAN=$CXXFLAGS
-CFLAGS_CLEAN=$CFLAGS
+CFLAGS_CLEAN="$CFLAGS \$(PROF_FLAGS)"
CFLAGS="\$(CFLAGS_CLEAN) $standard_libtool_flag"
INLINE_CFLAGS="$INLINE_CFLAGS $standard_libtool_flag"
-CXXFLAGS="$CXXFLAGS $standard_libtool_flag"
+CXXFLAGS="$CXXFLAGS $standard_libtool_flag \$(PROF_FLAGS)"
if test "$PHP_PHAR" != "no" && test "$PHP_CLI" != "no"; then
pharcmd=pharcmd
@@ -1466,6 +1467,8 @@ PHP_ADD_SOURCES(main, main.c snprintf.c spprintf.c php_sprintf.c \
network.c php_open_temporary_file.c \
output.c getopt.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
+PHP_ADD_SOURCES_X(main, fastcgi.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, PHP_FASTCGI_OBJS, no)
+
PHP_ADD_SOURCES(main/streams, streams.c cast.c memory.c filter.c \
plain_wrapper.c userspace.c transports.c xp_socket.c mmap.c \
glob_wrapper.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1)
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index e0b9176200..cae8c46519 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -2562,9 +2562,9 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{
* use since curl needs a long not an int. */
form_error = curl_formadd(&first, &last,
CURLFORM_COPYNAME, string_key->val,
- CURLFORM_NAMELENGTH, (zend_long)string_key->len,
+ CURLFORM_NAMELENGTH, string_key->len,
CURLFORM_COPYCONTENTS, postval->val,
- CURLFORM_CONTENTSLENGTH, (zend_long)Z_STRLEN_P(current),
+ CURLFORM_CONTENTSLENGTH, postval->len,
CURLFORM_END);
if (form_error != CURL_FORMADD_OK) {
@@ -3008,7 +3008,7 @@ PHP_FUNCTION(curl_getinfo)
}
#endif
if (ch->header.str) {
- CAASTR("request_header", ch->header.str);
+ CAASTR("request_header", zend_string_copy(ch->header.str));
}
} else {
switch (option) {
diff --git a/ext/date/lib/timelib_structs.h b/ext/date/lib/timelib_structs.h
index d68fbc1f28..33e9fce88c 100644
--- a/ext/date/lib/timelib_structs.h
+++ b/ext/date/lib/timelib_structs.h
@@ -121,7 +121,7 @@ typedef unsigned __int64 uint64_t;
#include <strings.h>
#endif
-#if defined(__X86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)
+#if defined(__x86_64__) || defined(__LP64__) || defined(_LP64) || defined(_WIN64)
typedef int64_t timelib_long;
typedef uint64_t timelib_ulong;
# define TIMELIB_LONG_MAX INT64_MAX
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index 4ca8d19e24..be48b13a8c 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -163,7 +163,7 @@ ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_date_create_from_format, 0, 0, 2)
ZEND_ARG_INFO(0, format)
ZEND_ARG_INFO(0, time)
- ZEND_ARG_OBJ_INFO(0, object, DateTimeZone, 1)
+ ZEND_ARG_INFO(0, object)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_date_parse, 0, 0, 1)
@@ -889,6 +889,10 @@ PHP_MSHUTDOWN_FUNCTION(date)
timelib_error_container_dtor(DATEG(last_errors));
}
+#ifndef ZTS
+ DATEG(default_timezone) = NULL;
+#endif
+
return SUCCESS;
}
/* }}} */
@@ -2569,18 +2573,16 @@ PHP_FUNCTION(date_create)
zval *timezone_object = NULL;
char *time_str = NULL;
size_t time_str_len = 0;
- zval datetime_object;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sO!", &time_str, &time_str_len, &timezone_object, date_ce_timezone) == FAILURE) {
RETURN_FALSE;
}
- php_date_instantiate(date_ce_date, &datetime_object);
- if (!php_date_initialize(Z_PHPDATE_P(&datetime_object), time_str, time_str_len, NULL, timezone_object, 0)) {
- zval_dtor(&datetime_object);
+ php_date_instantiate(date_ce_date, return_value);
+ if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, NULL, timezone_object, 0)) {
+ zval_ptr_dtor(return_value);
RETURN_FALSE;
}
- RETVAL_ZVAL(&datetime_object, 0, 0);
}
/* }}} */
@@ -2592,18 +2594,16 @@ PHP_FUNCTION(date_create_immutable)
zval *timezone_object = NULL;
char *time_str = NULL;
size_t time_str_len = 0;
- zval datetime_object;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "|sO!", &time_str, &time_str_len, &timezone_object, date_ce_timezone) == FAILURE) {
RETURN_FALSE;
}
- php_date_instantiate(date_ce_immutable, &datetime_object);
- if (!php_date_initialize(Z_PHPDATE_P(&datetime_object), time_str, time_str_len, NULL, timezone_object, 0)) {
- zval_dtor(&datetime_object);
+ php_date_instantiate(date_ce_immutable, return_value);
+ if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, NULL, timezone_object, 0)) {
+ zval_ptr_dtor(return_value);
RETURN_FALSE;
}
- RETVAL_ZVAL(&datetime_object, 0, 0);
}
/* }}} */
@@ -2615,18 +2615,16 @@ PHP_FUNCTION(date_create_from_format)
zval *timezone_object = NULL;
char *time_str = NULL, *format_str = NULL;
size_t time_str_len = 0, format_str_len = 0;
- zval datetime_object;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|O!", &format_str, &format_str_len, &time_str, &time_str_len, &timezone_object, date_ce_timezone) == FAILURE) {
RETURN_FALSE;
}
- php_date_instantiate(date_ce_date, &datetime_object);
- if (!php_date_initialize(Z_PHPDATE_P(&datetime_object), time_str, time_str_len, format_str, timezone_object, 0)) {
- zval_dtor(&datetime_object);
+ php_date_instantiate(date_ce_date, return_value);
+ if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, 0)) {
+ zval_ptr_dtor(return_value);
RETURN_FALSE;
}
- RETVAL_ZVAL(&datetime_object, 0, 0);
}
/* }}} */
@@ -2638,18 +2636,16 @@ PHP_FUNCTION(date_create_immutable_from_format)
zval *timezone_object = NULL;
char *time_str = NULL, *format_str = NULL;
size_t time_str_len = 0, format_str_len = 0;
- zval datetime_object;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss|O!", &format_str, &format_str_len, &time_str, &time_str_len, &timezone_object, date_ce_timezone) == FAILURE) {
RETURN_FALSE;
}
- php_date_instantiate(date_ce_immutable, &datetime_object);
- if (!php_date_initialize(Z_PHPDATE_P(&datetime_object), time_str, time_str_len, format_str, timezone_object, 0)) {
- zval_dtor(&datetime_object);
+ php_date_instantiate(date_ce_immutable, return_value);
+ if (!php_date_initialize(Z_PHPDATE_P(return_value), time_str, time_str_len, format_str, timezone_object, 0)) {
+ zval_ptr_dtor(return_value);
RETURN_FALSE;
}
- RETVAL_ZVAL(&datetime_object, 0, 0);
}
/* }}} */
@@ -3075,11 +3071,12 @@ PHP_FUNCTION(date_modify)
RETURN_FALSE;
}
- if (php_date_modify(object, modify, modify_len)) {
- RETURN_ZVAL(object, 1, 0);
+ if (!php_date_modify(object, modify, modify_len)) {
+ RETURN_FALSE;
}
- RETURN_FALSE;
+ Z_ADDREF_P(object);
+ ZVAL_COPY_VALUE(return_value, object);
}
/* }}} */
@@ -3096,11 +3093,11 @@ PHP_METHOD(DateTimeImmutable, modify)
}
date_clone_immutable(object, &new_object);
- if (php_date_modify(&new_object, modify, modify_len)) {
- RETURN_ZVAL(&new_object, 0, 1);
+ if (!php_date_modify(&new_object, modify, modify_len)) {
+ RETURN_FALSE;
}
- RETURN_FALSE;
+ ZVAL_COPY_VALUE(return_value, &new_object);
}
/* }}} */
@@ -3133,7 +3130,8 @@ PHP_FUNCTION(date_add)
php_date_add(object, interval, return_value);
- RETURN_ZVAL(object, 1, 0);
+ Z_ADDREF_P(object);
+ ZVAL_COPY_VALUE(return_value, object);
}
/* }}} */
@@ -3150,7 +3148,7 @@ PHP_METHOD(DateTimeImmutable, add)
date_clone_immutable(object, &new_object);
php_date_add(&new_object, interval, return_value);
- RETURN_ZVAL(&new_object, 0, 1);
+ ZVAL_COPY_VALUE(return_value, &new_object);
}
/* }}} */
@@ -3188,7 +3186,8 @@ PHP_FUNCTION(date_sub)
php_date_sub(object, interval, return_value);
- RETURN_ZVAL(object, 1, 0);
+ Z_ADDREF_P(object);
+ ZVAL_COPY_VALUE(return_value, object);
}
/* }}} */
@@ -3205,7 +3204,7 @@ PHP_METHOD(DateTimeImmutable, sub)
date_clone_immutable(object, &new_object);
php_date_sub(&new_object, interval, return_value);
- RETURN_ZVAL(&new_object, 0, 1);
+ ZVAL_COPY_VALUE(return_value, &new_object);
}
/* }}} */
@@ -3290,7 +3289,8 @@ PHP_FUNCTION(date_timezone_set)
php_date_timezone_set(object, timezone_object, return_value);
- RETURN_ZVAL(object, 1, 0);
+ Z_ADDREF_P(object);
+ ZVAL_COPY_VALUE(return_value, object);
}
/* }}} */
@@ -3308,7 +3308,7 @@ PHP_METHOD(DateTimeImmutable, setTimezone)
date_clone_immutable(object, &new_object);
php_date_timezone_set(&new_object, timezone_object, return_value);
- RETURN_ZVAL(&new_object, 0, 1);
+ ZVAL_COPY_VALUE(return_value, &new_object);
}
/* }}} */
@@ -3373,7 +3373,8 @@ PHP_FUNCTION(date_time_set)
php_date_time_set(object, h, i, s, return_value);
- RETURN_ZVAL(object, 1, 0);
+ Z_ADDREF_P(object);
+ ZVAL_COPY_VALUE(return_value, object);
}
/* }}} */
@@ -3391,7 +3392,7 @@ PHP_METHOD(DateTimeImmutable, setTime)
date_clone_immutable(object, &new_object);
php_date_time_set(&new_object, h, i, s, return_value);
- RETURN_ZVAL(&new_object, 0, 1);
+ ZVAL_COPY_VALUE(return_value, &new_object);
}
/* }}} */
@@ -3421,7 +3422,8 @@ PHP_FUNCTION(date_date_set)
php_date_date_set(object, y, m, d, return_value);
- RETURN_ZVAL(object, 1, 0);
+ Z_ADDREF_P(object);
+ ZVAL_COPY_VALUE(return_value, object);
}
/* }}} */
@@ -3439,7 +3441,7 @@ PHP_METHOD(DateTimeImmutable, setDate)
date_clone_immutable(object, &new_object);
php_date_date_set(&new_object, y, m, d, return_value);
- RETURN_ZVAL(&new_object, 0, 1);
+ ZVAL_COPY_VALUE(return_value, &new_object);
}
/* }}} */
@@ -3473,7 +3475,8 @@ PHP_FUNCTION(date_isodate_set)
php_date_isodate_set(object, y, w, d, return_value);
- RETURN_ZVAL(object, 1, 0);
+ Z_ADDREF_P(object);
+ ZVAL_COPY_VALUE(return_value, object);
}
/* }}} */
@@ -3491,7 +3494,7 @@ PHP_METHOD(DateTimeImmutable, setISODate)
date_clone_immutable(object, &new_object);
php_date_isodate_set(&new_object, y, w, d, return_value);
- RETURN_ZVAL(&new_object, 0, 1);
+ ZVAL_COPY_VALUE(return_value, &new_object);
}
/* }}} */
@@ -3519,7 +3522,8 @@ PHP_FUNCTION(date_timestamp_set)
php_date_timestamp_set(object, timestamp, return_value);
- RETURN_ZVAL(object, 1, 0);
+ Z_ADDREF_P(object);
+ ZVAL_COPY_VALUE(return_value, object);
}
/* }}} */
@@ -3537,7 +3541,7 @@ PHP_METHOD(DateTimeImmutable, setTimestamp)
date_clone_immutable(object, &new_object);
php_date_timestamp_set(&new_object, timestamp, return_value);
- RETURN_ZVAL(&new_object, 0, 1);
+ ZVAL_COPY_VALUE(return_value, &new_object);
}
/* }}} */
diff --git a/ext/date/tests/009_win32.phpt b/ext/date/tests/009_win32.phpt
index cbdc8b7c0a..3ad04f5849 100644
--- a/ext/date/tests/009_win32.phpt
+++ b/ext/date/tests/009_win32.phpt
@@ -4,11 +4,15 @@ strftime() and gmstrftime() tests
<?php
if (substr(PHP_OS, 0, 3) != 'WIN') die('skip only windows test.');
if (!function_exists('strftime')) die("skip, strftime not available");
+if (false === setlocale(LC_TIME, "en-us")) die("skip, couldn't set the locale to en-us");
?>
--FILE--
<?php
date_default_timezone_set('Asia/Jerusalem');
+$loc = setlocale(LC_TIME, "0");
+setlocale(LC_TIME, "en-us");
+
$t = mktime(0,0,0, 6, 27, 2006);
var_dump(strftime());
@@ -32,19 +36,21 @@ var_dump(gmstrftime("%%q %%a", $t));
var_dump(gmstrftime("blah", $t));
echo "Done\n";
+
+setlocale(LC_TIME, $loc);
?>
--EXPECTF--
Warning: strftime() expects at least 1 parameter, 0 given in %s on line %d
bool(false)
bool(false)
-string(%d) "Tue Tuesday Jun June 06/27/06 00:00:00 27 00 12 178 06 00 AM 00 26 26 2 06/27/06 00:00:00 06 2006 %s"
+string(%d) "Tue Tuesday Jun June 6/27/2006 12:00:00 AM 27 00 12 178 06 00 AM 00 26 26 2 6/27/2006 12:00:00 AM 06 2006 %s"
string(5) "%q %a"
string(4) "blah"
Warning: gmstrftime() expects at least 1 parameter, 0 given in %s on line %d
bool(false)
bool(false)
-string(%d) "Mon Monday Jun June 06/26/06 21:00:00 26 21 09 177 06 00 PM 00 26 26 1 06/26/06 21:00:00 06 2006 %s"
+string(%d) "Mon Monday Jun June 6/26/2006 9:00:00 PM 26 21 09 177 06 00 PM 00 26 26 1 6/26/2006 9:00:00 PM 06 2006 %s"
string(5) "%q %a"
string(4) "blah"
Done
diff --git a/ext/date/tests/bug55407.phpt b/ext/date/tests/bug55407.phpt
index 00c3356461..925640554a 100644
--- a/ext/date/tests/bug55407.phpt
+++ b/ext/date/tests/bug55407.phpt
@@ -2,6 +2,8 @@
Bug #55407 (Impossible to prototype DateTime::createFromFormat)
--INI--
error_reporting=-1
+--XFAIL--
+Bug #55407
--FILE--
<?php namespace melt\core;
diff --git a/ext/date/tests/gmstrftime_variation11.phpt b/ext/date/tests/gmstrftime_variation11.phpt
index 482ff6d2d7..f90e51ec16 100644
--- a/ext/date/tests/gmstrftime_variation11.phpt
+++ b/ext/date/tests/gmstrftime_variation11.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test gmstrftime() function : usage variation - Checking month related formats which are not supported on Windows.
+Test gmstrftime() function : usage variation - Checking month related formats which was not supported on Windows before VC14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -32,6 +32,6 @@ var_dump( gmstrftime($format, $timestamp) );
*** Testing gmstrftime() : usage variation ***
-- Testing gmstrftime() function with Abbreviated month name format %h --
-bool(false)
-bool(false)
+string(%d) "%s"
+string(3) "Aug"
===DONE===
diff --git a/ext/date/tests/gmstrftime_variation13.phpt b/ext/date/tests/gmstrftime_variation13.phpt
index 42f33f01ea..cccfa89d42 100644
--- a/ext/date/tests/gmstrftime_variation13.phpt
+++ b/ext/date/tests/gmstrftime_variation13.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test gmstrftime() function : usage variation - Checking date related formats which are not supported on Windows.
+Test gmstrftime() function : usage variation - Checking date related formats which was not supported on Windows before VC14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -18,7 +18,7 @@ echo "*** Testing gmstrftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
$timestamp = gmmktime(8, 8, 8, 8, 8, 2008);
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
//array of values to iterate over
@@ -43,18 +43,18 @@ foreach($inputs as $key =>$value) {
*** Testing gmstrftime() : usage variation ***
--Century number--
-bool(false)
-bool(false)
+string(2) "%d"
+string(2) "20"
--Month Date Year--
-bool(false)
-bool(false)
+string(%d) "%d/%d/%d"
+string(8) "08/08/08"
--Year with century--
-bool(false)
-bool(false)
+string(%d) "%d"
+string(4) "2008"
--Year without century--
-bool(false)
-bool(false)
+string(2) "%d"
+string(2) "08"
===DONE===
diff --git a/ext/date/tests/gmstrftime_variation15.phpt b/ext/date/tests/gmstrftime_variation15.phpt
index c0df364789..0a32b43322 100644
--- a/ext/date/tests/gmstrftime_variation15.phpt
+++ b/ext/date/tests/gmstrftime_variation15.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test gmstrftime() function : usage variation - Checking time related formats which are not supported on Windows.
+Test gmstrftime() function : usage variation - Checking time related formats which was not supported on Windows before VC14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -18,7 +18,7 @@ echo "*** Testing gmstrftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
$timestamp = gmmktime(8, 8, 8, 8, 8, 2008);
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
//array of values to iterate over
@@ -42,14 +42,14 @@ foreach($inputs as $key =>$value) {
*** Testing gmstrftime() : usage variation ***
--Time in a.m/p.m notation--
-bool(false)
-bool(false)
+string(%d) "%d:%d:%d %c%c"
+string(11) "08:08:08 AM"
--Time in 24 hour notation--
-bool(false)
-bool(false)
+string(%d) "%d:%d"
+string(5) "08:08"
--Current time %H:%M:%S format--
-bool(false)
-bool(false)
+string(%d) "%d:%d:%d"
+string(8) "08:08:08"
===DONE===
diff --git a/ext/date/tests/gmstrftime_variation17.phpt b/ext/date/tests/gmstrftime_variation17.phpt
index e3070a5144..5fa308f645 100644
--- a/ext/date/tests/gmstrftime_variation17.phpt
+++ b/ext/date/tests/gmstrftime_variation17.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test gmstrftime() function : usage variation - Checking day related formats which are not supported on Windows.
+Test gmstrftime() function : usage variation - Checking day related formats which was not supported on Windows before vc14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -18,7 +18,7 @@ echo "*** Testing gmstrftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
$timestamp = gmmktime(8, 8, 8, 8, 8, 2008);
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
echo "\n-- Testing gmstrftime() function with Day of the month as decimal single digit format --\n";
@@ -32,6 +32,6 @@ var_dump( gmstrftime($format, $timestamp) );
*** Testing gmstrftime() : usage variation ***
-- Testing gmstrftime() function with Day of the month as decimal single digit format --
-bool(false)
-bool(false)
+string(2) "%A%d"
+string(2) " 8"
===DONE===
diff --git a/ext/date/tests/gmstrftime_variation19.phpt b/ext/date/tests/gmstrftime_variation19.phpt
index 3131e01ca1..9ba714750e 100644
--- a/ext/date/tests/gmstrftime_variation19.phpt
+++ b/ext/date/tests/gmstrftime_variation19.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test gmstrftime() function : usage variation - Checking newline and tab formats which are not supported on Windows.
+Test gmstrftime() function : usage variation - Checking newline and tab formats which was not supported on Windows before VC14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -18,7 +18,7 @@ echo "*** Testing gmstrftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
$timestamp = gmmktime(8, 8, 8, 8, 8, 2008);
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
//array of values to iterate over
@@ -41,10 +41,12 @@ foreach($inputs as $key =>$value) {
*** Testing gmstrftime() : usage variation ***
--Newline character--
-bool(false)
-bool(false)
+string(1) "
+"
+string(1) "
+"
--Tab character--
-bool(false)
-bool(false)
+string(1) " "
+string(1) " "
===DONE===
diff --git a/ext/date/tests/gmstrftime_variation21.phpt b/ext/date/tests/gmstrftime_variation21.phpt
index 26ed157c3f..08ca2fc606 100644
--- a/ext/date/tests/gmstrftime_variation21.phpt
+++ b/ext/date/tests/gmstrftime_variation21.phpt
@@ -18,7 +18,7 @@ echo "*** Testing gmstrftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
$timestamp = gmmktime(8, 8, 8, 8, 8, 2008);
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
//array of values to iterate over
@@ -42,8 +42,8 @@ foreach($inputs as $key =>$value) {
*** Testing gmstrftime() : usage variation ***
--Preferred date and time representation--
-string(%d) "%d/%d/%d %d:%d:%d"
-string(17) "08/08/08 08:08:08"
+string(%d) "%s %s %d %d:%d:%d %d"
+string(24) "Fri Aug 8 08:08:08 2008"
--Preferred date representation--
string(%d) "%d/%d/%d"
diff --git a/ext/date/tests/gmstrftime_variation9.phpt b/ext/date/tests/gmstrftime_variation9.phpt
index 95b6c904f9..6ba33ac394 100644
--- a/ext/date/tests/gmstrftime_variation9.phpt
+++ b/ext/date/tests/gmstrftime_variation9.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test gmstrftime() function : usage variation - Checking week related formats which are not supported on Windows.
+Test gmstrftime() function : usage variation - Checking week related formats which was not supported on Windows before vc14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -18,7 +18,7 @@ echo "*** Testing gmstrftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
$timestamp = gmmktime(8, 8, 8, 8, 8, 2008);
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
//array of values to iterate over
@@ -41,10 +41,10 @@ foreach($inputs as $key =>$value) {
*** Testing gmstrftime() : usage variation ***
--The ISO 8601:1988 week number--
-bool(false)
-bool(false)
+string(%d) "%d"
+string(2) "32"
--Weekday as decimal--
-bool(false)
-bool(false)
+string(1) "%d"
+string(1) "5"
===DONE===
diff --git a/ext/date/tests/strftime_variation11.phpt b/ext/date/tests/strftime_variation11.phpt
index a063f0ad20..08d5634daa 100644
--- a/ext/date/tests/strftime_variation11.phpt
+++ b/ext/date/tests/strftime_variation11.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test strftime() function : usage variation - Checking month related formats which are not supported on Windows.
+Test strftime() function : usage variation - Checking month related formats which was not supported on Windows before VC14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -17,7 +17,7 @@ if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
echo "*** Testing strftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
$timestamp = mktime(8, 8, 8, 8, 8, 2008);
@@ -32,6 +32,6 @@ var_dump( strftime($format, $timestamp) );
*** Testing strftime() : usage variation ***
-- Testing strftime() function with Abbreviated month name format %h --
-bool(false)
-bool(false)
+string(%d) "%s"
+string(3) "Aug"
===DONE===
diff --git a/ext/date/tests/strftime_variation13.phpt b/ext/date/tests/strftime_variation13.phpt
index 58ad283ffd..3218558184 100644
--- a/ext/date/tests/strftime_variation13.phpt
+++ b/ext/date/tests/strftime_variation13.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test strftime() function : usage variation - Checking date related formats which are not supported on Windows.
+Test strftime() function : usage variation - Checking date related formats which was not supported on Windows before VC14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -17,7 +17,7 @@ if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
echo "*** Testing strftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
$timestamp = mktime(8, 8, 8, 8, 8, 2008);
@@ -43,18 +43,18 @@ foreach($inputs as $key =>$value) {
*** Testing strftime() : usage variation ***
--Century number--
-bool(false)
-bool(false)
+string(2) "20"
+string(2) "20"
--Month Date Year--
-bool(false)
-bool(false)
+string(%d) "%d/%d/%d"
+string(8) "08/08/08"
--Year with century--
-bool(false)
-bool(false)
+string(4) "%d"
+string(4) "2008"
--Year without century--
-bool(false)
-bool(false)
+string(2) "%d"
+string(2) "08"
===DONE===
diff --git a/ext/date/tests/strftime_variation15.phpt b/ext/date/tests/strftime_variation15.phpt
index 5b2946bf5d..962afd89c5 100644
--- a/ext/date/tests/strftime_variation15.phpt
+++ b/ext/date/tests/strftime_variation15.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test strftime() function : usage variation - Checking time related formats which are not supported on Windows.
+Test strftime() function : usage variation - Checking time related formats which was not supported on Windows before VC14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -17,7 +17,7 @@ if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
echo "*** Testing strftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
$timestamp = mktime(8, 8, 8, 8, 8, 2008);
@@ -42,14 +42,14 @@ foreach($inputs as $key =>$value) {
*** Testing strftime() : usage variation ***
--Time in a.m/p.m notation--
-bool(false)
-bool(false)
+string(%d) "%d:%d:%d %s"
+string(11) "08:08:08 AM"
--Time in 24 hour notation--
-bool(false)
-bool(false)
+string(%d) "%d:%d"
+string(5) "08:08"
--Current time %H:%M:%S format--
-bool(false)
-bool(false)
+string(%d) "%d:%d:%d"
+string(8) "08:08:08"
===DONE===
diff --git a/ext/date/tests/strftime_variation17.phpt b/ext/date/tests/strftime_variation17.phpt
index 90b3269e83..66527e3436 100644
--- a/ext/date/tests/strftime_variation17.phpt
+++ b/ext/date/tests/strftime_variation17.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test strftime() function : usage variation - Checking day related formats which are not supported on Windows.
+Test strftime() function : usage variation - Checking day related formats which was not supported on Windows before VC14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -17,7 +17,7 @@ if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
echo "*** Testing strftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
$timestamp = mktime(8, 8, 8, 8, 8, 2008);
@@ -31,6 +31,6 @@ var_dump( strftime($format, $timestamp) );
*** Testing strftime() : usage variation ***
-- Testing strftime() function with Day of the month as decimal single digit format --
-bool(false)
-bool(false)
+string(%d) "%A%d"
+string(2) " 8"
===DONE===
diff --git a/ext/date/tests/strftime_variation19.phpt b/ext/date/tests/strftime_variation19.phpt
index b41607719c..f36d0a189e 100644
--- a/ext/date/tests/strftime_variation19.phpt
+++ b/ext/date/tests/strftime_variation19.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test strftime() function : usage variation - Checking newline and tab formats which are not supported on Windows.
+Test strftime() function : usage variation - Checking newline and tab formats which was not supported on Windows before VC14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -41,10 +41,12 @@ foreach($inputs as $key =>$value) {
*** Testing strftime() : usage variation ***
--Newline character--
-bool(false)
-bool(false)
+string(1) "
+"
+string(1) "
+"
--Tab character--
-bool(false)
-bool(false)
+string(1) " "
+string(1) " "
===DONE===
diff --git a/ext/date/tests/strftime_variation21.phpt b/ext/date/tests/strftime_variation21.phpt
index f6aed15eff..735659298a 100644
--- a/ext/date/tests/strftime_variation21.phpt
+++ b/ext/date/tests/strftime_variation21.phpt
@@ -17,7 +17,7 @@ if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
echo "*** Testing strftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
$timestamp = mktime(8, 8, 8, 8, 8, 2008);
@@ -42,8 +42,8 @@ foreach($inputs as $key =>$value) {
*** Testing strftime() : usage variation ***
--Preferred date and time representation--
-string(%d) "%d/%d/%d %d:%d:%d"
-string(17) "08/08/08 08:08:08"
+string(%d) "%s %s %d %d:%d:%d %d"
+string(24) "Fri Aug 8 08:08:08 2008"
--Preferred date representation--
string(%d) "%d/%d/%d"
diff --git a/ext/date/tests/strftime_variation9.phpt b/ext/date/tests/strftime_variation9.phpt
index 23aa92d98d..eff030984f 100644
--- a/ext/date/tests/strftime_variation9.phpt
+++ b/ext/date/tests/strftime_variation9.phpt
@@ -1,5 +1,5 @@
--TEST--
-Test strftime() function : usage variation - Checking week related formats which are not supported on Windows.
+Test strftime() function : usage variation - Checking week related formats which was not supported on Windows before VC14.
--SKIPIF--
<?php
if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
@@ -17,7 +17,7 @@ if (strtoupper(substr(PHP_OS, 0, 3)) != 'WIN') {
echo "*** Testing strftime() : usage variation ***\n";
// Initialise function arguments not being substituted (if any)
-setlocale(LC_ALL, "en_US");
+setlocale(LC_ALL, "C");
date_default_timezone_set("Asia/Calcutta");
$timestamp = mktime(8, 8, 8, 8, 8, 2008);
@@ -41,10 +41,10 @@ foreach($inputs as $key =>$value) {
*** Testing strftime() : usage variation ***
--The ISO 8601:1988 week number--
-bool(false)
-bool(false)
+string(2) "%d"
+string(2) "32"
--Weekday as decimal--
-bool(false)
-bool(false)
+string(1) "%d"
+string(1) "5"
===DONE===
diff --git a/ext/dba/config.w32 b/ext/dba/config.w32
index 4f3514e62f..4abba8dbf4 100644
--- a/ext/dba/config.w32
+++ b/ext/dba/config.w32
@@ -4,7 +4,7 @@
ARG_WITH("dba", "DBA support", "no");
if (PHP_DBA != "no") {
- if (CHECK_LIB("libdb31s.lib", "dba", PHP_DBA) &&
+ if (CHECK_LIB("libdb31s.lib;libdb61.lib", "dba", PHP_DBA) &&
CHECK_HEADER_ADD_INCLUDE("db.h", "CFLAGS_DBA")) {
EXTENSION("dba", "dba.c dba_cdb.c dba_db1.c dba_db2.c dba_db3.c dba_dbm.c dba_flatfile.c dba_gdbm.c dba_ndbm.c dba_inifile.c");
ADD_SOURCES("ext/dba/libcdb", "cdb.c cdb_make.c uint32.c", "dba");
diff --git a/ext/dba/dba_db3.c b/ext/dba/dba_db3.c
index 1b4629510b..a582ad5821 100644
--- a/ext/dba/dba_db3.c
+++ b/ext/dba/dba_db3.c
@@ -35,7 +35,11 @@
#include <db.h>
#endif
-static void php_dba_db3_errcall_fcn(const char *errpfx, char *msg)
+static void php_dba_db3_errcall_fcn(
+#if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 3))
+ const DB_ENV *dbenv,
+#endif
+ const char *errpfx, const char *msg)
{
php_error_docref(NULL, E_NOTICE, "%s%s", errpfx?errpfx:"", msg);
@@ -90,7 +94,12 @@ DBA_OPEN_FUNC(db3)
if ((err=db_create(&dbp, NULL, 0)) == 0) {
dbp->set_errcall(dbp, php_dba_db3_errcall_fcn);
- if ((err=dbp->open(dbp, info->path, NULL, type, gmode, filemode)) == 0) {
+ if(
+#if (DB_VERSION_MAJOR > 4 || (DB_VERSION_MAJOR == 4 && DB_VERSION_MINOR >= 1))
+ (err=dbp->open(dbp, 0, info->path, NULL, type, gmode, filemode)) == 0) {
+#else
+ (err=dbp->open(dbp, info->path, NULL, type, gmode, filemode)) == 0) {
+#endif
dba_db3_data *data;
data = pemalloc(sizeof(*data), info->flags&DBA_PERSISTENT);
diff --git a/ext/dom/document.c b/ext/dom/document.c
index d435b1c281..3e4e298654 100644
--- a/ext/dom/document.c
+++ b/ext/dom/document.c
@@ -1562,7 +1562,7 @@ PHP_FUNCTION(dom_document_save)
char *file;
zend_long options = 0;
- if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|l", &id, dom_document_class_entry, &file, &file_len, &options) == FAILURE) {
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Op|l", &id, dom_document_class_entry, &file, &file_len, &options) == FAILURE) {
return;
}
@@ -1793,7 +1793,7 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type
int is_valid;
char resolved_path[MAXPATHLEN + 1];
- if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Op|l", &id, dom_document_class_entry, &source, &source_len, &flags) == FAILURE) {
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os|l", &id, dom_document_class_entry, &source, &source_len, &flags) == FAILURE) {
return;
}
@@ -1806,7 +1806,11 @@ static void _dom_document_schema_validate(INTERNAL_FUNCTION_PARAMETERS, int type
switch (type) {
case DOM_LOAD_FILE:
- valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN );
+ if (CHECK_NULL_PATH(source, source_len)) {
+ php_error_docref(NULL, E_WARNING, "Invalid Schema file source");
+ RETURN_FALSE;
+ }
+ valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN TSRMLS_CC);
if (!valid_file) {
php_error_docref(NULL, E_WARNING, "Invalid Schema file source");
RETURN_FALSE;
@@ -1889,7 +1893,7 @@ static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int typ
int is_valid;
char resolved_path[MAXPATHLEN + 1];
- if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Op", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_document_class_entry, &source, &source_len) == FAILURE) {
return;
}
@@ -1902,7 +1906,11 @@ static void _dom_document_relaxNG_validate(INTERNAL_FUNCTION_PARAMETERS, int typ
switch (type) {
case DOM_LOAD_FILE:
- valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN );
+ if (CHECK_NULL_PATH(source, source_len)) {
+ php_error_docref(NULL, E_WARNING, "Invalid RelaxNG file source");
+ RETURN_FALSE;
+ }
+ valid_file = _dom_get_valid_file_path(source, resolved_path, MAXPATHLEN TSRMLS_CC);
if (!valid_file) {
php_error_docref(NULL, E_WARNING, "Invalid RelaxNG file source");
RETURN_FALSE;
@@ -1983,7 +1991,7 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
id = getThis();
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "p|l", &source, &source_len, &options) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s|l", &source, &source_len, &options) == FAILURE) {
return;
}
@@ -1993,6 +2001,10 @@ static void dom_load_html(INTERNAL_FUNCTION_PARAMETERS, int mode) /* {{{ */
}
if (mode == DOM_LOAD_FILE) {
+ if (CHECK_NULL_PATH(source, source_len)) {
+ php_error_docref(NULL, E_WARNING, "Invalid file source");
+ RETURN_FALSE;
+ }
ctxt = htmlCreateFileParserCtxt(source, NULL);
} else {
source_len = xmlStrlen((xmlChar *) source);
@@ -2082,7 +2094,7 @@ PHP_FUNCTION(dom_document_save_html_file)
char *file;
const char *encoding;
- if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Os", &id, dom_document_class_entry, &file, &file_len) == FAILURE) {
+ if (zend_parse_method_parameters(ZEND_NUM_ARGS(), getThis(), "Op", &id, dom_document_class_entry, &file, &file_len) == FAILURE) {
return;
}
diff --git a/ext/dom/tests/DOMDocument_loadHTMLfile_error2.phpt b/ext/dom/tests/DOMDocument_loadHTMLfile_error2.phpt
index 75004e2a74..e0d0923642 100644
--- a/ext/dom/tests/DOMDocument_loadHTMLfile_error2.phpt
+++ b/ext/dom/tests/DOMDocument_loadHTMLfile_error2.phpt
@@ -15,9 +15,9 @@ $result = $doc->loadHTMLFile("");
assert('$result === false');
$doc = new DOMDocument();
$result = $doc->loadHTMLFile("text.html\0something");
-assert('$result === null');
+assert('$result === false');
?>
--EXPECTF--
%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): Empty string supplied as input %s
-%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile() expects parameter 1 to be a valid path, string given %s
+%r(PHP ){0,1}%rWarning: DOMDocument::loadHTMLFile(): Invalid file source %s
diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c
index 40df99df47..8663372de3 100644
--- a/ext/fileinfo/fileinfo.c
+++ b/ext/fileinfo/fileinfo.c
@@ -39,10 +39,6 @@
#include "fopen_wrappers.h" /* needed for is_url */
#include "Zend/zend_exceptions.h"
-#ifndef _S_IFDIR
-# define _S_IFDIR S_IFDIR
-#endif
-
/* {{{ macros and type definitions */
typedef struct _php_fileinfo {
zend_long options;
diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c
index 12828c676b..bb41b1a621 100644
--- a/ext/ftp/ftp.c
+++ b/ext/ftp/ftp.c
@@ -1837,8 +1837,6 @@ ftp_genlist(ftpbuf_t *ftp, const char *cmd, const char *path)
for (ptr = data->buf; rcvd; rcvd--, ptr++) {
if (*ptr == '\n' && lastch == '\r') {
lines++;
- } else {
- size++;
}
lastch = *ptr;
}
diff --git a/ext/gd/config.m4 b/ext/gd/config.m4
index e643e52736..36688e127a 100644
--- a/ext/gd/config.m4
+++ b/ext/gd/config.m4
@@ -35,9 +35,6 @@ PHP_ARG_WITH(xpm-dir, for the location of libXpm,
PHP_ARG_WITH(freetype-dir, for FreeType 2,
[ --with-freetype-dir[=DIR] GD: Set the path to FreeType 2 install prefix], no, no)
-PHP_ARG_WITH(t1lib, for T1lib support,
-[ --with-t1lib[=DIR] GD: Include T1lib support. T1lib version >= 5.0.0 required], no, no)
-
PHP_ARG_ENABLE(gd-native-ttf, whether to enable truetype string function in GD,
[ --enable-gd-native-ttf GD: Enable TrueType string function], no, no)
@@ -209,30 +206,6 @@ AC_DEFUN([PHP_GD_FREETYPE2],[
fi
])
-AC_DEFUN([PHP_GD_T1LIB],[
- if test "$PHP_T1LIB" != "no"; then
-
- for i in $PHP_T1LIB /usr/local /usr; do
- test -f "$i/include/t1lib.h" && GD_T1_DIR=$i && break
- done
-
- if test -z "$GD_T1_DIR"; then
- AC_MSG_ERROR([Your t1lib distribution is not installed correctly. Please reinstall it.])
- fi
-
- PHP_CHECK_LIBRARY(t1, T1_StrError,
- [
- AC_DEFINE(HAVE_LIBT1,1,[ ])
- PHP_ADD_INCLUDE($GD_T1_DIR/include)
- PHP_ADD_LIBRARY_WITH_PATH(t1, $GD_T1_DIR/$PHP_LIBDIR, GD_SHARED_LIBADD)
- ],[
- AC_MSG_ERROR([Problem with libt1.(a|so). Please check config.log for more information.])
- ],[
- -L$GD_T1_DIR/$PHP_LIBDIR
- ])
- fi
-])
-
AC_DEFUN([PHP_GD_TTSTR],[
if test "$PHP_GD_NATIVE_TTF" = "yes"; then
AC_DEFINE(USE_GD_IMGSTRTTF, 1, [ ])
@@ -274,7 +247,6 @@ dnl Various checks for GD features
PHP_GD_PNG
PHP_GD_XPM
PHP_GD_FREETYPE2
- PHP_GD_T1LIB
PHP_GD_JISX0208
fi
@@ -343,7 +315,6 @@ dnl Various checks for GD features
PHP_GD_PNG
PHP_GD_XPM
PHP_GD_FREETYPE2
- PHP_GD_T1LIB
dnl Header path
for i in include/gd include gd ""; do
diff --git a/ext/gd/config.w32 b/ext/gd/config.w32
index da6d0d2ff5..a51f027d38 100644
--- a/ext/gd/config.w32
+++ b/ext/gd/config.w32
@@ -2,7 +2,6 @@
// vim:ft=javascript
ARG_WITH("gd", "Bundled GD support", "yes,shared");
-ARG_WITH("t1lib", "t1lib support", "yes");
ARG_WITH("libvpx", "vpx support", "yes");
if (PHP_GD != "no") {
@@ -21,15 +20,6 @@ if (PHP_GD != "no") {
CHECK_LIB("libXpm_a.lib", "gd", PHP_GD) &&
CHECK_HEADER_ADD_INCLUDE("xpm.h", "CFLAGS_GD", PHP_GD + ";" + PHP_PHP_BUILD + "\\include\\X11")
) {
- if (PHP_T1LIB != "no") {
- if (CHECK_LIB("T1_StaticMD.lib", "gd", PHP_GD) &&
- CHECK_HEADER_ADD_INCLUDE("t1lib.h", "CFLAGS_GD", PHP_GD + ";" + PHP_PHP_BUILD + "\\include\\t1lib")
- ) {
- ADD_FLAG("CFLAGS_GD", "/D HAVE_LIBT1");
- } else {
- WARNING("t1lib not enabled; libraries and headers not found");
- }
- }
if (PHP_LIBVPX != "no") {
if (CHECK_LIB("vpxmt.lib", "gd", PHP_GD) &&
diff --git a/ext/gd/gd.c b/ext/gd/gd.c
index 9105fe6609..70f98f6a50 100644
--- a/ext/gd/gd.c
+++ b/ext/gd/gd.c
@@ -61,12 +61,6 @@
static int le_gd, le_gd_font;
-#if HAVE_LIBT1
-#include <t1lib.h>
-static int le_ps_font, le_ps_enc;
-static void php_free_ps_font(zend_resource *rsrc);
-static void php_free_ps_enc(zend_resource *rsrc);
-#endif
#include <gd.h>
#include <gdfontt.h> /* 1 Tiny font */
@@ -730,61 +724,6 @@ ZEND_BEGIN_ARG_INFO(arginfo_imagettftext, 0)
ZEND_END_ARG_INFO()
#endif
-#ifdef HAVE_LIBT1
-ZEND_BEGIN_ARG_INFO(arginfo_imagepsloadfont, 0)
- ZEND_ARG_INFO(0, pathname)
-ZEND_END_ARG_INFO()
-
-/*
-ZEND_BEGIN_ARG_INFO(arginfo_imagepscopyfont, 0)
- ZEND_ARG_INFO(0, font_index)
-ZEND_END_ARG_INFO()
-*/
-
-ZEND_BEGIN_ARG_INFO(arginfo_imagepsfreefont, 0)
- ZEND_ARG_INFO(0, font_index)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_imagepsencodefont, 0)
- ZEND_ARG_INFO(0, font_index)
- ZEND_ARG_INFO(0, filename)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_imagepsextendfont, 0)
- ZEND_ARG_INFO(0, font_index)
- ZEND_ARG_INFO(0, extend)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_imagepsslantfont, 0)
- ZEND_ARG_INFO(0, font_index)
- ZEND_ARG_INFO(0, slant)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_imagepstext, 0, 0, 8)
- ZEND_ARG_INFO(0, im)
- ZEND_ARG_INFO(0, text)
- ZEND_ARG_INFO(0, font)
- ZEND_ARG_INFO(0, size)
- ZEND_ARG_INFO(0, foreground)
- ZEND_ARG_INFO(0, background)
- ZEND_ARG_INFO(0, xcoord)
- ZEND_ARG_INFO(0, ycoord)
- ZEND_ARG_INFO(0, space)
- ZEND_ARG_INFO(0, tightness)
- ZEND_ARG_INFO(0, angle)
- ZEND_ARG_INFO(0, antialias)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO_EX(arginfo_imagepsbbox, 0, 0, 3)
- ZEND_ARG_INFO(0, text)
- ZEND_ARG_INFO(0, font)
- ZEND_ARG_INFO(0, size)
- ZEND_ARG_INFO(0, space)
- ZEND_ARG_INFO(0, tightness)
- ZEND_ARG_INFO(0, angle)
-ZEND_END_ARG_INFO()
-#endif
-
ZEND_BEGIN_ARG_INFO_EX(arginfo_image2wbmp, 0, 0, 1)
ZEND_ARG_INFO(0, im)
ZEND_ARG_INFO(0, filename)
@@ -1005,18 +944,6 @@ const zend_function_entry gd_functions[] = {
#endif
#endif
-#ifdef HAVE_LIBT1
- PHP_FE(imagepsloadfont, arginfo_imagepsloadfont)
- /*
- PHP_FE(imagepscopyfont, arginfo_imagepscopyfont)
- */
- PHP_FE(imagepsfreefont, arginfo_imagepsfreefont)
- PHP_FE(imagepsencodefont, arginfo_imagepsencodefont)
- PHP_FE(imagepsextendfont, arginfo_imagepsextendfont)
- PHP_FE(imagepsslantfont, arginfo_imagepsslantfont)
- PHP_FE(imagepstext, arginfo_imagepstext)
- PHP_FE(imagepsbbox, arginfo_imagepsbbox)
-#endif
PHP_FE(imagetypes, arginfo_imagetypes)
#if defined(HAVE_GD_JPG)
@@ -1044,11 +971,7 @@ zend_module_entry gd_module_entry = {
"gd",
gd_functions,
PHP_MINIT(gd),
-#if HAVE_LIBT1
- PHP_MSHUTDOWN(gd),
-#else
NULL,
-#endif
NULL,
#if HAVE_GD_FREETYPE && HAVE_LIBFREETYPE
PHP_RSHUTDOWN(gd),
@@ -1103,22 +1026,6 @@ void php_gd_error_method(int type, const char *format, va_list args)
/* }}} */
#endif
-/* {{{ PHP_MSHUTDOWN_FUNCTION
- */
-#if HAVE_LIBT1
-PHP_MSHUTDOWN_FUNCTION(gd)
-{
- T1_CloseLib();
-#if HAVE_GD_BUNDLED && HAVE_LIBFREETYPE
- gdFontCacheMutexShutdown();
-#endif
- UNREGISTER_INI_ENTRIES();
- return SUCCESS;
-}
-#endif
-/* }}} */
-
-
/* {{{ PHP_MINIT_FUNCTION
*/
PHP_MINIT_FUNCTION(gd)
@@ -1129,13 +1036,6 @@ PHP_MINIT_FUNCTION(gd)
#if HAVE_GD_BUNDLED && HAVE_LIBFREETYPE
gdFontCacheMutexSetup();
#endif
-#if HAVE_LIBT1
- T1_SetBitmapPad(8);
- T1_InitLib(NO_LOGFILE | IGNORE_CONFIGFILE | IGNORE_FONTDATABASE);
- T1_SetLogLevel(T1LOG_DEBUG);
- le_ps_font = zend_register_list_destructors_ex(php_free_ps_font, NULL, "gd PS font", module_number);
- le_ps_enc = zend_register_list_destructors_ex(php_free_ps_enc, NULL, "gd PS encoding", module_number);
-#endif
#ifndef HAVE_GD_BUNDLED
gdSetErrorMethod(php_gd_error_method);
#endif
@@ -1318,10 +1218,6 @@ PHP_MINFO_FUNCTION(gd)
#endif
#endif
-#ifdef HAVE_LIBT1
- php_info_print_table_row(2, "T1Lib Support", "enabled");
-#endif
-
php_info_print_table_row(2, "GIF Read Support", "enabled");
php_info_print_table_row(2, "GIF Create Support", "enabled");
@@ -1379,12 +1275,6 @@ PHP_FUNCTION(gd_info)
#else
add_assoc_bool(return_value, "FreeType Support", 0);
#endif
-
-#ifdef HAVE_LIBT1
- add_assoc_bool(return_value, "T1Lib Support", 1);
-#else
- add_assoc_bool(return_value, "T1Lib Support", 0);
-#endif
add_assoc_bool(return_value, "GIF Read Support", 1);
add_assoc_bool(return_value, "GIF Create Support", 1);
#ifdef HAVE_GD_JPG
@@ -4011,475 +3901,6 @@ static void php_imagettftext_common(INTERNAL_FUNCTION_PARAMETERS, int mode, int
/* }}} */
#endif /* ENABLE_GD_TTF */
-#if HAVE_LIBT1
-
-/* {{{ php_free_ps_font
- */
-static void php_free_ps_font(zend_resource *rsrc)
-{
- int *font = (int *)rsrc->ptr;
-
- T1_DeleteFont(*font);
- efree(font);
-}
-/* }}} */
-
-/* {{{ php_free_ps_enc
- */
-static void php_free_ps_enc(zend_resource *rsrc)
-{
- char **enc = (char **)rsrc->ptr;
-
- T1_DeleteEncoding(enc);
-}
-/* }}} */
-
-/* {{{ proto resource imagepsloadfont(string pathname)
- Load a new font from specified file */
-PHP_FUNCTION(imagepsloadfont)
-{
- zend_string *file;
- int f_ind, *font;
-#ifdef PHP_WIN32
- zend_stat_t st;
-#endif
-
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "P", &file) == FAILURE) {
- return;
- }
-
-#ifdef PHP_WIN32
- if (VCWD_STAT(file->val, &st) < 0) {
- php_error_docref(NULL, E_WARNING, "Font file not found (%s)", file);
- RETURN_FALSE;
- }
-#endif
-
- f_ind = T1_AddFont(file->val);
-
- if (f_ind < 0) {
- php_error_docref(NULL, E_WARNING, "T1Lib Error (%i): %s", f_ind, T1_StrError(f_ind));
- RETURN_FALSE;
- }
-
- if (T1_LoadFont(f_ind)) {
- php_error_docref(NULL, E_WARNING, "Couldn't load the font");
- RETURN_FALSE;
- }
-
- font = (int *) emalloc(sizeof(int));
- *font = f_ind;
- RETURN_RES(zend_register_resource(font, le_gd));
-}
-/* }}} */
-
-/* {{{ proto int imagepscopyfont(int font_index)
- Make a copy of a font for purposes like extending or reenconding */
-/* The function in t1lib which this function uses seem to be buggy...
-PHP_FUNCTION(imagepscopyfont)
-{
- int l_ind, type;
- gd_ps_font *nf_ind, *of_ind;
- zend_long fnt;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &fnt) == FAILURE) {
- return;
- }
-
- of_ind = zend_list_find(fnt, &type);
-
- if (type != le_ps_font) {
- php_error_docref(NULL, E_WARNING, "%ld is not a Type 1 font index", fnt);
- RETURN_FALSE;
- }
-
- nf_ind = emalloc(sizeof(gd_ps_font));
- nf_ind->font_id = T1_CopyFont(of_ind->font_id);
-
- if (nf_ind->font_id < 0) {
- l_ind = nf_ind->font_id;
- efree(nf_ind);
- switch (l_ind) {
- case -1:
- php_error_docref(NULL, E_WARNING, "FontID %d is not loaded in memory", l_ind);
- RETURN_FALSE;
- break;
- case -2:
- php_error_docref(NULL, E_WARNING, "Tried to copy a logical font");
- RETURN_FALSE;
- break;
- case -3:
- php_error_docref(NULL, E_WARNING, "Memory allocation fault in t1lib");
- RETURN_FALSE;
- break;
- default:
- php_error_docref(NULL, E_WARNING, "An unknown error occurred in t1lib");
- RETURN_FALSE;
- break;
- }
- }
-
- nf_ind->extend = 1;
- l_ind = zend_list_insert(nf_ind, le_ps_font);
- RETURN_LONG(l_ind);
-}
-*/
-/* }}} */
-
-/* {{{ proto bool imagepsfreefont(resource font_index)
- Free memory used by a font */
-PHP_FUNCTION(imagepsfreefont)
-{
- zval *fnt;
- int *f_ind;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "r", &fnt) == FAILURE) {
- return;
- }
-
- if ((f_ind = (int *)zend_fetch_resource(Z_RES_P(fnt), "Type 1 font", le_ps_font)) == NULL) {
- RETURN_FALSE;
- }
-
- zend_list_close(Z_RES_P(fnt));
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool imagepsencodefont(resource font_index, string filename)
- To change a fonts character encoding vector */
-PHP_FUNCTION(imagepsencodefont)
-{
- zval *fnt;
- char *enc, **enc_vector;
- size_t enc_len;
- int *f_ind;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rp", &fnt, &enc, &enc_len) == FAILURE) {
- return;
- }
-
- if ((f_ind = (int *)zend_fetch_resource(Z_RES_P(fnt), "Type 1 font", le_ps_font)) == NULL) {
- RETURN_FALSE;
- }
-
- if ((enc_vector = T1_LoadEncoding(enc)) == NULL) {
- php_error_docref(NULL, E_WARNING, "Couldn't load encoding vector from %s", enc);
- RETURN_FALSE;
- }
-
- T1_DeleteAllSizes(*f_ind);
- if (T1_ReencodeFont(*f_ind, enc_vector)) {
- T1_DeleteEncoding(enc_vector);
- php_error_docref(NULL, E_WARNING, "Couldn't re-encode font");
- RETURN_FALSE;
- }
-
- zend_list_insert(enc_vector, le_ps_enc);
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool imagepsextendfont(resource font_index, float extend)
- Extend or or condense (if extend < 1) a font */
-PHP_FUNCTION(imagepsextendfont)
-{
- zval *fnt;
- double ext;
- int *f_ind;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rd", &fnt, &ext) == FAILURE) {
- return;
- }
-
- if ((f_ind = (int *)zend_fetch_resource(Z_RES_P(fnt), "Type 1 font", le_ps_font)) == NULL) {
- RETURN_FALSE;
- }
-
- T1_DeleteAllSizes(*f_ind);
-
- if (ext <= 0) {
- php_error_docref(NULL, E_WARNING, "Second parameter %F out of range (must be > 0)", ext);
- RETURN_FALSE;
- }
-
- if (T1_ExtendFont(*f_ind, ext) != 0) {
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto bool imagepsslantfont(resource font_index, float slant)
- Slant a font */
-PHP_FUNCTION(imagepsslantfont)
-{
- zval *fnt;
- double slt;
- int *f_ind;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rd", &fnt, &slt) == FAILURE) {
- return;
- }
-
- if ((f_ind = (int *)zend_fetch_resource(Z_RES_P(fnt), "Type 1 font", le_ps_font)) == NULL) {
- RETURN_FALSE;
- }
-
- if (T1_SlantFont(*f_ind, slt) != 0) {
- RETURN_FALSE;
- }
-
- RETURN_TRUE;
-}
-/* }}} */
-
-/* {{{ proto array imagepstext(resource image, string text, resource font, int size, int foreground, int background, int xcoord, int ycoord [, int space [, int tightness [, float angle [, int antialias])
- Rasterize a string over an image */
-PHP_FUNCTION(imagepstext)
-{
- zval *img, *fnt;
- int i, j;
- zend_long _fg, _bg, x, y, size, space = 0, aa_steps = 4, width = 0;
- int *f_ind;
- int h_lines, v_lines, c_ind;
- int rd, gr, bl, fg_rd, fg_gr, fg_bl, bg_rd, bg_gr, bg_bl;
- int fg_al, bg_al, al;
- int aa[16];
- int amount_kern, add_width;
- double angle = 0.0, extend;
- unsigned long aa_greys[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16};
- gdImagePtr bg_img;
- GLYPH *str_img;
- T1_OUTLINE *char_path, *str_path;
- T1_TMATRIX *transform = NULL;
- zend_string *str;
-
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "rSrlllll|lldl", &img, &str, &fnt, &size, &_fg, &_bg, &x, &y, &space, &width, &angle, &aa_steps) == FAILURE) {
- return;
- }
-
- if (aa_steps != 4 && aa_steps != 16) {
- php_error_docref(NULL, E_WARNING, "Antialias steps must be 4 or 16");
- RETURN_FALSE;
- }
-
- if ((bg_img = (gdImagePtr)zend_fetch_resource(Z_RES_P(img), "Image", le_gd)) == NULL) {
- RETURN_FALSE;
- }
- if ((f_ind = (int *)zend_fetch_resource(Z_RES_P(fnt), "Type 1 font", le_ps_font)) == NULL) {
- RETURN_FALSE;
- }
-
- /* Ensure that the provided colors are valid */
- if (_fg < 0 || (!gdImageTrueColor(bg_img) && _fg > gdImageColorsTotal(bg_img))) {
- php_error_docref(NULL, E_WARNING, "Foreground color index %pd out of range", _fg);
- RETURN_FALSE;
- }
-
- if (_bg < 0 || (!gdImageTrueColor(bg_img) && _fg > gdImageColorsTotal(bg_img))) {
- php_error_docref(NULL, E_WARNING, "Background color index %pd out of range", _bg);
- RETURN_FALSE;
- }
-
- fg_rd = gdImageRed (bg_img, _fg);
- fg_gr = gdImageGreen(bg_img, _fg);
- fg_bl = gdImageBlue (bg_img, _fg);
- fg_al = gdImageAlpha(bg_img, _fg);
-
- bg_rd = gdImageRed (bg_img, _bg);
- bg_gr = gdImageGreen(bg_img, _bg);
- bg_bl = gdImageBlue (bg_img, _bg);
- bg_al = gdImageAlpha(bg_img, _bg);
-
- for (i = 0; i < aa_steps; i++) {
- rd = bg_rd + (double) (fg_rd - bg_rd) / aa_steps * (i + 1);
- gr = bg_gr + (double) (fg_gr - bg_gr) / aa_steps * (i + 1);
- bl = bg_bl + (double) (fg_bl - bg_bl) / aa_steps * (i + 1);
- al = bg_al + (double) (fg_al - bg_al) / aa_steps * (i + 1);
- aa[i] = gdImageColorResolveAlpha(bg_img, rd, gr, bl, al);
- }
-
- T1_AASetBitsPerPixel(8);
-
- switch (aa_steps) {
- case 4:
- T1_AASetGrayValues(0, 1, 2, 3, 4);
- T1_AASetLevel(T1_AA_LOW);
- break;
- case 16:
- T1_AAHSetGrayValues(aa_greys);
- T1_AASetLevel(T1_AA_HIGH);
- break;
- default:
- php_error_docref(NULL, E_WARNING, "Invalid value %pd as number of steps for antialiasing", aa_steps);
- RETURN_FALSE;
- }
-
- if (angle) {
- transform = T1_RotateMatrix(NULL, angle);
- }
-
- if (width) {
- extend = T1_GetExtend(*f_ind);
- str_path = T1_GetCharOutline(*f_ind, str->val[0], size, transform);
-
- if (!str_path) {
- if (T1_errno) {
- php_error_docref(NULL, E_WARNING, "T1Lib Error: %s", T1_StrError(T1_errno));
- }
- RETURN_FALSE;
- }
-
- for (i = 1; i < str->len; i++) {
- amount_kern = (int) T1_GetKerning(*f_ind, str->val[i - 1], str->val[i]);
- amount_kern += str->val[i - 1] == ' ' ? space : 0;
- add_width = (int) (amount_kern + width) / extend;
-
- char_path = T1_GetMoveOutline(*f_ind, add_width, 0, 0, size, transform);
- str_path = T1_ConcatOutlines(str_path, char_path);
-
- char_path = T1_GetCharOutline(*f_ind, str->val[i], size, transform);
- str_path = T1_ConcatOutlines(str_path, char_path);
- }
- str_img = T1_AAFillOutline(str_path, 0);
- } else {
- str_img = T1_AASetString(*f_ind, str->val, str->len, space, T1_KERNING, size, transform);
- }
- if (T1_errno) {
- php_error_docref(NULL, E_WARNING, "T1Lib Error: %s", T1_StrError(T1_errno));
- RETURN_FALSE;
- }
-
- h_lines = str_img->metrics.ascent - str_img->metrics.descent;
- v_lines = str_img->metrics.rightSideBearing - str_img->metrics.leftSideBearing;
-
- for (i = 0; i < v_lines; i++) {
- for (j = 0; j < h_lines; j++) {
- switch (str_img->bits[j * v_lines + i]) {
- case 0:
- break;
- default:
- c_ind = aa[str_img->bits[j * v_lines + i] - 1];
- gdImageSetPixel(bg_img, x + str_img->metrics.leftSideBearing + i, y - str_img->metrics.ascent + j, c_ind);
- break;
- }
- }
- }
-
- array_init(return_value);
-
- add_next_index_long(return_value, str_img->metrics.leftSideBearing);
- add_next_index_long(return_value, str_img->metrics.descent);
- add_next_index_long(return_value, str_img->metrics.rightSideBearing);
- add_next_index_long(return_value, str_img->metrics.ascent);
-}
-/* }}} */
-
-/* {{{ proto array imagepsbbox(string text, resource font, int size [, int space, int tightness, float angle])
- Return the bounding box needed by a string if rasterized */
-PHP_FUNCTION(imagepsbbox)
-{
- zval *fnt;
- zend_long sz = 0, sp = 0, wd = 0;
- zend_string *str;
- int i, space = 0, add_width = 0, char_width, amount_kern;
- int cur_x, cur_y, dx, dy;
- int x1, y1, x2, y2, x3, y3, x4, y4;
- int *f_ind;
- int per_char = 0;
- int argc = ZEND_NUM_ARGS();
- double angle = 0, sin_a = 0, cos_a = 0;
- BBox char_bbox, str_bbox = {0, 0, 0, 0};
-
- if (argc != 3 && argc != 6) {
- ZEND_WRONG_PARAM_COUNT();
- }
-
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "Srl|lld", &str, &fnt, &sz, &sp, &wd, &angle) == FAILURE) {
- return;
- }
-
- if (argc == 6) {
- space = sp;
- add_width = wd;
- angle = angle * M_PI / 180;
- sin_a = sin(angle);
- cos_a = cos(angle);
- per_char = add_width || angle ? 1 : 0;
- }
-
- if ((f_ind = (int *)zend_fetch_resource(Z_RES_P(fnt), "Type 1 font", le_ps_font)) == NULL) {
- RETURN_FALSE;
- }
-
-#define max(a, b) (a > b ? a : b)
-#define min(a, b) (a < b ? a : b)
-#define new_x(a, b) (int) ((a) * cos_a - (b) * sin_a)
-#define new_y(a, b) (int) ((a) * sin_a + (b) * cos_a)
-
- if (per_char) {
- space += T1_GetCharWidth(*f_ind, ' ');
- cur_x = cur_y = 0;
-
- for (i = 0; i < str->len; i++) {
- if (str->val[i] == ' ') {
- char_bbox.llx = char_bbox.lly = char_bbox.ury = 0;
- char_bbox.urx = char_width = space;
- } else {
- char_bbox = T1_GetCharBBox(*f_ind, str->val[i]);
- char_width = T1_GetCharWidth(*f_ind, str->val[i]);
- }
- amount_kern = i ? T1_GetKerning(*f_ind, str->val[i - 1], str->val[i]) : 0;
-
- /* Transfer character bounding box to right place */
- x1 = new_x(char_bbox.llx, char_bbox.lly) + cur_x;
- y1 = new_y(char_bbox.llx, char_bbox.lly) + cur_y;
- x2 = new_x(char_bbox.llx, char_bbox.ury) + cur_x;
- y2 = new_y(char_bbox.llx, char_bbox.ury) + cur_y;
- x3 = new_x(char_bbox.urx, char_bbox.ury) + cur_x;
- y3 = new_y(char_bbox.urx, char_bbox.ury) + cur_y;
- x4 = new_x(char_bbox.urx, char_bbox.lly) + cur_x;
- y4 = new_y(char_bbox.urx, char_bbox.lly) + cur_y;
-
- /* Find min & max values and compare them with current bounding box */
- str_bbox.llx = min(str_bbox.llx, min(x1, min(x2, min(x3, x4))));
- str_bbox.lly = min(str_bbox.lly, min(y1, min(y2, min(y3, y4))));
- str_bbox.urx = max(str_bbox.urx, max(x1, max(x2, max(x3, x4))));
- str_bbox.ury = max(str_bbox.ury, max(y1, max(y2, max(y3, y4))));
-
- /* Move to the next base point */
- dx = new_x(char_width + add_width + amount_kern, 0);
- dy = new_y(char_width + add_width + amount_kern, 0);
- cur_x += dx;
- cur_y += dy;
- /*
- printf("%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\t%d\n", x1, y1, x2, y2, x3, y3, x4, y4, char_bbox.llx, char_bbox.lly, char_bbox.urx, char_bbox.ury, char_width, amount_kern, cur_x, cur_y, dx, dy);
- */
- }
-
- } else {
- str_bbox = T1_GetStringBBox(*f_ind, str->val, str->len, space, T1_KERNING);
- }
-
- if (T1_errno) {
- RETURN_FALSE;
- }
-
- array_init(return_value);
- /*
- printf("%d %d %d %d\n", str_bbox.llx, str_bbox.lly, str_bbox.urx, str_bbox.ury);
- */
- add_next_index_long(return_value, (int) ceil(((double) str_bbox.llx)*sz/1000));
- add_next_index_long(return_value, (int) ceil(((double) str_bbox.lly)*sz/1000));
- add_next_index_long(return_value, (int) ceil(((double) str_bbox.urx)*sz/1000));
- add_next_index_long(return_value, (int) ceil(((double) str_bbox.ury)*sz/1000));
-}
-/* }}} */
-#endif
-
/* {{{ proto bool image2wbmp(resource im [, string filename [, int threshold]])
Output WBMP image to browser or file */
PHP_FUNCTION(image2wbmp)
diff --git a/ext/gd/libgd/webpimg.c b/ext/gd/libgd/webpimg.c
index 1f1c02322e..9d801a29a3 100644
--- a/ext/gd/libgd/webpimg.c
+++ b/ext/gd/libgd/webpimg.c
@@ -706,14 +706,14 @@ static WebPResult VPXEncode(const uint8* Y,
codec_ctl(&enc, VP8E_SET_STATIC_THRESHOLD, 0);
codec_ctl(&enc, VP8E_SET_TOKEN_PARTITIONS, 2);
- vpx_img_wrap(&img, IMG_FMT_I420,
+ vpx_img_wrap(&img, VPX_IMG_FMT_I420,
y_width, y_height, 16, (uint8*)(Y));
- img.planes[PLANE_Y] = (uint8*)(Y);
- img.planes[PLANE_U] = (uint8*)(U);
- img.planes[PLANE_V] = (uint8*)(V);
- img.stride[PLANE_Y] = y_stride;
- img.stride[PLANE_U] = uv_stride;
- img.stride[PLANE_V] = uv_stride;
+ img.planes[VPX_PLANE_Y] = (uint8*)(Y);
+ img.planes[VPX_PLANE_U] = (uint8*)(U);
+ img.planes[VPX_PLANE_V] = (uint8*)(V);
+ img.stride[VPX_PLANE_Y] = y_stride;
+ img.stride[VPX_PLANE_U] = uv_stride;
+ img.stride[VPX_PLANE_V] = uv_stride;
res = vpx_codec_encode(&enc, &img, 0, 1, 0, VPX_DL_BEST_QUALITY);
diff --git a/ext/gd/php_gd.h b/ext/gd/php_gd.h
index 2af7887ebc..f02c6aba34 100644
--- a/ext/gd/php_gd.h
+++ b/ext/gd/php_gd.h
@@ -70,9 +70,6 @@ extern zend_module_entry gd_module_entry;
/* gd.c functions */
PHP_MINFO_FUNCTION(gd);
PHP_MINIT_FUNCTION(gd);
-#if HAVE_LIBT1
-PHP_MSHUTDOWN_FUNCTION(gd);
-#endif
#if HAVE_GD_FREETYPE && HAVE_LIBFREETYPE
PHP_RSHUTDOWN_FUNCTION(gd);
#endif
diff --git a/ext/gd/tests/gd_info_variation1.phpt b/ext/gd/tests/gd_info_variation1.phpt
index a725f6554d..1810a82f85 100644
--- a/ext/gd/tests/gd_info_variation1.phpt
+++ b/ext/gd/tests/gd_info_variation1.phpt
@@ -28,8 +28,6 @@ array(%d) {
string(%d) %a
["FreeType Support"]=>
bool%a
- ["T1Lib Support"]=>
- bool%a
["GIF Read Support"]=>
bool%a
["GIF Create Support"]=>
@@ -47,4 +45,4 @@ array(%d) {
["JIS-mapped Japanese Font Support"]=>
bool%a
}
-===DONE=== \ No newline at end of file
+===DONE===
diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c
index 1994052686..663bbc96e4 100644
--- a/ext/gmp/gmp.c
+++ b/ext/gmp/gmp.c
@@ -1837,6 +1837,7 @@ ZEND_FUNCTION(gmp_random_range)
{
zval *min_arg, *max_arg;
mpz_ptr gmpnum_min, gmpnum_max, gmpnum_result;
+ mpz_t gmpnum_range;
gmp_temp_t temp_a, temp_b;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "zz", &min_arg, &max_arg) == FAILURE) {
@@ -1855,22 +1856,23 @@ ZEND_FUNCTION(gmp_random_range)
}
INIT_GMP_RETVAL(gmpnum_result);
+ mpz_init(gmpnum_range);
- if (Z_LVAL_P(min_arg)) {
- mpz_sub_ui(gmpnum_max, gmpnum_max, Z_LVAL_P(min_arg));
+ if (Z_LVAL_P(min_arg) != 0) {
+ mpz_sub_ui(gmpnum_range, gmpnum_max, Z_LVAL_P(min_arg) - 1);
+ } else {
+ mpz_add_ui(gmpnum_range, gmpnum_max, 1);
}
- mpz_add_ui(gmpnum_max, gmpnum_max, 1);
- mpz_urandomm(gmpnum_result, GMPG(rand_state), gmpnum_max);
+ mpz_urandomm(gmpnum_result, GMPG(rand_state), gmpnum_range);
- if (Z_LVAL_P(min_arg)) {
+ if (Z_LVAL_P(min_arg) != 0) {
mpz_add_ui(gmpnum_result, gmpnum_result, Z_LVAL_P(min_arg));
}
+ mpz_clear(gmpnum_range);
FREE_GMP_TEMP(temp_a);
-
- }
- else {
+ } else {
FETCH_GMP_ZVAL_DEP(gmpnum_min, min_arg, temp_b, temp_a);
if (mpz_cmp(gmpnum_max, gmpnum_min) <= 0) {
@@ -1881,12 +1883,14 @@ ZEND_FUNCTION(gmp_random_range)
}
INIT_GMP_RETVAL(gmpnum_result);
+ mpz_init(gmpnum_range);
- mpz_sub(gmpnum_max, gmpnum_max, gmpnum_min);
- mpz_add_ui(gmpnum_max, gmpnum_max, 1);
- mpz_urandomm(gmpnum_result, GMPG(rand_state), gmpnum_max);
+ mpz_sub(gmpnum_range, gmpnum_max, gmpnum_min);
+ mpz_add_ui(gmpnum_range, gmpnum_range, 1);
+ mpz_urandomm(gmpnum_result, GMPG(rand_state), gmpnum_range);
mpz_add(gmpnum_result, gmpnum_result, gmpnum_min);
+ mpz_clear(gmpnum_range);
FREE_GMP_TEMP(temp_b);
FREE_GMP_TEMP(temp_a);
}
diff --git a/ext/gmp/tests/bug69803.phpt b/ext/gmp/tests/bug69803.phpt
new file mode 100644
index 0000000000..e158cc5c0c
--- /dev/null
+++ b/ext/gmp/tests/bug69803.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Bug #69803: gmp_random_range() modifies second parameter if GMP number
+--FILE--
+<?php
+
+$a = gmp_init(100);
+$b = gmp_init(200);
+echo $a . ", ", $b . "\n";
+gmp_random_range($a, $b);
+echo $a . ", ", $b . "\n";
+
+$b = gmp_init(200);
+echo $a . ", ", $b . "\n";
+gmp_random_range(100, $b);
+echo $a . ", ", $b . "\n";
+
+?>
+--EXPECT--
+100, 200
+100, 200
+100, 200
+100, 200
diff --git a/ext/gmp/tests/gmp_random_range.phpt b/ext/gmp/tests/gmp_random_range.phpt
index db2ece61c5..654ffbefb3 100644
--- a/ext/gmp/tests/gmp_random_range.phpt
+++ b/ext/gmp/tests/gmp_random_range.phpt
@@ -5,8 +5,8 @@ gmp_random_range() basic tests
--FILE--
<?php
-$minusTen = gmp_init(-1);
-$plusTen = gmp_init(1);
+$minusTen = gmp_init(-10);
+$plusTen = gmp_init(10);
$zero = gmp_init(0);
var_dump(gmp_random_range());
diff --git a/ext/hash/hash.c b/ext/hash/hash.c
index 0510d3749c..d72b88c879 100644
--- a/ext/hash/hash.c
+++ b/ext/hash/hash.c
@@ -794,6 +794,9 @@ static void php_hash_dtor(zend_resource *rsrc) /* {{{ */
#ifdef PHP_MHASH_BC
+#if 0
+/* See #69823, we should not insert module into module_registry while doing startup */
+
PHP_MINFO_FUNCTION(mhash)
{
php_info_print_table_start();
@@ -814,6 +817,7 @@ zend_module_entry mhash_module_entry = {
PHP_MHASH_VERSION,
STANDARD_MODULE_PROPERTIES,
};
+#endif
static void mhash_init(INIT_FUNC_ARGS)
{
@@ -830,7 +834,8 @@ static void mhash_init(INIT_FUNC_ARGS)
len = slprintf(buf, 127, "MHASH_%s", algorithm.mhash_name, strlen(algorithm.mhash_name));
zend_register_long_constant(buf, len, algorithm.value, CONST_CS | CONST_PERSISTENT, module_number);
}
- zend_register_internal_module(&mhash_module_entry);
+
+ /* TODO: this cause #69823 zend_register_internal_module(&mhash_module_entry); */
}
/* {{{ proto string mhash(int hash, string data [, string key])
@@ -1090,6 +1095,14 @@ PHP_MINFO_FUNCTION(hash)
php_info_print_table_row(2, "hash support", "enabled");
php_info_print_table_row(2, "Hashing Engines", buffer);
php_info_print_table_end();
+
+#ifdef PHP_MHASH_BC
+ php_info_print_table_start();
+ php_info_print_table_row(2, "MHASH support", "Enabled");
+ php_info_print_table_row(2, "MHASH API Version", "Emulated Support");
+ php_info_print_table_end();
+#endif
+
}
/* }}} */
diff --git a/ext/hash/tests/skip_mhash.inc b/ext/hash/tests/skip_mhash.inc
index 17e5fe7f9e..608b557b28 100644
--- a/ext/hash/tests/skip_mhash.inc
+++ b/ext/hash/tests/skip_mhash.inc
@@ -1,5 +1,5 @@
<?php
-if (!extension_loaded("mhash") || !function_exists("mhash")) {
+if (!function_exists("mhash")) {
die("skip mhash extension is not available");
}
?>
diff --git a/ext/iconv/config.m4 b/ext/iconv/config.m4
index efde95e038..6a056979e7 100644
--- a/ext/iconv/config.m4
+++ b/ext/iconv/config.m4
@@ -186,8 +186,8 @@ int main() {
AC_DEFINE([ICONV_BROKEN_IGNORE],1,[Whether iconv supports IGNORE])
],[
AC_MSG_RESULT(no, cross-compiling)
- PHP_DEFINE([ICONV_SUPPORTS_ERRNO],0,[ext/iconv])
- AC_DEFINE([ICONV_SUPPORTS_ERRNO],0,[Whether iconv supports IGNORE])
+ PHP_DEFINE([ICONV_BROKEN_IGNORE],0,[ext/iconv])
+ AC_DEFINE([ICONV_BROKEN_IGNORE],0,[Whether iconv supports IGNORE])
])
AC_MSG_CHECKING([if your cpp allows macro usage in include lines])
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
index 8042916c0d..897185da8a 100644
--- a/ext/iconv/iconv.c
+++ b/ext/iconv/iconv.c
@@ -2209,8 +2209,8 @@ PHP_FUNCTION(iconv_mime_encode)
{
zend_string *field_name = NULL;
zend_string *field_value = NULL;
+ zend_string *tmp_str = NULL;
zval *pref = NULL;
- zval tmp_zv, *tmp_zv_p = NULL;
smart_str retval = {0};
php_iconv_err_t err;
@@ -2273,12 +2273,8 @@ PHP_FUNCTION(iconv_mime_encode)
if ((pzval = zend_hash_str_find(Z_ARRVAL_P(pref), "line-break-chars", sizeof("line-break-chars") - 1)) != NULL) {
if (Z_TYPE_P(pzval) != IS_STRING) {
- ZVAL_DUP(&tmp_zv, pzval);
- convert_to_string(&tmp_zv);
-
- lfchars = Z_STRVAL(tmp_zv);
-
- tmp_zv_p = &tmp_zv;
+ tmp_str = zval_get_string(pzval);
+ lfchars = tmp_str->val;
} else {
lfchars = Z_STRVAL_P(pzval);
}
@@ -2301,8 +2297,8 @@ PHP_FUNCTION(iconv_mime_encode)
RETVAL_FALSE;
}
- if (tmp_zv_p != NULL) {
- zval_dtor(tmp_zv_p);
+ if (tmp_str) {
+ zend_string_release(tmp_str);
}
}
/* }}} */
diff --git a/ext/intl/breakiterator/breakiterator_iterators.cpp b/ext/intl/breakiterator/breakiterator_iterators.cpp
index 93a49d1290..5bd77a5f2d 100644
--- a/ext/intl/breakiterator/breakiterator_iterators.cpp
+++ b/ext/intl/breakiterator/breakiterator_iterators.cpp
@@ -289,7 +289,8 @@ U_CFUNC PHP_METHOD(IntlPartsIterator, getBreakIterator)
INTLITERATOR_METHOD_FETCH_OBJECT;
zval *biter_zval = &ii->iterator->data;
- RETURN_ZVAL(biter_zval, 1, 0);
+ ZVAL_DEREF(biter_zval);
+ ZVAL_COPY(return_value, biter_zval);
}
ZEND_BEGIN_ARG_INFO_EX(ainfo_parts_it_void, 0, 0, 0)
diff --git a/ext/intl/common/common_enum.cpp b/ext/intl/common/common_enum.cpp
index 4160c30258..e76f3b830f 100644
--- a/ext/intl/common/common_enum.cpp
+++ b/ext/intl/common/common_enum.cpp
@@ -219,7 +219,8 @@ static PHP_METHOD(IntlIterator, current)
INTLITERATOR_METHOD_FETCH_OBJECT;
data = ii->iterator->funcs->get_current_data(ii->iterator);
if (data) {
- RETURN_ZVAL(data, 1, 0);
+ ZVAL_DEREF(data);
+ ZVAL_COPY(return_value, data);
}
}
diff --git a/ext/intl/tests/collator_get_sort_key_variant4.phpt b/ext/intl/tests/collator_get_sort_key_variant4.phpt
index 2c86f21111..ed2c9bc175 100644
--- a/ext/intl/tests/collator_get_sort_key_variant4.phpt
+++ b/ext/intl/tests/collator_get_sort_key_variant4.phpt
@@ -1,7 +1,8 @@
--TEST--
-collator_get_sort_key() icu >= 54.1
+collator_get_sort_key() icu >= 55.1
--SKIPIF--
<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+<?php if (version_compare(INTL_ICU_VERSION, '55.1') >= 0) die('skip for ICU < 55.1'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '54.1') < 0) die('skip for ICU >= 54.1'); ?>
--FILE--
<?php
diff --git a/ext/intl/tests/collator_get_sort_key_variant5.phpt b/ext/intl/tests/collator_get_sort_key_variant5.phpt
new file mode 100644
index 0000000000..52a3af9766
--- /dev/null
+++ b/ext/intl/tests/collator_get_sort_key_variant5.phpt
@@ -0,0 +1,98 @@
+--TEST--
+collator_get_sort_key() icu >= 55.1
+--SKIPIF--
+<?php if( !extension_loaded( 'intl' ) ) print 'skip'; ?>
+<?php if (version_compare(INTL_ICU_VERSION, '55.1') < 0) die('skip for ICU >= 55.1'); ?>
+--FILE--
+<?php
+
+/*
+ * Get sort keys using various locales
+ */
+function sort_arrays( $locale, $data )
+{
+ $res_str = '';
+
+ $coll = ut_coll_create( $locale );
+
+ foreach($data as $value) {
+ $res_val = ut_coll_get_sort_key( $coll, $value );
+ $res_str .= "source: ".$value."\n".
+ "key: ".bin2hex($res_val)."\n";
+ }
+
+ return $res_str;
+}
+
+
+function ut_main()
+{
+ $res_str = '';
+
+ // Regular strings keys
+ $test_params = array(
+ 'abc', 'abd', 'aaa',
+ 'аа', 'а', 'z',
+ '', null , '3',
+ 'y' , 'i' , 'k'
+ );
+
+ $res_str .= sort_arrays( 'en_US', $test_params );
+
+ // Sort a non-ASCII array using ru_RU locale.
+ $test_params = array(
+ 'абг', 'абв', 'жжж', 'эюя'
+ );
+
+ $res_str .= sort_arrays( 'ru_RU', $test_params );
+
+ // Sort an array using Lithuanian locale.
+ $res_str .= sort_arrays( 'lt_LT', $test_params );
+
+ return $res_str . "\n";
+}
+
+include_once( 'ut_common.inc' );
+ut_run();
+?>
+--EXPECT--
+source: abc
+key: 292b2d01070107
+source: abd
+key: 292b2f01070107
+source: aaa
+key: 29292901070107
+source: аа
+key: 60060601060106
+source: а
+key: 600601050105
+source: z
+key: 5b01050105
+source:
+key: 0101
+source:
+key: 0101
+source: 3
+key: 1801050105
+source: y
+key: 5901050105
+source: i
+key: 3901050105
+source: k
+key: 3d01050105
+source: абг
+key: 26060c1001070107
+source: абв
+key: 26060c0e01070107
+source: жжж
+key: 2626262601070107
+source: эюя
+key: 26b4b6ba01070107
+source: абг
+key: 60060c1001070107
+source: абв
+key: 60060c0e01070107
+source: жжж
+key: 6026262601070107
+source: эюя
+key: 60b4b6ba01070107
diff --git a/ext/intl/tests/dateformat_calendars_variant3.phpt b/ext/intl/tests/dateformat_calendars_variant3.phpt
index 36a67e6f04..d5bdac7fcd 100644
--- a/ext/intl/tests/dateformat_calendars_variant3.phpt
+++ b/ext/intl/tests/dateformat_calendars_variant3.phpt
@@ -41,5 +41,8 @@ string(47) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12"
string(47) "Sunday, January 1, 2012 at 5:12:00 AM GMT+05:12"
string(44) "Sunday, 6 Tevet 5772 at 5:12:00 AM GMT+05:12"
-Warning: IntlDateFormatter::__construct(): datefmt_create: invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object in %sdateformat_calendars_variant%d.php on line %d
-==DONE==
+Fatal error: Uncaught IntlException: IntlDateFormatter::__construct(): datefmt_create: invalid value for calendar type; it must be one of IntlDateFormatter::TRADITIONAL (locale's default calendar) or IntlDateFormatter::GREGORIAN. Alternatively, it can be an IntlCalendar object in %sdateformat_calendars_variant3.php:27
+Stack trace:
+#0 %sdateformat_calendars_variant3.php(%d): IntlDateFormatter->__construct('en_US@calendar=...', 0, 0, 'GMT+05:12', -1)
+#1 {main}
+ thrown %sdateformat_calendars_variant3.php on line %d
diff --git a/ext/intl/tests/dateformat_formatObject_calendar_variant4.phpt b/ext/intl/tests/dateformat_formatObject_calendar_variant4.phpt
index 2ca57c245f..70a8adc913 100644
--- a/ext/intl/tests/dateformat_formatObject_calendar_variant4.phpt
+++ b/ext/intl/tests/dateformat_formatObject_calendar_variant4.phpt
@@ -4,6 +4,7 @@ IntlDateFormatter::formatObject(): IntlCalendar tests
<?php
if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '54.1') < 0) die('skip for ICU >= 54.1'); ?>
+<?php if (version_compare(INTL_ICU_VERSION, '55.1') >= 0) die('skip for ICU < 55.1'); ?>
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
diff --git a/ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt b/ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt
new file mode 100644
index 0000000000..d68b1f5fcb
--- /dev/null
+++ b/ext/intl/tests/dateformat_formatObject_calendar_variant5.phpt
@@ -0,0 +1,40 @@
+--TEST--
+IntlDateFormatter::formatObject(): IntlCalendar tests
+--SKIPIF--
+<?php
+if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
+<?php if (version_compare(INTL_ICU_VERSION, '55.1') < 0) die('skip for ICU >= 55.1'); ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+ini_set("intl.default_locale", "pt_PT");
+ini_set("date.timezone", "Europe/Lisbon");
+
+$cal = IntlCalendar::fromDateTime('2012-01-01 00:00:00'); //Europe/Lisbon
+echo IntlDateFormatter::formatObject($cal), "\n";
+echo IntlDateFormatter::formatObject($cal, IntlDateFormatter::FULL), "\n";
+echo IntlDateFormatter::formatObject($cal, null, "en-US"), "\n";
+echo IntlDateFormatter::formatObject($cal, array(IntlDateFormatter::SHORT, IntlDateFormatter::FULL), "en-US"), "\n";
+echo IntlDateFormatter::formatObject($cal, 'E y-MM-d HH,mm,ss.SSS v', "en-US"), "\n";
+
+$cal = IntlCalendar::fromDateTime('2012-01-01 05:00:00+03:00');
+echo datefmt_format_object($cal, IntlDateFormatter::FULL), "\n";
+
+$cal = IntlCalendar::createInstance(null,'en-US@calendar=islamic-civil');
+$cal->setTime(strtotime('2012-01-01 00:00:00')*1000.);
+echo IntlDateFormatter::formatObject($cal), "\n";
+echo IntlDateFormatter::formatObject($cal, IntlDateFormatter::FULL, "en-US"), "\n";
+
+?>
+==DONE==
+
+--EXPECTF--
+01/01/2012, 00:00:00
+domingo, 1 de janeiro de 2012 às 00:00:00 Hora padrão %Sda Europa Ocidental
+Jan 1, 2012, 12:00:00 AM
+1/1/12, 12:00:00 AM Western European Standard %STime
+Sun 2012-01-1 00,00,00.000 Portugal Time
+domingo, 1 de janeiro de 2012 às 05:00:00 GMT+03:00
+06/02/1433, 00:00:00
+Sunday, Safar 6, 1433 at 12:00:00 AM Western European Standard Time
+==DONE==
diff --git a/ext/intl/tests/dateformat_formatObject_datetime_variant4.phpt b/ext/intl/tests/dateformat_formatObject_datetime_variant4.phpt
index c47e2b59bd..6ae6dfedd3 100644
--- a/ext/intl/tests/dateformat_formatObject_datetime_variant4.phpt
+++ b/ext/intl/tests/dateformat_formatObject_datetime_variant4.phpt
@@ -4,6 +4,7 @@ IntlDateFormatter::formatObject(): DateTime tests
<?php
if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '54.1') < 0) die('skip for ICU >= 54.1'); ?>
+<?php if (version_compare(INTL_ICU_VERSION, '55.1') >= 0) die('skip for ICU < 55.1'); ?>
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
diff --git a/ext/intl/tests/dateformat_formatObject_datetime_variant5.phpt b/ext/intl/tests/dateformat_formatObject_datetime_variant5.phpt
new file mode 100644
index 0000000000..22b0f6adbe
--- /dev/null
+++ b/ext/intl/tests/dateformat_formatObject_datetime_variant5.phpt
@@ -0,0 +1,33 @@
+--TEST--
+IntlDateFormatter::formatObject(): DateTime tests
+--SKIPIF--
+<?php
+if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
+<?php if (version_compare(INTL_ICU_VERSION, '55.1') < 0) die('skip for ICU >= 55.1'); ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+ini_set("intl.default_locale", "pt_PT");
+ini_set("date.timezone", "Europe/Lisbon");
+
+$dt = new DateTime('2012-01-01 00:00:00'); //Europe/Lisbon
+echo IntlDateFormatter::formatObject($dt), "\n";
+echo IntlDateFormatter::formatObject($dt, IntlDateFormatter::FULL), "\n";
+echo IntlDateFormatter::formatObject($dt, null, "en-US"), "\n";
+echo IntlDateFormatter::formatObject($dt, array(IntlDateFormatter::SHORT, IntlDateFormatter::FULL), "en-US"), "\n";
+echo IntlDateFormatter::formatObject($dt, 'E y-MM-d HH,mm,ss.SSS v', "en-US"), "\n";
+
+$dt = new DateTime('2012-01-01 05:00:00+03:00');
+echo IntlDateFormatter::formatObject($dt, IntlDateFormatter::FULL), "\n";
+
+?>
+==DONE==
+
+--EXPECTF--
+01/01/2012, 00:00:00
+domingo, 1 de janeiro de 2012 às 00:00:00 Hora padrão %Sda Europa Ocidental
+Jan 1, 2012, 12:00:00 AM
+1/1/12, 12:00:00 AM Western European Standard %STime
+Sun 2012-01-1 00,00,00.000 Portugal Time
+domingo, 1 de janeiro de 2012 às 05:00:00 GMT+03:00
+==DONE==
diff --git a/ext/intl/tests/dateformat_get_set_timezone_variant4.phpt b/ext/intl/tests/dateformat_get_set_timezone_variant4.phpt
index adedd74965..8a563d8a90 100644
--- a/ext/intl/tests/dateformat_get_set_timezone_variant4.phpt
+++ b/ext/intl/tests/dateformat_get_set_timezone_variant4.phpt
@@ -4,6 +4,7 @@ IntlDateFormatter: get/setTimeZone()
<?php
if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
<?php if (version_compare(INTL_ICU_VERSION, '54.1') < 0) die('skip for ICU >= 54.1'); ?>
+<?php if (version_compare(INTL_ICU_VERSION, '55.1') >= 0) die('skip for ICU < 55.1'); ?>
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
diff --git a/ext/intl/tests/dateformat_get_set_timezone_variant5.phpt b/ext/intl/tests/dateformat_get_set_timezone_variant5.phpt
new file mode 100644
index 0000000000..1487751bd6
--- /dev/null
+++ b/ext/intl/tests/dateformat_get_set_timezone_variant5.phpt
@@ -0,0 +1,62 @@
+--TEST--
+IntlDateFormatter: get/setTimeZone()
+--SKIPIF--
+<?php
+if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
+<?php if (version_compare(INTL_ICU_VERSION, '55.1') < 0) die('skip for ICU >= 55.1'); ?>
+--FILE--
+<?php
+ini_set("intl.error_level", E_WARNING);
+ini_set("intl.default_locale", "pt_PT");
+ini_set("date.timezone", 'Atlantic/Azores');
+
+$ts = strtotime('2012-01-01 00:00:00 UTC');
+
+function d(IntlDateFormatter $df) {
+global $ts;
+echo $df->format($ts), "\n";
+var_dump(
+$df->getTimeZoneID(),
+$df->getTimeZone()->getID());
+echo "\n";
+}
+
+$df = new IntlDateFormatter('pt_PT', 0, 0, 'Europe/Minsk');
+d($df);
+
+$df->setTimeZone(NULL);
+d($df);
+
+$df->setTimeZone('Europe/Madrid');
+d($df);
+
+$df->setTimeZone(IntlTimeZone::createTimeZone('Europe/Paris'));
+d($df);
+
+$df->setTimeZone(new DateTimeZone('Europe/Amsterdam'));
+d($df);
+
+?>
+==DONE==
+--EXPECTF--
+domingo, 1 de janeiro de 2012 às 03:00:00 Hor%s do Extremo Leste da Europa
+string(12) "Europe/Minsk"
+string(12) "Europe/Minsk"
+
+sábado, 31 de dezembro de 2011 às 23:00:00 Hor%s padrão %Sdos Açores
+string(15) "Atlantic/Azores"
+string(15) "Atlantic/Azores"
+
+domingo, 1 de janeiro de 2012 às 01:00:00 Hor%s padrão %Sda Europa Central
+string(13) "Europe/Madrid"
+string(13) "Europe/Madrid"
+
+domingo, 1 de janeiro de 2012 às 01:00:00 Hor%s padrão %Sda Europa Central
+string(12) "Europe/Paris"
+string(12) "Europe/Paris"
+
+domingo, 1 de janeiro de 2012 às 01:00:00 Hor%s padrão %Sda Europa Central
+string(16) "Europe/Amsterdam"
+string(16) "Europe/Amsterdam"
+
+==DONE==
diff --git a/ext/intl/tests/spoofchecker_004.phpt b/ext/intl/tests/spoofchecker_004.phpt
index b38c61d717..a26b39209f 100644
--- a/ext/intl/tests/spoofchecker_004.phpt
+++ b/ext/intl/tests/spoofchecker_004.phpt
@@ -2,6 +2,7 @@
spoofchecker with settings changed
--SKIPIF--
<?php if(!extension_loaded('intl') || !class_exists("Spoofchecker")) print 'skip'; ?>
+<?php if (version_compare(INTL_ICU_VERSION, '55.1') >= 0) die('skip for ICU < 55.1'); ?>
--FILE--
<?php
diff --git a/ext/intl/tests/spoofchecker_005.phpt b/ext/intl/tests/spoofchecker_005.phpt
new file mode 100644
index 0000000000..0fc3d52a8c
--- /dev/null
+++ b/ext/intl/tests/spoofchecker_005.phpt
@@ -0,0 +1,29 @@
+--TEST--
+spoofchecker with settings changed
+--SKIPIF--
+<?php if(!extension_loaded('intl') || !class_exists("Spoofchecker")) print 'skip'; ?>
+<?php if (version_compare(INTL_ICU_VERSION, '55.1') < 0) die('skip for ICU >= 55.1'); ?>
+--FILE--
+<?php
+
+$korean = "\xED\x95\x9C" . "\xEA\xB5\xAD" . "\xEB\xA7\x90";
+
+$x = new Spoofchecker();
+echo "Check with default settings\n";
+var_dump($x->areConfusable("HELLO", "H\xD0\x95LLO"));
+var_dump($x->areConfusable("hello", "h\xD0\xB5llo"));
+
+echo "Change confusable settings\n";
+$x->setChecks(Spoofchecker::MIXED_SCRIPT_CONFUSABLE |
+ Spoofchecker::WHOLE_SCRIPT_CONFUSABLE |
+ Spoofchecker::SINGLE_SCRIPT_CONFUSABLE);
+var_dump($x->areConfusable("HELLO", "H\xD0\x95LLO"));
+var_dump($x->areConfusable("hello", "h\xD0\xB5llo"));
+?>
+--EXPECTF--
+Check with default settings
+bool(true)
+bool(true)
+Change confusable settings
+bool(true)
+bool(true)
diff --git a/ext/intl/tests/timezone_getDisplayName_variant3-49+.phpt b/ext/intl/tests/timezone_getDisplayName_variant3-49+.phpt
index e90cc4748c..e67fcab491 100644
--- a/ext/intl/tests/timezone_getDisplayName_variant3-49+.phpt
+++ b/ext/intl/tests/timezone_getDisplayName_variant3-49+.phpt
@@ -1,11 +1,9 @@
--TEST--
IntlTimeZone::getDisplayName(): locale parameter
--SKIPIF--
-<?php
-if (!extension_loaded('intl'))
- die('skip intl extension not enabled');
-if (version_compare(INTL_ICU_VERSION, '49') < 0)
- die('skip for ICU 49+');
+<?php if (!extension_loaded('intl')) die('skip intl extension not enabled'); ?>
+<?php if (version_compare(INTL_ICU_VERSION, '49') < 0) die('skip for ICU >= 49'); ?>
+<?php if (version_compare(INTL_ICU_VERSION, '55.1') >= 0) die('skip for ICU < 55.1'); ?>
--FILE--
<?php
ini_set("intl.error_level", E_WARNING);
diff --git a/ext/intl/timezone/timezone_methods.cpp b/ext/intl/timezone/timezone_methods.cpp
index 641727d7ed..728f9bde8b 100644
--- a/ext/intl/timezone/timezone_methods.cpp
+++ b/ext/intl/timezone/timezone_methods.cpp
@@ -614,7 +614,7 @@ U_CFUNC PHP_FUNCTION(intltz_to_date_time_zone)
&TIMEZONE_ERROR(to), "intltz_to_date_time_zone", &tmp);
if (ret) {
- RETURN_ZVAL(ret, 1, 1);
+ ZVAL_COPY_VALUE(return_value, ret);
} else {
RETURN_FALSE;
}
diff --git a/ext/json/json_parser.tab.c b/ext/json/json_parser.tab.c
index a5f5c6fb09..45a982bbcc 100644
--- a/ext/json/json_parser.tab.c
+++ b/ext/json/json_parser.tab.c
@@ -514,10 +514,10 @@ static const yytype_uint8 yytranslate[] =
/* YYRLINE[YYN] -- Source line where rule number YYN was defined. */
static const yytype_uint8 yyrline[] =
{
- 0, 92, 92, 93, 97, 97, 101, 102, 106, 107,
- 111, 112, 113, 117, 118, 122, 122, 126, 127, 131,
- 132, 136, 137, 138, 142, 143, 147, 148, 149, 150,
- 151, 152, 153, 154, 155, 156, 160
+ 0, 92, 92, 98, 105, 105, 113, 114, 123, 126,
+ 130, 135, 140, 147, 152, 159, 159, 167, 168, 177,
+ 180, 184, 189, 194, 201, 202, 206, 207, 208, 209,
+ 210, 211, 212, 213, 214, 215, 219
};
#endif
@@ -1447,13 +1447,19 @@ yyreduce:
{
case 2:
- { ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-1].value)); ZVAL_COPY_VALUE(parser->return_value, &(yyvsp[-1].value)); PHP_JSON_USE((yyvsp[0].value)); YYACCEPT; }
+ {
+ ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-1].value));
+ ZVAL_COPY_VALUE(parser->return_value, &(yyvsp[-1].value));
+ PHP_JSON_USE((yyvsp[0].value)); YYACCEPT;
+ }
break;
case 3:
- { PHP_JSON_USE_2((yyval.value), (yyvsp[-1].value), (yyvsp[0].value)); }
+ {
+ PHP_JSON_USE_2((yyval.value), (yyvsp[-1].value), (yyvsp[0].value));
+ }
break;
@@ -1465,49 +1471,70 @@ yyreduce:
case 5:
- { PHP_JSON_DEPTH_DEC; (yyval.value) = (yyvsp[-1].value); }
+ {
+ PHP_JSON_DEPTH_DEC;
+ (yyval.value) = (yyvsp[-1].value);
+ }
break;
case 7:
- { parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH; YYERROR; }
+ {
+ parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH;
+ YYERROR;
+ }
break;
case 8:
- { php_json_parser_object_init(parser, &(yyval.value)); }
+ {
+ php_json_parser_object_init(parser, &(yyval.value));
+ }
break;
case 10:
- { php_json_parser_object_init(parser, &(yyval.value)); php_json_parser_object_update(parser, &(yyval.value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val); }
+ {
+ php_json_parser_object_init(parser, &(yyval.value));
+ php_json_parser_object_update(parser, &(yyval.value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val);
+ }
break;
case 11:
- { php_json_parser_object_update(parser, &(yyvsp[-2].value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val); ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-2].value)); }
+ {
+ php_json_parser_object_update(parser, &(yyvsp[-2].value), (yyvsp[0].pair).key, &(yyvsp[0].pair).val);
+ ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-2].value));
+ }
break;
case 12:
- { PHP_JSON_USE_2((yyval.value), (yyvsp[-1].value), (yyvsp[0].value)); }
+ {
+ PHP_JSON_USE_2((yyval.value), (yyvsp[-1].value), (yyvsp[0].value));
+ }
break;
case 13:
- { (yyval.pair).key = Z_STR((yyvsp[-2].value)); ZVAL_COPY_VALUE(&(yyval.pair).val, &(yyvsp[0].value)); }
+ {
+ (yyval.pair).key = Z_STR((yyvsp[-2].value));
+ ZVAL_COPY_VALUE(&(yyval.pair).val, &(yyvsp[0].value));
+ }
break;
case 14:
- { PHP_JSON_USE_2((yyval.pair), (yyvsp[-1].value), (yyvsp[0].value)); }
+ {
+ PHP_JSON_USE_2((yyval.pair), (yyvsp[-1].value), (yyvsp[0].value));
+ }
break;
@@ -1519,43 +1546,62 @@ yyreduce:
case 16:
- { PHP_JSON_DEPTH_DEC; ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-1].value)); }
+ {
+ PHP_JSON_DEPTH_DEC;
+ ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-1].value));
+ }
break;
case 18:
- { parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH; YYERROR; }
+ {
+ parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH;
+ YYERROR;
+ }
break;
case 19:
- { php_json_parser_array_init(&(yyval.value)); }
+ {
+ php_json_parser_array_init(&(yyval.value));
+ }
break;
case 21:
- { php_json_parser_array_init(&(yyval.value)); php_json_parser_array_append(&(yyval.value), &(yyvsp[0].value)); }
+ {
+ php_json_parser_array_init(&(yyval.value));
+ php_json_parser_array_append(&(yyval.value), &(yyvsp[0].value));
+ }
break;
case 22:
- { php_json_parser_array_append(&(yyvsp[-2].value), &(yyvsp[0].value)); ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-2].value)); }
+ {
+ php_json_parser_array_append(&(yyvsp[-2].value), &(yyvsp[0].value));
+ ZVAL_COPY_VALUE(&(yyval.value), &(yyvsp[-2].value));
+ }
break;
case 23:
- { PHP_JSON_USE_2((yyval.value), (yyvsp[-1].value), (yyvsp[0].value)); }
+ {
+ PHP_JSON_USE_2((yyval.value), (yyvsp[-1].value), (yyvsp[0].value));
+ }
break;
case 36:
- { PHP_JSON_USE_1((yyval.value), (yyvsp[0].value)); YYERROR; }
+ {
+ PHP_JSON_USE_1((yyval.value), (yyvsp[0].value));
+ YYERROR;
+ }
break;
diff --git a/ext/json/json_parser.y b/ext/json/json_parser.y
index 044b82eb51..500a0ff11d 100644
--- a/ext/json/json_parser.y
+++ b/ext/json/json_parser.y
@@ -89,53 +89,112 @@ void php_json_parser_array_append(zval *array, zval *zvalue);
%% /* Rules */
start:
- value PHP_JSON_T_EOI { ZVAL_COPY_VALUE(&$$, &$1); ZVAL_COPY_VALUE(parser->return_value, &$1); PHP_JSON_USE($2); YYACCEPT; }
- | value errlex { PHP_JSON_USE_2($$, $1, $2); }
+ value PHP_JSON_T_EOI
+ {
+ ZVAL_COPY_VALUE(&$$, &$1);
+ ZVAL_COPY_VALUE(parser->return_value, &$1);
+ PHP_JSON_USE($2); YYACCEPT;
+ }
+ | value errlex
+ {
+ PHP_JSON_USE_2($$, $1, $2);
+ }
;
object:
- '{' { PHP_JSON_DEPTH_INC; } members object_end { PHP_JSON_DEPTH_DEC; $$ = $3; }
+ '{' { PHP_JSON_DEPTH_INC; } members object_end
+ {
+ PHP_JSON_DEPTH_DEC;
+ $$ = $3;
+ }
;
object_end:
'}'
- | ']' { parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH; YYERROR; }
+ | ']'
+ {
+ parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH;
+ YYERROR;
+ }
;
members:
- /* empty */ { php_json_parser_object_init(parser, &$$); }
+ /* empty */
+ {
+ php_json_parser_object_init(parser, &$$);
+ }
| member
;
member:
- pair { php_json_parser_object_init(parser, &$$); php_json_parser_object_update(parser, &$$, $1.key, &$1.val); }
- | member ',' pair { php_json_parser_object_update(parser, &$1, $3.key, &$3.val); ZVAL_COPY_VALUE(&$$, &$1); }
- | member errlex { PHP_JSON_USE_2($$, $1, $2); }
+ pair
+ {
+ php_json_parser_object_init(parser, &$$);
+ php_json_parser_object_update(parser, &$$, $1.key, &$1.val);
+ }
+ | member ',' pair
+ {
+ php_json_parser_object_update(parser, &$1, $3.key, &$3.val);
+ ZVAL_COPY_VALUE(&$$, &$1);
+ }
+ | member errlex
+ {
+ PHP_JSON_USE_2($$, $1, $2);
+ }
;
pair:
- key ':' value { $$.key = Z_STR($1); ZVAL_COPY_VALUE(&$$.val, &$3); }
- | key errlex { PHP_JSON_USE_2($$, $1, $2); }
+ key ':' value
+ {
+ $$.key = Z_STR($1);
+ ZVAL_COPY_VALUE(&$$.val, &$3);
+ }
+ | key errlex
+ {
+ PHP_JSON_USE_2($$, $1, $2);
+ }
;
array:
- '[' { PHP_JSON_DEPTH_INC; } elements array_end { PHP_JSON_DEPTH_DEC; ZVAL_COPY_VALUE(&$$, &$3); }
+ '[' { PHP_JSON_DEPTH_INC; } elements array_end
+ {
+ PHP_JSON_DEPTH_DEC;
+ ZVAL_COPY_VALUE(&$$, &$3);
+ }
;
array_end:
']'
- | '}' { parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH; YYERROR; }
+ | '}'
+ {
+ parser->scanner.errcode = PHP_JSON_ERROR_STATE_MISMATCH;
+ YYERROR;
+ }
;
elements:
- /* empty */ { php_json_parser_array_init(&$$); }
+ /* empty */
+ {
+ php_json_parser_array_init(&$$);
+ }
| element
;
element:
- value { php_json_parser_array_init(&$$); php_json_parser_array_append(&$$, &$1); }
- | element ',' value { php_json_parser_array_append(&$1, &$3); ZVAL_COPY_VALUE(&$$, &$1); }
- | element errlex { PHP_JSON_USE_2($$, $1, $2); }
+ value
+ {
+ php_json_parser_array_init(&$$);
+ php_json_parser_array_append(&$$, &$1);
+ }
+ | element ',' value
+ {
+ php_json_parser_array_append(&$1, &$3);
+ ZVAL_COPY_VALUE(&$$, &$1);
+ }
+ | element errlex
+ {
+ PHP_JSON_USE_2($$, $1, $2);
+ }
;
key:
@@ -157,7 +216,11 @@ value:
;
errlex:
- PHP_JSON_T_ERROR { PHP_JSON_USE_1($$, $1); YYERROR; }
+ PHP_JSON_T_ERROR
+ {
+ PHP_JSON_USE_1($$, $1);
+ YYERROR;
+ }
;
%% /* Functions */
diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
index b96d25aa80..bb87a389b4 100644
--- a/ext/libxml/libxml.c
+++ b/ext/libxml/libxml.c
@@ -815,6 +815,9 @@ static PHP_MINIT_FUNCTION(libxml)
#if LIBXML_VERSION >= 20703
REGISTER_LONG_CONSTANT("LIBXML_PARSEHUGE", XML_PARSE_HUGE, CONST_CS | CONST_PERSISTENT);
#endif
+#if LIBXML_VERSION >= 20900
+ REGISTER_LONG_CONSTANT("LIBXML_BIGLINES", XML_PARSE_BIG_LINES, CONST_CS | CONST_PERSISTENT);
+#endif
REGISTER_LONG_CONSTANT("LIBXML_NOEMPTYTAG", LIBXML_SAVE_NOEMPTYTAG, CONST_CS | CONST_PERSISTENT);
/* Schema validation options */
@@ -1341,7 +1344,7 @@ PHP_LIBXML_API void php_libxml_node_decrement_resource(php_libxml_node_object *o
}
/* }}} */
-#ifdef PHP_WIN32
+#if defined(PHP_WIN32) && defined(COMPILE_DL_LIBXML)
PHP_LIBXML_API BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
{
return xmlDllMain(hinstDLL, fdwReason, lpvReserved);
diff --git a/ext/libxml/tests/bug54138.phpt b/ext/libxml/tests/bug54138.phpt
new file mode 100644
index 0000000000..5a03f2ce07
--- /dev/null
+++ b/ext/libxml/tests/bug54138.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Bug #54138 - DOMNode::getLineNo() doesn't return line number higher than 65535
+--SKIPIF--
+<?php
+if (!extension_loaded('dom')) die('skip dom extension not available');
+if (!defined('LIBXML_BIGLINES')) die('skip this test requires LIBXML_BIGLINES');
+?>
+--FILE--
+<?php
+$foos = str_repeat('<foo/>' . PHP_EOL, 65535);
+$xml = <<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+$foos
+<bar/>
+</root>
+XML;
+$dom = new DOMDocument();
+$dom->loadXML($xml, LIBXML_BIGLINES);
+var_dump($dom->getElementsByTagName('bar')->item(0)->getLineNo());
+?>
+--EXPECT--
+int(65540)
diff --git a/ext/libxml/tests/bug54138_1.phpt b/ext/libxml/tests/bug54138_1.phpt
new file mode 100644
index 0000000000..f0a8a04698
--- /dev/null
+++ b/ext/libxml/tests/bug54138_1.phpt
@@ -0,0 +1,24 @@
+--TEST--
+Bug #54138 - DOMNode::getLineNo() doesn't return line number higher than 65535
+--SKIPIF--
+<?php
+if (!extension_loaded('dom')) die('skip dom extension not available');
+if (LIBXML_VERSION >= 20900) die('skip this test is for libxml < 2.9.0 only');
+?>
+--FILE--
+<?php
+define('LIBXML_BIGLINES', 1<<22);
+$foos = str_repeat('<foo/>' . PHP_EOL, 65535);
+$xml = <<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+$foos
+<bar/>
+</root>
+XML;
+$dom = new DOMDocument();
+$dom->loadXML($xml, LIBXML_BIGLINES);
+var_dump($dom->getElementsByTagName('bar')->item(0)->getLineNo());
+?>
+--EXPECT--
+int(65535)
diff --git a/ext/libxml/tests/bug54138_2.phpt b/ext/libxml/tests/bug54138_2.phpt
new file mode 100644
index 0000000000..b25e451527
--- /dev/null
+++ b/ext/libxml/tests/bug54138_2.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Bug #54138 - DOMNode::getLineNo() doesn't return line number higher than 65535
+--SKIPIF--
+<?php
+if (!extension_loaded('dom')) die('skip dom extension not available');
+if (LIBXML_VERSION < 20900) die('skip this test is for libxml >= 2.9.0 only');
+if (defined('LIBXML_BIGLINES')) die('skip this test is for LIBXML_BIGLINES being undefined');
+?>
+--FILE--
+<?php
+define('LIBXML_BIGLINES', 1<<22);
+$foos = str_repeat('<foo/>' . PHP_EOL, 65535);
+$xml = <<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+$foos
+<bar/>
+</root>
+XML;
+$dom = new DOMDocument();
+$dom->loadXML($xml, LIBXML_BIGLINES);
+var_dump($dom->getElementsByTagName('bar')->item(0)->getLineNo());
+?>
+--EXPECT--
+int(65540)
diff --git a/ext/libxml/tests/bug69753.phpt b/ext/libxml/tests/bug69753.phpt
new file mode 100644
index 0000000000..63d1295b6e
--- /dev/null
+++ b/ext/libxml/tests/bug69753.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #69753 - libXMLError::file contains invalid URI
+--XFAIL--
+Awaiting upstream fix: https://bugzilla.gnome.org/show_bug.cgi?id=750365
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') die("skip this test is for Windows platforms only");
+if (!extension_loaded('dom')) die('skip dom extension not available');
+?>
+--FILE--
+<?php
+libxml_use_internal_errors(true);
+$doc = new DomDocument();
+$doc->load(__DIR__ . DIRECTORY_SEPARATOR . 'bug69753.xml');
+$error = libxml_get_last_error();
+var_dump($error->file);
+?>
+--EXPECTF--
+string(%d) "file:///%s/ext/libxml/tests/bug69753.xml"
diff --git a/ext/libxml/tests/bug69753.xml b/ext/libxml/tests/bug69753.xml
new file mode 100644
index 0000000000..63b18d5c6d
--- /dev/null
+++ b/ext/libxml/tests/bug69753.xml
@@ -0,0 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<root>
+ <sub>
+</root>
diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c
index 9bc81769d5..d076614418 100644
--- a/ext/mysqli/mysqli.c
+++ b/ext/mysqli/mysqli.c
@@ -306,7 +306,7 @@ zval *mysqli_read_property(zval *object, zval *member, int type, void **cache_sl
obj = Z_MYSQLI_P(object);
if (Z_TYPE_P(member) != IS_STRING) {
- ZVAL_DUP(&tmp_member, member);
+ ZVAL_COPY(&tmp_member, member);
convert_to_string(&tmp_member);
member = &tmp_member;
}
@@ -341,7 +341,7 @@ void mysqli_write_property(zval *object, zval *member, zval *value, void **cache
mysqli_prop_handler *hnd = NULL;
if (Z_TYPE_P(member) != IS_STRING) {
- ZVAL_DUP(&tmp_member, member);
+ ZVAL_COPY(&tmp_member, member);
convert_to_string(&tmp_member);
member = &tmp_member;
}
diff --git a/ext/mysqlnd/mysqlnd_ps.c b/ext/mysqlnd/mysqlnd_ps.c
index 70ea4e4874..767ba34ab0 100644
--- a/ext/mysqlnd/mysqlnd_ps.c
+++ b/ext/mysqlnd/mysqlnd_ps.c
@@ -925,6 +925,8 @@ mysqlnd_stmt_fetch_row_unbuffered(MYSQLND_RES * result, void * param, unsigned i
ZVAL_COPY_VALUE(result, data);
/* copied data, thus also the ownership. Thus null data */
ZVAL_NULL(data);
+ } else {
+ ZVAL_NULL(result);
}
}
}
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c
index 275e3f5fa2..fe20248fee 100644
--- a/ext/opcache/Optimizer/block_pass.c
+++ b/ext/opcache/Optimizer/block_pass.c
@@ -123,12 +123,9 @@ static int find_code_blocks(zend_op_array *op_array, zend_cfg *cfg, zend_optimiz
blocks[0].start_opline_no = 0;
while (opline < end) {
switch((unsigned)opline->opcode) {
- case ZEND_BRK:
- case ZEND_CONT:
case ZEND_GOTO:
- /* would not optimize non-optimized BRK/CONTs - we cannot
- really know where it jumps, so these optimizations are
- too dangerous */
+ /* would not optimize GOTOs - we cannot really know where it jumps,
+ * so these optimizations are too dangerous */
return 0;
case ZEND_FAST_CALL:
START_BLOCK_OP(ZEND_OP1(opline).opline_num);
diff --git a/ext/opcache/Optimizer/compact_literals.c b/ext/opcache/Optimizer/compact_literals.c
index fd83e76461..c72e8f6772 100644
--- a/ext/opcache/Optimizer/compact_literals.c
+++ b/ext/opcache/Optimizer/compact_literals.c
@@ -301,13 +301,14 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
#if DEBUG_COMPACT_LITERALS
{
int i, use_copy;
- 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");
fprintf(stderr, "Literlas table size %d\n", op_array->last_literal);
for (i = 0; i < op_array->last_literal; i++) {
- zval zv = op_array->literals[i].constant;
- use_copy = zend_make_printable_zval(&op_array->literals[i].constant, &zv);
+ zval zv;
+ ZVAL_COPY_VALUE(&zv, op_array->literals + i);
+ use_copy = zend_make_printable_zval(op_array->literals + i, &zv);
fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv));
if (use_copy) {
zval_dtor(&zv);
@@ -487,8 +488,9 @@ void zend_optimizer_compact_literals(zend_op_array *op_array, zend_optimizer_ctx
fprintf(stderr, "Optimized literlas table size %d\n", op_array->last_literal);
for (i = 0; i < op_array->last_literal; i++) {
- zval zv = op_array->literals[i].constant;
- use_copy = zend_make_printable_zval(&op_array->literals[i].constant, &zv);
+ zval zv;
+ ZVAL_COPY_VALUE(&zv, op_array->literals + i);
+ use_copy = zend_make_printable_zval(op_array->literals + i, &zv);
fprintf(stderr, "Literal %d, val (%d):%s\n", i, Z_STRLEN(zv), Z_STRVAL(zv));
if (use_copy) {
zval_dtor(&zv);
diff --git a/ext/opcache/Optimizer/pass1_5.c b/ext/opcache/Optimizer/pass1_5.c
index c042940b0e..611b39df24 100644
--- a/ext/opcache/Optimizer/pass1_5.c
+++ b/ext/opcache/Optimizer/pass1_5.c
@@ -613,8 +613,6 @@ void zend_optimizer_pass1(zend_op_array *op_array, zend_optimizer_ctx *ctx)
case ZEND_EXIT:
case ZEND_THROW:
case ZEND_CATCH:
- case ZEND_BRK:
- case ZEND_CONT:
case ZEND_GOTO:
case ZEND_FAST_CALL:
case ZEND_FAST_RET:
diff --git a/ext/opcache/Optimizer/pass2.c b/ext/opcache/Optimizer/pass2.c
index c0832a1cbf..a9d85daa6f 100644
--- a/ext/opcache/Optimizer/pass2.c
+++ b/ext/opcache/Optimizer/pass2.c
@@ -181,59 +181,6 @@ void zend_optimizer_pass2(zend_op_array *op_array)
opline->opcode = ZEND_JMP;
}
break;
-
- case ZEND_BRK:
- case ZEND_CONT:
- {
- zend_brk_cont_element *jmp_to;
- int array_offset;
- int nest_levels;
- int dont_optimize = 0;
-
- ZEND_ASSERT(ZEND_OP2_TYPE(opline) == IS_CONST);
- ZEND_ASSERT(Z_TYPE(ZEND_OP2_LITERAL(opline)) == IS_LONG);
-
- nest_levels = Z_LVAL(ZEND_OP2_LITERAL(opline));
-
- array_offset = ZEND_OP1(opline).opline_num;
- while (1) {
- if (array_offset == -1) {
- dont_optimize = 1; /* don't optimize this bogus break/continue, let the executor shout */
- break;
- }
- jmp_to = &op_array->brk_cont_array[array_offset];
- array_offset = jmp_to->parent;
- if (--nest_levels > 0) {
- if (op_array->opcodes[jmp_to->brk].opcode == ZEND_FREE ||
- op_array->opcodes[jmp_to->brk].opcode == ZEND_FE_FREE ||
- op_array->opcodes[jmp_to->brk].opcode == ZEND_END_SILENCE) {
- dont_optimize = 1;
- break;
- }
- } else {
- break;
- }
- }
-
- if (dont_optimize) {
- break;
- }
-
- /* optimize - convert to a JMP */
- switch (opline->opcode) {
- case ZEND_BRK:
- MAKE_NOP(opline);
- ZEND_OP1(opline).opline_num = jmp_to->brk;
- break;
- case ZEND_CONT:
- MAKE_NOP(opline);
- ZEND_OP1(opline).opline_num = jmp_to->cont;
- break;
- }
- opline->opcode = ZEND_JMP;
- /* MAKE_NOP() already set op1 and op2 to IS_UNUSED */
- }
- break;
}
opline++;
}
diff --git a/ext/opcache/Optimizer/pass3.c b/ext/opcache/Optimizer/pass3.c
index 3019b274e9..cb717998d6 100644
--- a/ext/opcache/Optimizer/pass3.c
+++ b/ext/opcache/Optimizer/pass3.c
@@ -322,8 +322,6 @@ continue_jmp_ex_optimization:
op->opcode == ZEND_JMPNZ ||
op->opcode == ZEND_JMPNZ_EX ||
op->opcode == ZEND_JMPZNZ ||
- op->opcode == ZEND_BRK ||
- op->opcode == ZEND_CONT ||
op->opcode == ZEND_CASE ||
op->opcode == ZEND_RETURN ||
op->opcode == ZEND_RETURN_BY_REF ||
@@ -358,8 +356,6 @@ continue_jmp_ex_optimization:
op->opcode == ZEND_JMPNZ ||
op->opcode == ZEND_JMPNZ_EX ||
op->opcode == ZEND_JMPZNZ ||
- op->opcode == ZEND_BRK ||
- op->opcode == ZEND_CONT ||
op->opcode == ZEND_CASE ||
op->opcode == ZEND_RETURN ||
op->opcode == ZEND_RETURN_BY_REF ||
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index c9f58963ac..36684218d8 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -2146,7 +2146,6 @@ static inline void zend_accel_fast_del_bucket(HashTable *ht, uint32_t idx, Bucke
uint32_t nIndex = p->h | ht->nTableMask;
uint32_t i = HT_HASH(ht, nIndex);
- ht->nNumUsed--;
ht->nNumOfElements--;
if (idx != i) {
Bucket *prev = HT_HASH_TO_BUCKET(ht, i);
@@ -2267,6 +2266,9 @@ static void zend_accel_fast_shutdown(void)
zend_accel_fast_del_bucket(EG(zend_constants), HT_IDX_TO_HASH(_idx-1), _p);
}
} ZEND_HASH_FOREACH_END();
+ EG(function_table)->nNumUsed = EG(function_table)->nNumOfElements;
+ EG(class_table)->nNumUsed = EG(class_table)->nNumOfElements;
+ EG(zend_constants)->nNumUsed = EG(zend_constants)->nNumOfElements;
CG(unclean_shutdown) = 1;
}
diff --git a/ext/opcache/tests/bug69688.phpt b/ext/opcache/tests/bug69688.phpt
new file mode 100644
index 0000000000..cc75960e73
--- /dev/null
+++ b/ext/opcache/tests/bug69688.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #69688 (segfault with eval and opcache fast shutdown)
+--INI--
+opcache.enable=1
+opcache.enable_cli=1
+opcache.fast_shutdown=1
+--SKIPIF--
+<?php require_once('skipif.inc'); ?>
+--FILE--
+<?php
+eval('function g() {} function g2() {} function g3() {}');
+
+eval('class A{} class B{} class C{}');
+
+?>
+okey
+--EXPECT--
+okey
diff --git a/ext/opcache/tests/optimize_func_calls.phpt b/ext/opcache/tests/optimize_func_calls.phpt
index b3bc8da6a9..3f795f5fc6 100644
--- a/ext/opcache/tests/optimize_func_calls.phpt
+++ b/ext/opcache/tests/optimize_func_calls.phpt
@@ -127,4 +127,8 @@ Array
string(7) "changed"
string(7) "changed"
-Fatal error: Cannot pass parameter 1 by reference in %soptimize_func_calls.php on line %d
+Fatal error: Uncaught EngineException: Cannot pass parameter 1 by reference in %soptimize_func_calls.php:%d
+Stack trace:
+#0 {main}
+ thrown in %soptimize_func_calls.php on line %d
+
diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c
index 13118a0a4e..7a8ef8d3e8 100644
--- a/ext/opcache/zend_accelerator_module.c
+++ b/ext/opcache/zend_accelerator_module.c
@@ -243,10 +243,6 @@ static ZEND_INI_MH(OnEnable)
#ifdef HAVE_OPCACHE_FILE_CACHE
-#ifndef S_ISDIR
-# define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
-#endif
-
static ZEND_INI_MH(OnUpdateFileCache)
{
if (new_value) {
diff --git a/ext/opcache/zend_accelerator_util_funcs.c b/ext/opcache/zend_accelerator_util_funcs.c
index 9407b2ec39..9582b723a2 100644
--- a/ext/opcache/zend_accelerator_util_funcs.c
+++ b/ext/opcache/zend_accelerator_util_funcs.c
@@ -27,10 +27,10 @@
#if SIZEOF_SIZE_T <= SIZEOF_ZEND_LONG
/* If sizeof(void*) == sizeof(ulong) we can use zend_hash index functions */
-# define accel_xlat_set(old, new) zend_hash_index_update_ptr(&ZCG(bind_hash), (zend_ulong)(zend_uintptr_t)(old), (new))
+# define accel_xlat_set(old, new) zend_hash_index_add_new_ptr(&ZCG(bind_hash), (zend_ulong)(zend_uintptr_t)(old), (new))
# define accel_xlat_get(old) zend_hash_index_find_ptr(&ZCG(bind_hash), (zend_ulong)(zend_uintptr_t)(old))
#else
-# define accel_xlat_set(old, new) (zend_hash_str_add_ptr(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (zend_ulong)(zend_uintptr_t)(old), (void**)&(new))
+# define accel_xlat_set(old, new) (zend_hash_str_add_new_ptr(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (zend_ulong)(zend_uintptr_t)(old), (void**)&(new))
# define accel_xlat_get(old, new) ((new) = zend_hash_str_find_ptr(&ZCG(bind_hash), (char*)&(old), sizeof(void*), (zend_ulong)(zend_uintptr_t)(old), (void**)&(new)))
#endif
@@ -40,7 +40,6 @@
typedef int (*id_function_t)(void *, void *);
typedef void (*unique_copy_ctor_func_t)(void *pElement);
-static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind);
static zend_ast *zend_ast_clone(zend_ast *ast);
static void zend_accel_destroy_zend_function(zval *zv)
@@ -124,11 +123,12 @@ void zend_accel_move_user_functions(HashTable *src, HashTable *dst)
dtor_func_t orig_dtor = src->pDestructor;
src->pDestructor = NULL;
+ zend_hash_extend(dst, dst->nNumUsed + src->nNumUsed, 0);
ZEND_HASH_REVERSE_FOREACH_BUCKET(src, p) {
zend_function *function = Z_PTR(p->val);
if (EXPECTED(function->type == ZEND_USER_FUNCTION)) {
- zend_hash_add_new_ptr(dst, p->key, function);
+ _zend_hash_append_ptr(dst, p->key, function);
zend_hash_del_bucket(src, p);
} else {
break;
@@ -152,80 +152,36 @@ void zend_accel_copy_internal_functions(void)
ZCG(internal_functions_count) = zend_hash_num_elements(&ZCG(function_table));
}
-static zend_always_inline zend_string *zend_clone_str(zend_string *str)
-{
- zend_string *ret;
-
- if (EXPECTED(IS_INTERNED(str))) {
- ret = str;
- } else if (GC_REFCOUNT(str) <= 1 || (ret = accel_xlat_get(str)) == NULL) {
- ret = zend_string_dup(str, 0);
- GC_FLAGS(ret) = GC_FLAGS(str);
- if (GC_REFCOUNT(str) > 1) {
- accel_xlat_set(str, ret);
- }
- } else {
- GC_REFCOUNT(ret)++;
- }
- return ret;
-}
-
-static inline void zend_clone_zval(zval *src, int bind)
+static inline void zend_clone_zval(zval *src)
{
void *ptr;
- if (Z_IMMUTABLE_P(src)) {
- return;
+ if (Z_TYPE_P(src) == IS_REFERENCE) {
+ ptr = accel_xlat_get(Z_REF_P(src));
+ if (ptr != NULL) {
+ Z_REF_P(src) = ptr;
+ return;
+ } else {
+ zend_reference *old = Z_REF_P(src);
+ ZVAL_NEW_REF(src, &old->val);
+ Z_REF_P(src)->gc = old->gc;
+ accel_xlat_set(old, Z_REF_P(src));
+ src = Z_REFVAL_P(src);
+ }
}
+ if (Z_TYPE_P(src) == IS_CONSTANT_AST) {
+ if (Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_AST_P(src))) != NULL) {
+ Z_AST_P(src) = ptr;
+ } else {
+ zend_ast_ref *old = Z_AST_P(src);
- switch (Z_TYPE_P(src)) {
- case IS_STRING:
- case IS_CONSTANT:
- Z_STR_P(src) = zend_clone_str(Z_STR_P(src));
- break;
- case IS_ARRAY:
- if (Z_ARR_P(src) != &EG(symbol_table)) {
- if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_ARR_P(src))) != NULL) {
- Z_ARR_P(src) = ptr;
- } else {
- zend_array *old = Z_ARR_P(src);
-
- Z_ARR_P(src) = emalloc(sizeof(zend_array));
- Z_ARR_P(src)->gc = old->gc;
- if (bind && Z_REFCOUNT_P(src) > 1) {
- accel_xlat_set(old, Z_ARR_P(src));
- }
- zend_hash_clone_zval(Z_ARRVAL_P(src), old, 0);
- }
- }
- break;
- case IS_REFERENCE:
- if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_REF_P(src))) != NULL) {
- Z_REF_P(src) = ptr;
- } else {
- zend_reference *old = Z_REF_P(src);
- ZVAL_NEW_REF(src, &old->val);
- Z_REF_P(src)->gc = old->gc;
- if (bind && Z_REFCOUNT_P(src) > 1) {
- accel_xlat_set(old, Z_REF_P(src));
- }
- zend_clone_zval(Z_REFVAL_P(src), bind);
- }
- break;
- case IS_CONSTANT_AST:
- if (bind && Z_REFCOUNT_P(src) > 1 && (ptr = accel_xlat_get(Z_AST_P(src))) != NULL) {
- Z_AST_P(src) = ptr;
- } else {
- zend_ast_ref *old = Z_AST_P(src);
-
- ZVAL_NEW_AST(src, old->ast);
- Z_AST_P(src)->gc = old->gc;
- if (bind && Z_REFCOUNT_P(src) > 1) {
- accel_xlat_set(old, Z_AST_P(src));
- }
- Z_ASTVAL_P(src) = zend_ast_clone(Z_ASTVAL_P(src));
+ ZVAL_NEW_AST(src, old->ast);
+ Z_AST_P(src)->gc = old->gc;
+ if (Z_REFCOUNT_P(src) > 1) {
+ accel_xlat_set(old, Z_AST_P(src));
}
- break;
+ Z_ASTVAL_P(src) = zend_ast_clone(Z_ASTVAL_P(src));
+ }
}
}
@@ -238,7 +194,6 @@ static zend_ast *zend_ast_clone(zend_ast *ast)
copy->kind = ZEND_AST_ZVAL;
copy->attr = ast->attr;
ZVAL_COPY_VALUE(&copy->val, zend_ast_get_zval(ast));
- zend_clone_zval(&copy->val, 0);
return (zend_ast *) copy;
} else if (zend_ast_is_list(ast)) {
zend_ast_list *list = zend_ast_get_list(ast);
@@ -271,10 +226,9 @@ static zend_ast *zend_ast_clone(zend_ast *ast)
}
}
-static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
+static void zend_hash_clone_constants(HashTable *ht, HashTable *source)
{
- uint idx;
- Bucket *p, *q, *r;
+ Bucket *p, *q, *end;
zend_ulong nIndex;
ht->nTableSize = source->nTableSize;
@@ -291,65 +245,34 @@ static void zend_hash_clone_zval(HashTable *ht, HashTable *source, int bind)
return;
}
- if (source->u.flags & HASH_FLAG_PACKED) {
- ht->u.flags |= HASH_FLAG_PACKED;
- HT_SET_DATA_ADDR(ht, (Bucket *) emalloc(HT_SIZE(ht)));
- HT_HASH_RESET_PACKED(ht);
-
- for (idx = 0; idx < source->nNumUsed; idx++) {
- p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- nIndex = p->h | ht->nTableMask;
+ ZEND_ASSERT((source->u.flags & HASH_FLAG_PACKED) == 0);
+ HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
+ HT_HASH_RESET(ht);
- r = ht->arData + ht->nNumUsed;
- q = ht->arData + p->h;
- while (r != q) {
- ZVAL_UNDEF(&r->val);
- r++;
- }
- ht->nNumUsed = p->h + 1;
+ p = source->arData;
+ end = p + source->nNumUsed;
+ for (; p != end; p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
+ nIndex = p->h | ht->nTableMask;
- /* Initialize key */
- q->h = p->h;
- q->key = NULL;
+ /* Insert into hash collision list */
+ q = ht->arData + ht->nNumUsed;
+ Z_NEXT(q->val) = HT_HASH(ht, nIndex);
+ HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(ht->nNumUsed++);
- /* Copy data */
- ZVAL_COPY_VALUE(&q->val, &p->val);
- zend_clone_zval(&q->val, bind);
- }
- } else {
- HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
- HT_HASH_RESET(ht);
-
- for (idx = 0; idx < source->nNumUsed; idx++) {
- p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
- nIndex = p->h | ht->nTableMask;
-
- /* Insert into hash collision list */
- q = ht->arData + ht->nNumUsed;
- Z_NEXT(q->val) = HT_HASH(ht, nIndex);
- HT_HASH(ht, nIndex) = HT_IDX_TO_HASH(ht->nNumUsed++);
-
- /* Initialize key */
- q->h = p->h;
- if (!p->key) {
- q->key = NULL;
- } else {
- q->key = zend_clone_str(p->key);
- }
+ /* Initialize key */
+ q->h = p->h;
+ q->key = p->key;
- /* Copy data */
- ZVAL_COPY_VALUE(&q->val, &p->val);
- zend_clone_zval(&q->val, bind);
- }
+ /* Copy data */
+ ZVAL_COPY_VALUE(&q->val, &p->val);
+ zend_clone_zval(&q->val);
}
}
static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class_entry *old_ce, zend_class_entry *ce)
{
- uint idx;
- Bucket *p, *q;
+ Bucket *p, *q, *end;
zend_ulong nIndex;
zend_op_array *new_entry;
@@ -371,9 +294,10 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class
HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
HT_HASH_RESET(ht);
- for (idx = 0; idx < source->nNumUsed; idx++) {
- p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ p = source->arData;
+ end = p + source->nNumUsed;
+ for (; p != end; p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
nIndex = p->h | ht->nTableMask;
@@ -385,7 +309,7 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class
/* Initialize key */
q->h = p->h;
ZEND_ASSERT(p->key != NULL);
- q->key = zend_clone_str(p->key);
+ q->key = p->key;
/* Copy data */
ZVAL_PTR(&q->val, ARENA_REALLOC(Z_PTR(p->val)));
@@ -406,8 +330,7 @@ static void zend_hash_clone_methods(HashTable *ht, HashTable *source, zend_class
static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_class_entry *old_ce)
{
- uint idx;
- Bucket *p, *q;
+ Bucket *p, *q, *end;
zend_ulong nIndex;
zend_property_info *prop_info;
@@ -429,9 +352,10 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla
HT_SET_DATA_ADDR(ht, emalloc(HT_SIZE(ht)));
HT_HASH_RESET(ht);
- for (idx = 0; idx < source->nNumUsed; idx++) {
- p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ p = source->arData;
+ end = p + source->nNumUsed;
+ for (; p != end; p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
nIndex = p->h | ht->nTableMask;
@@ -443,7 +367,7 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla
/* Initialize key */
q->h = p->h;
ZEND_ASSERT(p->key != NULL);
- q->key = zend_clone_str(p->key);
+ q->key = p->key;
/* Copy data */
prop_info = ARENA_REALLOC(Z_PTR(p->val));
@@ -451,7 +375,6 @@ static void zend_hash_clone_prop_info(HashTable *ht, HashTable *source, zend_cla
if (prop_info->ce == old_ce || (prop_info->flags & ZEND_ACC_SHADOW)) {
/* Copy constructor */
- prop_info->name = zend_clone_str(prop_info->name);
if (prop_info->doc_comment) {
if (ZCG(accel_directives).load_comments) {
prop_info->doc_comment = zend_string_dup(prop_info->doc_comment, 0);
@@ -479,17 +402,19 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
{
zend_class_entry *ce = *pce;
zend_class_entry *old_ce = ce;
+ zval *src, *dst, *end;
*pce = ce = ARENA_REALLOC(old_ce);
ce->refcount = 1;
if (old_ce->default_properties_table) {
- int i;
-
ce->default_properties_table = emalloc(sizeof(zval) * old_ce->default_properties_count);
- for (i = 0; i < old_ce->default_properties_count; i++) {
- ZVAL_COPY_VALUE(&ce->default_properties_table[i], &old_ce->default_properties_table[i]);
- zend_clone_zval(&ce->default_properties_table[i], 1);
+ src = old_ce->default_properties_table;
+ end = src + old_ce->default_properties_count;
+ dst = ce->default_properties_table;
+ for (; src != end; src++, dst++) {
+ ZVAL_COPY_VALUE(dst, src);
+ zend_clone_zval(dst);
}
}
@@ -497,12 +422,13 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
/* static members */
if (old_ce->default_static_members_table) {
- int i;
-
ce->default_static_members_table = emalloc(sizeof(zval) * old_ce->default_static_members_count);
- for (i = 0; i < old_ce->default_static_members_count; i++) {
- ZVAL_COPY_VALUE(&ce->default_static_members_table[i], &old_ce->default_static_members_table[i]);
- zend_clone_zval(&ce->default_static_members_table[i], 1);
+ src = old_ce->default_static_members_table;
+ end = src + old_ce->default_static_members_count;
+ dst = ce->default_static_members_table;
+ for (; src != end; src++, dst++) {
+ ZVAL_COPY_VALUE(dst, src);
+ zend_clone_zval(dst);
}
}
ce->static_members_table = ce->default_static_members_table;
@@ -511,11 +437,9 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
zend_hash_clone_prop_info(&ce->properties_info, &old_ce->properties_info, old_ce);
/* constants table */
- zend_hash_clone_zval(&ce->constants_table, &old_ce->constants_table, 1);
+ zend_hash_clone_constants(&ce->constants_table, &old_ce->constants_table);
ce->constants_table.u.flags &= ~HASH_FLAG_APPLY_PROTECTION;
- ce->name = zend_clone_str(ce->name);
-
/* interfaces aren't really implemented, so we create a new table */
if (ce->num_interfaces) {
ce->interfaces = emalloc(sizeof(zend_class_entry *) * ce->num_interfaces);
@@ -568,21 +492,6 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
memcpy(trait_aliases[i], ce->trait_aliases[i], sizeof(zend_trait_alias));
trait_aliases[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
memcpy(trait_aliases[i]->trait_method, ce->trait_aliases[i]->trait_method, sizeof(zend_trait_method_reference));
- if (trait_aliases[i]->trait_method) {
- if (trait_aliases[i]->trait_method->method_name) {
- trait_aliases[i]->trait_method->method_name =
- zend_clone_str(trait_aliases[i]->trait_method->method_name);
- }
- if (trait_aliases[i]->trait_method->class_name) {
- trait_aliases[i]->trait_method->class_name =
- zend_clone_str(trait_aliases[i]->trait_method->class_name);
- }
- }
-
- if (trait_aliases[i]->alias) {
- trait_aliases[i]->alias =
- zend_clone_str(trait_aliases[i]->alias);
- }
i++;
}
trait_aliases[i] = NULL;
@@ -604,11 +513,6 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
trait_precedences[i]->trait_method = emalloc(sizeof(zend_trait_method_reference));
memcpy(trait_precedences[i]->trait_method, ce->trait_precedences[i]->trait_method, sizeof(zend_trait_method_reference));
- trait_precedences[i]->trait_method->method_name =
- zend_clone_str(trait_precedences[i]->trait_method->method_name);
- trait_precedences[i]->trait_method->class_name =
- zend_clone_str(trait_precedences[i]->trait_method->class_name);
-
if (trait_precedences[i]->exclude_from_classes) {
zend_string **exclude_from_classes;
int j = 0;
@@ -620,7 +524,7 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
j = 0;
while (trait_precedences[i]->exclude_from_classes[j].class_name) {
exclude_from_classes[j] =
- zend_clone_str(trait_precedences[i]->exclude_from_classes[j].class_name);
+ trait_precedences[i]->exclude_from_classes[j].class_name;
j++;
}
exclude_from_classes[j] = NULL;
@@ -636,23 +540,25 @@ static void zend_class_copy_ctor(zend_class_entry **pce)
static void zend_accel_function_hash_copy(HashTable *target, HashTable *source)
{
zend_function *function1, *function2;
- uint idx;
- Bucket *p;
+ Bucket *p, *end;
zval *t;
- for (idx = 0; idx < source->nNumUsed; idx++) {
- p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ zend_hash_extend(target, target->nNumUsed + source->nNumUsed, 0);
+ p = source->arData;
+ end = p + source->nNumUsed;
+ for (; p != end; p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
ZEND_ASSERT(p->key);
- t = zend_hash_add(target, p->key, &p->val);
- if (UNEXPECTED(t == NULL)) {
- if (p->key->len > 0 && p->key->val[0] == 0) {
+ t = zend_hash_find(target, p->key);
+ if (UNEXPECTED(t != NULL)) {
+ if (EXPECTED(p->key->len > 0) && EXPECTED(p->key->val[0] == 0)) {
/* Mangled key */
t = zend_hash_update(target, p->key, &p->val);
} else {
- t = zend_hash_find(target, p->key);
goto failure;
}
+ } else {
+ _zend_hash_append_ptr(target, p->key, Z_PTR(p->val));
}
}
target->nInternalPointer = target->nNumOfElements ? 0 : HT_INVALID_IDX;
@@ -678,25 +584,26 @@ failure:
static void zend_accel_function_hash_copy_from_shm(HashTable *target, HashTable *source)
{
zend_function *function1, *function2;
- uint idx;
- Bucket *p;
+ Bucket *p, *end;
zval *t;
- for (idx = 0; idx < source->nNumUsed; idx++) {
- p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ zend_hash_extend(target, target->nNumUsed + source->nNumUsed, 0);
+ p = source->arData;
+ end = p + source->nNumUsed;
+ for (; p != end; p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
ZEND_ASSERT(p->key);
- t = zend_hash_add(target, p->key, &p->val);
- if (UNEXPECTED(t == NULL)) {
- if (p->key->len > 0 && p->key->val[0] == 0) {
+ t = zend_hash_find(target, p->key);
+ if (UNEXPECTED(t != NULL)) {
+ if (EXPECTED(p->key->len > 0) && EXPECTED(p->key->val[0] == 0)) {
/* Mangled key */
- t = zend_hash_update(target, p->key, &p->val);
+ zend_hash_update_ptr(target, p->key, ARENA_REALLOC(Z_PTR(p->val)));
} else {
- t = zend_hash_find(target, p->key);
goto failure;
}
+ } else {
+ _zend_hash_append_ptr(target, p->key, ARENA_REALLOC(Z_PTR(p->val)));
}
- Z_PTR_P(t) = ARENA_REALLOC(Z_PTR(p->val));
}
target->nInternalPointer = target->nNumOfElements ? 0 : HT_INVALID_IDX;
return;
@@ -721,26 +628,28 @@ failure:
static void zend_accel_class_hash_copy(HashTable *target, HashTable *source, unique_copy_ctor_func_t pCopyConstructor)
{
zend_class_entry *ce1;
- uint idx;
- Bucket *p;
+ Bucket *p, *end;
zval *t;
- for (idx = 0; idx < source->nNumUsed; idx++) {
- p = source->arData + idx;
- if (Z_TYPE(p->val) == IS_UNDEF) continue;
+ zend_hash_extend(target, target->nNumUsed + source->nNumUsed, 0);
+ p = source->arData;
+ end = p + source->nNumUsed;
+ for (; p != end; p++) {
+ if (UNEXPECTED(Z_TYPE(p->val) == IS_UNDEF)) continue;
ZEND_ASSERT(p->key);
- t = zend_hash_add(target, p->key, &p->val);
- if (UNEXPECTED(t == NULL)) {
- if (p->key->len > 0 && p->key->val[0] == 0) {
+ t = zend_hash_find(target, p->key);
+ if (UNEXPECTED(t != NULL)) {
+ if (EXPECTED(p->key->len > 0) && EXPECTED(p->key->val[0] == 0)) {
/* Mangled key - ignore and wait for runtime */
continue;
- } else if (!ZCG(accel_directives).ignore_dups) {
- t = zend_hash_find(target, p->key);
+ } else if (UNEXPECTED(!ZCG(accel_directives).ignore_dups)) {
goto failure;
}
- }
- if (pCopyConstructor) {
- pCopyConstructor(&Z_PTR_P(t));
+ } else {
+ t = _zend_hash_append_ptr(target, p->key, Z_PTR(p->val));
+ if (pCopyConstructor) {
+ pCopyConstructor(&Z_PTR_P(t));
+ }
}
}
target->nInternalPointer = target->nNumOfElements ? 0 : HT_INVALID_IDX;
diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c
index 52ee49d5e1..10a149c9f6 100644
--- a/ext/opcache/zend_file_cache.c
+++ b/ext/opcache/zend_file_cache.c
@@ -113,8 +113,6 @@ static int zend_file_cache_flock(int fd, int type)
ZEND_ASSERT(IS_UNSERIALIZED(ptr)); \
/* script->corrupted shows if the script in SHM or not */ \
if (EXPECTED(script->corrupted)) { \
- GC_FLAGS(ptr) |= IS_STR_INTERNED | IS_STR_PERMANENT; \
- } else { \
GC_FLAGS(ptr) |= IS_STR_INTERNED; \
GC_FLAGS(ptr) &= ~IS_STR_PERMANENT; \
} \
@@ -125,12 +123,12 @@ static int zend_file_cache_flock(int fd, int type)
#define UNSERIALIZE_STR(ptr) do { \
if (ptr) { \
if (IS_SERIALIZED_INTERNED(ptr)) { \
- (ptr) = (void*)zend_file_cache_unserialize_interned((zend_string*)(ptr), script->corrupted); \
+ (ptr) = (void*)zend_file_cache_unserialize_interned((zend_string*)(ptr), !script->corrupted); \
} else { \
ZEND_ASSERT(IS_SERIALIZED(ptr)); \
(ptr) = (void*)((char*)buf + (size_t)(ptr)); \
/* script->corrupted shows if the script in SHM or not */ \
- if (EXPECTED(script->corrupted)) { \
+ if (EXPECTED(!script->corrupted)) { \
GC_FLAGS(ptr) |= IS_STR_INTERNED | IS_STR_PERMANENT; \
} else { \
GC_FLAGS(ptr) |= IS_STR_INTERNED; \
@@ -440,6 +438,9 @@ static void zend_file_cache_serialize_op_array(zend_op_array *op_arra
if (!IS_SERIALIZED(p->class_name)) {
SERIALIZE_STR(p->class_name);
}
+ if (p->class_name && !IS_SERIALIZED(p->lower_class_name)) {
+ SERIALIZE_STR(p->lower_class_name);
+ }
p++;
}
}
@@ -722,9 +723,13 @@ int zend_file_cache_script_store(zend_persistent_script *script, int in_shm)
ZCG(mem) = zend_string_alloc(4096 - (_STR_HEADER_SIZE + 1), 0);
zend_shared_alloc_init_xlat_table();
- script->corrupted = in_shm; /* used to check if script restored to SHM or process memory */
+ if (!in_shm) {
+ script->corrupted = 1; /* used to check if script restored to SHM or process memory */
+ }
zend_file_cache_serialize(script, &info, buf);
- script->corrupted = 0;
+ if (!in_shm) {
+ script->corrupted = 0;
+ }
zend_shared_alloc_destroy_xlat_table();
info.checksum = zend_adler32(ADLER32_INIT, buf, script->size);
@@ -960,6 +965,9 @@ static void zend_file_cache_unserialize_op_array(zend_op_array *op_arr
if (!IS_UNSERIALIZED(p->class_name)) {
UNSERIALIZE_STR(p->class_name);
}
+ if (p->class_name && !IS_UNSERIALIZED(p->lower_class_name)) {
+ UNSERIALIZE_STR(p->lower_class_name);
+ }
p++;
}
}
@@ -1307,7 +1315,7 @@ use_process_mem:
ZCG(mem) = ((char*)mem + info.mem_size);
script = (zend_persistent_script*)((char*)buf + info.script_offset);
- script->corrupted = cache_it; /* used to check if script restored to SHM or process memory */
+ script->corrupted = !cache_it; /* used to check if script restored to SHM or process memory */
zend_file_cache_unserialize(script, buf);
script->corrupted = 0;
diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c
index d1c1bb279a..585c34f46e 100644
--- a/ext/opcache/zend_persist.c
+++ b/ext/opcache/zend_persist.c
@@ -342,6 +342,7 @@ static void zend_persist_zval_static(zval *z)
new_ptr = zend_shared_alloc_get_xlat_entry(Z_AST_P(z));
if (new_ptr) {
Z_AST_P(z) = new_ptr;
+ Z_TYPE_FLAGS_P(z) = IS_TYPE_CONSTANT | IS_TYPE_IMMUTABLE;
} else {
zend_accel_store(Z_AST_P(z), sizeof(zend_ast_ref));
Z_ASTVAL_P(z) = zend_persist_ast(Z_ASTVAL_P(z));
@@ -580,6 +581,9 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc
}
if (arg_info[i].class_name) {
zend_accel_store_interned_string(arg_info[i].class_name);
+ if (arg_info[i].lower_class_name) {
+ zend_accel_store_interned_string(arg_info[i].lower_class_name);
+ }
}
}
}
diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c
index 98412109a5..d721db2feb 100644
--- a/ext/opcache/zend_persist_calc.c
+++ b/ext/opcache/zend_persist_calc.c
@@ -225,6 +225,9 @@ static void zend_persist_op_array_calc_ex(zend_op_array *op_array)
}
if (arg_info[i].class_name) {
ADD_INTERNED_STRING(arg_info[i].class_name, 1);
+ if (arg_info[i].lower_class_name) {
+ ADD_INTERNED_STRING(arg_info[i].lower_class_name, 1);
+ }
}
}
}
diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c
index 19b51e7c59..ca50ab9219 100644
--- a/ext/opcache/zend_shared_alloc.c
+++ b/ext/opcache/zend_shared_alloc.c
@@ -435,7 +435,7 @@ void zend_shared_alloc_clear_xlat_table(void)
void zend_shared_alloc_register_xlat_entry(const void *old, const void *new)
{
- zend_hash_index_update_ptr(&ZCG(xlat_table), (zend_ulong)old, (void*)new);
+ zend_hash_index_add_new_ptr(&ZCG(xlat_table), (zend_ulong)old, (void*)new);
}
void *zend_shared_alloc_get_xlat_entry(const void *old)
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 1ae741136d..c79447097d 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -3217,7 +3217,7 @@ static EVP_PKEY * php_openssl_evp_from_zval(zval * val, int public_key, char * p
if (Z_TYPE_P(zphrase) == IS_STRING) {
passphrase = Z_STRVAL_P(zphrase);
} else {
- ZVAL_DUP(&tmp, zphrase);
+ ZVAL_COPY(&tmp, zphrase);
convert_to_string(&tmp);
passphrase = Z_STRVAL(tmp);
}
@@ -5253,7 +5253,7 @@ PHP_FUNCTION(openssl_encrypt)
/* }}} */
/* {{{ proto string openssl_decrypt(string data, string method, string password [, long options=0 [, string $iv = '']])
- Takes raw or base64 encoded string and dectupt it using given method and key */
+ Takes raw or base64 encoded string and decrypts it using given method and key */
PHP_FUNCTION(openssl_decrypt)
{
zend_long options = 0;
diff --git a/ext/pcre/pcrelib/config.h b/ext/pcre/pcrelib/config.h
index d0fde3b497..9714cf5bbd 100644
--- a/ext/pcre/pcrelib/config.h
+++ b/ext/pcre/pcrelib/config.h
@@ -262,7 +262,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_NAME "PCRE"
/* Define to the full name and version of this package. */
-#define PACKAGE_STRING "PCRE 8.36"
+#define PACKAGE_STRING "PCRE 8.37"
/* Define to the one symbol short name of this package. */
#define PACKAGE_TARNAME "pcre"
@@ -271,7 +271,7 @@ sure both macros are undefined; an emulation function will then be used. */
#define PACKAGE_URL ""
/* Define to the version of this package. */
-#define PACKAGE_VERSION "8.36"
+#define PACKAGE_VERSION "8.37"
/* The value of PARENS_NEST_LIMIT specifies the maximum depth of nested
parentheses (of any kind) in a pattern. This limits the amount of system
@@ -364,7 +364,7 @@ sure both macros are undefined; an emulation function will then be used. */
/* Version number of package */
#ifndef VERSION
-#define VERSION "8.36"
+#define VERSION "8.37"
#endif
/* Define to empty if `const' does not conform to ANSI C. */
diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c
index 8189473524..76a5eb4520 100644
--- a/ext/pdo/pdo_dbh.c
+++ b/ext/pdo/pdo_dbh.c
@@ -1364,6 +1364,14 @@ static int dbh_compare(zval *object1, zval *object2)
return -1;
}
+static HashTable *dbh_get_gc(zval *object, zval **gc_data, int *gc_count)
+{
+ pdo_dbh_t *dbh = Z_PDO_DBH_P(object);
+ *gc_data = &dbh->def_stmt_ctor_args;
+ *gc_count = 1;
+ return zend_std_get_properties(object);
+}
+
static zend_object_handlers pdo_dbh_object_handlers;
static void pdo_dbh_free_storage(zend_object *std);
@@ -1381,6 +1389,7 @@ void pdo_dbh_init(void)
pdo_dbh_object_handlers.free_obj = pdo_dbh_free_storage;
pdo_dbh_object_handlers.get_method = dbh_method_get;
pdo_dbh_object_handlers.compare_objects = dbh_compare;
+ pdo_dbh_object_handlers.get_gc = dbh_get_gc;
REGISTER_PDO_CLASS_CONST_LONG("PARAM_BOOL", (zend_long)PDO_PARAM_BOOL);
REGISTER_PDO_CLASS_CONST_LONG("PARAM_NULL", (zend_long)PDO_PARAM_NULL);
diff --git a/ext/pdo_pgsql/pgsql_driver.c b/ext/pdo_pgsql/pgsql_driver.c
index 0a7ce6368d..f913eb7c31 100644
--- a/ext/pdo_pgsql/pgsql_driver.c
+++ b/ext/pdo_pgsql/pgsql_driver.c
@@ -27,6 +27,7 @@
#include "php.h"
#include "php_ini.h"
#include "ext/standard/info.h"
+#include "ext/standard/php_string.h"
#include "main/php_network.h"
#include "pdo/php_pdo.h"
#include "pdo/php_pdo_driver.h"
@@ -62,6 +63,17 @@ static char * _pdo_pgsql_trim_message(const char *message, int persistent)
return tmp;
}
+static zend_string* _pdo_pgsql_escape_credentials(char *str)
+{
+ if (str) {
+ zend_string *tmp = zend_string_init(str, strlen(str), 0);
+
+ return php_addcslashes(tmp, 1, "\\'", sizeof("\\'"));
+ }
+
+ return NULL;
+}
+
int _pdo_pgsql_error(pdo_dbh_t *dbh, pdo_stmt_t *stmt, int errcode, const char *sqlstate, const char *msg, const char *file, int line) /* {{{ */
{
pdo_pgsql_db_handle *H = (pdo_pgsql_db_handle *)dbh->driver_data;
@@ -1179,7 +1191,7 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{
pdo_pgsql_db_handle *H;
int ret = 0;
char *conn_str, *p, *e;
- char *tmp_pass;
+ zend_string *tmp_user, *tmp_pass;
zend_long connect_timeout = 30;
H = pecalloc(1, sizeof(pdo_pgsql_db_handle), dbh->is_persistent);
@@ -1201,43 +1213,28 @@ static int pdo_pgsql_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{
connect_timeout = pdo_attr_lval(driver_options, PDO_ATTR_TIMEOUT, 30);
}
- if (dbh->password) {
- if (dbh->password[0] != '\'' && dbh->password[strlen(dbh->password) - 1] != '\'') {
- char *pwd = dbh->password;
- int pos = 1;
-
- tmp_pass = safe_emalloc(2, strlen(dbh->password), 3);
- tmp_pass[0] = '\'';
-
- while (*pwd != '\0') {
- if (*pwd == '\\' || *pwd == '\'') {
- tmp_pass[pos++] = '\\';
- }
-
- tmp_pass[pos++] = *pwd++;
- }
-
- tmp_pass[pos++] = '\'';
- tmp_pass[pos] = '\0';
- } else {
- tmp_pass = dbh->password;
- }
- }
+ /* escape username and password, if provided */
+ tmp_user = _pdo_pgsql_escape_credentials(dbh->username);
+ tmp_pass = _pdo_pgsql_escape_credentials(dbh->password);
/* support both full connection string & connection string + login and/or password */
- if (dbh->username && dbh->password) {
- spprintf(&conn_str, 0, "%s user=%s password=%s connect_timeout=%pd", dbh->data_source, dbh->username, tmp_pass, connect_timeout);
- } else if (dbh->username) {
- spprintf(&conn_str, 0, "%s user=%s connect_timeout=%pd", dbh->data_source, dbh->username, connect_timeout);
- } else if (dbh->password) {
- spprintf(&conn_str, 0, "%s password=%s connect_timeout=%pd", dbh->data_source, tmp_pass, connect_timeout);
+ if (tmp_user && tmp_pass) {
+ spprintf(&conn_str, 0, "%s user='%s' password='%s' connect_timeout=%pd", (char *) dbh->data_source, tmp_user->val, tmp_pass->val, connect_timeout);
+ } else if (tmp_user) {
+ spprintf(&conn_str, 0, "%s user='%s' connect_timeout=%pd", (char *) dbh->data_source, tmp_user->val, connect_timeout);
+ } else if (tmp_pass) {
+ spprintf(&conn_str, 0, "%s password='%s' connect_timeout=%pd", (char *) dbh->data_source, tmp_pass->val, connect_timeout);
} else {
spprintf(&conn_str, 0, "%s connect_timeout=%pd", (char *) dbh->data_source, connect_timeout);
}
H->server = PQconnectdb(conn_str);
- if (dbh->password && tmp_pass != dbh->password) {
- efree(tmp_pass);
+
+ if (tmp_user) {
+ zend_string_release(tmp_user);
+ }
+ if (tmp_pass) {
+ zend_string_release(tmp_pass);
}
efree(conn_str);
diff --git a/ext/pdo_pgsql/pgsql_statement.c b/ext/pdo_pgsql/pgsql_statement.c
index 60553b36ce..9c2a0e2efd 100644
--- a/ext/pdo_pgsql/pgsql_statement.c
+++ b/ext/pdo_pgsql/pgsql_statement.c
@@ -224,7 +224,7 @@ stmt_retry:
return 0;
}
- if (!stmt->executed && !stmt->column_count) {
+ if (!stmt->executed && (!stmt->column_count || S->cols == NULL)) {
stmt->column_count = (int) PQnfields(S->result);
S->cols = ecalloc(stmt->column_count, sizeof(pdo_pgsql_column));
}
@@ -301,8 +301,8 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *
if (param->paramno >= 0) {
zval *parameter;
- if (param->paramno >= zend_hash_num_elements(stmt->bound_param_map)) {
- pdo_pgsql_error_stmt(stmt, PGRES_FATAL_ERROR, "HY105");
+ if (param->paramno >= zend_hash_num_elements(stmt->bound_params)) {
+ pdo_raise_impl_error(stmt->dbh, stmt, "HY093", "parameter was not defined");
return 0;
}
@@ -618,6 +618,12 @@ done:
static int pdo_pgsql_stmt_cursor_closer(pdo_stmt_t *stmt)
{
+ pdo_pgsql_stmt *S = (pdo_pgsql_stmt*)stmt->driver_data;
+
+ if (S->cols != NULL){
+ efree(S->cols);
+ S->cols = NULL;
+ }
return 1;
}
diff --git a/ext/pdo_pgsql/tests/bug69344.phpt b/ext/pdo_pgsql/tests/bug69344.phpt
new file mode 100644
index 0000000000..d274e0608c
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug69344.phpt
@@ -0,0 +1,44 @@
+--TEST--
+PDO PgSQL Bug #69344 (PDO PgSQL Incorrect binding numeric array with gaps)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$pdo = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$pdo->setAttribute (\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
+$pdo->setAttribute (\PDO::ATTR_DEFAULT_FETCH_MODE, \PDO::FETCH_ASSOC);
+
+$test = function () use ($pdo) {
+ $arr = [
+ 0 => "a",
+ 2 => "b",
+ ];
+
+ $stmt = $pdo->prepare("SELECT (?)::text AS a, (?)::text AS b");
+
+ try {
+ $stmt->execute($arr);
+ var_dump($stmt->fetch());
+ } catch (\Exception $e) {
+ echo $e->getMessage()."\n";
+ }
+};
+
+$test();
+
+$pdo->setAttribute(\PDO::ATTR_EMULATE_PREPARES, true);
+
+$test();
+
+?>
+--EXPECT--
+SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
+SQLSTATE[HY093]: Invalid parameter number: parameter was not defined
+
diff --git a/ext/pdo_pgsql/tests/bug69362.phpt b/ext/pdo_pgsql/tests/bug69362.phpt
new file mode 100644
index 0000000000..33212a8863
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug69362.phpt
@@ -0,0 +1,63 @@
+--TEST--
+PDO PgSQL Bug #69362 (PDO-pgsql fails to connect if password contains a leading single quote)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+
+$dsn = getenv('PDOTEST_DSN');
+if (empty($dsn)) die('skip no dsn found in env');
+
+$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
+
+
+$user = 'pdo_test_'.rand(5, 400);
+$pass = 'testpass';
+
+// Assume that if we can't create or drop a user, this test needs to be skipped
+try {
+ $db->exec("DROP USER IF EXISTS $user");
+ $db->exec("CREATE USER $user WITH PASSWORD '$pass'");
+} catch (PDOException $e) {
+ die("skip You need CREATEUSER permissions to run the test");
+}
+
+// Peer authentication might prevent the test from properly running
+try {
+ $testConn = new PDO($dsn, $user, $pass);
+} catch (PDOException $e) {
+ echo "skip ".$e->getMessage();
+}
+
+$db->exec("DROP USER $user");
+
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$pdo = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+$pdo->setAttribute(PDO::ATTR_EMULATE_PREPARES, true);
+$rand = rand(5, 400);
+$user = "pdo_test_$rand";
+$template = "CREATE USER $user WITH PASSWORD '%s'";
+$dropUser = "DROP USER $user";
+$testQuery = 'SELECT 1 as verification';
+
+// Create temp user with leading single quote
+$sql = sprintf($template, "''mypassword");
+$pdo->query($sql);
+$testConn = new PDO($conf['ENV']['PDOTEST_DSN'], $user, "'mypassword");
+$result = $testConn->query($testQuery)->fetch();
+$check = $result[0];
+var_dump($check);
+
+// Remove the user
+$pdo->query($dropUser);
+
+?>
+--EXPECT--
+int(1)
+
diff --git a/ext/pdo_pgsql/tests/bug69752.phpt b/ext/pdo_pgsql/tests/bug69752.phpt
new file mode 100644
index 0000000000..bb7e5e87e7
--- /dev/null
+++ b/ext/pdo_pgsql/tests/bug69752.phpt
@@ -0,0 +1,55 @@
+--TEST--
+PDO PgSQL Bug #69752 (memory leak with closeCursor)
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+PDOTest::skip();
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/../../../ext/pdo/tests/pdo_test.inc';
+$pdo = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
+
+$pdo->setAttribute(\PDO::ATTR_ERRMODE, \PDO::ERRMODE_EXCEPTION);
+
+$pdo->beginTransaction();
+
+$pdo->exec("
+ create table foo (
+ id bigserial not null primary key,
+ field1 text not null,
+ field2 text not null,
+ field3 text not null,
+ field4 int4 not null
+ )
+");
+$stmt = $pdo->prepare("insert into foo (field1, field2, field3, field4) values (:field1, :field2, :field3, :field4)");
+$max = 1000;
+$first_time_usage = null;
+
+for($i = 0; $i < $max; $i++) {
+ $data = array(
+ 'field1' => "field1: $i",
+ 'field2' => "field2: $i",
+ 'field3' => "field3: $i",
+ 'field4' => $i
+ );
+ $stmt->execute($data);
+ $stmt->closeCursor();
+ $usage = intval(floor(memory_get_usage() / 1024));
+
+ if ($first_time_usage === null) $first_time_usage = $usage;
+
+ /* Use delta instead of direct comparison here */
+ if (abs($first_time_usage - $usage) > 3){
+ printf("Memory Leak Detected: %d != %d\n", $usage, $first_time_usage);
+ break;
+ }
+}
+$pdo->rollBack();
+echo "done\n"
+?>
+--EXPECTF--
+done
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
index 6a86b8941b..6965589154 100644
--- a/ext/pgsql/pgsql.c
+++ b/ext/pgsql/pgsql.c
@@ -4246,7 +4246,7 @@ PHP_FUNCTION(pg_copy_from)
#if HAVE_PQPUTCOPYDATA
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pg_rows), value) {
zval tmp;
- ZVAL_DUP(&tmp, value);
+ ZVAL_COPY(&tmp, value);
convert_to_string_ex(&tmp);
query = (char *)emalloc(Z_STRLEN(tmp) + 2);
strlcpy(query, Z_STRVAL(tmp), Z_STRLEN(tmp) + 2);
@@ -4270,7 +4270,7 @@ PHP_FUNCTION(pg_copy_from)
#else
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pg_rows), value) {
zval tmp;
- ZVAL_DUP(&tmp, value);
+ ZVAL_COPY(&tmp, value);
convert_to_string_ex(&tmp);
query = (char *)emalloc(Z_STRLEN(tmp) + 2);
strlcpy(query, Z_STRVAL(tmp), Z_STRLEN(tmp) + 2);
@@ -5504,7 +5504,11 @@ PHP_PGSQL_API int php_pgsql_meta_data(PGconn *pg_link, const char *table_name, z
src = estrdup(table_name);
tmp_name = php_strtok_r(src, ".", &tmp_name2);
-
+ if (!tmp_name) {
+ efree(src);
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "The table name must be specified");
+ return FAILURE;
+ }
if (!tmp_name2 || !*tmp_name2) {
/* Default schema */
tmp_name2 = tmp_name;
@@ -6502,7 +6506,8 @@ static int do_exec(smart_str *querystr, int expect, PGconn *pg_link, zend_ulong
static inline void build_tablename(smart_str *querystr, PGconn *pg_link, const char *table) /* {{{ */
{
- char *table_copy, *escaped, *token, *tmp;
+ char *table_copy, *escaped, *tmp;
+ const char *token;
size_t len;
/* schame.table should be "schame"."table" */
diff --git a/ext/pgsql/tests/pg_insert_002.phpt b/ext/pgsql/tests/pg_insert_002.phpt
new file mode 100644
index 0000000000..329f525b27
--- /dev/null
+++ b/ext/pgsql/tests/pg_insert_002.phpt
@@ -0,0 +1,27 @@
+--TEST--
+PostgreSQL pg_insert() - test for CVE-2015-1532
+--SKIPIF--
+<?php include("skipif.inc"); ?>
+--FILE--
+<?php
+
+include('config.inc');
+
+$conn = pg_connect($conn_str);
+
+foreach (array('', '.', '..') as $table) {
+ var_dump(pg_insert($conn, $table, array('id' => 1, 'id2' => 1)));
+}
+?>
+Done
+--EXPECTF--
+
+Warning: pg_insert(): The table name must be specified in %s on line %d
+bool(false)
+
+Warning: pg_insert(): The table name must be specified in %s on line %d
+bool(false)
+
+Warning: pg_insert(): The table name must be specified in %s on line %d
+bool(false)
+Done \ No newline at end of file
diff --git a/ext/phar/Makefile.frag b/ext/phar/Makefile.frag
index e5d756fa16..e58795deea 100644
--- a/ext/phar/Makefile.frag
+++ b/ext/phar/Makefile.frag
@@ -39,7 +39,7 @@ install-pharcmd: pharcmd
-@$(mkinstalldirs) $(INSTALL_ROOT)$(bindir)
$(INSTALL) $(builddir)/phar.phar $(INSTALL_ROOT)$(bindir)
-@rm -f $(INSTALL_ROOT)$(bindir)/phar
- $(LN_S) -f $(INSTALL_ROOT)$(bindir)/phar.phar $(INSTALL_ROOT)$(bindir)/phar
+ $(LN_S) -f phar.phar $(INSTALL_ROOT)$(bindir)/phar
@$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man1
@$(INSTALL_DATA) $(builddir)/phar.1 $(INSTALL_ROOT)$(mandir)/man1/phar.1
@$(INSTALL_DATA) $(builddir)/phar.phar.1 $(INSTALL_ROOT)$(mandir)/man1/phar.phar.1
diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c
index 8cadeb5a4a..c4912649db 100644
--- a/ext/phar/func_interceptors.c
+++ b/ext/phar/func_interceptors.c
@@ -429,18 +429,6 @@ skip_phar:
}
/* }}} */
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
-#endif
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
-#endif
-#ifndef S_ISLNK
-#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK)
-#endif
-
-#define S_IXROOT ( S_IXUSR | S_IXGRP | S_IXOTH )
-
#define IS_LINK_OPERATION(__t) ((__t) == FS_TYPE || (__t) == FS_IS_LINK || (__t) == FS_LSTAT)
#define IS_EXISTS_CHECK(__t) ((__t) == FS_EXISTS || (__t) == FS_IS_W || (__t) == FS_IS_R || (__t) == FS_IS_X || (__t) == FS_IS_FILE || (__t) == FS_IS_DIR || (__t) == FS_IS_LINK)
#define IS_ABLE_CHECK(__t) ((__t) == FS_IS_R || (__t) == FS_IS_W || (__t) == FS_IS_X)
diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
index 8ef5b0f7ed..11e5d5a7f1 100644
--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@ -3965,14 +3965,13 @@ PHP_METHOD(Phar, getMetadata)
if (Z_TYPE(phar_obj->archive->metadata) != IS_UNDEF) {
if (phar_obj->archive->is_persistent) {
- zval ret;
char *buf = estrndup((char *) Z_PTR(phar_obj->archive->metadata), phar_obj->archive->metadata_len);
/* assume success, we would have failed before */
- phar_parse_metadata(&buf, &ret, phar_obj->archive->metadata_len);
+ phar_parse_metadata(&buf, return_value, phar_obj->archive->metadata_len);
efree(buf);
- RETURN_ZVAL(&ret, 0, 1);
+ } else {
+ ZVAL_COPY(return_value, &phar_obj->archive->metadata);
}
- RETURN_ZVAL(&phar_obj->archive->metadata, 1, 0);
}
}
/* }}} */
@@ -4005,7 +4004,7 @@ PHP_METHOD(Phar, setMetadata)
ZVAL_UNDEF(&phar_obj->archive->metadata);
}
- ZVAL_ZVAL(&phar_obj->archive->metadata, metadata, 1, 0);
+ ZVAL_COPY(&phar_obj->archive->metadata, metadata);
phar_obj->archive->is_modified = 1;
phar_flush(phar_obj->archive, 0, 0, 0, &error);
@@ -4622,14 +4621,13 @@ PHP_METHOD(PharFileInfo, getMetadata)
if (Z_TYPE(entry_obj->entry->metadata) != IS_UNDEF) {
if (entry_obj->entry->is_persistent) {
- zval ret;
char *buf = estrndup((char *) Z_PTR(entry_obj->entry->metadata), entry_obj->entry->metadata_len);
/* assume success, we would have failed before */
- phar_parse_metadata(&buf, &ret, entry_obj->entry->metadata_len);
+ phar_parse_metadata(&buf, return_value, entry_obj->entry->metadata_len);
efree(buf);
- RETURN_ZVAL(&ret, 0, 1);
+ } else {
+ ZVAL_COPY(return_value, &entry_obj->entry->metadata);
}
- RETURN_ZVAL(&entry_obj->entry->metadata, 1, 0);
}
}
/* }}} */
@@ -4674,7 +4672,7 @@ PHP_METHOD(PharFileInfo, setMetadata)
ZVAL_UNDEF(&entry_obj->entry->metadata);
}
- ZVAL_ZVAL(&entry_obj->entry->metadata, metadata, 1, 0);
+ ZVAL_COPY(&entry_obj->entry->metadata, metadata);
entry_obj->entry->is_modified = 1;
entry_obj->entry->phar->is_modified = 1;
diff --git a/ext/phar/tar.c b/ext/phar/tar.c
index 81b08de36a..52df81971b 100644
--- a/ext/phar/tar.c
+++ b/ext/phar/tar.c
@@ -460,9 +460,7 @@ bail:
entry.flags = phar_tar_number(hdr->mode, sizeof(hdr->mode)) & PHAR_ENT_PERM_MASK;
entry.timestamp = phar_tar_number(hdr->mtime, sizeof(hdr->mtime));
entry.is_persistent = myphar->is_persistent;
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
-#endif
+
if (old && entry.tar_type == TAR_FILE && S_ISDIR(entry.flags)) {
entry.tar_type = TAR_DIR;
}
diff --git a/ext/phar/tests/bug69441.phpt b/ext/phar/tests/bug69441.phpt
index 3e995e03c0..3536c3a835 100644
--- a/ext/phar/tests/bug69441.phpt
+++ b/ext/phar/tests/bug69441.phpt
@@ -14,7 +14,7 @@ $r = new Phar($fname, 0);
==DONE==
--EXPECTF--
-UnexpectedValueException: phar error: corrupted central directory entry, no magic signature in zip-based phar "%s%ebug69441.phar" in %s%ebug69441.php:%d
+UnexpectedValueException: phar error: corrupted central directory entry, no magic signature in zip-based phar "%sbug69441.phar" in %sbug69441.php:%d
Stack trace:
#0 %s%ebug69441.php(%d): Phar->__construct('%s', 0)
#1 {main}
diff --git a/ext/phar/tests/bug69453.phpt b/ext/phar/tests/bug69453.phpt
index 12b437639a..6f280a5351 100644
--- a/ext/phar/tests/bug69453.phpt
+++ b/ext/phar/tests/bug69453.phpt
@@ -14,8 +14,8 @@ $r = new Phar($fname, 0);
==DONE==
--EXPECTF--
-UnexpectedValueException: phar error: "%s/bug69453.tar.phar" is a corrupted tar file (checksum mismatch of file "") in %s:%d
+UnexpectedValueException: phar error: "%s%ebug69453.tar.phar" is a corrupted tar file (checksum mismatch of file "") in %s:%d
Stack trace:
-#0 %s/bug69453.php(%d): Phar->__construct('%s', 0)
+#0 %s%ebug69453.php(%d): Phar->__construct('%s', 0)
#1 {main}
-==DONE== \ No newline at end of file
+==DONE==
diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c
index 92f67972d2..4c570d7573 100644
--- a/ext/reflection/php_reflection.c
+++ b/ext/reflection/php_reflection.c
@@ -59,6 +59,7 @@ PHPAPI zend_class_entry *reflection_function_abstract_ptr;
PHPAPI zend_class_entry *reflection_function_ptr;
PHPAPI zend_class_entry *reflection_generator_ptr;
PHPAPI zend_class_entry *reflection_parameter_ptr;
+PHPAPI zend_class_entry *reflection_type_ptr;
PHPAPI zend_class_entry *reflection_class_ptr;
PHPAPI zend_class_entry *reflection_object_ptr;
PHPAPI zend_class_entry *reflection_method_ptr;
@@ -201,11 +202,18 @@ typedef struct _parameter_reference {
zend_function *fptr;
} parameter_reference;
+/* Struct for type hints */
+typedef struct _type_reference {
+ struct _zend_arg_info *arg_info;
+ zend_function *fptr;
+} type_reference;
+
typedef enum {
REF_TYPE_OTHER, /* Must be 0 */
REF_TYPE_FUNCTION,
REF_TYPE_GENERATOR,
REF_TYPE_PARAMETER,
+ REF_TYPE_TYPE,
REF_TYPE_PROPERTY,
REF_TYPE_DYNAMIC_PROPERTY
} reflection_type_t;
@@ -299,6 +307,7 @@ static void reflection_free_objects_storage(zend_object *object) /* {{{ */
reflection_object *intern = reflection_object_from_obj(object);
parameter_reference *reference;
property_reference *prop_reference;
+ type_reference *typ_reference;
if (intern->ptr) {
switch (intern->ref_type) {
@@ -307,6 +316,11 @@ static void reflection_free_objects_storage(zend_object *object) /* {{{ */
_free_function(reference->fptr);
efree(intern->ptr);
break;
+ case REF_TYPE_TYPE:
+ typ_reference = (type_reference*)intern->ptr;
+ _free_function(typ_reference->fptr);
+ efree(intern->ptr);
+ break;
case REF_TYPE_FUNCTION:
_free_function(intern->ptr);
break;
@@ -1236,6 +1250,27 @@ static void reflection_parameter_factory(zend_function *fptr, zval *closure_obje
}
/* }}} */
+/* {{{ reflection_type_factory */
+static void reflection_type_factory(zend_function *fptr, zval *closure_object, struct _zend_arg_info *arg_info, zval *object)
+{
+ reflection_object *intern;
+ type_reference *reference;
+
+ reflection_instantiate(reflection_type_ptr, object);
+ intern = Z_REFLECTION_P(object);
+ reference = (type_reference*) emalloc(sizeof(type_reference));
+ reference->arg_info = arg_info;
+ reference->fptr = fptr;
+ intern->ptr = reference;
+ intern->ref_type = REF_TYPE_TYPE;
+ intern->ce = fptr->common.scope;
+ if (closure_object) {
+ Z_ADDREF_P(closure_object);
+ ZVAL_COPY_VALUE(&intern->obj, closure_object);
+ }
+}
+/* }}} */
+
/* {{{ reflection_function_factory */
static void reflection_function_factory(zend_function *function, zval *closure_object, zval *object)
{
@@ -1685,7 +1720,7 @@ ZEND_METHOD(reflection_function, getClosureThis)
if (!Z_ISUNDEF(intern->obj)) {
closure_this = zend_get_closure_this_ptr(&intern->obj);
if (!Z_ISUNDEF_P(closure_this)) {
- RETURN_ZVAL(closure_this, 1, 0);
+ ZVAL_COPY(return_value, closure_this);
}
}
}
@@ -2504,6 +2539,7 @@ ZEND_METHOD(reflection_parameter, __toString)
_parameter_string(&str, param->fptr, param->arg_info, param->offset, param->required, "");
RETURN_NEW_STR(str.buf);
}
+
/* }}} */
/* {{{ proto public string ReflectionParameter::getName()
@@ -2538,7 +2574,7 @@ ZEND_METHOD(reflection_parameter, getDeclaringFunction)
/* }}} */
/* {{{ proto public ReflectionClass|NULL ReflectionParameter::getDeclaringClass()
- Returns in which class this parameter is defined (not the typehint of the parameter) */
+ Returns in which class this parameter is defined (not the type of the parameter) */
ZEND_METHOD(reflection_parameter, getDeclaringClass)
{
reflection_object *intern;
@@ -2630,6 +2666,44 @@ ZEND_METHOD(reflection_parameter, getClass)
}
/* }}} */
+/* {{{ proto public bool ReflectionParameter::hasType()
+ Returns whether parameter has a type */
+ZEND_METHOD(reflection_parameter, hasType)
+{
+ reflection_object *intern;
+ parameter_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(param);
+
+ RETVAL_BOOL(param->arg_info->type_hint != 0);
+}
+/* }}} */
+
+/* {{{ proto public ReflectionType ReflectionParameter::getType()
+ Returns the type associated with the parameter */
+ZEND_METHOD(reflection_parameter, getType)
+{
+ reflection_object *intern;
+ parameter_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(param);
+
+ if ((param->fptr->type == ZEND_INTERNAL_FUNCTION ?
+ ((zend_internal_arg_info*)param->arg_info)->type_hint :
+ param->arg_info->type_hint) == 0)
+ {
+ RETURN_NULL();
+ }
+ reflection_type_factory(_copy_function(param->fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, param->arg_info, return_value);
+}
+/* }}} */
+
/* {{{ proto public bool ReflectionParameter::isArray()
Returns whether parameter MUST be an array */
ZEND_METHOD(reflection_parameter, isArray)
@@ -2867,6 +2941,69 @@ ZEND_METHOD(reflection_parameter, isVariadic)
}
/* }}} */
+/* {{{ proto public bool ReflectionType::allowsNull()
+ Returns whether parameter MAY be null */
+ZEND_METHOD(reflection_type, allowsNull)
+{
+ reflection_object *intern;
+ type_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(param);
+
+ RETVAL_BOOL(param->arg_info->allow_null);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionType::isBuiltin()
+ Returns whether parameter is a builtin type */
+ZEND_METHOD(reflection_type, isBuiltin)
+{
+ reflection_object *intern;
+ type_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(param);
+
+ RETVAL_BOOL(param->arg_info->type_hint != IS_OBJECT);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionType::__toString()
+ Return the text of the type hint */
+ZEND_METHOD(reflection_type, __toString)
+{
+ reflection_object *intern;
+ type_reference *param;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+ GET_REFLECTION_OBJECT_PTR(param);
+
+ switch (param->arg_info->type_hint) {
+ case IS_ARRAY: RETURN_STRINGL("array", sizeof("array") - 1);
+ case IS_CALLABLE: RETURN_STRINGL("callable", sizeof("callable") - 1);
+ case IS_OBJECT:
+ if (param->fptr->type == ZEND_INTERNAL_FUNCTION) {
+ if (!(param->fptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE)) {
+ RETURN_STRING(((zend_internal_arg_info*)param->arg_info)->class_name);
+ }
+ }
+ RETURN_STR_COPY(param->arg_info->class_name);
+ case IS_STRING: RETURN_STRINGL("string", sizeof("string") - 1);
+ case _IS_BOOL: RETURN_STRINGL("bool", sizeof("bool") - 1);
+ case IS_LONG: RETURN_STRINGL("int", sizeof("int") - 1);
+ case IS_DOUBLE: RETURN_STRINGL("float", sizeof("float") - 1);
+ EMPTY_SWITCH_DEFAULT_CASE()
+ }
+}
+/* }}} */
+
/* {{{ proto public static mixed ReflectionMethod::export(mixed class, string name [, bool return]) throws ReflectionException
Exports a reflection object. Returns the output if TRUE is specified for return, printing it otherwise. */
ZEND_METHOD(reflection_method, export)
@@ -3016,7 +3153,7 @@ ZEND_METHOD(reflection_method, getClosure)
if (Z_OBJCE_P(obj) == zend_ce_closure &&
(mptr->internal_function.fn_flags & ZEND_ACC_CALL_VIA_TRAMPOLINE))
{
- RETURN_ZVAL(obj, 1, 0);
+ ZVAL_COPY(return_value, obj);
} else {
zend_create_closure(return_value, mptr, mptr->common.scope, Z_OBJCE_P(obj), obj);
}
@@ -3375,7 +3512,46 @@ ZEND_METHOD(reflection_function, getShortName)
{
RETURN_STRINGL(backslash + 1, Z_STRLEN_P(name) - (backslash - Z_STRVAL_P(name) + 1));
}
- RETURN_ZVAL(name, 1, 0);
+ ZVAL_DEREF(name);
+ ZVAL_COPY(return_value, name);
+}
+/* }}} */
+
+/* {{{ proto public bool ReflectionFunctionAbstract:hasReturnType()
+ Return whether the function has a return type */
+ZEND_METHOD(reflection_function, hasReturnType)
+{
+ reflection_object *intern;
+ zend_function *fptr;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ GET_REFLECTION_OBJECT_PTR(fptr);
+
+ RETVAL_BOOL(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE);
+}
+/* }}} */
+
+/* {{{ proto public string ReflectionFunctionAbstract::getReturnType()
+ Returns the return type associated with the function */
+ZEND_METHOD(reflection_function, getReturnType)
+{
+ reflection_object *intern;
+ zend_function *fptr;
+
+ if (zend_parse_parameters_none() == FAILURE) {
+ return;
+ }
+
+ GET_REFLECTION_OBJECT_PTR(fptr);
+
+ if (!(fptr->op_array.fn_flags & ZEND_ACC_HAS_RETURN_TYPE)) {
+ RETURN_NULL();
+ }
+
+ reflection_type_factory(_copy_function(fptr), Z_ISUNDEF(intern->obj)? NULL : &intern->obj, &fptr->common.arg_info[-1], return_value);
}
/* }}} */
@@ -3644,14 +3820,15 @@ ZEND_METHOD(reflection_class, getStaticPropertyValue)
prop = zend_std_get_static_property(ce, name, 1);
if (!prop) {
if (def_value) {
- RETURN_ZVAL(def_value, 1, 0);
+ ZVAL_COPY(return_value, def_value);
} else {
zend_throw_exception_ex(reflection_exception_ptr, 0,
"Class %s does not have a property named %s", ce->name->val, name->val);
}
return;
} else {
- RETURN_ZVAL(prop, 1, 0);
+ ZVAL_DEREF(prop);
+ ZVAL_COPY(return_value, prop);
}
}
/* }}} */
@@ -4963,7 +5140,8 @@ ZEND_METHOD(reflection_class, getShortName)
{
RETURN_STRINGL(backslash + 1, Z_STRLEN_P(name) - (backslash - Z_STRVAL_P(name) + 1));
}
- RETURN_ZVAL(name, 1, 0);
+ ZVAL_DEREF(name);
+ ZVAL_COPY(return_value, name);
}
/* }}} */
@@ -5984,6 +6162,8 @@ static const zend_function_entry reflection_function_abstract_functions[] = {
ZEND_ME(reflection_function, getStartLine, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, getStaticVariables, arginfo_reflection__void, 0)
ZEND_ME(reflection_function, returnsReference, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_function, hasReturnType, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_function, getReturnType, arginfo_reflection__void, 0)
PHP_FE_END
};
@@ -6064,7 +6244,7 @@ static const zend_function_entry reflection_method_functions[] = {
ZEND_ME(reflection_method, invokeArgs, arginfo_reflection_method_invokeArgs, 0)
ZEND_ME(reflection_method, getDeclaringClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_method, getPrototype, arginfo_reflection__void, 0)
- ZEND_ME(reflection_property, setAccessible, arginfo_reflection_method_setAccessible, 0)
+ ZEND_ME(reflection_method, setAccessible, arginfo_reflection_method_setAccessible, 0)
PHP_FE_END
};
@@ -6281,6 +6461,8 @@ static const zend_function_entry reflection_parameter_functions[] = {
ZEND_ME(reflection_parameter, getDeclaringFunction, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getDeclaringClass, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, getClass, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_parameter, hasType, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_parameter, getType, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, isArray, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, isCallable, arginfo_reflection__void, 0)
ZEND_ME(reflection_parameter, allowsNull, arginfo_reflection__void, 0)
@@ -6294,6 +6476,14 @@ static const zend_function_entry reflection_parameter_functions[] = {
PHP_FE_END
};
+static const zend_function_entry reflection_type_functions[] = {
+ ZEND_ME(reflection, __clone, arginfo_reflection__void, ZEND_ACC_PRIVATE|ZEND_ACC_FINAL)
+ ZEND_ME(reflection_type, allowsNull, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_type, isBuiltin, arginfo_reflection__void, 0)
+ ZEND_ME(reflection_type, __toString, arginfo_reflection__void, 0)
+ PHP_FE_END
+};
+
ZEND_BEGIN_ARG_INFO_EX(arginfo_reflection_extension_export, 0, 0, 1)
ZEND_ARG_INFO(0, name)
ZEND_ARG_INFO(0, return)
@@ -6407,6 +6597,10 @@ PHP_MINIT_FUNCTION(reflection) /* {{{ */
zend_class_implements(reflection_parameter_ptr, 1, reflector_ptr);
zend_declare_property_string(reflection_parameter_ptr, "name", sizeof("name")-1, "", ZEND_ACC_PUBLIC);
+ INIT_CLASS_ENTRY(_reflection_entry, "ReflectionType", reflection_type_functions);
+ _reflection_entry.create_object = reflection_objects_new;
+ reflection_type_ptr = zend_register_internal_class(&_reflection_entry);
+
INIT_CLASS_ENTRY(_reflection_entry, "ReflectionMethod", reflection_method_functions);
_reflection_entry.create_object = reflection_objects_new;
reflection_method_ptr = zend_register_internal_class_ex(&_reflection_entry, reflection_function_abstract_ptr);
diff --git a/ext/reflection/php_reflection.h b/ext/reflection/php_reflection.h
index 1bb47b16c8..b50309d9ff 100644
--- a/ext/reflection/php_reflection.h
+++ b/ext/reflection/php_reflection.h
@@ -37,6 +37,7 @@ extern PHPAPI zend_class_entry *reflection_ptr;
extern PHPAPI zend_class_entry *reflection_function_abstract_ptr;
extern PHPAPI zend_class_entry *reflection_function_ptr;
extern PHPAPI zend_class_entry *reflection_parameter_ptr;
+extern PHPAPI zend_class_entry *reflection_type_ptr;
extern PHPAPI zend_class_entry *reflection_class_ptr;
extern PHPAPI zend_class_entry *reflection_object_ptr;
extern PHPAPI zend_class_entry *reflection_method_ptr;
diff --git a/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt b/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt
index 508f73ee55..4eda22a3f9 100644
--- a/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt
+++ b/ext/reflection/tests/ReflectionExtension_getClasses_basic.phpt
@@ -9,7 +9,7 @@ var_dump($ext->getClasses());
?>
==DONE==
--EXPECT--
-array(13) {
+array(14) {
["ReflectionException"]=>
object(ReflectionClass)#2 (1) {
["name"]=>
@@ -45,33 +45,38 @@ array(13) {
["name"]=>
string(19) "ReflectionParameter"
}
- ["ReflectionMethod"]=>
+ ["ReflectionType"]=>
object(ReflectionClass)#9 (1) {
["name"]=>
+ string(14) "ReflectionType"
+ }
+ ["ReflectionMethod"]=>
+ object(ReflectionClass)#10 (1) {
+ ["name"]=>
string(16) "ReflectionMethod"
}
["ReflectionClass"]=>
- object(ReflectionClass)#10 (1) {
+ object(ReflectionClass)#11 (1) {
["name"]=>
string(15) "ReflectionClass"
}
["ReflectionObject"]=>
- object(ReflectionClass)#11 (1) {
+ object(ReflectionClass)#12 (1) {
["name"]=>
string(16) "ReflectionObject"
}
["ReflectionProperty"]=>
- object(ReflectionClass)#12 (1) {
+ object(ReflectionClass)#13 (1) {
["name"]=>
string(18) "ReflectionProperty"
}
["ReflectionExtension"]=>
- object(ReflectionClass)#13 (1) {
+ object(ReflectionClass)#14 (1) {
["name"]=>
string(19) "ReflectionExtension"
}
["ReflectionZendExtension"]=>
- object(ReflectionClass)#14 (1) {
+ object(ReflectionClass)#15 (1) {
["name"]=>
string(23) "ReflectionZendExtension"
}
diff --git a/ext/reflection/tests/ReflectionType_001.phpt b/ext/reflection/tests/ReflectionType_001.phpt
new file mode 100644
index 0000000000..f764cf1519
--- /dev/null
+++ b/ext/reflection/tests/ReflectionType_001.phpt
@@ -0,0 +1,185 @@
+--TEST--
+ReflectionParameter::get/hasType and ReflectionType tests
+--FILE--
+<?php
+function foo(stdClass $a, array $b, callable $c, stdClass $d = null, $e = null, string $f, bool $g, int $h, float $i, NotExisting $j) { }
+
+function bar(): stdClass { return new stdClass; }
+
+class c extends stdClass {
+ function bar(self $x): int { return 1; }
+ function pbar(parent $x): int { return 1; }
+ function factory(): self { return new c; }
+ function pfactory(): parent { return new stdClass; }
+}
+
+$closure = function (Test $a): Test { return $a; };
+
+echo "*** functions\n";
+
+foreach ([
+ new ReflectionFunction('foo'),
+ new ReflectionFunction($closure),
+] as $idx => $rf) {
+ foreach ($rf->getParameters() as $idx2 => $rp) {
+ echo "** Function $idx - Parameter $idx2\n";
+ var_dump($rp->hasType());
+ $ra = $rp->getType();
+ if ($ra) {
+ var_dump($ra->allowsNull());
+ var_dump($ra->isBuiltin());
+ var_dump((string)$ra);
+ }
+ }
+}
+
+echo "\n*** methods\n";
+
+foreach ([
+ new ReflectionMethod('SplObserver', 'update'),
+ new ReflectionMethod('c', 'bar'),
+ new ReflectionMethod('c', 'pbar'),
+ new ReflectionMethod($closure, '__invoke'),
+] as $idx => $rm) {
+ foreach ($rm->getParameters() as $idx2 => $rp) {
+ echo "** Method $idx - parameter $idx2\n";
+ var_dump($rp->hasType());
+ $ra = $rp->getType();
+ if ($ra) {
+ var_dump($ra->allowsNull());
+ var_dump($ra->isBuiltin());
+ var_dump((string)$ra);
+ }
+ }
+}
+
+echo "\n*** return types\n";
+
+foreach ([
+ new ReflectionMethod('SplObserver', 'update'),
+ new ReflectionFunction('bar'),
+ new ReflectionMethod('c', 'bar'),
+ new ReflectionMethod('c', 'factory'),
+ new ReflectionMethod('c', 'pfactory'),
+ new ReflectionFunction($closure),
+ new ReflectionMethod($closure, '__invoke'),
+] as $idx => $rf) {
+ echo "** Function/method return type $idx\n";
+ var_dump($rf->hasReturnType());
+ $ra = $rf->getReturnType();
+ if ($ra) {
+ var_dump($ra->allowsNull());
+ var_dump($ra->isBuiltin());
+ var_dump((string)$ra);
+ }
+}
+--EXPECT--
+*** functions
+** Function 0 - Parameter 0
+bool(true)
+bool(false)
+bool(false)
+string(8) "stdClass"
+** Function 0 - Parameter 1
+bool(true)
+bool(false)
+bool(true)
+string(5) "array"
+** Function 0 - Parameter 2
+bool(true)
+bool(false)
+bool(true)
+string(8) "callable"
+** Function 0 - Parameter 3
+bool(true)
+bool(true)
+bool(false)
+string(8) "stdClass"
+** Function 0 - Parameter 4
+bool(false)
+** Function 0 - Parameter 5
+bool(true)
+bool(false)
+bool(true)
+string(6) "string"
+** Function 0 - Parameter 6
+bool(true)
+bool(false)
+bool(true)
+string(4) "bool"
+** Function 0 - Parameter 7
+bool(true)
+bool(false)
+bool(true)
+string(3) "int"
+** Function 0 - Parameter 8
+bool(true)
+bool(false)
+bool(true)
+string(5) "float"
+** Function 0 - Parameter 9
+bool(true)
+bool(false)
+bool(false)
+string(11) "NotExisting"
+** Function 1 - Parameter 0
+bool(true)
+bool(false)
+bool(false)
+string(4) "Test"
+
+*** methods
+** Method 0 - parameter 0
+bool(true)
+bool(false)
+bool(false)
+string(10) "SplSubject"
+** Method 1 - parameter 0
+bool(true)
+bool(false)
+bool(false)
+string(4) "self"
+** Method 2 - parameter 0
+bool(true)
+bool(false)
+bool(false)
+string(6) "parent"
+** Method 3 - parameter 0
+bool(true)
+bool(false)
+bool(false)
+string(4) "Test"
+
+*** return types
+** Function/method return type 0
+bool(false)
+** Function/method return type 1
+bool(true)
+bool(false)
+bool(false)
+string(8) "stdClass"
+** Function/method return type 2
+bool(true)
+bool(false)
+bool(true)
+string(3) "int"
+** Function/method return type 3
+bool(true)
+bool(false)
+bool(false)
+string(4) "self"
+** Function/method return type 4
+bool(true)
+bool(false)
+bool(false)
+string(6) "parent"
+** Function/method return type 5
+bool(true)
+bool(false)
+bool(false)
+string(4) "Test"
+** Function/method return type 6
+bool(true)
+bool(false)
+bool(false)
+string(4) "Test"
diff --git a/ext/reflection/tests/ReflectionType_002.phpt b/ext/reflection/tests/ReflectionType_002.phpt
new file mode 100644
index 0000000000..8313862ec5
--- /dev/null
+++ b/ext/reflection/tests/ReflectionType_002.phpt
@@ -0,0 +1,17 @@
+--TEST--
+ReflectionType leak
+--FILE--
+<?php
+
+$closure = function(Test $x): Test2 { return new Test2($x); };
+$rm = new ReflectionMethod($closure, '__invoke');
+$rp = $rm->getParameters()[0];
+$rt = $rp->getType();
+$rrt = $rm->getReturnType();
+unset($rm, $rp);
+var_dump((string) $rt, (string) $rrt);
+
+--EXPECT--
+string(4) "Test"
+string(5) "Test2"
+
diff --git a/ext/session/session.c b/ext/session/session.c
index 70adf8e1ac..66b1a8628b 100644
--- a/ext/session/session.c
+++ b/ext/session/session.c
@@ -2743,7 +2743,8 @@ static zend_bool early_find_sid_in(zval *dest, int where, php_session_rfc1867_pr
if ((ppid = zend_hash_str_find(Z_ARRVAL(PG(http_globals)[where]), PS(session_name), progress->sname_len))
&& Z_TYPE_P(ppid) == IS_STRING) {
zval_dtor(dest);
- ZVAL_ZVAL(dest, ppid, 1, 0);
+ ZVAL_DEREF(ppid);
+ ZVAL_COPY(dest, ppid);
return 1;
}
diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c
index 7a9775b752..9beb946aea 100644
--- a/ext/simplexml/simplexml.c
+++ b/ext/simplexml/simplexml.c
@@ -517,7 +517,7 @@ static int sxe_prop_dim_write(zval *object, zval *member, zval *value, zend_bool
case IS_DOUBLE:
case IS_NULL:
if (Z_TYPE_P(value) != IS_STRING) {
- ZVAL_DUP(&zval_copy, value);
+ ZVAL_COPY(&zval_copy, value);
value = &zval_copy;
convert_to_string(value);
new_value = 1;
@@ -1066,7 +1066,7 @@ static int sxe_prop_is_empty(zval *object) /* {{{ */
if (node->type == XML_ATTRIBUTE_NODE) {
return 0;
} else if (sxe->iter.type != SXE_ITER_CHILD) {
- if (!node->children || !node->parent || !node->next || node->children->next || node->children->children || node->parent->children == node->parent->last) {
+ if (sxe->iter.type == SXE_ITER_NONE || !node->children || !node->parent || node->children->next || node->children->children || node->parent->children == node->parent->last) {
node = node->children;
} else {
ZVAL_COPY_VALUE(&iter_data, &sxe->iter.data);
@@ -1186,7 +1186,7 @@ static HashTable *sxe_get_prop_hash(zval *object, int is_debug) /* {{{ */
node = NULL;
} else if (sxe->iter.type != SXE_ITER_CHILD) {
- if ( !node->children || !node->parent || !node->next || node->children->next || node->children->children || node->parent->children == node->parent->last ) {
+ if ( sxe->iter.type == SXE_ITER_NONE || !node->children || !node->parent || node->children->next || node->children->children || node->parent->children == node->parent->last ) {
node = node->children;
} else {
ZVAL_COPY_VALUE(&iter_data, &sxe->iter.data);
@@ -1930,12 +1930,8 @@ static int sxe_object_cast(zval *readobj, zval *writeobj, int type)
Returns the string content */
SXE_METHOD(__toString)
{
- zval result;
-
- if (sxe_object_cast_ex(getThis(), &result, IS_STRING) == SUCCESS) {
- RETURN_ZVAL(&result, 0, 0);
- } else {
- zval_ptr_dtor(&result);
+ if (sxe_object_cast_ex(getThis(), return_value, IS_STRING) != SUCCESS) {
+ zval_ptr_dtor(return_value);
RETURN_EMPTY_STRING();
}
}
@@ -1979,9 +1975,9 @@ static int sxe_count_elements(zval *object, zend_long *count) /* {{{ */
if (!Z_ISUNDEF(intern->tmp)) {
zval_ptr_dtor(&intern->tmp);
}
- ZVAL_ZVAL(&intern->tmp, &rv, 0, 0);
- convert_to_long(&intern->tmp);
- *count = (zend_long)Z_LVAL(intern->tmp);
+ ZVAL_LONG(&intern->tmp, zval_get_long(&rv));
+ zval_ptr_dtor(&rv);
+ *count = Z_LVAL(intern->tmp);
return SUCCESS;
}
return FAILURE;
diff --git a/ext/simplexml/sxe.c b/ext/simplexml/sxe.c
index c5241a804a..fc3f28d6d3 100644
--- a/ext/simplexml/sxe.c
+++ b/ext/simplexml/sxe.c
@@ -71,6 +71,7 @@ PHP_METHOD(ce_SimpleXMLIterator, valid)
PHP_METHOD(ce_SimpleXMLIterator, current)
{
php_sxe_object *sxe = Z_SXEOBJ_P(getThis());
+ zval *data;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -80,7 +81,9 @@ PHP_METHOD(ce_SimpleXMLIterator, current)
return; /* return NULL */
}
- RETURN_ZVAL(&sxe->iter.data, 1, 0);
+ data = &sxe->iter.data;
+ ZVAL_DEREF(data);
+ ZVAL_COPY(return_value, data);
}
/* }}} */
@@ -158,6 +161,7 @@ PHP_METHOD(ce_SimpleXMLIterator, hasChildren)
PHP_METHOD(ce_SimpleXMLIterator, getChildren)
{
php_sxe_object *sxe = Z_SXEOBJ_P(getThis());
+ zval *data;
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -166,7 +170,10 @@ PHP_METHOD(ce_SimpleXMLIterator, getChildren)
if (Z_ISUNDEF(sxe->iter.data) || sxe->iter.type == SXE_ITER_ATTRLIST) {
return; /* return NULL */
}
- RETURN_ZVAL(&sxe->iter.data, 1, 0);
+
+ data = &sxe->iter.data;
+ ZVAL_DEREF(data);
+ ZVAL_COPY(return_value, data);
}
/* {{{ arginfo */
diff --git a/ext/simplexml/tests/SimpleXMLElement_xpath.phpt b/ext/simplexml/tests/SimpleXMLElement_xpath.phpt
index 8e84c51d67..fb7e6e90f0 100644
--- a/ext/simplexml/tests/SimpleXMLElement_xpath.phpt
+++ b/ext/simplexml/tests/SimpleXMLElement_xpath.phpt
@@ -1,17 +1,15 @@
--TEST--
Testing xpath() with invalid XML
---SKIPIF--
-<?php PHP_INT_SIZE == 4 or die("skip - 32-bit only");
--FILE--
<?php
-$xml = simplexml_load_string("XXXXXXX^",$x,0x6000000000000001);
-var_dump($xml->xpath("BBBB"));
---EXPECTF--
-Notice: Undefined variable: x in %s on line %d
-
-Warning: simplexml_load_string() expects parameter 3 to be integer, float given in %s on line %d
+// gracefully recover from parsing of invalid XML; not available in PHP
+const XML_PARSE_RECOVER = 1;
-Fatal error: Uncaught Error: Call to a member function xpath() on null in %s:%d
-Stack trace:
-#0 {main}
- thrown in %s on line %d
+// we're not interested in checking concrete warnings regarding invalid XML
+$xml = @simplexml_load_string("XXXXXXX^", 'SimpleXMLElement', XML_PARSE_RECOVER);
+
+// $xml is supposed to hold a SimpleXMLElement, but not FALSE/NULL
+var_dump($xml->xpath("BBBB"));
+?>
+--EXPECT--
+bool(false)
diff --git a/ext/simplexml/tests/SimpleXMLElement_xpath_3.phpt b/ext/simplexml/tests/SimpleXMLElement_xpath_3.phpt
new file mode 100644
index 0000000000..e2997f19d1
--- /dev/null
+++ b/ext/simplexml/tests/SimpleXMLElement_xpath_3.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Testing xpath() with invalid XML
+--SKIPIF--
+<?php
+if (PHP_MAJOR_VERSION < 7) die("skip this test is for PHP 7+ only");
+if (PHP_INT_SIZE != 4) die("skip this test is for 32bit platforms only");
+?>
+--FILE--
+<?php
+$xml = simplexml_load_string("XXXXXXX^",$x,0x6000000000000001);
+var_dump($xml->xpath("BBBB"));
+?>
+--EXPECTF--
+Notice: Undefined variable: x in %s on line %d
+
+Warning: simplexml_load_string() expects parameter 3 to be integer, float given in %s on line %d
+
+Fatal error: Uncaught EngineException: Call to a member function xpath() on null in %s:%d
+Stack trace:
+#0 {main}
+ thrown in %s on line %d
diff --git a/ext/simplexml/tests/SimpleXMLElement_xpath_4.phpt b/ext/simplexml/tests/SimpleXMLElement_xpath_4.phpt
new file mode 100644
index 0000000000..d4d709753f
--- /dev/null
+++ b/ext/simplexml/tests/SimpleXMLElement_xpath_4.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Testing xpath() with invalid XML
+--SKIPIF--
+<?php
+if (PHP_MAJOR_VERSION < 7) die("skip this test is for PHP 7+ only");
+if (PHP_INT_SIZE != 8) die("skip this test is for 64bit platforms only");
+?>
+--FILE--
+<?php
+$xml = simplexml_load_string("XXXXXXX^",$x,0x6000000000000001);
+var_dump($xml->xpath("BBBB"));
+?>
+--EXPECTF--
+Notice: Undefined variable: x in %s on line %d
+
+Warning: simplexml_load_string(): Entity: line 1: parser error : Start tag expected, '<' not found in %s on line %d
+
+Warning: simplexml_load_string(): XXXXXXX^ in %s on line %d
+
+Warning: simplexml_load_string(): ^ in %s on line %d
+bool(false)
+
diff --git a/ext/simplexml/tests/bug61335.phpt b/ext/simplexml/tests/bug61335.phpt
new file mode 100644
index 0000000000..d2b9477ceb
--- /dev/null
+++ b/ext/simplexml/tests/bug61335.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Bug #61335 - Access to array node returns wrong truth value
+--SKIPIF--
+<?php
+if (!extension_loaded("simplexml")) die("skip SimpleXML not available");
+?>
+--FILE--
+<?php
+$rec1 = simplexml_load_string("<foo><bar>aa</bar>\n</foo>");
+$rec2 = simplexml_load_string("<foo><bar>aa</bar></foo>");
+
+if ($rec1->bar[0]) echo "NONEMPTY1\n";
+if ($rec1->bar[0] . "") echo "NONEMPTY2\n";
+if ($rec2->bar[0]) echo "NONEMPTY3\n";
+?>
+--EXPECT--
+NONEMPTY1
+NONEMPTY2
+NONEMPTY3
diff --git a/ext/simplexml/tests/bug62639.phpt b/ext/simplexml/tests/bug62639.phpt
new file mode 100644
index 0000000000..4a4e157b76
--- /dev/null
+++ b/ext/simplexml/tests/bug62639.phpt
@@ -0,0 +1,63 @@
+--TEST--
+Bug #62639 (XML structure broken)
+--SKIPIF--
+<?php
+if (!extension_loaded("simplexml")) die("skip SimpleXML not available");
+?>
+--FILE--
+<?php
+
+class A extends SimpleXMLElement
+{
+}
+
+$xml1 = <<<XML
+<?xml version="1.0"?>
+<a>
+ <b>
+ <c>
+ <value attr="Some Attr">Some Value</value>
+ </c>
+ </b>
+</a>
+XML;
+
+$a1 = new A($xml1);
+
+foreach ($a1->b->c->children() as $key => $value) {
+ var_dump($value);
+}
+
+$xml2 = <<<XML
+<?xml version="1.0"?>
+<a>
+ <b>
+ <c><value attr="Some Attr">Some Value</value></c>
+ </b>
+</a>
+XML;
+
+$a2 = new A($xml2);
+
+foreach ($a2->b->c->children() as $key => $value) {
+ var_dump($value);
+}?>
+--EXPECT--
+object(A)#2 (2) {
+ ["@attributes"]=>
+ array(1) {
+ ["attr"]=>
+ string(9) "Some Attr"
+ }
+ [0]=>
+ string(10) "Some Value"
+}
+object(A)#3 (2) {
+ ["@attributes"]=>
+ array(1) {
+ ["attr"]=>
+ string(9) "Some Attr"
+ }
+ [0]=>
+ string(10) "Some Value"
+} \ No newline at end of file
diff --git a/ext/simplexml/tests/bug67116.phpt b/ext/simplexml/tests/bug67116.phpt
new file mode 100644
index 0000000000..774e43c99b
--- /dev/null
+++ b/ext/simplexml/tests/bug67116.phpt
@@ -0,0 +1,93 @@
+--TEST--
+Bug #67116 (Inconsistent parsing of Nodes w/o linefeed)
+--SKIPIF--
+<?php
+if (!extension_loaded("simplexml")) die("skip SimpleXML not available");
+?>
+--FILE--
+<?php
+
+$xml = <<<XML
+<?xml version="1.0" encoding="UTF-8"?>
+<aa>
+ <bs>
+ <b>b</b>
+ </bs>
+ <cs><c>b</c></cs>
+ <ds><d id="d"></d></ds>
+ <es>
+ <e id="e"></e>
+ </es>
+ <fs><f id="f"></f><f id="f"></f></fs>
+</aa>
+XML;
+$sxe = simplexml_load_string($xml);
+print_r($sxe);
+
+?>
+--EXPECT--
+SimpleXMLElement Object
+(
+ [bs] => SimpleXMLElement Object
+ (
+ [b] => b
+ )
+
+ [cs] => SimpleXMLElement Object
+ (
+ [c] => b
+ )
+
+ [ds] => SimpleXMLElement Object
+ (
+ [d] => SimpleXMLElement Object
+ (
+ [@attributes] => Array
+ (
+ [id] => d
+ )
+
+ )
+
+ )
+
+ [es] => SimpleXMLElement Object
+ (
+ [e] => SimpleXMLElement Object
+ (
+ [@attributes] => Array
+ (
+ [id] => e
+ )
+
+ )
+
+ )
+
+ [fs] => SimpleXMLElement Object
+ (
+ [f] => Array
+ (
+ [0] => SimpleXMLElement Object
+ (
+ [@attributes] => Array
+ (
+ [id] => f
+ )
+
+ )
+
+ [1] => SimpleXMLElement Object
+ (
+ [@attributes] => Array
+ (
+ [id] => f
+ )
+
+ )
+
+ )
+
+ )
+
+)
diff --git a/ext/simplexml/tests/bug67572.phpt b/ext/simplexml/tests/bug67572.phpt
new file mode 100644
index 0000000000..4631f16142
--- /dev/null
+++ b/ext/simplexml/tests/bug67572.phpt
@@ -0,0 +1,33 @@
+--TEST--
+Bug #67572 - SimpleXMLElement not parsing \n correctly
+--SKIPIF--
+<?php
+if (!extension_loaded("simplexml")) die("skip SimpleXML not available");
+?>
+--FILE--
+<?php
+$foo = 'bar';
+print "regular string ... ";
+var_dump(empty($foo));
+
+$xml = simplexml_load_string("<xml><something>somevalue</something></xml>");
+$xml2 = simplexml_load_string("<xml>\n<something>somevalue</something>\n</xml>");
+
+foreach($xml as $key => $value) {
+ print "$key = $value ... ";
+ var_dump(empty($value));
+ var_dump($value == false);
+}
+
+foreach($xml2 as $key => $value) {
+ print "$key = $value ... ";
+ var_dump(empty($value));
+ var_dump($value == false);
+}
+?>
+--EXPECT--
+regular string ... bool(false)
+something = somevalue ... bool(false)
+bool(false)
+something = somevalue ... bool(false)
+bool(false)
diff --git a/ext/simplexml/tests/bug69169.phpt b/ext/simplexml/tests/bug69169.phpt
new file mode 100644
index 0000000000..08cf299290
--- /dev/null
+++ b/ext/simplexml/tests/bug69169.phpt
@@ -0,0 +1,70 @@
+--TEST--
+Bug #69169 (simplexml_load_string parse wrongly when xml given in one row)
+--SKIPIF--
+<?php
+if (!extension_loaded("simplexml")) die("skip SimpleXML not available");
+?>
+--FILE--
+<?php
+$a = '<?xml version="1.0" encoding="UTF-8"?>
+<root a="b">
+ <row b="y">
+ <item s="t" />
+ </row>
+ <row p="c">
+ <item y="n" />
+ </row>
+</root>';
+$b = str_replace(array("\n", "\r", "\t"), "", $a);
+$simple_xml = simplexml_load_string($b);
+print_r($simple_xml);
+?>
+--EXPECT--
+SimpleXMLElement Object
+(
+ [@attributes] => Array
+ (
+ [a] => b
+ )
+
+ [row] => Array
+ (
+ [0] => SimpleXMLElement Object
+ (
+ [@attributes] => Array
+ (
+ [b] => y
+ )
+
+ [item] => SimpleXMLElement Object
+ (
+ [@attributes] => Array
+ (
+ [s] => t
+ )
+
+ )
+
+ )
+
+ [1] => SimpleXMLElement Object
+ (
+ [@attributes] => Array
+ (
+ [p] => c
+ )
+
+ [item] => SimpleXMLElement Object
+ (
+ [@attributes] => Array
+ (
+ [y] => n
+ )
+
+ )
+
+ )
+
+ )
+
+)
diff --git a/ext/simplexml/tests/bug69491.phpt b/ext/simplexml/tests/bug69491.phpt
new file mode 100644
index 0000000000..b48a40bf95
--- /dev/null
+++ b/ext/simplexml/tests/bug69491.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #69491 (simplexml doesn't correctly parse empty nodes on same line as another node)
+--SKIPIF--
+<?php
+if (!extension_loaded("simplexml")) die("skip SimpleXML not available");
+?>
+--FILE--
+<?php
+var_dump(simplexml_load_string('<a>
+ <b><c/></b>
+</a>'));?>
+--EXPECT--
+object(SimpleXMLElement)#1 (1) {
+ ["b"]=>
+ object(SimpleXMLElement)#2 (1) {
+ ["c"]=>
+ object(SimpleXMLElement)#3 (0) {
+ }
+ }
+}
diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c
index 96207f7975..7bff2aeab6 100644
--- a/ext/soap/php_encoding.c
+++ b/ext/soap/php_encoding.c
@@ -923,21 +923,16 @@ static xmlNodePtr to_xml_base64(encodeTypePtr type, zval *data, int style, xmlNo
if (Z_TYPE_P(data) == IS_STRING) {
str = php_base64_encode((unsigned char*)Z_STRVAL_P(data), Z_STRLEN_P(data));
- text = xmlNewTextLen(BAD_CAST(str->val), str->len);
- xmlAddChild(ret, text);
- zend_string_release(str);
} else {
- zval tmp;
-
- ZVAL_DUP(&tmp, data);
- convert_to_string(&tmp);
- str = php_base64_encode((unsigned char*)Z_STRVAL(tmp), Z_STRLEN(tmp));
- text = xmlNewTextLen(BAD_CAST(str->val), str->len);
- xmlAddChild(ret, text);
- zend_string_release(str);
- zval_dtor(&tmp);
+ zend_string *tmp = zval_get_string(data);
+ str = php_base64_encode((unsigned char*) tmp->val, tmp->len);
+ zend_string_release(tmp);
}
+ text = xmlNewTextLen(BAD_CAST(str->val), str->len);
+ xmlAddChild(ret, text);
+ zend_string_release(str);
+
if (style == SOAP_ENCODED) {
set_ns_and_type(ret, type);
}
diff --git a/ext/sockets/tests/socket_import_stream-4-win.phpt b/ext/sockets/tests/socket_import_stream-4-win.phpt
index 0effd04d34..1c9a7789c6 100644
--- a/ext/sockets/tests/socket_import_stream-4-win.phpt
+++ b/ext/sockets/tests/socket_import_stream-4-win.phpt
@@ -80,11 +80,11 @@ stream_set_blocking
Warning: stream_set_blocking(): supplied resource is not a valid stream resource in %s on line %d
socket_set_block
-Warning: socket_set_block(): unable to set blocking mode [%d]: An operation was attempted on something that is not a socket.
+Warning: socket_set_block(): unable to set blocking mode [10038]: %s
in %ssocket_import_stream-4-win.php on line %d
socket_get_option
-Warning: socket_get_option(): unable to retrieve socket option [%d]: An operation was attempted on something that is not a socket.
+Warning: socket_get_option(): unable to retrieve socket option [10038]: %s
in %ssocket_import_stream-4-win.php on line %d
diff --git a/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp-win32.phpt b/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp-win32.phpt
index ec965094bc..8754028f84 100644
--- a/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp-win32.phpt
+++ b/ext/sockets/tests/socket_sentto_recvfrom_ipv6_udp-win32.phpt
@@ -48,7 +48,7 @@ require 'ipv6_skipif.inc';
socket_close($socket);
--EXPECTF--
-Warning: socket_recvfrom(): unable to recvfrom [10022]: An invalid argument was supplied.
+Warning: socket_recvfrom(): unable to recvfrom [10022]: %s
in %s on line %d
Warning: Wrong parameter count for socket_sendto() in %s on line %d
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index c56e2d5f22..4ade06a5d8 100644
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -831,6 +831,15 @@ static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp) /* {{{ */
}
/* }}} */
+static HashTable *spl_array_get_gc(zval *obj, zval **gc_data, int *gc_data_count) /* {{{ */
+{
+ spl_array_object *intern = Z_SPLARRAY_P(obj);
+ *gc_data = &intern->array;
+ *gc_data_count = 1;
+ return zend_std_get_properties(obj);
+}
+/* }}} */
+
static zval *spl_array_read_property(zval *object, zval *member, int type, void **cache_slot, zval *rv) /* {{{ */
{
spl_array_object *intern = Z_SPLARRAY_P(object);
@@ -1913,6 +1922,7 @@ PHP_MINIT_FUNCTION(spl_array)
spl_handler_ArrayObject.get_properties = spl_array_get_properties;
spl_handler_ArrayObject.get_debug_info = spl_array_get_debug_info;
+ spl_handler_ArrayObject.get_gc = spl_array_get_gc;
spl_handler_ArrayObject.read_property = spl_array_read_property;
spl_handler_ArrayObject.write_property = spl_array_write_property;
spl_handler_ArrayObject.get_property_ptr_ptr = spl_array_get_property_ptr_ptr;
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index 12c50c0b46..3fed81949a 100644
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -1854,8 +1854,8 @@ static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type)
zval *retval_ptr = &retval;
ZVAL_STRINGL(retval_ptr, intern->file_name, intern->file_name_len);
- zval_dtor(readobj);
- ZVAL_ZVAL(writeobj, retval_ptr, 0, 0);
+ zval_ptr_dtor(readobj);
+ ZVAL_COPY_VALUE(writeobj, retval_ptr);
} else {
ZVAL_STRINGL(writeobj, intern->file_name, intern->file_name_len);
}
@@ -1866,8 +1866,8 @@ static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type)
zval *retval_ptr = &retval;
ZVAL_STRING(retval_ptr, intern->u.dir.entry.d_name);
- zval_dtor(readobj);
- ZVAL_ZVAL(writeobj, retval_ptr, 0, 0);
+ zval_ptr_dtor(readobj);
+ ZVAL_COPY_VALUE(writeobj, retval_ptr);
} else {
ZVAL_STRING(writeobj, intern->u.dir.entry.d_name);
}
@@ -1878,7 +1878,7 @@ static int spl_filesystem_object_cast(zval *readobj, zval *writeobj, int type)
return SUCCESS;
}
if (readobj == writeobj) {
- zval_dtor(readobj);
+ zval_ptr_dtor(readobj);
}
ZVAL_NULL(writeobj);
return FAILURE;
@@ -2031,7 +2031,7 @@ static int spl_filesystem_file_read(spl_filesystem_object *intern, int silent) /
if (intern->u.file.max_line_len > 0) {
buf = safe_emalloc((intern->u.file.max_line_len + 1), sizeof(char), 0);
- if (php_stream_get_line(intern->u.file.stream, buf, intern->u.file.max_line_len, &line_len) == NULL) {
+ if (php_stream_get_line(intern->u.file.stream, buf, intern->u.file.max_line_len + 1, &line_len) == NULL) {
efree(buf);
buf = NULL;
} else {
@@ -2140,7 +2140,7 @@ static int spl_filesystem_file_read_csv(spl_filesystem_object *intern, char deli
php_fgetcsv(intern->u.file.stream, delimiter, enclosure, escape, buf_len, buf, &intern->u.file.current_zval);
if (return_value) {
if (Z_TYPE_P(return_value) != IS_NULL) {
- zval_dtor(return_value);
+ zval_ptr_dtor(return_value);
ZVAL_NULL(return_value);
}
ZVAL_ZVAL(return_value, &intern->u.file.current_zval, 1, 0);
diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c
index a92707bd93..c4857663e7 100644
--- a/ext/spl/spl_heap.c
+++ b/ext/spl/spl_heap.c
@@ -249,9 +249,10 @@ static void spl_ptr_heap_insert(spl_ptr_heap *heap, zval *elem, void *cmp_userda
}
/* sifting up */
- for (i = heap->count++; i > 0 && heap->cmp(&heap->elements[(i-1)/2], elem, cmp_userdata) < 0; i = (i-1)/2) {
+ for (i = heap->count; i > 0 && heap->cmp(&heap->elements[(i-1)/2], elem, cmp_userdata) < 0; i = (i-1)/2) {
heap->elements[i] = heap->elements[(i-1)/2];
}
+ heap->count++;
if (EG(exception)) {
/* exception thrown during comparison */
diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c
index 37f97866c7..aa0854ab78 100644
--- a/ext/spl/spl_iterators.c
+++ b/ext/spl/spl_iterators.c
@@ -494,7 +494,7 @@ static void spl_recursive_it_it_construct(INTERNAL_FUNCTION_PARAMETERS, zend_cla
}
if (user_caching_it_flags) {
- ZVAL_ZVAL(&caching_it_flags, user_caching_it_flags, 1, 0);
+ ZVAL_COPY(&caching_it_flags, user_caching_it_flags);
} else {
ZVAL_LONG(&caching_it_flags, CIT_CATCH_GET_CHILD);
}
@@ -1067,10 +1067,10 @@ static void spl_recursive_tree_iterator_get_entry(spl_recursive_it_object *objec
if (data) {
RETVAL_ZVAL(data, 1, 0);
if (Z_TYPE_P(return_value) == IS_ARRAY) {
- zval_dtor(return_value);
+ zval_ptr_dtor(return_value);
ZVAL_STRINGL(return_value, "Array", sizeof("Array")-1);
} else {
- convert_to_string(return_value);
+ convert_to_string_ex(return_value);
}
}
zend_restore_error_handling(&error_handling);
@@ -1268,9 +1268,7 @@ SPL_METHOD(RecursiveTreeIterator, key)
}
if (object->flags & RTIT_BYPASS_KEY) {
- zval *key_ptr = &key;
- RETVAL_ZVAL(key_ptr, 1, 0);
- zval_dtor(&key);
+ RETVAL_ZVAL(&key, 1, 1);
return;
}
@@ -2074,8 +2072,7 @@ SPL_METHOD(RegexIterator, accept)
case REGIT_MODE_REPLACE:
replacement = zend_read_property(intern->std.ce, getThis(), "replacement", sizeof("replacement")-1, 1, &rv);
if (Z_TYPE_P(replacement) != IS_STRING) {
- tmp_replacement = *replacement;
- zval_copy_ctor(&tmp_replacement);
+ ZVAL_COPY(&tmp_replacement, replacement);
convert_to_string(&tmp_replacement);
replacement = &tmp_replacement;
}
@@ -2090,7 +2087,7 @@ SPL_METHOD(RegexIterator, accept)
}
if (replacement == &tmp_replacement) {
- zval_dtor(replacement);
+ zval_ptr_dtor(replacement);
}
RETVAL_BOOL(count > 0);
}
@@ -2787,11 +2784,11 @@ SPL_METHOD(CachingIterator, __toString)
return;
}
if (intern->u.caching.flags & CIT_TOSTRING_USE_KEY) {
- ZVAL_DUP(return_value, &intern->current.key);
+ ZVAL_COPY(return_value, &intern->current.key);
convert_to_string(return_value);
return;
} else if (intern->u.caching.flags & CIT_TOSTRING_USE_CURRENT) {
- ZVAL_DUP(return_value, &intern->current.data);
+ ZVAL_COPY(return_value, &intern->current.data);
convert_to_string(return_value);
return;
}
@@ -3529,7 +3526,7 @@ static int spl_iterator_to_array_apply(zend_object_iterator *iter, void *puser)
return ZEND_HASH_APPLY_STOP;
}
array_set_zval_key(Z_ARRVAL_P(return_value), &key, data);
- zval_dtor(&key);
+ zval_ptr_dtor(&key);
} else {
Z_TRY_ADDREF_P(data);
add_next_index_zval(return_value, data);
@@ -3571,7 +3568,7 @@ PHP_FUNCTION(iterator_to_array)
array_init(return_value);
if (spl_iterator_apply(obj, use_keys ? spl_iterator_to_array_apply : spl_iterator_to_values_apply, (void*)return_value) != SUCCESS) {
- zval_dtor(return_value);
+ zval_ptr_dtor(return_value);
RETURN_NULL();
}
} /* }}} */
diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c
index ddff20ea4f..e2a55735a3 100644
--- a/ext/spl/spl_observer.c
+++ b/ext/spl/spl_observer.c
@@ -657,7 +657,7 @@ SPL_METHOD(SplObjectStorage, current)
if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) {
return;
}
- RETVAL_ZVAL(&element->obj, 1, 0);
+ ZVAL_COPY(return_value, &element->obj);
} /* }}} */
/* {{{ proto mixed SplObjectStorage::getInfo()
@@ -674,7 +674,7 @@ SPL_METHOD(SplObjectStorage, getInfo)
if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) {
return;
}
- RETVAL_ZVAL(&element->inf, 1, 0);
+ ZVAL_COPY(return_value, &element->inf);
} /* }}} */
/* {{{ proto mixed SplObjectStorage::setInfo(mixed $inf)
@@ -693,7 +693,7 @@ SPL_METHOD(SplObjectStorage, setInfo)
return;
}
zval_ptr_dtor(&element->inf);
- ZVAL_ZVAL(&element->inf, inf, 1, 0);
+ ZVAL_COPY(&element->inf, inf);
} /* }}} */
/* {{{ proto void SplObjectStorage::next()
diff --git a/ext/spl/tests/bug67805.phpt b/ext/spl/tests/bug67805.phpt
new file mode 100644
index 0000000000..ba07b3da92
--- /dev/null
+++ b/ext/spl/tests/bug67805.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #67805 SplFileObject setMaxLineLength
+--CREDITS--
+Willian Gustavo Veiga <contact@willianveiga.com>
+--FILE--
+<?php
+$splFileObject = new SplFileObject(__FILE__);
+$splFileObject->setMaxLineLen(3);
+$line = $splFileObject->getCurrentLine();
+var_dump($line === '<?p');
+var_dump(strlen($line) === 3);
+?>
+--EXPECTF--
+bool(true)
+bool(true)
diff --git a/ext/spl/tests/bug69737.phpt b/ext/spl/tests/bug69737.phpt
new file mode 100644
index 0000000000..02815c296a
--- /dev/null
+++ b/ext/spl/tests/bug69737.phpt
@@ -0,0 +1,21 @@
+--TEST--
+Bug #69737 (Segfault when SplMinHeap::compare produces fatal error)
+--FILE--
+<?php
+class SplMinHeap1 extends SplMinHeap {
+ public function compare($a, $b) {
+ return -parent::notexist($a, $b);
+ }
+}
+$h = new SplMinHeap1();
+$h->insert(1);
+$h->insert(6);
+?>
+===DONE===
+--EXPECTF--
+Fatal error: Uncaught Error: Call to undefined method SplMinHeap::notexist() in %s%ebug69737.php:%d
+Stack trace:
+#0 [internal function]: SplMinHeap1->compare(1, 6)
+#1 %s%ebug69737.php(%d): SplHeap->insert(6)
+#2 {main}
+ thrown in %s%ebug69737.php on line %d
diff --git a/ext/spl/tests/fileobject_setmaxlinelen_basic.phpt b/ext/spl/tests/fileobject_setmaxlinelen_basic.phpt
index c2307663cb..1d81a6f651 100644
--- a/ext/spl/tests/fileobject_setmaxlinelen_basic.phpt
+++ b/ext/spl/tests/fileobject_setmaxlinelen_basic.phpt
@@ -12,4 +12,4 @@ $s->setMaxLineLen( 3);
echo $s->getCurrentLine();
?>
--EXPECT--
-<?
+<?p
diff --git a/ext/sqlite3/libsqlite/sqlite3.c b/ext/sqlite3/libsqlite/sqlite3.c
index c9ed48f4bf..dff4538dd3 100644
--- a/ext/sqlite3/libsqlite/sqlite3.c
+++ b/ext/sqlite3/libsqlite/sqlite3.c
@@ -1,6 +1,6 @@
/******************************************************************************
** This file is an amalgamation of many separate C source files from SQLite
-** version 3.8.8.3. By combining all the individual C code files into this
+** version 3.8.10.2. By combining all the individual C code files into this
** single large file, the entire code can be compiled as a single translation
** unit. This allows many compilers to do optimizations that would not be
** possible if the files were compiled separately. Performance improvements
@@ -22,9 +22,6 @@
#ifndef SQLITE_PRIVATE
# define SQLITE_PRIVATE static
#endif
-#ifndef SQLITE_API
-# define SQLITE_API
-#endif
/************** Begin file sqliteInt.h ***************************************/
/*
** 2001 September 15
@@ -73,6 +70,7 @@
#pragma warning(disable : 4055)
#pragma warning(disable : 4100)
#pragma warning(disable : 4127)
+#pragma warning(disable : 4130)
#pragma warning(disable : 4152)
#pragma warning(disable : 4189)
#pragma warning(disable : 4206)
@@ -91,6 +89,44 @@
/************** Continuing where we left off in sqliteInt.h ******************/
/*
+** Special setup for VxWorks
+*/
+/************** Include vxworks.h in the middle of sqliteInt.h ***************/
+/************** Begin file vxworks.h *****************************************/
+/*
+** 2015-03-02
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains code that is specific to Wind River's VxWorks
+*/
+#if defined(__RTP__) || defined(_WRS_KERNEL)
+/* This is VxWorks. Set up things specially for that OS
+*/
+#include <vxWorks.h>
+#include <pthread.h> /* amalgamator: dontcache */
+#define OS_VXWORKS 1
+#define SQLITE_OS_OTHER 0
+#define SQLITE_HOMEGROWN_RECURSIVE_MUTEX 1
+#define SQLITE_OMIT_LOAD_EXTENSION 1
+#define SQLITE_ENABLE_LOCKING_STYLE 0
+#define HAVE_UTIME 1
+#else
+/* This is not VxWorks. */
+#define OS_VXWORKS 0
+#endif /* defined(_WRS_KERNEL) */
+
+/************** End of vxworks.h *********************************************/
+/************** Continuing where we left off in sqliteInt.h ******************/
+
+/*
** These #defines should enable >2GB file support on POSIX if the
** underlying operating system supports it. If the OS lacks
** large file support, or if the OS is windows, these should be no-ops.
@@ -214,16 +250,20 @@ extern "C" {
/*
-** Add the ability to override 'extern'
+** Provide the ability to override linkage features of the interface.
*/
#ifndef SQLITE_EXTERN
# define SQLITE_EXTERN extern
#endif
-
#ifndef SQLITE_API
# define SQLITE_API
#endif
-
+#ifndef SQLITE_CDECL
+# define SQLITE_CDECL
+#endif
+#ifndef SQLITE_STDCALL
+# define SQLITE_STDCALL
+#endif
/*
** These no-op macros are used in front of interfaces to mark those
@@ -278,9 +318,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.8.8.3"
-#define SQLITE_VERSION_NUMBER 3008008
-#define SQLITE_SOURCE_ID "2015-02-25 13:29:11 9d6c1880fb75660bbabd693175579529785f8a6b"
+#define SQLITE_VERSION "3.8.10.2"
+#define SQLITE_VERSION_NUMBER 3008010
+#define SQLITE_SOURCE_ID "2015-05-20 18:17:19 2ef4f3a5b1d1d0c4338f8243d40a2452cc1f7fe4"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -313,9 +353,9 @@ extern "C" {
** See also: [sqlite_version()] and [sqlite_source_id()].
*/
SQLITE_API const char sqlite3_version[] = SQLITE_VERSION;
-SQLITE_API const char *sqlite3_libversion(void);
-SQLITE_API const char *sqlite3_sourceid(void);
-SQLITE_API int sqlite3_libversion_number(void);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void);
/*
** CAPI3REF: Run-Time Library Compilation Options Diagnostics
@@ -340,8 +380,8 @@ SQLITE_API int sqlite3_libversion_number(void);
** [sqlite_compileoption_get()] and the [compile_options pragma].
*/
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-SQLITE_API int sqlite3_compileoption_used(const char *zOptName);
-SQLITE_API const char *sqlite3_compileoption_get(int N);
+SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N);
#endif
/*
@@ -380,7 +420,7 @@ SQLITE_API const char *sqlite3_compileoption_get(int N);
**
** See the [threading mode] documentation for additional information.
*/
-SQLITE_API int sqlite3_threadsafe(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void);
/*
** CAPI3REF: Database Connection Handle
@@ -437,6 +477,7 @@ typedef sqlite_uint64 sqlite3_uint64;
/*
** CAPI3REF: Closing A Database Connection
+** DESTRUCTOR: sqlite3
**
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
** for the [sqlite3] object.
@@ -476,8 +517,8 @@ typedef sqlite_uint64 sqlite3_uint64;
** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
** argument is a harmless no-op.
*/
-SQLITE_API int sqlite3_close(sqlite3*);
-SQLITE_API int sqlite3_close_v2(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3*);
/*
** The type for a callback function.
@@ -488,6 +529,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
/*
** CAPI3REF: One-Step Query Execution Interface
+** METHOD: sqlite3
**
** The sqlite3_exec() interface is a convenience wrapper around
** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
@@ -547,7 +589,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
** </ul>
*/
-SQLITE_API int sqlite3_exec(
+SQLITE_API int SQLITE_STDCALL sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
@@ -927,14 +969,16 @@ struct sqlite3_io_methods {
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
** interface.
**
+** <ul>
+** <li>[[SQLITE_FCNTL_LOCKSTATE]]
** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
** opcode causes the xFileControl method to write the current state of
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
** into an integer that the pArg argument points to. This capability
-** is used during testing and only needs to be supported when SQLITE_TEST
-** is defined.
-** <ul>
+** is used during testing and is only available when the SQLITE_TEST
+** compile-time option is used.
+**
** <li>[[SQLITE_FCNTL_SIZE_HINT]]
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
** layer a hint of how large the database file will grow to be during the
@@ -1059,7 +1103,9 @@ struct sqlite3_io_methods {
** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
** file control returns [SQLITE_OK], then the parser assumes that the
** VFS has handled the PRAGMA itself and the parser generates a no-op
-** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
+** prepared statement if result string is NULL, or that returns a copy
+** of the result string if the string is non-NULL.
+** ^If the [SQLITE_FCNTL_PRAGMA] file control returns
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
** that the VFS encountered an error while handling the [PRAGMA] and the
** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
@@ -1117,12 +1163,19 @@ struct sqlite3_io_methods {
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
+** <li>[[SQLITE_FCNTL_WAL_BLOCK]]
+** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
+** be advantageous to block on the next WAL lock if the lock is not immediately
+** available. The WAL subsystem issues this signal during rare
+** circumstances in order to fix a problem with priority inversion.
+** Applications should <em>not</em> use this file-control.
+**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
-#define SQLITE_GET_LOCKPROXYFILE 2
-#define SQLITE_SET_LOCKPROXYFILE 3
-#define SQLITE_LAST_ERRNO 4
+#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
+#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3
+#define SQLITE_FCNTL_LAST_ERRNO 4
#define SQLITE_FCNTL_SIZE_HINT 5
#define SQLITE_FCNTL_CHUNK_SIZE 6
#define SQLITE_FCNTL_FILE_POINTER 7
@@ -1141,6 +1194,13 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_SYNC 21
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
+#define SQLITE_FCNTL_WAL_BLOCK 24
+
+/* deprecated names */
+#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
+#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
+#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
+
/*
** CAPI3REF: Mutex Handle
@@ -1489,10 +1549,10 @@ struct sqlite3_vfs {
** must return [SQLITE_OK] on success and some other [error code] upon
** failure.
*/
-SQLITE_API int sqlite3_initialize(void);
-SQLITE_API int sqlite3_shutdown(void);
-SQLITE_API int sqlite3_os_init(void);
-SQLITE_API int sqlite3_os_end(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void);
/*
** CAPI3REF: Configuring The SQLite Library
@@ -1523,10 +1583,11 @@ SQLITE_API int sqlite3_os_end(void);
** ^If the option is unknown or SQLite is unable to set the option
** then this routine returns a non-zero [error code].
*/
-SQLITE_API int sqlite3_config(int, ...);
+SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...);
/*
** CAPI3REF: Configure database connections
+** METHOD: sqlite3
**
** The sqlite3_db_config() interface is used to make configuration
** changes to a [database connection]. The interface is similar to
@@ -1541,7 +1602,7 @@ SQLITE_API int sqlite3_config(int, ...);
** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if
** the call is considered successful.
*/
-SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
+SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3*, int op, ...);
/*
** CAPI3REF: Memory Allocation Routines
@@ -1701,7 +1762,7 @@ struct sqlite3_mem_methods {
** <li> [sqlite3_memory_used()]
** <li> [sqlite3_memory_highwater()]
** <li> [sqlite3_soft_heap_limit64()]
-** <li> [sqlite3_status()]
+** <li> [sqlite3_status64()]
** </ul>)^
** ^Memory allocation statistics are enabled by default unless SQLite is
** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
@@ -1912,7 +1973,6 @@ struct sqlite3_mem_methods {
** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro
** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
** that specifies the maximum size of the created heap.
-** </dl>
**
** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
@@ -2025,15 +2085,17 @@ struct sqlite3_mem_methods {
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
+** METHOD: sqlite3
**
** ^The sqlite3_extended_result_codes() routine enables or disables the
** [extended result codes] feature of SQLite. ^The extended result
** codes are disabled by default for historical compatibility.
*/
-SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
+SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff);
/*
** CAPI3REF: Last Insert Rowid
+** METHOD: sqlite3
**
** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables)
** has a unique 64-bit signed
@@ -2081,10 +2143,11 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
** unpredictable and might not equal either the old or the new
** last insert [rowid].
*/
-SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*);
/*
** CAPI3REF: Count The Number Of Rows Modified
+** METHOD: sqlite3
**
** ^This function returns the number of rows modified, inserted or
** deleted by the most recently completed INSERT, UPDATE or DELETE
@@ -2133,10 +2196,11 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
** while [sqlite3_changes()] is running then the value returned
** is unpredictable and not meaningful.
*/
-SQLITE_API int sqlite3_changes(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*);
/*
** CAPI3REF: Total Number Of Rows Modified
+** METHOD: sqlite3
**
** ^This function returns the total number of rows inserted, modified or
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
@@ -2156,10 +2220,11 @@ SQLITE_API int sqlite3_changes(sqlite3*);
** while [sqlite3_total_changes()] is running then the value
** returned is unpredictable and not meaningful.
*/
-SQLITE_API int sqlite3_total_changes(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*);
/*
** CAPI3REF: Interrupt A Long-Running Query
+** METHOD: sqlite3
**
** ^This function causes any pending database operation to abort and
** return at its earliest opportunity. This routine is typically
@@ -2195,7 +2260,7 @@ SQLITE_API int sqlite3_total_changes(sqlite3*);
** If the database connection closes while [sqlite3_interrupt()]
** is running then bad things will likely happen.
*/
-SQLITE_API void sqlite3_interrupt(sqlite3*);
+SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*);
/*
** CAPI3REF: Determine If An SQL Statement Is Complete
@@ -2230,12 +2295,13 @@ SQLITE_API void sqlite3_interrupt(sqlite3*);
** The input to [sqlite3_complete16()] must be a zero-terminated
** UTF-16 string in native byte order.
*/
-SQLITE_API int sqlite3_complete(const char *sql);
-SQLITE_API int sqlite3_complete16(const void *sql);
+SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *sql);
+SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql);
/*
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
** KEYWORDS: {busy-handler callback} {busy handler}
+** METHOD: sqlite3
**
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
** that might be invoked with argument P whenever
@@ -2291,10 +2357,11 @@ SQLITE_API int sqlite3_complete16(const void *sql);
** A busy handler must not close the database connection
** or [prepared statement] that invoked the busy handler.
*/
-SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
+SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
/*
** CAPI3REF: Set A Busy Timeout
+** METHOD: sqlite3
**
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
** for a specified amount of time when a table is locked. ^The handler
@@ -2313,10 +2380,11 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
**
** See also: [PRAGMA busy_timeout]
*/
-SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
+SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms);
/*
** CAPI3REF: Convenience Routines For Running Queries
+** METHOD: sqlite3
**
** This is a legacy interface that is preserved for backwards compatibility.
** Use of this interface is not recommended.
@@ -2387,7 +2455,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
** reflected in subsequent calls to [sqlite3_errcode()] or
** [sqlite3_errmsg()].
*/
-SQLITE_API int sqlite3_get_table(
+SQLITE_API int SQLITE_STDCALL sqlite3_get_table(
sqlite3 *db, /* An open database */
const char *zSql, /* SQL to be evaluated */
char ***pazResult, /* Results of the query */
@@ -2395,13 +2463,17 @@ SQLITE_API int sqlite3_get_table(
int *pnColumn, /* Number of result columns written here */
char **pzErrmsg /* Error msg written here */
);
-SQLITE_API void sqlite3_free_table(char **result);
+SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result);
/*
** CAPI3REF: Formatted String Printing Functions
**
** These routines are work-alikes of the "printf()" family of functions
** from the standard C library.
+** These routines understand most of the common K&R formatting options,
+** plus some additional non-standard formats, detailed below.
+** Note that some of the more obscure formatting options from recent
+** C-library standards are omitted from this implementation.
**
** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
** results into memory obtained from [sqlite3_malloc()].
@@ -2434,7 +2506,7 @@ SQLITE_API void sqlite3_free_table(char **result);
** These routines all implement some additional formatting
** options that are useful for constructing SQL statements.
** All of the usual printf() formatting options apply. In addition, there
-** is are "%q", "%Q", and "%z" options.
+** is are "%q", "%Q", "%w" and "%z" options.
**
** ^(The %q option works like %s in that it substitutes a nul-terminated
** string from the argument list. But %q also doubles every '\'' character.
@@ -2487,14 +2559,20 @@ SQLITE_API void sqlite3_free_table(char **result);
** The code above will render a correct SQL statement in the zSQL
** variable even if the zText variable is a NULL pointer.
**
+** ^(The "%w" formatting option is like "%q" except that it expects to
+** be contained within double-quotes instead of single quotes, and it
+** escapes the double-quote character instead of the single-quote
+** character.)^ The "%w" formatting option is intended for safely inserting
+** table and column names into a constructed SQL statement.
+**
** ^(The "%z" formatting option works like "%s" but with the
** addition that after the string has been read and copied into
** the result, [sqlite3_free()] is called on the input string.)^
*/
-SQLITE_API char *sqlite3_mprintf(const char*,...);
-SQLITE_API char *sqlite3_vmprintf(const char*, va_list);
-SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...);
-SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
+SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...);
+SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char*, va_list);
+SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int,char*,const char*, ...);
+SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list);
/*
** CAPI3REF: Memory Allocation Subsystem
@@ -2584,12 +2662,12 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
** a block of memory after it has been released using
** [sqlite3_free()] or [sqlite3_realloc()].
*/
-SQLITE_API void *sqlite3_malloc(int);
-SQLITE_API void *sqlite3_malloc64(sqlite3_uint64);
-SQLITE_API void *sqlite3_realloc(void*, int);
-SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64);
-SQLITE_API void sqlite3_free(void*);
-SQLITE_API sqlite3_uint64 sqlite3_msize(void*);
+SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int);
+SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64);
+SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void*, int);
+SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void*, sqlite3_uint64);
+SQLITE_API void SQLITE_STDCALL sqlite3_free(void*);
+SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*);
/*
** CAPI3REF: Memory Allocator Statistics
@@ -2614,8 +2692,8 @@ SQLITE_API sqlite3_uint64 sqlite3_msize(void*);
** by [sqlite3_memory_highwater(1)] is the high-water mark
** prior to the reset.
*/
-SQLITE_API sqlite3_int64 sqlite3_memory_used(void);
-SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag);
/*
** CAPI3REF: Pseudo-Random Number Generator
@@ -2638,10 +2716,11 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
** internally and without recourse to the [sqlite3_vfs] xRandomness
** method.
*/
-SQLITE_API void sqlite3_randomness(int N, void *P);
+SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P);
/*
** CAPI3REF: Compile-Time Authorization Callbacks
+** METHOD: sqlite3
**
** ^This routine registers an authorizer callback with a particular
** [database connection], supplied in the first argument.
@@ -2720,7 +2799,7 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** as stated in the previous paragraph, sqlite3_step() invokes
** sqlite3_prepare_v2() to reprepare a statement after a schema change.
*/
-SQLITE_API int sqlite3_set_authorizer(
+SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer(
sqlite3*,
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
void *pUserData
@@ -2798,6 +2877,7 @@ SQLITE_API int sqlite3_set_authorizer(
/*
** CAPI3REF: Tracing And Profiling Functions
+** METHOD: sqlite3
**
** These routines register callback functions that can be used for
** tracing and profiling the execution of SQL statements.
@@ -2824,12 +2904,13 @@ SQLITE_API int sqlite3_set_authorizer(
** sqlite3_profile() function is considered experimental and is
** subject to change in future versions of SQLite.
*/
-SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
-SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
+SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
+SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*,
void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
/*
** CAPI3REF: Query Progress Callbacks
+** METHOD: sqlite3
**
** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback
** function X to be invoked periodically during long running calls to
@@ -2859,10 +2940,11 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
** database connections for the meaning of "modify" in this paragraph.
**
*/
-SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
+SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
/*
** CAPI3REF: Opening A New Database Connection
+** CONSTRUCTOR: sqlite3
**
** ^These routines open an SQLite database file as specified by the
** filename argument. ^The filename argument is interpreted as UTF-8 for
@@ -3087,15 +3169,15 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
**
** See also: [sqlite3_temp_directory]
*/
-SQLITE_API int sqlite3_open(
+SQLITE_API int SQLITE_STDCALL sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
-SQLITE_API int sqlite3_open16(
+SQLITE_API int SQLITE_STDCALL sqlite3_open16(
const void *filename, /* Database filename (UTF-16) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
-SQLITE_API int sqlite3_open_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_open_v2(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb, /* OUT: SQLite db handle */
int flags, /* Flags */
@@ -3141,19 +3223,22 @@ SQLITE_API int sqlite3_open_v2(
** VFS method, then the behavior of this routine is undefined and probably
** undesirable.
*/
-SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
-SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
-SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam);
+SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
/*
** CAPI3REF: Error Codes And Messages
-**
-** ^The sqlite3_errcode() interface returns the numeric [result code] or
-** [extended result code] for the most recent failed sqlite3_* API call
-** associated with a [database connection]. If a prior API call failed
-** but the most recent API call succeeded, the return value from
-** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode()
+** METHOD: sqlite3
+**
+** ^If the most recent sqlite3_* API call associated with
+** [database connection] D failed, then the sqlite3_errcode(D) interface
+** returns the numeric [result code] or [extended result code] for that
+** API call.
+** If the most recent API call was successful,
+** then the return value from sqlite3_errcode() is undefined.
+** ^The sqlite3_extended_errcode()
** interface is the same except that it always returns the
** [extended result code] even when extended result codes are
** disabled.
@@ -3184,40 +3269,41 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
** was invoked incorrectly by the application. In that case, the
** error code and message may or may not be set.
*/
-SQLITE_API int sqlite3_errcode(sqlite3 *db);
-SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
-SQLITE_API const char *sqlite3_errmsg(sqlite3*);
-SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
-SQLITE_API const char *sqlite3_errstr(int);
+SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db);
+SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3*);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3*);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int);
/*
-** CAPI3REF: SQL Statement Object
+** CAPI3REF: Prepared Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
**
-** An instance of this object represents a single SQL statement.
-** This object is variously known as a "prepared statement" or a
-** "compiled SQL statement" or simply as a "statement".
+** An instance of this object represents a single SQL statement that
+** has been compiled into binary form and is ready to be evaluated.
**
-** The life of a statement object goes something like this:
+** Think of each SQL statement as a separate computer program. The
+** original SQL text is source code. A prepared statement object
+** is the compiled object code. All SQL must be converted into a
+** prepared statement before it can be run.
+**
+** The life-cycle of a prepared statement object usually goes like this:
**
** <ol>
-** <li> Create the object using [sqlite3_prepare_v2()] or a related
-** function.
-** <li> Bind values to [host parameters] using the sqlite3_bind_*()
+** <li> Create the prepared statement object using [sqlite3_prepare_v2()].
+** <li> Bind values to [parameters] using the sqlite3_bind_*()
** interfaces.
** <li> Run the SQL by calling [sqlite3_step()] one or more times.
-** <li> Reset the statement using [sqlite3_reset()] then go back
+** <li> Reset the prepared statement using [sqlite3_reset()] then go back
** to step 2. Do this zero or more times.
** <li> Destroy the object using [sqlite3_finalize()].
** </ol>
-**
-** Refer to documentation on individual methods above for additional
-** information.
*/
typedef struct sqlite3_stmt sqlite3_stmt;
/*
** CAPI3REF: Run-time Limits
+** METHOD: sqlite3
**
** ^(This interface allows the size of various constructs to be limited
** on a connection by connection basis. The first parameter is the
@@ -3255,7 +3341,7 @@ typedef struct sqlite3_stmt sqlite3_stmt;
**
** New run-time limit categories may be added in future releases.
*/
-SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
+SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal);
/*
** CAPI3REF: Run-Time Limit Categories
@@ -3329,6 +3415,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
/*
** CAPI3REF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
+** METHOD: sqlite3
+** CONSTRUCTOR: sqlite3_stmt
**
** To execute an SQL query, it must first be compiled into a byte-code
** program using one of these routines.
@@ -3342,16 +3430,14 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
** use UTF-16.
**
-** ^If the nByte argument is less than zero, then zSql is read up to the
-** first zero terminator. ^If nByte is non-negative, then it is the maximum
-** number of bytes read from zSql. ^When nByte is non-negative, the
-** zSql string ends at either the first '\000' or '\u0000' character or
-** the nByte-th byte, whichever comes first. If the caller knows
-** that the supplied string is nul-terminated, then there is a small
-** performance advantage to be gained by passing an nByte parameter that
-** is equal to the number of bytes in the input string <i>including</i>
-** the nul-terminator bytes as this saves SQLite from having to
-** make a copy of the input string.
+** ^If the nByte argument is negative, then zSql is read up to the
+** first zero terminator. ^If nByte is positive, then it is the
+** number of bytes read from zSql. ^If nByte is zero, then no prepared
+** statement is generated.
+** If the caller knows that the supplied string is nul-terminated, then
+** there is a small performance advantage to passing an nByte parameter that
+** is the number of bytes in the input string <i>including</i>
+** the nul-terminator.
**
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql. These routines only
@@ -3407,28 +3493,28 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** </li>
** </ol>
*/
-SQLITE_API int sqlite3_prepare(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
-SQLITE_API int sqlite3_prepare_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
-SQLITE_API int sqlite3_prepare16(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare16(
sqlite3 *db, /* Database handle */
const void *zSql, /* SQL statement, UTF-16 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const void **pzTail /* OUT: Pointer to unused portion of zSql */
);
-SQLITE_API int sqlite3_prepare16_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2(
sqlite3 *db, /* Database handle */
const void *zSql, /* SQL statement, UTF-16 encoded */
int nByte, /* Maximum length of zSql in bytes. */
@@ -3438,15 +3524,17 @@ SQLITE_API int sqlite3_prepare16_v2(
/*
** CAPI3REF: Retrieving Statement SQL
+** METHOD: sqlite3_stmt
**
** ^This interface can be used to retrieve a saved copy of the original
** SQL text used to create a [prepared statement] if that statement was
** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()].
*/
-SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If An SQL Statement Writes The Database
+** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
** and only if the [prepared statement] X makes no direct changes to
@@ -3474,10 +3562,11 @@ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
** change the configuration of a database connection, they do not make
** changes to the content of the database files on disk.
*/
-SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
+SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
+** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using
@@ -3493,7 +3582,7 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
** for example, in diagnostic routines to search for prepared
** statements that are holding a transaction open.
*/
-SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
+SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*);
/*
** CAPI3REF: Dynamically Typed Value Object
@@ -3552,6 +3641,7 @@ typedef struct sqlite3_context sqlite3_context;
** CAPI3REF: Binding Values To Prepared Statements
** KEYWORDS: {host parameter} {host parameters} {host parameter name}
** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
+** METHOD: sqlite3_stmt
**
** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
** literals may be replaced by a [parameter] that matches one of following
@@ -3654,22 +3744,23 @@ typedef struct sqlite3_context sqlite3_context;
** See also: [sqlite3_bind_parameter_count()],
** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
*/
-SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
-SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
void(*)(void*));
-SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
-SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
-SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
-SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
-SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
-SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
-SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt*, int, double);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt*, int, int);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
void(*)(void*), unsigned char encoding);
-SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
-SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
/*
** CAPI3REF: Number Of SQL Parameters
+** METHOD: sqlite3_stmt
**
** ^This routine can be used to find the number of [SQL parameters]
** in a [prepared statement]. SQL parameters are tokens of the
@@ -3686,10 +3777,11 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
** [sqlite3_bind_parameter_name()], and
** [sqlite3_bind_parameter_index()].
*/
-SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*);
/*
** CAPI3REF: Name Of A Host Parameter
+** METHOD: sqlite3_stmt
**
** ^The sqlite3_bind_parameter_name(P,N) interface returns
** the name of the N-th [SQL parameter] in the [prepared statement] P.
@@ -3713,10 +3805,11 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
** [sqlite3_bind_parameter_count()], and
** [sqlite3_bind_parameter_index()].
*/
-SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, int);
/*
** CAPI3REF: Index Of A Parameter With A Given Name
+** METHOD: sqlite3_stmt
**
** ^Return the index of an SQL parameter given its name. ^The
** index value returned is suitable for use as the second
@@ -3729,19 +3822,21 @@ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
** [sqlite3_bind_parameter_count()], and
** [sqlite3_bind_parameter_index()].
*/
-SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
/*
** CAPI3REF: Reset All Bindings On A Prepared Statement
+** METHOD: sqlite3_stmt
**
** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset
** the [sqlite3_bind_blob | bindings] on a [prepared statement].
** ^Use this routine to reset all host parameters to NULL.
*/
-SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
+SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*);
/*
** CAPI3REF: Number Of Columns In A Result Set
+** METHOD: sqlite3_stmt
**
** ^Return the number of columns in the result set returned by the
** [prepared statement]. ^This routine returns 0 if pStmt is an SQL
@@ -3749,10 +3844,11 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
**
** See also: [sqlite3_data_count()]
*/
-SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt);
+SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Column Names In A Result Set
+** METHOD: sqlite3_stmt
**
** ^These routines return the name assigned to a particular column
** in the result set of a [SELECT] statement. ^The sqlite3_column_name()
@@ -3777,11 +3873,12 @@ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt);
** then the name of the column is unspecified and may change from
** one release of SQLite to the next.
*/
-SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N);
-SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt*, int N);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N);
/*
** CAPI3REF: Source Of Data In A Query Result
+** METHOD: sqlite3_stmt
**
** ^These routines provide a means to determine the database, table, and
** table column that is the origin of a particular result column in
@@ -3825,15 +3922,16 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
** for the same [prepared statement] and result column
** at the same time then the results are undefined.
*/
-SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
-SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int);
-SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt*,int);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt*,int);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt*,int);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt*,int);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt*,int);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt*,int);
/*
** CAPI3REF: Declared Datatype Of A Query Result
+** METHOD: sqlite3_stmt
**
** ^(The first parameter is a [prepared statement].
** If this statement is a [SELECT] statement and the Nth column of the
@@ -3861,11 +3959,12 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
** is associated with individual values, not with the containers
** used to hold those values.
*/
-SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt*,int);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,int);
/*
** CAPI3REF: Evaluate An SQL Statement
+** METHOD: sqlite3_stmt
**
** After a [prepared statement] has been prepared using either
** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy
@@ -3941,10 +4040,11 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** then the more specific [error codes] are returned directly
** by sqlite3_step(). The use of the "v2" interface is recommended.
*/
-SQLITE_API int sqlite3_step(sqlite3_stmt*);
+SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*);
/*
** CAPI3REF: Number of columns in a result set
+** METHOD: sqlite3_stmt
**
** ^The sqlite3_data_count(P) interface returns the number of columns in the
** current row of the result set of [prepared statement] P.
@@ -3961,7 +4061,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt*);
**
** See also: [sqlite3_column_count()]
*/
-SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
+SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Fundamental Datatypes
@@ -3998,6 +4098,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Result Values From A Query
** KEYWORDS: {column access functions}
+** METHOD: sqlite3_stmt
**
** These routines form the "result set" interface.
**
@@ -4157,19 +4258,20 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** pointer. Subsequent calls to [sqlite3_errcode()] will return
** [SQLITE_NOMEM].)^
*/
-SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
-SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol);
-SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
-SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
-SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
-SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*, int iCol);
+SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*, int iCol);
+SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
+SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*, int iCol);
+SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*, int iCol);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*, int iCol);
+SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*, int iCol);
+SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*, int iCol);
+SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int iCol);
/*
** CAPI3REF: Destroy A Prepared Statement Object
+** DESTRUCTOR: sqlite3_stmt
**
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
** ^If the most recent evaluation of the statement encountered no errors
@@ -4193,10 +4295,11 @@ SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
** statement after it has been finalized can result in undefined and
** undesirable behavior such as segfaults and heap corruption.
*/
-SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
+SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Reset A Prepared Statement Object
+** METHOD: sqlite3_stmt
**
** The sqlite3_reset() function is called to reset a [prepared statement]
** object back to its initial state, ready to be re-executed.
@@ -4219,13 +4322,14 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
** ^The [sqlite3_reset(S)] interface does not change the values
** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
*/
-SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
+SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Create Or Redefine SQL Functions
** KEYWORDS: {function creation routines}
** KEYWORDS: {application-defined SQL function}
** KEYWORDS: {application-defined SQL functions}
+** METHOD: sqlite3
**
** ^These functions (collectively known as "function creation routines")
** are used to add SQL functions or aggregates or to redefine the behavior
@@ -4318,7 +4422,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** close the database connection nor finalize or reset the prepared
** statement in which the function is running.
*/
-SQLITE_API int sqlite3_create_function(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_function(
sqlite3 *db,
const char *zFunctionName,
int nArg,
@@ -4328,7 +4432,7 @@ SQLITE_API int sqlite3_create_function(
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*)
);
-SQLITE_API int sqlite3_create_function16(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_function16(
sqlite3 *db,
const void *zFunctionName,
int nArg,
@@ -4338,7 +4442,7 @@ SQLITE_API int sqlite3_create_function16(
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*)
);
-SQLITE_API int sqlite3_create_function_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2(
sqlite3 *db,
const char *zFunctionName,
int nArg,
@@ -4380,21 +4484,22 @@ SQLITE_API int sqlite3_create_function_v2(
** These functions are [deprecated]. In order to maintain
** backwards compatibility with older code, these functions continue
** to be supported. However, new applications should avoid
-** the use of these functions. To help encourage people to avoid
-** using these functions, we are not going to tell you what they do.
+** the use of these functions. To encourage programmers to avoid
+** these functions, we will not explain what they do.
*/
#ifndef SQLITE_OMIT_DEPRECATED
-SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
-SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
+SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context*);
+SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_global_recover(void);
+SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_thread_cleanup(void);
+SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
void*,sqlite3_int64);
#endif
/*
** CAPI3REF: Obtaining SQL Function Parameter Values
+** METHOD: sqlite3_value
**
** The C-language implementation of SQL functions and aggregates uses
** this set of interface routines to access the parameter values on
@@ -4438,21 +4543,22 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** These routines must be called from the same thread as
** the SQL function that supplied the [sqlite3_value*] parameters.
*/
-SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
-SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
-SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
-SQLITE_API double sqlite3_value_double(sqlite3_value*);
-SQLITE_API int sqlite3_value_int(sqlite3_value*);
-SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
-SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*);
-SQLITE_API int sqlite3_value_type(sqlite3_value*);
-SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value*);
+SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value*);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value*);
+SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value*);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value*);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value*);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*);
/*
** CAPI3REF: Obtain Aggregate Function Context
+** METHOD: sqlite3_context
**
** Implementations of aggregate SQL functions use this
** routine to allocate memory for storing their state.
@@ -4493,10 +4599,11 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
** This routine must be called from the same thread in which
** the aggregate SQL function is running.
*/
-SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
+SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int nBytes);
/*
** CAPI3REF: User Data For Functions
+** METHOD: sqlite3_context
**
** ^The sqlite3_user_data() interface returns a copy of
** the pointer that was the pUserData parameter (the 5th parameter)
@@ -4507,10 +4614,11 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
** This routine must be called from the same thread in which
** the application-defined function is running.
*/
-SQLITE_API void *sqlite3_user_data(sqlite3_context*);
+SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*);
/*
** CAPI3REF: Database Connection For Functions
+** METHOD: sqlite3_context
**
** ^The sqlite3_context_db_handle() interface returns a copy of
** the pointer to the [database connection] (the 1st parameter)
@@ -4518,10 +4626,11 @@ SQLITE_API void *sqlite3_user_data(sqlite3_context*);
** and [sqlite3_create_function16()] routines that originally
** registered the application defined function.
*/
-SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
+SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*);
/*
** CAPI3REF: Function Auxiliary Data
+** METHOD: sqlite3_context
**
** These functions may be used by (non-aggregate) SQL functions to
** associate metadata with argument values. If the same value is passed to
@@ -4570,8 +4679,8 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
** These routines must be called from the same thread in which
** the SQL function is running.
*/
-SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
-SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
+SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context*, int N);
+SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
/*
@@ -4594,6 +4703,7 @@ typedef void (*sqlite3_destructor_type)(void*);
/*
** CAPI3REF: Setting The Result Of An SQL Function
+** METHOD: sqlite3_context
**
** These routines are used by the xFunc or xFinal callbacks that
** implement SQL functions and aggregates. See
@@ -4706,29 +4816,30 @@ typedef void (*sqlite3_destructor_type)(void*);
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
*/
-SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,
+SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
+SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(sqlite3_context*,const void*,
sqlite3_uint64,void(*)(void*));
-SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
-SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
-SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
-SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
-SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
-SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
-SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
-SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
-SQLITE_API void sqlite3_result_null(sqlite3_context*);
-SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
+SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context*, double);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context*, const char*, int);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context*, const void*, int);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context*);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context*);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context*, int);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context*, int);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context*);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
void(*)(void*), unsigned char encoding);
-SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
-SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
-SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
-SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
+SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n);
/*
** CAPI3REF: Define New Collating Sequences
+** METHOD: sqlite3
**
** ^These functions add, remove, or modify a [collation] associated
** with the [database connection] specified as the first argument.
@@ -4806,14 +4917,14 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
**
** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
*/
-SQLITE_API int sqlite3_create_collation(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_collation(
sqlite3*,
const char *zName,
int eTextRep,
void *pArg,
int(*xCompare)(void*,int,const void*,int,const void*)
);
-SQLITE_API int sqlite3_create_collation_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2(
sqlite3*,
const char *zName,
int eTextRep,
@@ -4821,7 +4932,7 @@ SQLITE_API int sqlite3_create_collation_v2(
int(*xCompare)(void*,int,const void*,int,const void*),
void(*xDestroy)(void*)
);
-SQLITE_API int sqlite3_create_collation16(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16(
sqlite3*,
const void *zName,
int eTextRep,
@@ -4831,6 +4942,7 @@ SQLITE_API int sqlite3_create_collation16(
/*
** CAPI3REF: Collation Needed Callbacks
+** METHOD: sqlite3
**
** ^To avoid having to register all collation sequences before a database
** can be used, a single callback function may be registered with the
@@ -4855,12 +4967,12 @@ SQLITE_API int sqlite3_create_collation16(
** [sqlite3_create_collation()], [sqlite3_create_collation16()], or
** [sqlite3_create_collation_v2()].
*/
-SQLITE_API int sqlite3_collation_needed(
+SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed(
sqlite3*,
void*,
void(*)(void*,sqlite3*,int eTextRep,const char*)
);
-SQLITE_API int sqlite3_collation_needed16(
+SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16(
sqlite3*,
void*,
void(*)(void*,sqlite3*,int eTextRep,const void*)
@@ -4874,11 +4986,11 @@ SQLITE_API int sqlite3_collation_needed16(
** The code to implement this API is not available in the public release
** of SQLite.
*/
-SQLITE_API int sqlite3_key(
+SQLITE_API int SQLITE_STDCALL sqlite3_key(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The key */
);
-SQLITE_API int sqlite3_key_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_key_v2(
sqlite3 *db, /* Database to be rekeyed */
const char *zDbName, /* Name of the database */
const void *pKey, int nKey /* The key */
@@ -4892,11 +5004,11 @@ SQLITE_API int sqlite3_key_v2(
** The code to implement this API is not available in the public release
** of SQLite.
*/
-SQLITE_API int sqlite3_rekey(
+SQLITE_API int SQLITE_STDCALL sqlite3_rekey(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The new key */
);
-SQLITE_API int sqlite3_rekey_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2(
sqlite3 *db, /* Database to be rekeyed */
const char *zDbName, /* Name of the database */
const void *pKey, int nKey /* The new key */
@@ -4906,7 +5018,7 @@ SQLITE_API int sqlite3_rekey_v2(
** Specify the activation key for a SEE database. Unless
** activated, none of the SEE routines will work.
*/
-SQLITE_API void sqlite3_activate_see(
+SQLITE_API void SQLITE_STDCALL sqlite3_activate_see(
const char *zPassPhrase /* Activation phrase */
);
#endif
@@ -4916,7 +5028,7 @@ SQLITE_API void sqlite3_activate_see(
** Specify the activation key for a CEROD database. Unless
** activated, none of the CEROD routines will work.
*/
-SQLITE_API void sqlite3_activate_cerod(
+SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod(
const char *zPassPhrase /* Activation phrase */
);
#endif
@@ -4938,7 +5050,7 @@ SQLITE_API void sqlite3_activate_cerod(
** all, then the behavior of sqlite3_sleep() may deviate from the description
** in the previous paragraphs.
*/
-SQLITE_API int sqlite3_sleep(int);
+SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int);
/*
** CAPI3REF: Name Of The Folder Holding Temporary Files
@@ -5038,6 +5150,7 @@ SQLITE_API char *sqlite3_data_directory;
/*
** CAPI3REF: Test For Auto-Commit Mode
** KEYWORDS: {autocommit mode}
+** METHOD: sqlite3
**
** ^The sqlite3_get_autocommit() interface returns non-zero or
** zero if the given database connection is or is not in autocommit mode,
@@ -5056,10 +5169,11 @@ SQLITE_API char *sqlite3_data_directory;
** connection while this routine is running, then the return value
** is undefined.
*/
-SQLITE_API int sqlite3_get_autocommit(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*);
/*
** CAPI3REF: Find The Database Handle Of A Prepared Statement
+** METHOD: sqlite3_stmt
**
** ^The sqlite3_db_handle interface returns the [database connection] handle
** to which a [prepared statement] belongs. ^The [database connection]
@@ -5068,10 +5182,11 @@ SQLITE_API int sqlite3_get_autocommit(sqlite3*);
** to the [sqlite3_prepare_v2()] call (or its variants) that was used to
** create the statement in the first place.
*/
-SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
+SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*);
/*
** CAPI3REF: Return The Filename For A Database Connection
+** METHOD: sqlite3
**
** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
** associated with database N of connection D. ^The main database file
@@ -5084,19 +5199,21 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
** will be an absolute pathname, even if the filename used
** to open the database originally was a URI or relative pathname.
*/
-SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName);
/*
** CAPI3REF: Determine if a database is read-only
+** METHOD: sqlite3
**
** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
** of connection D is read-only, 0 if it is read/write, or -1 if N is not
** the name of a database on connection D.
*/
-SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
+SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
/*
** CAPI3REF: Find the next prepared statement
+** METHOD: sqlite3
**
** ^This interface returns a pointer to the next [prepared statement] after
** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
@@ -5108,10 +5225,11 @@ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
** [sqlite3_next_stmt(D,S)] must refer to an open database
** connection and in particular must not be a NULL pointer.
*/
-SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
+SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
/*
** CAPI3REF: Commit And Rollback Notification Callbacks
+** METHOD: sqlite3
**
** ^The sqlite3_commit_hook() interface registers a callback
** function to be invoked whenever a transaction is [COMMIT | committed].
@@ -5156,11 +5274,12 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
**
** See also the [sqlite3_update_hook()] interface.
*/
-SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
-SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
+SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
+SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
/*
** CAPI3REF: Data Change Notification Callbacks
+** METHOD: sqlite3
**
** ^The sqlite3_update_hook() interface registers a callback function
** with the [database connection] identified by the first argument
@@ -5207,7 +5326,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()]
** interfaces.
*/
-SQLITE_API void *sqlite3_update_hook(
+SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook(
sqlite3*,
void(*)(void *,int ,char const *,char const *,sqlite3_int64),
void*
@@ -5237,12 +5356,17 @@ SQLITE_API void *sqlite3_update_hook(
** future releases of SQLite. Applications that care about shared
** cache setting should set it explicitly.
**
+** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0
+** and will always return SQLITE_MISUSE. On those systems,
+** shared cache mode should be enabled per-database connection via
+** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE].
+**
** This interface is threadsafe on processors where writing a
** 32-bit integer is atomic.
**
** See Also: [SQLite Shared-Cache Mode]
*/
-SQLITE_API int sqlite3_enable_shared_cache(int);
+SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int);
/*
** CAPI3REF: Attempt To Free Heap Memory
@@ -5258,10 +5382,11 @@ SQLITE_API int sqlite3_enable_shared_cache(int);
**
** See also: [sqlite3_db_release_memory()]
*/
-SQLITE_API int sqlite3_release_memory(int);
+SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int);
/*
** CAPI3REF: Free Memory Used By A Database Connection
+** METHOD: sqlite3
**
** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
** memory as possible from database connection D. Unlike the
@@ -5271,7 +5396,7 @@ SQLITE_API int sqlite3_release_memory(int);
**
** See also: [sqlite3_release_memory()]
*/
-SQLITE_API int sqlite3_db_release_memory(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*);
/*
** CAPI3REF: Impose A Limit On Heap Size
@@ -5323,7 +5448,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** The circumstances under which SQLite will enforce the soft heap limit may
** changes in future releases of SQLite.
*/
-SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 N);
/*
** CAPI3REF: Deprecated Soft Heap Limit Interface
@@ -5334,11 +5459,12 @@ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
** only. All new applications should use the
** [sqlite3_soft_heap_limit64()] interface rather than this one.
*/
-SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
+SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N);
/*
** CAPI3REF: Extract Metadata About A Column Of A Table
+** METHOD: sqlite3
**
** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
** information about column C of table T in database D
@@ -5403,7 +5529,7 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
** parsed, if that has not already been done, and returns an error if
** any errors are encountered while loading the schema.
*/
-SQLITE_API int sqlite3_table_column_metadata(
+SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata(
sqlite3 *db, /* Connection handle */
const char *zDbName, /* Database name or NULL */
const char *zTableName, /* Table name */
@@ -5417,6 +5543,7 @@ SQLITE_API int sqlite3_table_column_metadata(
/*
** CAPI3REF: Load An Extension
+** METHOD: sqlite3
**
** ^This interface loads an SQLite extension library from the named file.
**
@@ -5449,7 +5576,7 @@ SQLITE_API int sqlite3_table_column_metadata(
**
** See also the [load_extension() SQL function].
*/
-SQLITE_API int sqlite3_load_extension(
+SQLITE_API int SQLITE_STDCALL sqlite3_load_extension(
sqlite3 *db, /* Load the extension into this database connection */
const char *zFile, /* Name of the shared library containing extension */
const char *zProc, /* Entry point. Derived from zFile if 0 */
@@ -5458,6 +5585,7 @@ SQLITE_API int sqlite3_load_extension(
/*
** CAPI3REF: Enable Or Disable Extension Loading
+** METHOD: sqlite3
**
** ^So as not to open security holes in older applications that are
** unprepared to deal with [extension loading], and as a means of disabling
@@ -5469,7 +5597,7 @@ SQLITE_API int sqlite3_load_extension(
** to turn extension loading on and call it with onoff==0 to turn
** it back off again.
*/
-SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
+SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff);
/*
** CAPI3REF: Automatically Load Statically Linked Extensions
@@ -5507,7 +5635,7 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
** See also: [sqlite3_reset_auto_extension()]
** and [sqlite3_cancel_auto_extension()]
*/
-SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
+SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xEntryPoint)(void));
/*
** CAPI3REF: Cancel Automatic Extension Loading
@@ -5519,7 +5647,7 @@ SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
** unregistered and it returns 0 if X was not on the list of initialization
** routines.
*/
-SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
+SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
/*
** CAPI3REF: Reset Automatic Extension Loading
@@ -5527,7 +5655,7 @@ SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
** ^This interface disables all automatic extensions previously
** registered using [sqlite3_auto_extension()].
*/
-SQLITE_API void sqlite3_reset_auto_extension(void);
+SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void);
/*
** The interface to the virtual-table mechanism is currently considered
@@ -5707,6 +5835,7 @@ struct sqlite3_index_info {
/*
** CAPI3REF: Register A Virtual Table Implementation
+** METHOD: sqlite3
**
** ^These routines are used to register a new [virtual table module] name.
** ^Module names must be registered before
@@ -5730,13 +5859,13 @@ struct sqlite3_index_info {
** interface is equivalent to sqlite3_create_module_v2() with a NULL
** destructor.
*/
-SQLITE_API int sqlite3_create_module(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *p, /* Methods for the module */
void *pClientData /* Client data for xCreate/xConnect */
);
-SQLITE_API int sqlite3_create_module_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *p, /* Methods for the module */
@@ -5764,7 +5893,7 @@ SQLITE_API int sqlite3_create_module_v2(
*/
struct sqlite3_vtab {
const sqlite3_module *pModule; /* The module for this virtual table */
- int nRef; /* NO LONGER USED */
+ int nRef; /* Number of open cursors */
char *zErrMsg; /* Error message from sqlite3_mprintf() */
/* Virtual table implementations will typically add additional fields */
};
@@ -5799,10 +5928,11 @@ struct sqlite3_vtab_cursor {
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
*/
-SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
+SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL);
/*
** CAPI3REF: Overload A Function For A Virtual Table
+** METHOD: sqlite3
**
** ^(Virtual tables can provide alternative implementations of functions
** using the [xFindFunction] method of the [virtual table module].
@@ -5817,7 +5947,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
** purpose is to be a placeholder function that can be overloaded
** by a [virtual table].
*/
-SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+SQLITE_API int SQLITE_STDCALL sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
/*
** The interface to the virtual-table mechanism defined above (back up
@@ -5845,6 +5975,8 @@ typedef struct sqlite3_blob sqlite3_blob;
/*
** CAPI3REF: Open A BLOB For Incremental I/O
+** METHOD: sqlite3
+** CONSTRUCTOR: sqlite3_blob
**
** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located
** in row iRow, column zColumn, table zTable in database zDb;
@@ -5914,7 +6046,7 @@ typedef struct sqlite3_blob sqlite3_blob;
** To avoid a resource leak, every open [BLOB handle] should eventually
** be released by a call to [sqlite3_blob_close()].
*/
-SQLITE_API int sqlite3_blob_open(
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_open(
sqlite3*,
const char *zDb,
const char *zTable,
@@ -5926,6 +6058,7 @@ SQLITE_API int sqlite3_blob_open(
/*
** CAPI3REF: Move a BLOB Handle to a New Row
+** METHOD: sqlite3_blob
**
** ^This function is used to move an existing blob handle so that it points
** to a different row of the same database table. ^The new row is identified
@@ -5946,10 +6079,11 @@ SQLITE_API int sqlite3_blob_open(
**
** ^This function sets the database handle error code and message.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
+SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
/*
** CAPI3REF: Close A BLOB Handle
+** DESTRUCTOR: sqlite3_blob
**
** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed
** unconditionally. Even if this routine returns an error code, the
@@ -5968,10 +6102,11 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_i
** is passed a valid open blob handle, the values returned by the
** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning.
*/
-SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *);
/*
** CAPI3REF: Return The Size Of An Open BLOB
+** METHOD: sqlite3_blob
**
** ^Returns the size in bytes of the BLOB accessible via the
** successfully opened [BLOB handle] in its only argument. ^The
@@ -5983,10 +6118,11 @@ SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
** been closed by [sqlite3_blob_close()]. Passing any other pointer in
** to this routine results in undefined and probably undesirable behavior.
*/
-SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *);
/*
** CAPI3REF: Read Data From A BLOB Incrementally
+** METHOD: sqlite3_blob
**
** ^(This function is used to read data from an open [BLOB handle] into a
** caller-supplied buffer. N bytes of data are copied into buffer Z
@@ -6011,10 +6147,11 @@ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
**
** See also: [sqlite3_blob_write()].
*/
-SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
/*
** CAPI3REF: Write Data Into A BLOB Incrementally
+** METHOD: sqlite3_blob
**
** ^(This function is used to write data into an open [BLOB handle] from a
** caller-supplied buffer. N bytes of data are copied from the buffer Z
@@ -6052,7 +6189,7 @@ SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
**
** See also: [sqlite3_blob_read()].
*/
-SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
/*
** CAPI3REF: Virtual File System Objects
@@ -6083,9 +6220,9 @@ SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOff
** ^(If the default VFS is unregistered, another VFS is chosen as
** the default. The choice for the new VFS is arbitrary.)^
*/
-SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
-SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
-SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
+SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfsName);
+SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
+SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*);
/*
** CAPI3REF: Mutexes
@@ -6198,11 +6335,11 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
**
** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
*/
-SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int);
-SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*);
-SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*);
-SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*);
-SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
+SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int);
+SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex*);
+SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex*);
+SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex*);
+SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*);
/*
** CAPI3REF: Mutex Methods Object
@@ -6312,8 +6449,8 @@ struct sqlite3_mutex_methods {
** interface should also return 1 when given a NULL pointer.
*/
#ifndef NDEBUG
-SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
-SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
+SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex*);
+SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*);
#endif
/*
@@ -6342,6 +6479,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
/*
** CAPI3REF: Retrieve the mutex for a database connection
+** METHOD: sqlite3
**
** ^This interface returns a pointer the [sqlite3_mutex] object that
** serializes access to the [database connection] given in the argument
@@ -6349,10 +6487,11 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
** ^If the [threading mode] is Single-thread or Multi-thread then this
** routine returns a NULL pointer.
*/
-SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
+SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*);
/*
** CAPI3REF: Low-Level Control Of Database Files
+** METHOD: sqlite3
**
** ^The [sqlite3_file_control()] interface makes a direct call to the
** xFileControl method for the [sqlite3_io_methods] object associated
@@ -6383,7 +6522,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
**
** See also: [SQLITE_FCNTL_LOCKSTATE]
*/
-SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
+SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
/*
** CAPI3REF: Testing Interface
@@ -6402,7 +6541,7 @@ SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*
** Unlike most of the SQLite API, this function is not guaranteed to
** operate consistently from one release to the next.
*/
-SQLITE_API int sqlite3_test_control(int op, ...);
+SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...);
/*
** CAPI3REF: Testing Interface Operation Codes
@@ -6436,12 +6575,13 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_BYTEORDER 22
#define SQLITE_TESTCTRL_ISINIT 23
#define SQLITE_TESTCTRL_SORTER_MMAP 24
-#define SQLITE_TESTCTRL_LAST 24
+#define SQLITE_TESTCTRL_IMPOSTER 25
+#define SQLITE_TESTCTRL_LAST 25
/*
** CAPI3REF: SQLite Runtime Status
**
-** ^This interface is used to retrieve runtime status information
+** ^These interfaces are used to retrieve runtime status information
** about the performance of SQLite, and optionally to reset various
** highwater marks. ^The first argument is an integer code for
** the specific parameter to measure. ^(Recognized integer codes
@@ -6455,19 +6595,22 @@ SQLITE_API int sqlite3_test_control(int op, ...);
** ^(Other parameters record only the highwater mark and not the current
** value. For these latter parameters nothing is written into *pCurrent.)^
**
-** ^The sqlite3_status() routine returns SQLITE_OK on success and a
-** non-zero [error code] on failure.
+** ^The sqlite3_status() and sqlite3_status64() routines return
+** SQLITE_OK on success and a non-zero [error code] on failure.
**
-** This routine is threadsafe but is not atomic. This routine can be
-** called while other threads are running the same or different SQLite
-** interfaces. However the values returned in *pCurrent and
-** *pHighwater reflect the status of SQLite at different points in time
-** and it is possible that another thread might change the parameter
-** in between the times when *pCurrent and *pHighwater are written.
+** If either the current value or the highwater mark is too large to
+** be represented by a 32-bit integer, then the values returned by
+** sqlite3_status() are undefined.
**
** See also: [sqlite3_db_status()]
*/
-SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+SQLITE_API int SQLITE_STDCALL sqlite3_status64(
+ int op,
+ sqlite3_int64 *pCurrent,
+ sqlite3_int64 *pHighwater,
+ int resetFlag
+);
/*
@@ -6565,6 +6708,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
/*
** CAPI3REF: Database Connection Status
+** METHOD: sqlite3
**
** ^This interface is used to retrieve runtime status information
** about a single [database connection]. ^The first argument is the
@@ -6585,7 +6729,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
**
** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
*/
-SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
/*
** CAPI3REF: Status Parameters for database connections
@@ -6693,6 +6837,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
/*
** CAPI3REF: Prepared Statement Status
+** METHOD: sqlite3_stmt
**
** ^(Each prepared statement maintains various
** [SQLITE_STMTSTATUS counters] that measure the number
@@ -6714,7 +6859,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
**
** See also: [sqlite3_status()] and [sqlite3_db_status()].
*/
-SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
+SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
/*
** CAPI3REF: Status Parameters for prepared statements
@@ -7137,20 +7282,20 @@ typedef struct sqlite3_backup sqlite3_backup;
** is not a permanent error and does not affect the return value of
** sqlite3_backup_finish().
**
-** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
+** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]]
** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
**
-** ^Each call to sqlite3_backup_step() sets two values inside
-** the [sqlite3_backup] object: the number of pages still to be backed
-** up and the total number of pages in the source database file.
-** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
-** retrieve these two values, respectively.
-**
-** ^The values returned by these functions are only updated by
-** sqlite3_backup_step(). ^If the source database is modified during a backup
-** operation, then the values are not updated to account for any extra
-** pages that need to be updated or the size of the source database file
-** changing.
+** ^The sqlite3_backup_remaining() routine returns the number of pages still
+** to be backed up at the conclusion of the most recent sqlite3_backup_step().
+** ^The sqlite3_backup_pagecount() routine returns the total number of pages
+** in the source database at the conclusion of the most recent
+** sqlite3_backup_step().
+** ^(The values returned by these functions are only updated by
+** sqlite3_backup_step(). If the source database is modified in a way that
+** changes the size of the source database or the number of pages remaining,
+** those changes are not reflected in the output of sqlite3_backup_pagecount()
+** and sqlite3_backup_remaining() until after the next
+** sqlite3_backup_step().)^
**
** <b>Concurrent Usage of Database Handles</b>
**
@@ -7183,19 +7328,20 @@ typedef struct sqlite3_backup sqlite3_backup;
** same time as another thread is invoking sqlite3_backup_step() it is
** possible that they return invalid values.
*/
-SQLITE_API sqlite3_backup *sqlite3_backup_init(
+SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init(
sqlite3 *pDest, /* Destination database handle */
const char *zDestName, /* Destination database name */
sqlite3 *pSource, /* Source database handle */
const char *zSourceName /* Source database name */
);
-SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage);
-SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p);
-SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p);
-SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage);
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p);
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p);
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p);
/*
** CAPI3REF: Unlock Notification
+** METHOD: sqlite3
**
** ^When running in shared-cache mode, a database operation may fail with
** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
@@ -7308,7 +7454,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** the special "DROP TABLE/INDEX" case, the extended error code is just
** SQLITE_LOCKED.)^
*/
-SQLITE_API int sqlite3_unlock_notify(
+SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify(
sqlite3 *pBlocked, /* Waiting connection */
void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */
void *pNotifyArg /* Argument to pass to xNotify */
@@ -7323,8 +7469,8 @@ SQLITE_API int sqlite3_unlock_notify(
** strings in a case-independent fashion, using the same definition of "case
** independence" that SQLite uses internally when comparing identifiers.
*/
-SQLITE_API int sqlite3_stricmp(const char *, const char *);
-SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
+SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *, const char *);
+SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int);
/*
** CAPI3REF: String Globbing
@@ -7339,7 +7485,7 @@ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
** Note that this routine returns zero on a match and non-zero if the strings
** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
*/
-SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr);
+SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zStr);
/*
** CAPI3REF: Error Logging Interface
@@ -7362,10 +7508,11 @@ SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr);
** a few hundred characters, it will be truncated to the length of the
** buffer.
*/
-SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
+SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...);
/*
** CAPI3REF: Write-Ahead Log Commit Hook
+** METHOD: sqlite3
**
** ^The [sqlite3_wal_hook()] function is used to register a callback that
** is invoked each time data is committed to a database in wal mode.
@@ -7397,7 +7544,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
** those overwrite any prior [sqlite3_wal_hook()] settings.
*/
-SQLITE_API void *sqlite3_wal_hook(
+SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook(
sqlite3*,
int(*)(void *,sqlite3*,const char*,int),
void*
@@ -7405,6 +7552,7 @@ SQLITE_API void *sqlite3_wal_hook(
/*
** CAPI3REF: Configure an auto-checkpoint
+** METHOD: sqlite3
**
** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
** [sqlite3_wal_hook()] that causes any database on [database connection] D
@@ -7431,10 +7579,11 @@ SQLITE_API void *sqlite3_wal_hook(
** is only necessary if the default setting is found to be suboptimal
** for a particular application.
*/
-SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
+SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
/*
** CAPI3REF: Checkpoint a database
+** METHOD: sqlite3
**
** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to
** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^
@@ -7452,10 +7601,11 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
** start a callback but which do not need the full power (and corresponding
** complication) of [sqlite3_wal_checkpoint_v2()].
*/
-SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
+SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
/*
** CAPI3REF: Checkpoint a database
+** METHOD: sqlite3
**
** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint
** operation on database X of [database connection] D in mode M. Status
@@ -7545,7 +7695,7 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface
** from SQL.
*/
-SQLITE_API int sqlite3_wal_checkpoint_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2(
sqlite3 *db, /* Database handle */
const char *zDb, /* Name of attached database (or NULL) */
int eMode, /* SQLITE_CHECKPOINT_* value */
@@ -7581,7 +7731,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
** may be added in the future.
*/
-SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
+SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...);
/*
** CAPI3REF: Virtual Table Configuration Options
@@ -7634,7 +7784,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** of the SQL statement that triggered the call to the [xUpdate] method of the
** [virtual table].
*/
-SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
+SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *);
/*
** CAPI3REF: Conflict resolution modes
@@ -7710,6 +7860,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
/*
** CAPI3REF: Prepared Statement Scan Status
+** METHOD: sqlite3_stmt
**
** This interface returns information about the predicted and measured
** performance for pStmt. Advanced applications can use this
@@ -7738,7 +7889,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
**
** See also: [sqlite3_stmt_scanstatus_reset()]
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus(
+SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
@@ -7747,13 +7898,14 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus(
/*
** CAPI3REF: Zero Scan-Status Counters
+** METHOD: sqlite3_stmt
**
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
**
** This API is only available if the library is built with pre-processor
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
*/
-SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
+SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
@@ -7808,7 +7960,7 @@ typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
**
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...)
*/
-SQLITE_API int sqlite3_rtree_geometry_callback(
+SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback(
sqlite3 *db,
const char *zGeom,
int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
@@ -7834,7 +7986,7 @@ struct sqlite3_rtree_geometry {
**
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
*/
-SQLITE_API int sqlite3_rtree_query_callback(
+SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback(
sqlite3 *db,
const char *zQueryFunc,
int (*xQueryFunc)(sqlite3_rtree_query_info*),
@@ -7998,15 +8150,17 @@ struct sqlite3_rtree_query_info {
#endif
/*
-** The maximum number of in-memory pages to use for the main database
-** table and for temporary tables. The SQLITE_DEFAULT_CACHE_SIZE
+** The suggested maximum number of in-memory pages to use for
+** the main database table and for temporary tables.
+**
+** IMPLEMENTATION-OF: R-31093-59126 The default suggested cache size
+** is 2000 pages.
+** IMPLEMENTATION-OF: R-48205-43578 The default suggested cache size can be
+** altered using the SQLITE_DEFAULT_CACHE_SIZE compile-time options.
*/
#ifndef SQLITE_DEFAULT_CACHE_SIZE
# define SQLITE_DEFAULT_CACHE_SIZE 2000
#endif
-#ifndef SQLITE_DEFAULT_TEMP_CACHE_SIZE
-# define SQLITE_DEFAULT_TEMP_CACHE_SIZE 500
-#endif
/*
** The default number of frames to accumulate in the log file before
@@ -8356,6 +8510,32 @@ SQLITE_PRIVATE void sqlite3Coverage(int);
#endif
/*
+** Declarations used for tracing the operating system interfaces.
+*/
+#if defined(SQLITE_FORCE_OS_TRACE) || defined(SQLITE_TEST) || \
+ (defined(SQLITE_DEBUG) && SQLITE_OS_WIN)
+ extern int sqlite3OSTrace;
+# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
+# define SQLITE_HAVE_OS_TRACE
+#else
+# define OSTRACE(X)
+# undef SQLITE_HAVE_OS_TRACE
+#endif
+
+/*
+** Is the sqlite3ErrName() function needed in the build? Currently,
+** it is needed by "mutex_w32.c" (when debugging), "os_win.c" (when
+** OSTRACE is enabled), and by several "test*.c" files (which are
+** compiled using SQLITE_TEST).
+*/
+#if defined(SQLITE_HAVE_OS_TRACE) || defined(SQLITE_TEST) || \
+ (defined(SQLITE_DEBUG) && SQLITE_OS_WIN)
+# define SQLITE_NEED_ERR_NAME
+#else
+# undef SQLITE_NEED_ERR_NAME
+#endif
+
+/*
** Return true (non-zero) if the input is an integer that is too large
** to fit in 32-bits. This macro is used inside of various testcase()
** macros to verify that we have tested SQLite for large-file support.
@@ -8851,6 +9031,20 @@ typedef INT8_TYPE i8; /* 1-byte signed integer */
typedef INT16_TYPE LogEst;
/*
+** Set the SQLITE_PTRSIZE macro to the number of bytes in a pointer
+*/
+#ifndef SQLITE_PTRSIZE
+# if defined(__SIZEOF_POINTER__)
+# define SQLITE_PTRSIZE __SIZEOF_POINTER__
+# elif defined(i386) || defined(__i386__) || defined(_M_IX86) || \
+ defined(_M_ARM) || defined(__arm__) || defined(__x86)
+# define SQLITE_PTRSIZE 4
+# else
+# define SQLITE_PTRSIZE 8
+# endif
+#endif
+
+/*
** Macros to determine whether the machine is big or little endian,
** and whether or not that determination is run-time or compile-time.
**
@@ -9062,8 +9256,8 @@ struct BusyHandler {
#define SQLITE_WSD const
#define GLOBAL(t,v) (*(t*)sqlite3_wsd_find((void*)&(v), sizeof(v)))
#define sqlite3GlobalConfig GLOBAL(struct Sqlite3Config, sqlite3Config)
-SQLITE_API int sqlite3_wsd_init(int N, int J);
-SQLITE_API void *sqlite3_wsd_find(void *K, int L);
+SQLITE_API int SQLITE_STDCALL sqlite3_wsd_init(int N, int J);
+SQLITE_API void *SQLITE_STDCALL sqlite3_wsd_find(void *K, int L);
#else
#define SQLITE_WSD
#define GLOBAL(t,v) v
@@ -9221,10 +9415,8 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree*);
SQLITE_PRIVATE int sqlite3BtreeMaxPageCount(Btree*,int);
SQLITE_PRIVATE u32 sqlite3BtreeLastPage(Btree*);
SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree*,int);
-SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree*);
-#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
+SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree*);
SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p);
-#endif
SQLITE_PRIVATE int sqlite3BtreeSetAutoVacuum(Btree *, int);
SQLITE_PRIVATE int sqlite3BtreeGetAutoVacuum(Btree *);
SQLITE_PRIVATE int sqlite3BtreeBeginTrans(Btree*,int);
@@ -9302,8 +9494,18 @@ SQLITE_PRIVATE int sqlite3BtreeNewDb(Btree *p);
/*
** Values that may be OR'd together to form the second argument of an
** sqlite3BtreeCursorHints() call.
+**
+** The BTREE_BULKLOAD flag is set on index cursors when the index is going
+** to be filled with content that is already in sorted order.
+**
+** The BTREE_SEEK_EQ flag is set on cursors that will get OP_SeekGE or
+** OP_SeekLE opcodes for a range search, but where the range of entries
+** selected will all have the same key. In other words, the cursor will
+** be used only for equality key searches.
+**
*/
-#define BTREE_BULKLOAD 0x00000001
+#define BTREE_BULKLOAD 0x00000001 /* Used to full index in sorted order */
+#define BTREE_SEEK_EQ 0x00000002 /* EQ seeks only - no range seeks */
SQLITE_PRIVATE int sqlite3BtreeCursor(
Btree*, /* BTree containing table to open */
@@ -9349,6 +9551,9 @@ SQLITE_PRIVATE void sqlite3BtreeIncrblobCursor(BtCursor *);
SQLITE_PRIVATE void sqlite3BtreeClearCursor(BtCursor *);
SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBt, int iVersion);
SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *, unsigned int mask);
+#ifdef SQLITE_DEBUG
+SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor*, unsigned int mask);
+#endif
SQLITE_PRIVATE int sqlite3BtreeIsReadonly(Btree *pBt);
SQLITE_PRIVATE int sqlite3HeaderSizeBtree(void);
@@ -9715,23 +9920,25 @@ typedef struct VdbeOpList VdbeOpList;
#define OP_MemMax 136 /* synopsis: r[P1]=max(r[P1],r[P2]) */
#define OP_IfPos 137 /* synopsis: if r[P1]>0 goto P2 */
#define OP_IfNeg 138 /* synopsis: r[P1]+=P3, if r[P1]<0 goto P2 */
-#define OP_IfZero 139 /* synopsis: r[P1]+=P3, if r[P1]==0 goto P2 */
-#define OP_AggFinal 140 /* synopsis: accum=r[P1] N=P2 */
-#define OP_IncrVacuum 141
-#define OP_Expire 142
-#define OP_TableLock 143 /* synopsis: iDb=P1 root=P2 write=P3 */
-#define OP_VBegin 144
-#define OP_VCreate 145
-#define OP_VDestroy 146
-#define OP_VOpen 147
-#define OP_VColumn 148 /* synopsis: r[P3]=vcolumn(P2) */
-#define OP_VNext 149
-#define OP_VRename 150
-#define OP_Pagecount 151
-#define OP_MaxPgcnt 152
-#define OP_Init 153 /* synopsis: Start at P2 */
-#define OP_Noop 154
-#define OP_Explain 155
+#define OP_IfNotZero 139 /* synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2 */
+#define OP_DecrJumpZero 140 /* synopsis: if (--r[P1])==0 goto P2 */
+#define OP_JumpZeroIncr 141 /* synopsis: if (r[P1]++)==0 ) goto P2 */
+#define OP_AggFinal 142 /* synopsis: accum=r[P1] N=P2 */
+#define OP_IncrVacuum 143
+#define OP_Expire 144
+#define OP_TableLock 145 /* synopsis: iDb=P1 root=P2 write=P3 */
+#define OP_VBegin 146
+#define OP_VCreate 147
+#define OP_VDestroy 148
+#define OP_VOpen 149
+#define OP_VColumn 150 /* synopsis: r[P3]=vcolumn(P2) */
+#define OP_VNext 151
+#define OP_VRename 152
+#define OP_Pagecount 153
+#define OP_MaxPgcnt 154
+#define OP_Init 155 /* synopsis: Start at P2 */
+#define OP_Noop 156
+#define OP_Explain 157
/* Properties such as "out2" or "jump" that are specified in
@@ -9739,33 +9946,32 @@ typedef struct VdbeOpList VdbeOpList;
** are encoded into bitvectors as follows:
*/
#define OPFLG_JUMP 0x0001 /* jump: P2 holds jmp target */
-#define OPFLG_OUT2_PRERELEASE 0x0002 /* out2-prerelease: */
-#define OPFLG_IN1 0x0004 /* in1: P1 is an input */
-#define OPFLG_IN2 0x0008 /* in2: P2 is an input */
-#define OPFLG_IN3 0x0010 /* in3: P3 is an input */
-#define OPFLG_OUT2 0x0020 /* out2: P2 is an output */
-#define OPFLG_OUT3 0x0040 /* out3: P3 is an output */
+#define OPFLG_IN1 0x0002 /* in1: P1 is an input */
+#define OPFLG_IN2 0x0004 /* in2: P2 is an input */
+#define OPFLG_IN3 0x0008 /* in3: P3 is an input */
+#define OPFLG_OUT2 0x0010 /* out2: P2 is an output */
+#define OPFLG_OUT3 0x0020 /* out3: P3 is an output */
#define OPFLG_INITIALIZER {\
/* 0 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,\
-/* 8 */ 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x01, 0x00,\
-/* 16 */ 0x01, 0x01, 0x04, 0x24, 0x01, 0x04, 0x05, 0x10,\
-/* 24 */ 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,\
-/* 32 */ 0x00, 0x00, 0x20, 0x00, 0x00, 0x04, 0x05, 0x04,\
-/* 40 */ 0x04, 0x00, 0x00, 0x01, 0x01, 0x05, 0x05, 0x00,\
-/* 48 */ 0x00, 0x00, 0x02, 0x02, 0x10, 0x00, 0x00, 0x00,\
-/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11,\
-/* 64 */ 0x11, 0x11, 0x08, 0x11, 0x11, 0x11, 0x11, 0x4c,\
-/* 72 */ 0x4c, 0x02, 0x02, 0x00, 0x05, 0x05, 0x15, 0x15,\
-/* 80 */ 0x15, 0x15, 0x15, 0x15, 0x00, 0x4c, 0x4c, 0x4c,\
-/* 88 */ 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x4c, 0x00,\
-/* 96 */ 0x24, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02,\
-/* 104 */ 0x00, 0x01, 0x01, 0x01, 0x01, 0x08, 0x08, 0x00,\
-/* 112 */ 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00,\
-/* 120 */ 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 128 */ 0x0c, 0x45, 0x15, 0x01, 0x02, 0x02, 0x00, 0x01,\
-/* 136 */ 0x08, 0x05, 0x05, 0x05, 0x00, 0x01, 0x00, 0x00,\
-/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x02,\
-/* 152 */ 0x02, 0x01, 0x00, 0x00,}
+/* 8 */ 0x01, 0x01, 0x00, 0x00, 0x10, 0x00, 0x01, 0x00,\
+/* 16 */ 0x01, 0x01, 0x02, 0x12, 0x01, 0x02, 0x03, 0x08,\
+/* 24 */ 0x00, 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10,\
+/* 32 */ 0x00, 0x00, 0x10, 0x00, 0x00, 0x02, 0x03, 0x02,\
+/* 40 */ 0x02, 0x00, 0x00, 0x01, 0x01, 0x03, 0x03, 0x00,\
+/* 48 */ 0x00, 0x00, 0x10, 0x10, 0x08, 0x00, 0x00, 0x00,\
+/* 56 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x09,\
+/* 64 */ 0x09, 0x09, 0x04, 0x09, 0x09, 0x09, 0x09, 0x26,\
+/* 72 */ 0x26, 0x10, 0x10, 0x00, 0x03, 0x03, 0x0b, 0x0b,\
+/* 80 */ 0x0b, 0x0b, 0x0b, 0x0b, 0x00, 0x26, 0x26, 0x26,\
+/* 88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x00,\
+/* 96 */ 0x12, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
+/* 104 */ 0x00, 0x01, 0x01, 0x01, 0x01, 0x04, 0x04, 0x00,\
+/* 112 */ 0x10, 0x01, 0x01, 0x01, 0x01, 0x10, 0x00, 0x00,\
+/* 120 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 128 */ 0x06, 0x23, 0x0b, 0x01, 0x10, 0x10, 0x00, 0x01,\
+/* 136 */ 0x04, 0x03, 0x03, 0x03, 0x03, 0x03, 0x00, 0x01,\
+/* 144 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01,\
+/* 152 */ 0x00, 0x10, 0x10, 0x01, 0x00, 0x00,}
/************** End of opcodes.h *********************************************/
/************** Continuing where we left off in vdbe.h ***********************/
@@ -9824,6 +10030,7 @@ SQLITE_PRIVATE int sqlite3MemCompare(const Mem*, const Mem*, const CollSeq*);
SQLITE_PRIVATE void sqlite3VdbeRecordUnpack(KeyInfo*,int,const void*,UnpackedRecord*);
SQLITE_PRIVATE int sqlite3VdbeRecordCompare(int,const void*,UnpackedRecord*);
+SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(int, const void *, UnpackedRecord *, int);
SQLITE_PRIVATE UnpackedRecord *sqlite3VdbeAllocUnpackedRecord(KeyInfo *, char *, int, char **);
typedef int (*RecordCompare)(int,const void*,UnpackedRecord*);
@@ -10841,11 +11048,13 @@ struct sqlite3 {
u8 iDb; /* Which db file is being initialized */
u8 busy; /* TRUE if currently initializing */
u8 orphanTrigger; /* Last statement is orphaned TEMP trigger */
+ u8 imposterTable; /* Building an imposter table */
} init;
int nVdbeActive; /* Number of VDBEs currently running */
int nVdbeRead; /* Number of active VDBEs that read or write */
int nVdbeWrite; /* Number of active VDBEs that read and write */
int nVdbeExec; /* Number of nested calls to VdbeExec() */
+ int nVDestroy; /* Number of active OP_VDestroy operations */
int nExtension; /* Number of loaded extensions */
void **aExtension; /* Array of shared library handles */
void (*xTrace)(void*,const char*); /* Trace function */
@@ -10959,6 +11168,7 @@ struct sqlite3 {
#define SQLITE_DeferFKs 0x01000000 /* Defer all FK constraints */
#define SQLITE_QueryOnly 0x02000000 /* Disable database changes */
#define SQLITE_VdbeEQP 0x04000000 /* Debug EXPLAIN QUERY PLAN */
+#define SQLITE_Vacuum 0x08000000 /* Currently in a VACUUM */
/*
@@ -11289,34 +11499,8 @@ struct VTable {
};
/*
-** Each SQL table is represented in memory by an instance of the
-** following structure.
-**
-** Table.zName is the name of the table. The case of the original
-** CREATE TABLE statement is stored, but case is not significant for
-** comparisons.
-**
-** Table.nCol is the number of columns in this table. Table.aCol is a
-** pointer to an array of Column structures, one for each column.
-**
-** If the table has an INTEGER PRIMARY KEY, then Table.iPKey is the index of
-** the column that is that key. Otherwise Table.iPKey is negative. Note
-** that the datatype of the PRIMARY KEY must be INTEGER for this field to
-** be set. An INTEGER PRIMARY KEY is used as the rowid for each row of
-** the table. If a table has no INTEGER PRIMARY KEY, then a random rowid
-** is generated for each row of the table. TF_HasPrimaryKey is set if
-** the table has any PRIMARY KEY, INTEGER or otherwise.
-**
-** Table.tnum is the page number for the root BTree page of the table in the
-** database file. If Table.iDb is the index of the database table backend
-** in sqlite.aDb[]. 0 is for the main database and 1 is for the file that
-** holds temporary tables and indices. If TF_Ephemeral is set
-** then the table is stored in a file that is automatically deleted
-** when the VDBE cursor to the table is closed. In this case Table.tnum
-** refers VDBE cursor number that holds the table open, not to the root
-** page number. Transient tables are used to hold the results of a
-** sub-query that appears instead of a real table name in the FROM clause
-** of a SELECT statement.
+** The schema for each SQL table and view is represented in memory
+** by an instance of the following structure.
*/
struct Table {
char *zName; /* Name of the table or view */
@@ -11328,11 +11512,11 @@ struct Table {
#ifndef SQLITE_OMIT_CHECK
ExprList *pCheck; /* All CHECK constraints */
#endif
- LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
- int tnum; /* Root BTree node for this table (see note above) */
- i16 iPKey; /* If not negative, use aCol[iPKey] as the primary key */
+ int tnum; /* Root BTree page for this table */
+ i16 iPKey; /* If not negative, use aCol[iPKey] as the rowid */
i16 nCol; /* Number of columns in this table */
u16 nRef; /* Number of pointers to this Table */
+ LogEst nRowLogEst; /* Estimated rows in table - from sqlite_stat1 table */
LogEst szTabRow; /* Estimated size of each table row in bytes */
#ifdef SQLITE_ENABLE_COSTMULT
LogEst costMult; /* Cost multiplier for using this table */
@@ -11354,6 +11538,12 @@ struct Table {
/*
** Allowed values for Table.tabFlags.
+**
+** TF_OOOHidden applies to virtual tables that have hidden columns that are
+** followed by non-hidden columns. Example: "CREATE VIRTUAL TABLE x USING
+** vtab1(a HIDDEN, b);". Since "b" is a non-hidden column but "a" is hidden,
+** the TF_OOOHidden attribute would apply in this case. Such tables require
+** special handling during INSERT processing.
*/
#define TF_Readonly 0x01 /* Read-only system table */
#define TF_Ephemeral 0x02 /* An ephemeral table */
@@ -11361,6 +11551,7 @@ struct Table {
#define TF_Autoincrement 0x08 /* Integer primary key is autoincrement */
#define TF_Virtual 0x10 /* Is a virtual table */
#define TF_WithoutRowid 0x20 /* No rowid used. PRIMARY KEY is the key */
+#define TF_OOOHidden 0x40 /* Out-of-Order hidden columns */
/*
@@ -11797,8 +11988,14 @@ struct Expr {
#define EP_MemToken 0x010000 /* Need to sqlite3DbFree() Expr.zToken */
#define EP_NoReduce 0x020000 /* Cannot EXPRDUP_REDUCE this Expr */
#define EP_Unlikely 0x040000 /* unlikely() or likelihood() function */
-#define EP_Constant 0x080000 /* Node is a constant */
+#define EP_ConstFunc 0x080000 /* Node is a SQLITE_FUNC_CONSTANT function */
#define EP_CanBeNull 0x100000 /* Can be null despite NOT NULL constraint */
+#define EP_Subquery 0x200000 /* Tree contains a TK_SELECT operator */
+
+/*
+** Combinations of two or more EP_* flags
+*/
+#define EP_Propagate (EP_Collate|EP_Subquery) /* Propagate these bits up tree */
/*
** These macros can be used to test, set, or clear bits in the
@@ -11997,7 +12194,7 @@ struct SrcList {
#define WHERE_OMIT_OPEN_CLOSE 0x0010 /* Table cursors are already open */
#define WHERE_FORCE_TABLE 0x0020 /* Do not use an index-only search */
#define WHERE_ONETABLE_ONLY 0x0040 /* Only code the 1st table in pTabList */
- /* 0x0080 // not currently used */
+#define WHERE_NO_AUTOINDEX 0x0080 /* Disallow automatic indexes */
#define WHERE_GROUPBY 0x0100 /* pOrderBy is really a GROUP BY */
#define WHERE_DISTINCTBY 0x0200 /* pOrderby is really a DISTINCT clause */
#define WHERE_WANT_DISTINCT 0x0400 /* All output needs to be distinct */
@@ -12111,11 +12308,12 @@ struct Select {
#define SF_HasTypeInfo 0x0020 /* FROM subqueries have Table metadata */
#define SF_Compound 0x0040 /* Part of a compound query */
#define SF_Values 0x0080 /* Synthesized from VALUES clause */
-#define SF_AllValues 0x0100 /* All terms of compound are VALUES */
+#define SF_MultiValue 0x0100 /* Single VALUES term with multiple rows */
#define SF_NestedFrom 0x0200 /* Part of a parenthesized FROM clause */
#define SF_MaybeConvert 0x0400 /* Need convertCompoundSelectToSubquery() */
#define SF_Recursive 0x0800 /* The recursive part of a recursive CTE */
#define SF_MinMaxAgg 0x1000 /* Aggregate containing min() or max() */
+#define SF_Converted 0x2000 /* By convertCompoundSelectToSubquery() */
/*
@@ -12434,7 +12632,8 @@ struct AuthContext {
#define OPFLAG_LENGTHARG 0x40 /* OP_Column only used for length() */
#define OPFLAG_TYPEOFARG 0x80 /* OP_Column only used for typeof() */
#define OPFLAG_BULKCSR 0x01 /* OP_Open** used to open bulk cursor */
-#define OPFLAG_P2ISREG 0x02 /* P2 to OP_Open** is a register number */
+#define OPFLAG_SEEKEQ 0x02 /* OP_Open** cursor uses EQ seek only */
+#define OPFLAG_P2ISREG 0x04 /* P2 to OP_Open** is a register number */
#define OPFLAG_PERMUTE 0x01 /* OP_Compare: use the permutation */
/*
@@ -12493,7 +12692,7 @@ struct Trigger {
* orconf -> stores the ON CONFLICT algorithm
* pSelect -> If this is an INSERT INTO ... SELECT ... statement, then
* this stores a pointer to the SELECT statement. Otherwise NULL.
- * target -> A token holding the quoted name of the table to insert into.
+ * zTarget -> Dequoted name of the table to insert into.
* pExprList -> If this is an INSERT INTO ... VALUES ... statement, then
* this stores values to be inserted. Otherwise NULL.
* pIdList -> If this is an INSERT INTO ... (<column-names>) VALUES ...
@@ -12501,12 +12700,12 @@ struct Trigger {
* inserted into.
*
* (op == TK_DELETE)
- * target -> A token holding the quoted name of the table to delete from.
+ * zTarget -> Dequoted name of the table to delete from.
* pWhere -> The WHERE clause of the DELETE statement if one is specified.
* Otherwise NULL.
*
* (op == TK_UPDATE)
- * target -> A token holding the quoted name of the table to update rows of.
+ * zTarget -> Dequoted name of the table to update.
* pWhere -> The WHERE clause of the UPDATE statement if one is specified.
* Otherwise NULL.
* pExprList -> A list of the columns to update and the expressions to update
@@ -12518,8 +12717,8 @@ struct TriggerStep {
u8 op; /* One of TK_DELETE, TK_UPDATE, TK_INSERT, TK_SELECT */
u8 orconf; /* OE_Rollback etc. */
Trigger *pTrig; /* The trigger that this step is a part of */
- Select *pSelect; /* SELECT statment or RHS of INSERT INTO .. SELECT ... */
- Token target; /* Target table for DELETE, UPDATE, INSERT */
+ Select *pSelect; /* SELECT statement or RHS of INSERT INTO SELECT ... */
+ char *zTarget; /* Target table for DELETE, UPDATE, INSERT */
Expr *pWhere; /* The WHERE clause for DELETE or UPDATE steps */
ExprList *pExprList; /* SET clause for UPDATE. */
IdList *pIdList; /* Column names for INSERT */
@@ -12552,8 +12751,7 @@ struct StrAccum {
char *zText; /* The string collected so far */
int nChar; /* Length of the string so far */
int nAlloc; /* Amount of space allocated in zText */
- int mxAlloc; /* Maximum allowed string length */
- u8 useMalloc; /* 0: none, 1: sqlite3DbMalloc, 2: sqlite3_malloc */
+ int mxAlloc; /* Maximum allowed allocation. 0 for no malloc usage */
u8 accError; /* STRACCUM_NOMEM or STRACCUM_TOOBIG */
};
#define STRACCUM_NOMEM 1
@@ -12838,10 +13036,15 @@ SQLITE_PRIVATE int sqlite3MutexInit(void);
SQLITE_PRIVATE int sqlite3MutexEnd(void);
#endif
-SQLITE_PRIVATE int sqlite3StatusValue(int);
-SQLITE_PRIVATE void sqlite3StatusAdd(int, int);
+SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int);
+SQLITE_PRIVATE void sqlite3StatusUp(int, int);
+SQLITE_PRIVATE void sqlite3StatusDown(int, int);
SQLITE_PRIVATE void sqlite3StatusSet(int, int);
+/* Access to mutexes used by sqlite3_status() */
+SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void);
+SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void);
+
#ifndef SQLITE_OMIT_FLOATING_POINT
SQLITE_PRIVATE int sqlite3IsNaN(double);
#else
@@ -12865,7 +13068,7 @@ SQLITE_PRIVATE void sqlite3XPrintf(StrAccum*, u32, const char*, ...);
SQLITE_PRIVATE char *sqlite3MPrintf(sqlite3*,const char*, ...);
SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3*,const char*, va_list);
SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3*,char*,const char*,...);
-#if defined(SQLITE_TEST) || defined(SQLITE_DEBUG)
+#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
SQLITE_PRIVATE void sqlite3DebugPrintf(const char*, ...);
#endif
#if defined(SQLITE_TEST)
@@ -12906,6 +13109,7 @@ SQLITE_PRIVATE ExprList *sqlite3ExprListAppend(Parse*,ExprList*,Expr*);
SQLITE_PRIVATE void sqlite3ExprListSetName(Parse*,ExprList*,Token*,int);
SQLITE_PRIVATE void sqlite3ExprListSetSpan(Parse*,ExprList*,ExprSpan*);
SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3*, ExprList*);
+SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList*);
SQLITE_PRIVATE int sqlite3Init(sqlite3*, char**);
SQLITE_PRIVATE int sqlite3InitCallback(void*, int, char**, char**);
SQLITE_PRIVATE void sqlite3Pragma(Parse*,Token*,Token*,Token*,int);
@@ -13211,7 +13415,7 @@ SQLITE_PRIVATE void *sqlite3HexToBlob(sqlite3*, const char *z, int n);
SQLITE_PRIVATE u8 sqlite3HexToInt(int h);
SQLITE_PRIVATE int sqlite3TwoPartName(Parse *, Token *, Token *, Token **);
-#if defined(SQLITE_TEST)
+#if defined(SQLITE_NEED_ERR_NAME)
SQLITE_PRIVATE const char *sqlite3ErrName(int);
#endif
@@ -13220,7 +13424,7 @@ SQLITE_PRIVATE int sqlite3ReadSchema(Parse *pParse);
SQLITE_PRIVATE CollSeq *sqlite3FindCollSeq(sqlite3*,u8 enc, const char*,int);
SQLITE_PRIVATE CollSeq *sqlite3LocateCollSeq(Parse *pParse, const char*zName);
SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr);
-SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*);
+SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(Parse *pParse, Expr*, const Token*, int);
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse*,Expr*,const char*);
SQLITE_PRIVATE Expr *sqlite3ExprSkipCollate(Expr*);
SQLITE_PRIVATE int sqlite3CheckCollSeq(Parse *, CollSeq *);
@@ -13305,7 +13509,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc(sqlite3 *, const char *, int, int, void *,
SQLITE_PRIVATE int sqlite3ApiExit(sqlite3 *db, int);
SQLITE_PRIVATE int sqlite3OpenTempDatabase(Parse *);
-SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, char*, int, int);
+SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum*, sqlite3*, char*, int, int);
SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum*,const char*,int);
SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum*,const char*);
SQLITE_PRIVATE void sqlite3AppendChar(StrAccum*,int,char);
@@ -13489,12 +13693,11 @@ SQLITE_PRIVATE void sqlite3MemJournalOpen(sqlite3_file *);
SQLITE_PRIVATE int sqlite3MemJournalSize(void);
SQLITE_PRIVATE int sqlite3IsMemJournal(sqlite3_file *);
+SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p);
#if SQLITE_MAX_EXPR_DEPTH>0
-SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p);
SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *);
SQLITE_PRIVATE int sqlite3ExprCheckHeight(Parse*, int);
#else
- #define sqlite3ExprSetHeight(x,y)
#define sqlite3SelectExprHeight(x) 0
#define sqlite3ExprCheckHeight(x,y)
#endif
@@ -13524,7 +13727,7 @@ SQLITE_PRIVATE void sqlite3ParserTrace(FILE*, char *);
#ifdef SQLITE_ENABLE_IOTRACE
# define IOTRACE(A) if( sqlite3IoTrace ){ sqlite3IoTrace A; }
SQLITE_PRIVATE void sqlite3VdbeIOTraceSql(Vdbe*);
-void (*sqlite3IoTrace)(const char*,...);
+SQLITE_API SQLITE_EXTERN void (SQLITE_CDECL *sqlite3IoTrace)(const char*,...);
#else
# define IOTRACE(A)
# define sqlite3VdbeIOTraceSql(X)
@@ -13631,16 +13834,16 @@ SQLITE_PRIVATE const unsigned char sqlite3UpperToLower[] = {
48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, /* 3x */
64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, /* 4x */
80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, /* 5x */
- 96, 97, 66, 67, 68, 69, 70, 71, 72, 73,106,107,108,109,110,111, /* 6x */
- 112, 81, 82, 83, 84, 85, 86, 87, 88, 89,122,123,124,125,126,127, /* 7x */
+ 96, 97, 98, 99,100,101,102,103,104,105,106,107,108,109,110,111, /* 6x */
+ 112,113,114,115,116,117,118,119,120,121,122,123,124,125,126,127, /* 7x */
128,129,130,131,132,133,134,135,136,137,138,139,140,141,142,143, /* 8x */
- 144,145,146,147,148,149,150,151,152,153,154,155,156,157,156,159, /* 9x */
+ 144,145,146,147,148,149,150,151,152,153,154,155,156,157,158,159, /* 9x */
160,161,162,163,164,165,166,167,168,169,170,171,140,141,142,175, /* Ax */
176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,191, /* Bx */
192,129,130,131,132,133,134,135,136,137,202,203,204,205,206,207, /* Cx */
208,145,146,147,148,149,150,151,152,153,218,219,220,221,222,223, /* Dx */
- 224,225,162,163,164,165,166,167,168,169,232,203,204,205,206,207, /* Ex */
- 239,240,241,242,243,244,245,246,247,248,249,219,220,221,222,255, /* Fx */
+ 224,225,162,163,164,165,166,167,168,169,234,235,236,237,238,239, /* Ex */
+ 240,241,242,243,244,245,246,247,248,249,250,251,252,253,254,255, /* Fx */
#endif
};
@@ -13923,6 +14126,9 @@ static const char * const azCompileOpt[] = {
#if SQLITE_ENABLE_COLUMN_METADATA
"ENABLE_COLUMN_METADATA",
#endif
+#if SQLITE_ENABLE_DBSTAT_VTAB
+ "ENABLE_DBSTAT_VTAB",
+#endif
#if SQLITE_ENABLE_EXPENSIVE_ASSERT
"ENABLE_EXPENSIVE_ASSERT",
#endif
@@ -14237,7 +14443,7 @@ static const char * const azCompileOpt[] = {
** The name can optionally begin with "SQLITE_" but the "SQLITE_" prefix
** is not required for a match.
*/
-SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
+SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName){
int i, n;
#if SQLITE_ENABLE_API_ARMOR
@@ -14265,7 +14471,7 @@ SQLITE_API int sqlite3_compileoption_used(const char *zOptName){
** Return the N-th compile-time option string. If N is out of range,
** return a NULL pointer.
*/
-SQLITE_API const char *sqlite3_compileoption_get(int N){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N){
if( N>=0 && N<ArraySize(azCompileOpt) ){
return azCompileOpt[N];
}
@@ -14608,14 +14814,6 @@ struct ScanStatus {
**
** The "sqlite3_stmt" structure pointer that is returned by sqlite3_prepare()
** is really a pointer to an instance of this structure.
-**
-** The Vdbe.inVtabMethod variable is set to non-zero for the duration of
-** any virtual table method invocations made by the vdbe program. It is
-** set to 2 for xDestroy method calls and 1 for all other methods. This
-** variable is used for two purposes: to allow xDestroy methods to execute
-** "DROP TABLE" statements and to prevent some nasty side effects of
-** malloc failure when SQLite is invoked recursively by a virtual table
-** method function.
*/
struct Vdbe {
sqlite3 *db; /* The database connection that owns this statement */
@@ -14639,11 +14837,13 @@ struct Vdbe {
u32 cacheCtr; /* VdbeCursor row cache generation counter */
int pc; /* The program counter */
int rc; /* Value to return */
+#ifdef SQLITE_DEBUG
+ int rcApp; /* errcode set by sqlite3_result_error_code() */
+#endif
u16 nResColumn; /* Number of columns in one row of the result set */
u8 errorAction; /* Recovery action to do in case of an error */
u8 minWriteFileFormat; /* Minimum file format for writable database files */
bft explain:2; /* True if EXPLAIN present on SQL command */
- bft inVtabMethod:2; /* See comments above */
bft changeCntOn:1; /* True to update the change-counter */
bft expired:1; /* True if the VM needs to be recompiled */
bft runOnlyOnce:1; /* Automatically expire on reset */
@@ -14803,10 +15003,32 @@ SQLITE_PRIVATE int sqlite3VdbeMemExpandBlob(Mem *);
*/
typedef struct sqlite3StatType sqlite3StatType;
static SQLITE_WSD struct sqlite3StatType {
- int nowValue[10]; /* Current value */
- int mxValue[10]; /* Maximum value */
+#if SQLITE_PTRSIZE>4
+ sqlite3_int64 nowValue[10]; /* Current value */
+ sqlite3_int64 mxValue[10]; /* Maximum value */
+#else
+ u32 nowValue[10]; /* Current value */
+ u32 mxValue[10]; /* Maximum value */
+#endif
} sqlite3Stat = { {0,}, {0,} };
+/*
+** Elements of sqlite3Stat[] are protected by either the memory allocator
+** mutex, or by the pcache1 mutex. The following array determines which.
+*/
+static const char statMutex[] = {
+ 0, /* SQLITE_STATUS_MEMORY_USED */
+ 1, /* SQLITE_STATUS_PAGECACHE_USED */
+ 1, /* SQLITE_STATUS_PAGECACHE_OVERFLOW */
+ 0, /* SQLITE_STATUS_SCRATCH_USED */
+ 0, /* SQLITE_STATUS_SCRATCH_OVERFLOW */
+ 0, /* SQLITE_STATUS_MALLOC_SIZE */
+ 0, /* SQLITE_STATUS_PARSER_STACK */
+ 1, /* SQLITE_STATUS_PAGECACHE_SIZE */
+ 0, /* SQLITE_STATUS_SCRATCH_SIZE */
+ 0, /* SQLITE_STATUS_MALLOC_COUNT */
+};
+
/* The "wsdStat" macro will resolve to the status information
** state vector. If writable static data is unsupported on the target,
@@ -14823,33 +15045,60 @@ static SQLITE_WSD struct sqlite3StatType {
#endif
/*
-** Return the current value of a status parameter.
+** Return the current value of a status parameter. The caller must
+** be holding the appropriate mutex.
*/
-SQLITE_PRIVATE int sqlite3StatusValue(int op){
+SQLITE_PRIVATE sqlite3_int64 sqlite3StatusValue(int op){
wsdStatInit;
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ assert( op>=0 && op<ArraySize(statMutex) );
+ assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
+ : sqlite3MallocMutex()) );
return wsdStat.nowValue[op];
}
/*
-** Add N to the value of a status record. It is assumed that the
-** caller holds appropriate locks.
+** Add N to the value of a status record. The caller must hold the
+** appropriate mutex. (Locking is checked by assert()).
+**
+** The StatusUp() routine can accept positive or negative values for N.
+** The value of N is added to the current status value and the high-water
+** mark is adjusted if necessary.
+**
+** The StatusDown() routine lowers the current value by N. The highwater
+** mark is unchanged. N must be non-negative for StatusDown().
*/
-SQLITE_PRIVATE void sqlite3StatusAdd(int op, int N){
+SQLITE_PRIVATE void sqlite3StatusUp(int op, int N){
wsdStatInit;
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ assert( op>=0 && op<ArraySize(statMutex) );
+ assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
+ : sqlite3MallocMutex()) );
wsdStat.nowValue[op] += N;
if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
wsdStat.mxValue[op] = wsdStat.nowValue[op];
}
}
+SQLITE_PRIVATE void sqlite3StatusDown(int op, int N){
+ wsdStatInit;
+ assert( N>=0 );
+ assert( op>=0 && op<ArraySize(statMutex) );
+ assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
+ : sqlite3MallocMutex()) );
+ assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ wsdStat.nowValue[op] -= N;
+}
/*
-** Set the value of a status to X.
+** Set the value of a status to X. The highwater mark is adjusted if
+** necessary. The caller must hold the appropriate mutex.
*/
SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){
wsdStatInit;
assert( op>=0 && op<ArraySize(wsdStat.nowValue) );
+ assert( op>=0 && op<ArraySize(statMutex) );
+ assert( sqlite3_mutex_held(statMutex[op] ? sqlite3Pcache1Mutex()
+ : sqlite3MallocMutex()) );
wsdStat.nowValue[op] = X;
if( wsdStat.nowValue[op]>wsdStat.mxValue[op] ){
wsdStat.mxValue[op] = wsdStat.nowValue[op];
@@ -14858,12 +15107,14 @@ SQLITE_PRIVATE void sqlite3StatusSet(int op, int X){
/*
** Query status information.
-**
-** This implementation assumes that reading or writing an aligned
-** 32-bit integer is an atomic operation. If that assumption is not true,
-** then this routine is not threadsafe.
*/
-SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
+SQLITE_API int SQLITE_STDCALL sqlite3_status64(
+ int op,
+ sqlite3_int64 *pCurrent,
+ sqlite3_int64 *pHighwater,
+ int resetFlag
+){
+ sqlite3_mutex *pMutex;
wsdStatInit;
if( op<0 || op>=ArraySize(wsdStat.nowValue) ){
return SQLITE_MISUSE_BKPT;
@@ -14871,18 +15122,35 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
#ifdef SQLITE_ENABLE_API_ARMOR
if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
#endif
+ pMutex = statMutex[op] ? sqlite3Pcache1Mutex() : sqlite3MallocMutex();
+ sqlite3_mutex_enter(pMutex);
*pCurrent = wsdStat.nowValue[op];
*pHighwater = wsdStat.mxValue[op];
if( resetFlag ){
wsdStat.mxValue[op] = wsdStat.nowValue[op];
}
+ sqlite3_mutex_leave(pMutex);
+ (void)pMutex; /* Prevent warning when SQLITE_THREADSAFE=0 */
return SQLITE_OK;
}
+SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag){
+ sqlite3_int64 iCur, iHwtr;
+ int rc;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( pCurrent==0 || pHighwater==0 ) return SQLITE_MISUSE_BKPT;
+#endif
+ rc = sqlite3_status64(op, &iCur, &iHwtr, resetFlag);
+ if( rc==0 ){
+ *pCurrent = (int)iCur;
+ *pHighwater = (int)iHwtr;
+ }
+ return rc;
+}
/*
** Query status information for a single database connection
*/
-SQLITE_API int sqlite3_db_status(
+SQLITE_API int SQLITE_STDCALL sqlite3_db_status(
sqlite3 *db, /* The database connection whose status is desired */
int op, /* Status verb */
int *pCurrent, /* Write current value here */
@@ -16506,7 +16774,7 @@ static sqlite3_vfs * SQLITE_WSD vfsList = 0;
** Locate a VFS by name. If no name is given, simply return the
** first VFS on the list.
*/
-SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfs){
+SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfs){
sqlite3_vfs *pVfs = 0;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex;
@@ -16552,7 +16820,7 @@ static void vfsUnlink(sqlite3_vfs *pVfs){
** VFS multiple times. The new VFS becomes the default if makeDflt is
** true.
*/
-SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
+SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
MUTEX_LOGIC(sqlite3_mutex *mutex;)
#ifndef SQLITE_OMIT_AUTOINIT
int rc = sqlite3_initialize();
@@ -16580,7 +16848,7 @@ SQLITE_API int sqlite3_vfs_register(sqlite3_vfs *pVfs, int makeDflt){
/*
** Unregister a VFS so that it is no longer accessible.
*/
-SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
+SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs *pVfs){
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
@@ -18916,7 +19184,7 @@ SQLITE_PRIVATE int sqlite3MutexEnd(void){
/*
** Retrieve a pointer to a static mutex or allocate a new dynamic one.
*/
-SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int id){
+SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int id){
#ifndef SQLITE_OMIT_AUTOINIT
if( id<=SQLITE_MUTEX_RECURSIVE && sqlite3_initialize() ) return 0;
if( id>SQLITE_MUTEX_RECURSIVE && sqlite3MutexInit() ) return 0;
@@ -18935,7 +19203,7 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3MutexAlloc(int id){
/*
** Free a dynamic mutex.
*/
-SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
+SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex *p){
if( p ){
sqlite3GlobalConfig.mutex.xMutexFree(p);
}
@@ -18945,7 +19213,7 @@ SQLITE_API void sqlite3_mutex_free(sqlite3_mutex *p){
** Obtain the mutex p. If some other thread already has the mutex, block
** until it can be obtained.
*/
-SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
+SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex *p){
if( p ){
sqlite3GlobalConfig.mutex.xMutexEnter(p);
}
@@ -18955,7 +19223,7 @@ SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex *p){
** Obtain the mutex p. If successful, return SQLITE_OK. Otherwise, if another
** thread holds the mutex and it cannot be obtained, return SQLITE_BUSY.
*/
-SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
+SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex *p){
int rc = SQLITE_OK;
if( p ){
return sqlite3GlobalConfig.mutex.xMutexTry(p);
@@ -18969,7 +19237,7 @@ SQLITE_API int sqlite3_mutex_try(sqlite3_mutex *p){
** is not currently entered. If a NULL pointer is passed as an argument
** this function is a no-op.
*/
-SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
+SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex *p){
if( p ){
sqlite3GlobalConfig.mutex.xMutexLeave(p);
}
@@ -18980,10 +19248,10 @@ SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex *p){
** The sqlite3_mutex_held() and sqlite3_mutex_notheld() routine are
** intended for use inside assert() statements.
*/
-SQLITE_API int sqlite3_mutex_held(sqlite3_mutex *p){
+SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex *p){
return p==0 || sqlite3GlobalConfig.mutex.xMutexHeld(p);
}
-SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex *p){
+SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex *p){
return p==0 || sqlite3GlobalConfig.mutex.xMutexNotheld(p);
}
#endif
@@ -19113,8 +19381,12 @@ static sqlite3_mutex *debugMutexAlloc(int id){
break;
}
default: {
- assert( id-2 >= 0 );
- assert( id-2 < (int)(sizeof(aStatic)/sizeof(aStatic[0])) );
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( id-2<0 || id-2>=ArraySize(aStatic) ){
+ (void)SQLITE_MISUSE_BKPT;
+ return 0;
+ }
+#endif
pNew = &aStatic[id-2];
pNew->id = id;
break;
@@ -19129,8 +19401,13 @@ static sqlite3_mutex *debugMutexAlloc(int id){
static void debugMutexFree(sqlite3_mutex *pX){
sqlite3_debug_mutex *p = (sqlite3_debug_mutex*)pX;
assert( p->cnt==0 );
- assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
- sqlite3_free(p);
+ if( p->id==SQLITE_MUTEX_RECURSIVE || p->id==SQLITE_MUTEX_FAST ){
+ sqlite3_free(p);
+ }else{
+#ifdef SQLITE_ENABLE_API_ARMOR
+ (void)SQLITE_MISUSE_BKPT;
+#endif
+ }
}
/*
@@ -19241,8 +19518,10 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
*/
struct sqlite3_mutex {
pthread_mutex_t mutex; /* Mutex controlling the lock */
-#if SQLITE_MUTEX_NREF
+#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
int id; /* Mutex type */
+#endif
+#if SQLITE_MUTEX_NREF
volatile int nRef; /* Number of entrances */
volatile pthread_t owner; /* Thread that is within this mutex */
int trace; /* True to trace changes */
@@ -19359,18 +19638,12 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
pthread_mutex_init(&p->mutex, &recursiveAttr);
pthread_mutexattr_destroy(&recursiveAttr);
#endif
-#if SQLITE_MUTEX_NREF
- p->id = iType;
-#endif
}
break;
}
case SQLITE_MUTEX_FAST: {
p = sqlite3MallocZero( sizeof(*p) );
if( p ){
-#if SQLITE_MUTEX_NREF
- p->id = iType;
-#endif
pthread_mutex_init(&p->mutex, 0);
}
break;
@@ -19383,12 +19656,12 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
}
#endif
p = &staticMutexes[iType-2];
-#if SQLITE_MUTEX_NREF
- p->id = iType;
-#endif
break;
}
}
+#if SQLITE_MUTEX_NREF || defined(SQLITE_ENABLE_API_ARMOR)
+ if( p ) p->id = iType;
+#endif
return p;
}
@@ -19400,9 +19673,18 @@ static sqlite3_mutex *pthreadMutexAlloc(int iType){
*/
static void pthreadMutexFree(sqlite3_mutex *p){
assert( p->nRef==0 );
- assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
- pthread_mutex_destroy(&p->mutex);
- sqlite3_free(p);
+#if SQLITE_ENABLE_API_ARMOR
+ if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE )
+#endif
+ {
+ pthread_mutex_destroy(&p->mutex);
+ sqlite3_free(p);
+ }
+#ifdef SQLITE_ENABLE_API_ARMOR
+ else{
+ (void)SQLITE_MISUSE_BKPT;
+ }
+#endif
}
/*
@@ -19614,16 +19896,6 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
#endif
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-# ifndef SQLITE_DEBUG_OS_TRACE
-# define SQLITE_DEBUG_OS_TRACE 0
-# endif
- int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
-# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
-#else
-# define OSTRACE(X)
-#endif
-
/*
** Macros for performance tracing. Normally turned off. Only works
** on i486 hardware.
@@ -19872,6 +20144,17 @@ SQLITE_API int sqlite3_open_file_count = 0;
# define SQLITE_WIN32_VOLATILE volatile
#endif
+/*
+** For some Windows sub-platforms, the _beginthreadex() / _endthreadex()
+** functions are not available (e.g. those not using MSVC, Cygwin, etc).
+*/
+#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && \
+ SQLITE_THREADSAFE>0 && !defined(__CYGWIN__)
+# define SQLITE_OS_WIN_THREADS 1
+#else
+# define SQLITE_OS_WIN_THREADS 0
+#endif
+
#endif /* _OS_WIN_H_ */
/************** End of os_win.h **********************************************/
@@ -19954,8 +20237,8 @@ static int winMutex_isNt = -1; /* <0 means "need to query" */
*/
static LONG SQLITE_WIN32_VOLATILE winMutex_lock = 0;
-SQLITE_API int sqlite3_win32_is_nt(void); /* os_win.c */
-SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
+SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void); /* os_win.c */
+SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds); /* os_win.c */
static int winMutexInit(void){
/* The first to increment to 1 does actual initialization */
@@ -20047,8 +20330,8 @@ static sqlite3_mutex *winMutexAlloc(int iType){
case SQLITE_MUTEX_RECURSIVE: {
p = sqlite3MallocZero( sizeof(*p) );
if( p ){
-#ifdef SQLITE_DEBUG
p->id = iType;
+#ifdef SQLITE_DEBUG
#ifdef SQLITE_WIN32_MUTEX_TRACE_DYNAMIC
p->trace = 1;
#endif
@@ -20068,12 +20351,9 @@ static sqlite3_mutex *winMutexAlloc(int iType){
return 0;
}
#endif
- assert( iType-2 >= 0 );
- assert( iType-2 < ArraySize(winMutex_staticMutexes) );
- assert( winMutex_isInit==1 );
p = &winMutex_staticMutexes[iType-2];
-#ifdef SQLITE_DEBUG
p->id = iType;
+#ifdef SQLITE_DEBUG
#ifdef SQLITE_WIN32_MUTEX_TRACE_STATIC
p->trace = 1;
#endif
@@ -20092,13 +20372,15 @@ static sqlite3_mutex *winMutexAlloc(int iType){
*/
static void winMutexFree(sqlite3_mutex *p){
assert( p );
-#ifdef SQLITE_DEBUG
assert( p->nRef==0 && p->owner==0 );
- assert( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE );
+ if( p->id==SQLITE_MUTEX_FAST || p->id==SQLITE_MUTEX_RECURSIVE ){
+ DeleteCriticalSection(&p->mutex);
+ sqlite3_free(p);
+ }else{
+#ifdef SQLITE_ENABLE_API_ARMOR
+ (void)SQLITE_MISUSE_BKPT;
#endif
- assert( winMutex_isInit==1 );
- DeleteCriticalSection(&p->mutex);
- sqlite3_free(p);
+ }
}
/*
@@ -20252,7 +20534,7 @@ SQLITE_PRIVATE sqlite3_mutex_methods const *sqlite3DefaultMutex(void){
** held by SQLite. An example of non-essential memory is memory used to
** cache database pages that are not currently in use.
*/
-SQLITE_API int sqlite3_release_memory(int n){
+SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int n){
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
return sqlite3PcacheReleaseMemory(n);
#else
@@ -20308,6 +20590,13 @@ static SQLITE_WSD struct Mem0Global {
#define mem0 GLOBAL(struct Mem0Global, mem0)
/*
+** Return the memory allocator mutex. sqlite3_status() needs it.
+*/
+SQLITE_PRIVATE sqlite3_mutex *sqlite3MallocMutex(void){
+ return mem0.mutex;
+}
+
+/*
** This routine runs when the memory allocator sees that the
** total memory allocation is about to exceed the soft heap
** limit.
@@ -20329,7 +20618,7 @@ static int sqlite3MemoryAlarm(
void *pArg,
sqlite3_int64 iThreshold
){
- int nUsed;
+ sqlite3_int64 nUsed;
sqlite3_mutex_enter(mem0.mutex);
mem0.alarmCallback = xCallback;
mem0.alarmArg = pArg;
@@ -20345,7 +20634,7 @@ static int sqlite3MemoryAlarm(
** Deprecated external interface. Internal/core SQLite code
** should call sqlite3MemoryAlarm.
*/
-SQLITE_API int sqlite3_memory_alarm(
+SQLITE_API int SQLITE_STDCALL sqlite3_memory_alarm(
void(*xCallback)(void *pArg, sqlite3_int64 used,int N),
void *pArg,
sqlite3_int64 iThreshold
@@ -20358,7 +20647,7 @@ SQLITE_API int sqlite3_memory_alarm(
** Set the soft heap-size limit for the library. Passing a zero or
** negative value indicates no limit.
*/
-SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 n){
sqlite3_int64 priorLimit;
sqlite3_int64 excess;
#ifndef SQLITE_OMIT_AUTOINIT
@@ -20378,7 +20667,7 @@ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 n){
if( excess>0 ) sqlite3_release_memory((int)(excess & 0x7fffffff));
return priorLimit;
}
-SQLITE_API void sqlite3_soft_heap_limit(int n){
+SQLITE_API void SQLITE_STDCALL sqlite3_soft_heap_limit(int n){
if( n<0 ) n = 0;
sqlite3_soft_heap_limit64(n);
}
@@ -20387,6 +20676,7 @@ SQLITE_API void sqlite3_soft_heap_limit(int n){
** Initialize the memory allocation subsystem.
*/
SQLITE_PRIVATE int sqlite3MallocInit(void){
+ int rc;
if( sqlite3GlobalConfig.m.xMalloc==0 ){
sqlite3MemSetDefault();
}
@@ -20422,7 +20712,9 @@ SQLITE_PRIVATE int sqlite3MallocInit(void){
sqlite3GlobalConfig.szPage = 0;
sqlite3GlobalConfig.nPage = 0;
}
- return sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
+ rc = sqlite3GlobalConfig.m.xInit(sqlite3GlobalConfig.m.pAppData);
+ if( rc!=SQLITE_OK ) memset(&mem0, 0, sizeof(mem0));
+ return rc;
}
/*
@@ -20447,7 +20739,7 @@ SQLITE_PRIVATE void sqlite3MallocEnd(void){
/*
** Return the amount of memory currently checked out.
*/
-SQLITE_API sqlite3_int64 sqlite3_memory_used(void){
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void){
int n, mx;
sqlite3_int64 res;
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, 0);
@@ -20460,7 +20752,7 @@ SQLITE_API sqlite3_int64 sqlite3_memory_used(void){
** checked out since either the beginning of this process
** or since the most recent reset.
*/
-SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag){
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag){
int n, mx;
sqlite3_int64 res;
sqlite3_status(SQLITE_STATUS_MEMORY_USED, &n, &mx, resetFlag);
@@ -20498,7 +20790,7 @@ static int mallocWithAlarm(int n, void **pp){
nFull = sqlite3GlobalConfig.m.xRoundup(n);
sqlite3StatusSet(SQLITE_STATUS_MALLOC_SIZE, n);
if( mem0.alarmCallback!=0 ){
- int nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
+ sqlite3_int64 nUsed = sqlite3StatusValue(SQLITE_STATUS_MEMORY_USED);
if( nUsed >= mem0.alarmThreshold - nFull ){
mem0.nearlyFull = 1;
sqlite3MallocAlarm(nFull);
@@ -20515,8 +20807,8 @@ static int mallocWithAlarm(int n, void **pp){
#endif
if( p ){
nFull = sqlite3MallocSize(p);
- sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nFull);
- sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, 1);
+ sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nFull);
+ sqlite3StatusUp(SQLITE_STATUS_MALLOC_COUNT, 1);
}
*pp = p;
return nFull;
@@ -20551,13 +20843,13 @@ SQLITE_PRIVATE void *sqlite3Malloc(u64 n){
** First make sure the memory subsystem is initialized, then do the
** allocation.
*/
-SQLITE_API void *sqlite3_malloc(int n){
+SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int n){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
return n<=0 ? 0 : sqlite3Malloc(n);
}
-SQLITE_API void *sqlite3_malloc64(sqlite3_uint64 n){
+SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64 n){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
@@ -20593,14 +20885,14 @@ SQLITE_PRIVATE void *sqlite3ScratchMalloc(int n){
p = mem0.pScratchFree;
mem0.pScratchFree = mem0.pScratchFree->pNext;
mem0.nScratchFree--;
- sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, 1);
+ sqlite3StatusUp(SQLITE_STATUS_SCRATCH_USED, 1);
sqlite3_mutex_leave(mem0.mutex);
}else{
sqlite3_mutex_leave(mem0.mutex);
p = sqlite3Malloc(n);
if( sqlite3GlobalConfig.bMemstat && p ){
sqlite3_mutex_enter(mem0.mutex);
- sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
+ sqlite3StatusUp(SQLITE_STATUS_SCRATCH_OVERFLOW, sqlite3MallocSize(p));
sqlite3_mutex_leave(mem0.mutex);
}
sqlite3MemdebugSetType(p, MEMTYPE_SCRATCH);
@@ -20641,19 +20933,19 @@ SQLITE_PRIVATE void sqlite3ScratchFree(void *p){
mem0.pScratchFree = pSlot;
mem0.nScratchFree++;
assert( mem0.nScratchFree <= (u32)sqlite3GlobalConfig.nScratch );
- sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_USED, -1);
+ sqlite3StatusDown(SQLITE_STATUS_SCRATCH_USED, 1);
sqlite3_mutex_leave(mem0.mutex);
}else{
/* Release memory back to the heap */
assert( sqlite3MemdebugHasType(p, MEMTYPE_SCRATCH) );
- assert( sqlite3MemdebugNoType(p, ~MEMTYPE_SCRATCH) );
+ assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_SCRATCH) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
if( sqlite3GlobalConfig.bMemstat ){
int iSize = sqlite3MallocSize(p);
sqlite3_mutex_enter(mem0.mutex);
- sqlite3StatusAdd(SQLITE_STATUS_SCRATCH_OVERFLOW, -iSize);
- sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -iSize);
- sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
+ sqlite3StatusDown(SQLITE_STATUS_SCRATCH_OVERFLOW, iSize);
+ sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, iSize);
+ sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
sqlite3GlobalConfig.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
@@ -20684,7 +20976,7 @@ SQLITE_PRIVATE int sqlite3MallocSize(void *p){
}
SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
if( db==0 ){
- assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
+ assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
return sqlite3MallocSize(p);
}else{
@@ -20693,13 +20985,13 @@ SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3 *db, void *p){
return db->lookaside.sz;
}else{
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
+ assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
return sqlite3GlobalConfig.m.xSize(p);
}
}
}
-SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){
- assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
+SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void *p){
+ assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
return (sqlite3_uint64)sqlite3GlobalConfig.m.xSize(p);
}
@@ -20707,14 +20999,14 @@ SQLITE_API sqlite3_uint64 sqlite3_msize(void *p){
/*
** Free memory previously obtained from sqlite3Malloc().
*/
-SQLITE_API void sqlite3_free(void *p){
+SQLITE_API void SQLITE_STDCALL sqlite3_free(void *p){
if( p==0 ) return; /* IMP: R-49053-54554 */
assert( sqlite3MemdebugHasType(p, MEMTYPE_HEAP) );
- assert( sqlite3MemdebugNoType(p, ~MEMTYPE_HEAP) );
+ assert( sqlite3MemdebugNoType(p, (u8)~MEMTYPE_HEAP) );
if( sqlite3GlobalConfig.bMemstat ){
sqlite3_mutex_enter(mem0.mutex);
- sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, -sqlite3MallocSize(p));
- sqlite3StatusAdd(SQLITE_STATUS_MALLOC_COUNT, -1);
+ sqlite3StatusDown(SQLITE_STATUS_MEMORY_USED, sqlite3MallocSize(p));
+ sqlite3StatusDown(SQLITE_STATUS_MALLOC_COUNT, 1);
sqlite3GlobalConfig.m.xFree(p);
sqlite3_mutex_leave(mem0.mutex);
}else{
@@ -20755,7 +21047,7 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
}
}
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
+ assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
sqlite3_free(p);
@@ -20768,7 +21060,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
int nOld, nNew, nDiff;
void *pNew;
assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
- assert( sqlite3MemdebugNoType(pOld, ~MEMTYPE_HEAP) );
+ assert( sqlite3MemdebugNoType(pOld, (u8)~MEMTYPE_HEAP) );
if( pOld==0 ){
return sqlite3Malloc(nBytes); /* IMP: R-04300-56712 */
}
@@ -20802,7 +21094,7 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
}
if( pNew ){
nNew = sqlite3MallocSize(pNew);
- sqlite3StatusAdd(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
+ sqlite3StatusUp(SQLITE_STATUS_MEMORY_USED, nNew-nOld);
}
sqlite3_mutex_leave(mem0.mutex);
}else{
@@ -20816,14 +21108,14 @@ SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
** The public interface to sqlite3Realloc. Make sure that the memory
** subsystem is initialized prior to invoking sqliteRealloc.
*/
-SQLITE_API void *sqlite3_realloc(void *pOld, int n){
+SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void *pOld, int n){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
if( n<0 ) n = 0; /* IMP: R-26507-47431 */
return sqlite3Realloc(pOld, n);
}
-SQLITE_API void *sqlite3_realloc64(void *pOld, sqlite3_uint64 n){
+SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void *pOld, sqlite3_uint64 n){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
@@ -20935,7 +21227,7 @@ SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *db, void *p, u64 n){
}
}else{
assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
- assert( sqlite3MemdebugNoType(p, ~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
+ assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
pNew = sqlite3_realloc64(p, n);
if( !pNew ){
@@ -21188,6 +21480,7 @@ static char et_getdigit(LONGDOUBLE_TYPE *val, int *cnt){
** Set the StrAccum object to an error mode.
*/
static void setStrAccumError(StrAccum *p, u8 eError){
+ assert( eError==STRACCUM_NOMEM || eError==STRACCUM_TOOBIG );
p->accError = eError;
p->nAlloc = 0;
}
@@ -21262,13 +21555,6 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
PrintfArguments *pArgList = 0; /* Arguments for SQLITE_PRINTF_SQLFUNC */
char buf[etBUFSIZE]; /* Conversion buffer */
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( ap==0 ){
- (void)SQLITE_MISUSE_BKPT;
- sqlite3StrAccumReset(pAccum);
- return;
- }
-#endif
bufpt = 0;
if( bFlags ){
if( (bArgList = (bFlags & SQLITE_PRINTF_SQLFUNC))!=0 ){
@@ -21309,7 +21595,6 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
}
}while( !done && (c=(*++fmt))!=0 );
/* Get the field width */
- width = 0;
if( c=='*' ){
if( bArgList ){
width = (int)getIntArg(pArgList);
@@ -21318,18 +21603,21 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
}
if( width<0 ){
flag_leftjustify = 1;
- width = -width;
+ width = width >= -2147483647 ? -width : 0;
}
c = *++fmt;
}else{
+ unsigned wx = 0;
while( c>='0' && c<='9' ){
- width = width*10 + c - '0';
+ wx = wx*10 + c - '0';
c = *++fmt;
}
+ testcase( wx>0x7fffffff );
+ width = wx & 0x7fffffff;
}
+
/* Get the precision */
if( c=='.' ){
- precision = 0;
c = *++fmt;
if( c=='*' ){
if( bArgList ){
@@ -21337,13 +21625,18 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
}else{
precision = va_arg(ap,int);
}
- if( precision<0 ) precision = -precision;
c = *++fmt;
+ if( precision<0 ){
+ precision = precision >= -2147483647 ? -precision : -1;
+ }
}else{
+ unsigned px = 0;
while( c>='0' && c<='9' ){
- precision = precision*10 + c - '0';
+ px = px*10 + c - '0';
c = *++fmt;
}
+ testcase( px>0x7fffffff );
+ precision = px & 0x7fffffff;
}
}else{
precision = -1;
@@ -21507,7 +21800,8 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
else prefix = 0;
}
if( xtype==etGENERIC && precision>0 ) precision--;
- for(idx=precision, rounder=0.5; idx>0; idx--, rounder*=0.1){}
+ testcase( precision>0xfff );
+ for(idx=precision&0xfff, rounder=0.5; idx>0; idx--, rounder*=0.1){}
if( xtype==etFLOAT ) realvalue += rounder;
/* Normalize realvalue to within 10.0 > realvalue >= 1.0 */
exp = 0;
@@ -21562,8 +21856,9 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
}else{
e2 = exp;
}
- if( MAX(e2,0)+precision+width > etBUFSIZE - 15 ){
- bufpt = zExtra = sqlite3Malloc( MAX(e2,0)+precision+width+15 );
+ if( MAX(e2,0)+(i64)precision+(i64)width > etBUFSIZE - 15 ){
+ bufpt = zExtra
+ = sqlite3Malloc( MAX(e2,0)+(i64)precision+(i64)width+15 );
if( bufpt==0 ){
setStrAccumError(pAccum, STRACCUM_NOMEM);
return;
@@ -21795,13 +22090,13 @@ SQLITE_PRIVATE void sqlite3VXPrintf(
*/
static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
char *zNew;
- assert( p->nChar+N >= p->nAlloc ); /* Only called if really needed */
+ assert( p->nChar+(i64)N >= p->nAlloc ); /* Only called if really needed */
if( p->accError ){
testcase(p->accError==STRACCUM_TOOBIG);
testcase(p->accError==STRACCUM_NOMEM);
return 0;
}
- if( !p->useMalloc ){
+ if( p->mxAlloc==0 ){
N = p->nAlloc - p->nChar - 1;
setStrAccumError(p, STRACCUM_TOOBIG);
return N;
@@ -21821,10 +22116,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
}else{
p->nAlloc = (int)szNew;
}
- if( p->useMalloc==1 ){
+ if( p->db ){
zNew = sqlite3DbRealloc(p->db, zOld, p->nAlloc);
}else{
- zNew = sqlite3_realloc(zOld, p->nAlloc);
+ zNew = sqlite3_realloc64(zOld, p->nAlloc);
}
if( zNew ){
assert( p->zText!=0 || p->nChar==0 );
@@ -21844,7 +22139,10 @@ static int sqlite3StrAccumEnlarge(StrAccum *p, int N){
** Append N copies of character c to the given string buffer.
*/
SQLITE_PRIVATE void sqlite3AppendChar(StrAccum *p, int N, char c){
- if( p->nChar+N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ) return;
+ testcase( p->nChar + (i64)N > 0x7fffffff );
+ if( p->nChar+(i64)N >= p->nAlloc && (N = sqlite3StrAccumEnlarge(p, N))<=0 ){
+ return;
+ }
while( (N--)>0 ) p->zText[p->nChar++] = c;
}
@@ -21869,7 +22167,7 @@ static void SQLITE_NOINLINE enlargeAndAppend(StrAccum *p, const char *z, int N){
** size of the memory allocation for StrAccum if necessary.
*/
SQLITE_PRIVATE void sqlite3StrAccumAppend(StrAccum *p, const char *z, int N){
- assert( z!=0 );
+ assert( z!=0 || N==0 );
assert( p->zText!=0 || p->nChar==0 || p->accError );
assert( N>=0 );
assert( p->accError==0 || p->nAlloc==0 );
@@ -21898,12 +22196,8 @@ SQLITE_PRIVATE void sqlite3StrAccumAppendAll(StrAccum *p, const char *z){
SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
if( p->zText ){
p->zText[p->nChar] = 0;
- if( p->useMalloc && p->zText==p->zBase ){
- if( p->useMalloc==1 ){
- p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
- }else{
- p->zText = sqlite3_malloc(p->nChar+1);
- }
+ if( p->mxAlloc>0 && p->zText==p->zBase ){
+ p->zText = sqlite3DbMallocRaw(p->db, p->nChar+1 );
if( p->zText ){
memcpy(p->zText, p->zBase, p->nChar+1);
}else{
@@ -21919,25 +22213,31 @@ SQLITE_PRIVATE char *sqlite3StrAccumFinish(StrAccum *p){
*/
SQLITE_PRIVATE void sqlite3StrAccumReset(StrAccum *p){
if( p->zText!=p->zBase ){
- if( p->useMalloc==1 ){
- sqlite3DbFree(p->db, p->zText);
- }else{
- sqlite3_free(p->zText);
- }
+ sqlite3DbFree(p->db, p->zText);
}
p->zText = 0;
}
/*
-** Initialize a string accumulator
+** Initialize a string accumulator.
+**
+** p: The accumulator to be initialized.
+** db: Pointer to a database connection. May be NULL. Lookaside
+** memory is used if not NULL. db->mallocFailed is set appropriately
+** when not NULL.
+** zBase: An initial buffer. May be NULL in which case the initial buffer
+** is malloced.
+** n: Size of zBase in bytes. If total space requirements never exceed
+** n then no memory allocations ever occur.
+** mx: Maximum number of bytes to accumulate. If mx==0 then no memory
+** allocations will ever occur.
*/
-SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, char *zBase, int n, int mx){
+SQLITE_PRIVATE void sqlite3StrAccumInit(StrAccum *p, sqlite3 *db, char *zBase, int n, int mx){
p->zText = p->zBase = zBase;
- p->db = 0;
+ p->db = db;
p->nChar = 0;
p->nAlloc = n;
p->mxAlloc = mx;
- p->useMalloc = 1;
p->accError = 0;
}
@@ -21950,9 +22250,8 @@ SQLITE_PRIVATE char *sqlite3VMPrintf(sqlite3 *db, const char *zFormat, va_list a
char zBase[SQLITE_PRINT_BUF_SIZE];
StrAccum acc;
assert( db!=0 );
- sqlite3StrAccumInit(&acc, zBase, sizeof(zBase),
+ sqlite3StrAccumInit(&acc, db, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
- acc.db = db;
sqlite3VXPrintf(&acc, SQLITE_PRINTF_INTERNAL, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
if( acc.accError==STRACCUM_NOMEM ){
@@ -21996,7 +22295,7 @@ SQLITE_PRIVATE char *sqlite3MAppendf(sqlite3 *db, char *zStr, const char *zForma
** Print into memory obtained from sqlite3_malloc(). Omit the internal
** %-conversion extensions.
*/
-SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){
+SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char *zFormat, va_list ap){
char *z;
char zBase[SQLITE_PRINT_BUF_SIZE];
StrAccum acc;
@@ -22010,8 +22309,7 @@ SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize() ) return 0;
#endif
- sqlite3StrAccumInit(&acc, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
- acc.useMalloc = 2;
+ sqlite3StrAccumInit(&acc, 0, zBase, sizeof(zBase), SQLITE_MAX_LENGTH);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
z = sqlite3StrAccumFinish(&acc);
return z;
@@ -22021,7 +22319,7 @@ SQLITE_API char *sqlite3_vmprintf(const char *zFormat, va_list ap){
** Print into memory obtained from sqlite3_malloc()(). Omit the internal
** %-conversion extensions.
*/
-SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){
+SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char *zFormat, ...){
va_list ap;
char *z;
#ifndef SQLITE_OMIT_AUTOINIT
@@ -22046,22 +22344,21 @@ SQLITE_API char *sqlite3_mprintf(const char *zFormat, ...){
**
** sqlite3_vsnprintf() is the varargs version.
*/
-SQLITE_API char *sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
+SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int n, char *zBuf, const char *zFormat, va_list ap){
StrAccum acc;
if( n<=0 ) return zBuf;
#ifdef SQLITE_ENABLE_API_ARMOR
if( zBuf==0 || zFormat==0 ) {
(void)SQLITE_MISUSE_BKPT;
- if( zBuf && n>0 ) zBuf[0] = 0;
+ if( zBuf ) zBuf[0] = 0;
return zBuf;
}
#endif
- sqlite3StrAccumInit(&acc, zBuf, n, 0);
- acc.useMalloc = 0;
+ sqlite3StrAccumInit(&acc, 0, zBuf, n, 0);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
return sqlite3StrAccumFinish(&acc);
}
-SQLITE_API char *sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
+SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int n, char *zBuf, const char *zFormat, ...){
char *z;
va_list ap;
va_start(ap,zFormat);
@@ -22083,8 +22380,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
StrAccum acc; /* String accumulator */
char zMsg[SQLITE_PRINT_BUF_SIZE*3]; /* Complete log message */
- sqlite3StrAccumInit(&acc, zMsg, sizeof(zMsg), 0);
- acc.useMalloc = 0;
+ sqlite3StrAccumInit(&acc, 0, zMsg, sizeof(zMsg), 0);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
sqlite3GlobalConfig.xLog(sqlite3GlobalConfig.pLogArg, iErrCode,
sqlite3StrAccumFinish(&acc));
@@ -22093,7 +22389,7 @@ static void renderLogMsg(int iErrCode, const char *zFormat, va_list ap){
/*
** Format and write a message to the log if logging is enabled.
*/
-SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){
+SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...){
va_list ap; /* Vararg list */
if( sqlite3GlobalConfig.xLog ){
va_start(ap, zFormat);
@@ -22102,7 +22398,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...){
}
}
-#if defined(SQLITE_DEBUG)
+#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
/*
** A version of printf() that understands %lld. Used for debugging.
** The printf() built into some versions of windows does not understand %lld
@@ -22112,8 +22408,7 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
va_list ap;
StrAccum acc;
char zBuf[500];
- sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
- acc.useMalloc = 0;
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
va_start(ap,zFormat);
sqlite3VXPrintf(&acc, 0, zFormat, ap);
va_end(ap);
@@ -22140,7 +22435,7 @@ SQLITE_PRIVATE void sqlite3DebugPrintf(const char *zFormat, ...){
** is not the last item in the tree. */
SQLITE_PRIVATE TreeView *sqlite3TreeViewPush(TreeView *p, u8 moreToFollow){
if( p==0 ){
- p = sqlite3_malloc( sizeof(*p) );
+ p = sqlite3_malloc64( sizeof(*p) );
if( p==0 ) return 0;
memset(p, 0, sizeof(*p));
}else{
@@ -22163,8 +22458,7 @@ SQLITE_PRIVATE void sqlite3TreeViewLine(TreeView *p, const char *zFormat, ...){
int i;
StrAccum acc;
char zBuf[500];
- sqlite3StrAccumInit(&acc, zBuf, sizeof(zBuf), 0);
- acc.useMalloc = 0;
+ sqlite3StrAccumInit(&acc, 0, zBuf, sizeof(zBuf), 0);
if( p ){
for(i=0; i<p->iLevel && i<sizeof(p->bLine)-1; i++){
sqlite3StrAccumAppend(&acc, p->bLine[i] ? "| " : " ", 4);
@@ -22229,7 +22523,7 @@ static SQLITE_WSD struct sqlite3PrngType {
/*
** Return N random bytes.
*/
-SQLITE_API void sqlite3_randomness(int N, void *pBuf){
+SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *pBuf){
unsigned char t;
unsigned char *zBuf = pBuf;
@@ -22435,7 +22729,7 @@ SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
/********************************* Win32 Threads ****************************/
-#if SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_THREADSAFE>0
+#if SQLITE_OS_WIN_THREADS
#define SQLITE_THREADS_IMPLEMENTED 1 /* Prevent the single-thread code below */
#include <process.h>
@@ -22528,7 +22822,7 @@ SQLITE_PRIVATE int sqlite3ThreadJoin(SQLiteThread *p, void **ppOut){
return (rc==WAIT_OBJECT_0) ? SQLITE_OK : SQLITE_ERROR;
}
-#endif /* SQLITE_OS_WIN && !SQLITE_OS_WINCE && !SQLITE_OS_WINRT */
+#endif /* SQLITE_OS_WIN_THREADS */
/******************************** End Win32 Threads *************************/
@@ -23381,7 +23675,7 @@ SQLITE_PRIVATE int sqlite3Dequote(char *z){
** case-independent fashion, using the same definition of "case
** independence" that SQLite uses internally when comparing identifiers.
*/
-SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
+SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *zLeft, const char *zRight){
register unsigned char *a, *b;
if( zLeft==0 ){
return zRight ? -1 : 0;
@@ -23393,7 +23687,7 @@ SQLITE_API int sqlite3_stricmp(const char *zLeft, const char *zRight){
while( *a!=0 && UpperToLower[*a]==UpperToLower[*b]){ a++; b++; }
return UpperToLower[*a] - UpperToLower[*b];
}
-SQLITE_API int sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
+SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *zLeft, const char *zRight, int N){
register unsigned char *a, *b;
if( zLeft==0 ){
return zRight ? -1 : 0;
@@ -23787,6 +24081,7 @@ SQLITE_PRIVATE int sqlite3GetInt32(const char *zNum, int *pValue){
}
}
#endif
+ while( zNum[0]=='0' ) zNum++;
for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
v = v*10 + c;
}
@@ -24924,23 +25219,25 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
/* 136 */ "MemMax" OpHelp("r[P1]=max(r[P1],r[P2])"),
/* 137 */ "IfPos" OpHelp("if r[P1]>0 goto P2"),
/* 138 */ "IfNeg" OpHelp("r[P1]+=P3, if r[P1]<0 goto P2"),
- /* 139 */ "IfZero" OpHelp("r[P1]+=P3, if r[P1]==0 goto P2"),
- /* 140 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
- /* 141 */ "IncrVacuum" OpHelp(""),
- /* 142 */ "Expire" OpHelp(""),
- /* 143 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
- /* 144 */ "VBegin" OpHelp(""),
- /* 145 */ "VCreate" OpHelp(""),
- /* 146 */ "VDestroy" OpHelp(""),
- /* 147 */ "VOpen" OpHelp(""),
- /* 148 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
- /* 149 */ "VNext" OpHelp(""),
- /* 150 */ "VRename" OpHelp(""),
- /* 151 */ "Pagecount" OpHelp(""),
- /* 152 */ "MaxPgcnt" OpHelp(""),
- /* 153 */ "Init" OpHelp("Start at P2"),
- /* 154 */ "Noop" OpHelp(""),
- /* 155 */ "Explain" OpHelp(""),
+ /* 139 */ "IfNotZero" OpHelp("if r[P1]!=0 then r[P1]+=P3, goto P2"),
+ /* 140 */ "DecrJumpZero" OpHelp("if (--r[P1])==0 goto P2"),
+ /* 141 */ "JumpZeroIncr" OpHelp("if (r[P1]++)==0 ) goto P2"),
+ /* 142 */ "AggFinal" OpHelp("accum=r[P1] N=P2"),
+ /* 143 */ "IncrVacuum" OpHelp(""),
+ /* 144 */ "Expire" OpHelp(""),
+ /* 145 */ "TableLock" OpHelp("iDb=P1 root=P2 write=P3"),
+ /* 146 */ "VBegin" OpHelp(""),
+ /* 147 */ "VCreate" OpHelp(""),
+ /* 148 */ "VDestroy" OpHelp(""),
+ /* 149 */ "VOpen" OpHelp(""),
+ /* 150 */ "VColumn" OpHelp("r[P3]=vcolumn(P2)"),
+ /* 151 */ "VNext" OpHelp(""),
+ /* 152 */ "VRename" OpHelp(""),
+ /* 153 */ "Pagecount" OpHelp(""),
+ /* 154 */ "MaxPgcnt" OpHelp(""),
+ /* 155 */ "Init" OpHelp("Start at P2"),
+ /* 156 */ "Noop" OpHelp(""),
+ /* 157 */ "Explain" OpHelp(""),
};
return azName[i];
}
@@ -25021,18 +25318,6 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
#endif
/*
-** Define the OS_VXWORKS pre-processor macro to 1 if building on
-** vxworks, or 0 otherwise.
-*/
-#ifndef OS_VXWORKS
-# if defined(__RTP__) || defined(_WRS_KERNEL)
-# define OS_VXWORKS 1
-# else
-# define OS_VXWORKS 0
-# endif
-#endif
-
-/*
** standard include files.
*/
#include <sys/types.h>
@@ -25046,18 +25331,30 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
# include <sys/mman.h>
#endif
-#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
+#if SQLITE_ENABLE_LOCKING_STYLE
# include <sys/ioctl.h>
-# if OS_VXWORKS
-# include <semaphore.h>
-# include <limits.h>
-# else
-# include <sys/file.h>
-# include <sys/param.h>
-# endif
+# include <sys/file.h>
+# include <sys/param.h>
#endif /* SQLITE_ENABLE_LOCKING_STYLE */
-#if defined(__APPLE__) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
+#if defined(__APPLE__) && ((__MAC_OS_X_VERSION_MIN_REQUIRED > 1050) || \
+ (__IPHONE_OS_VERSION_MIN_REQUIRED > 2000))
+# if (!defined(TARGET_OS_EMBEDDED) || (TARGET_OS_EMBEDDED==0)) \
+ && (!defined(TARGET_IPHONE_SIMULATOR) || (TARGET_IPHONE_SIMULATOR==0))
+# define HAVE_GETHOSTUUID 1
+# else
+# warning "gethostuuid() is disabled."
+# endif
+#endif
+
+
+#if OS_VXWORKS
+/* # include <sys/ioctl.h> */
+# include <semaphore.h>
+# include <limits.h>
+#endif /* OS_VXWORKS */
+
+#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
# include <sys/mount.h>
#endif
@@ -25098,6 +25395,10 @@ SQLITE_PRIVATE const char *sqlite3OpcodeName(int i){
*/
#define MAX_PATHNAME 512
+/* Always cast the getpid() return type for compatibility with
+** kernel modules in VxWorks. */
+#define osGetpid(X) (pid_t)getpid()
+
/*
** Only set the lastErrno if the error code is a real error and not
** a normal expected return code of SQLITE_BUSY or SQLITE_OK
@@ -25186,7 +25487,7 @@ struct unixFile {
** method was called. If xOpen() is called from a different process id,
** indicating that a fork() has occurred, the PRNG will be reset.
*/
-static int randomnessPid = 0;
+static pid_t randomnessPid = 0;
/*
** Allowed values for the unixFile.ctrlFlags bitmask:
@@ -25203,7 +25504,8 @@ static int randomnessPid = 0;
#define UNIXFILE_DELETE 0x20 /* Delete on close */
#define UNIXFILE_URI 0x40 /* Filename might have query parameters */
#define UNIXFILE_NOLOCK 0x80 /* Do no file locking */
-#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings have been issued */
+#define UNIXFILE_WARNED 0x0100 /* verifyDbFile() warnings issued */
+#define UNIXFILE_BLOCK 0x0200 /* Next SHM lock might block */
/*
** Include code that is common to all os_*.c files
@@ -25241,16 +25543,6 @@ static int randomnessPid = 0;
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
#endif
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-# ifndef SQLITE_DEBUG_OS_TRACE
-# define SQLITE_DEBUG_OS_TRACE 0
-# endif
- int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
-# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
-#else
-# define OSTRACE(X)
-#endif
-
/*
** Macros for performance tracing. Normally turned off. Only works
** on i486 hardware.
@@ -25542,7 +25834,7 @@ static struct unix_syscall {
{ "read", (sqlite3_syscall_ptr)read, 0 },
#define osRead ((ssize_t(*)(int,void*,size_t))aSyscall[8].pCurrent)
-#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
+#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
{ "pread", (sqlite3_syscall_ptr)pread, 0 },
#else
{ "pread", (sqlite3_syscall_ptr)0, 0 },
@@ -25559,7 +25851,7 @@ static struct unix_syscall {
{ "write", (sqlite3_syscall_ptr)write, 0 },
#define osWrite ((ssize_t(*)(int,const void*,size_t))aSyscall[11].pCurrent)
-#if defined(USE_PREAD) || (SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS)
+#if defined(USE_PREAD) || SQLITE_ENABLE_LOCKING_STYLE
{ "pwrite", (sqlite3_syscall_ptr)pwrite, 0 },
#else
{ "pwrite", (sqlite3_syscall_ptr)0, 0 },
@@ -25793,7 +26085,7 @@ static int unixMutexHeld(void) {
#endif
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
+#ifdef SQLITE_HAVE_OS_TRACE
/*
** Helper function for printing out trace information from debugging
** binaries. This returns the string representation of the supplied
@@ -25874,9 +26166,9 @@ static int lockTrace(int fd, int op, struct flock *p){
/*
** Retry ftruncate() calls that fail due to EINTR
**
-** All calls to ftruncate() within this file should be made through this wrapper.
-** On the Android platform, bypassing the logic below could lead to a corrupt
-** database.
+** All calls to ftruncate() within this file should be made through
+** this wrapper. On the Android platform, bypassing the logic below
+** could lead to a corrupt database.
*/
static int robust_ftruncate(int h, sqlite3_int64 sz){
int rc;
@@ -26056,7 +26348,7 @@ static struct vxworksFileId *vxworksFindFileId(const char *zAbsoluteName){
assert( zAbsoluteName[0]=='/' );
n = (int)strlen(zAbsoluteName);
- pNew = sqlite3_malloc( sizeof(*pNew) + (n+1) );
+ pNew = sqlite3_malloc64( sizeof(*pNew) + (n+1) );
if( pNew==0 ) return 0;
pNew->zCanonicalName = (char*)&pNew[1];
memcpy(pNew->zCanonicalName, zAbsoluteName, n+1);
@@ -26336,6 +26628,14 @@ static void robust_close(unixFile *pFile, int h, int lineno){
}
/*
+** Set the pFile->lastErrno. Do this in a subroutine as that provides
+** a convenient place to set a breakpoint.
+*/
+static void storeLastErrno(unixFile *pFile, int error){
+ pFile->lastErrno = error;
+}
+
+/*
** Close all file descriptors accumuated in the unixInodeInfo->pUnused list.
*/
static void closePendingFds(unixFile *pFile){
@@ -26408,7 +26708,7 @@ static int findInodeInfo(
fd = pFile->h;
rc = osFstat(fd, &statbuf);
if( rc!=0 ){
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
#ifdef EOVERFLOW
if( pFile->lastErrno==EOVERFLOW ) return SQLITE_NOLFS;
#endif
@@ -26429,12 +26729,12 @@ static int findInodeInfo(
if( statbuf.st_size==0 && (pFile->fsFlags & SQLITE_FSFLAGS_IS_MSDOS)!=0 ){
do{ rc = osWrite(fd, "S", 1); }while( rc<0 && errno==EINTR );
if( rc!=1 ){
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
return SQLITE_IOERR;
}
rc = osFstat(fd, &statbuf);
if( rc!=0 ){
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
return SQLITE_IOERR;
}
}
@@ -26452,7 +26752,7 @@ static int findInodeInfo(
pInode = pInode->pNext;
}
if( pInode==0 ){
- pInode = sqlite3_malloc( sizeof(*pInode) );
+ pInode = sqlite3_malloc64( sizeof(*pInode) );
if( pInode==0 ){
return SQLITE_NOMEM;
}
@@ -26557,7 +26857,7 @@ static int unixCheckReservedLock(sqlite3_file *id, int *pResOut){
lock.l_type = F_WRLCK;
if( osFcntl(pFile->h, F_GETLK, &lock) ){
rc = SQLITE_IOERR_CHECKRESERVEDLOCK;
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
} else if( lock.l_type!=F_UNLCK ){
reserved = 1;
}
@@ -26690,7 +26990,8 @@ static int unixLock(sqlite3_file *id, int eFileLock){
assert( pFile );
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (unix)\n", pFile->h,
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
- azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared , getpid()));
+ azFileLock(pFile->pInode->eFileLock), pFile->pInode->nShared,
+ osGetpid(0)));
/* If there is already a lock of this type or more restrictive on the
** unixFile, do nothing. Don't use the end_lock: exit path, as
@@ -26757,7 +27058,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
if( rc!=SQLITE_BUSY ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
}
goto end_lock;
}
@@ -26792,7 +27093,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
if( rc ){
if( rc!=SQLITE_BUSY ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
}
goto end_lock;
}else{
@@ -26825,7 +27126,7 @@ static int unixLock(sqlite3_file *id, int eFileLock){
tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
if( rc!=SQLITE_BUSY ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
}
}
}
@@ -26898,7 +27199,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
assert( pFile );
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (unix)\n", pFile->h, eFileLock,
pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
- getpid()));
+ osGetpid(0)));
assert( eFileLock<=SHARED_LOCK );
if( pFile->eFileLock<=eFileLock ){
@@ -26932,7 +27233,6 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
** 4: [RRRR.]
*/
if( eFileLock==SHARED_LOCK ){
-
#if !defined(__APPLE__) || !SQLITE_ENABLE_LOCKING_STYLE
(void)handleNFSUnlock;
assert( handleNFSUnlock==0 );
@@ -26950,7 +27250,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
tErrno = errno;
rc = SQLITE_IOERR_UNLOCK;
if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
}
goto end_unlock;
}
@@ -26962,7 +27262,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_RDLOCK);
if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
}
goto end_unlock;
}
@@ -26974,7 +27274,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
tErrno = errno;
rc = SQLITE_IOERR_UNLOCK;
if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
}
goto end_unlock;
}
@@ -26993,7 +27293,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
** SQLITE_BUSY would confuse the upper layer (in practice it causes
** an assert to fail). */
rc = SQLITE_IOERR_RDLOCK;
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
goto end_unlock;
}
}
@@ -27006,7 +27306,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
pInode->eFileLock = SHARED_LOCK;
}else{
rc = SQLITE_IOERR_UNLOCK;
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
goto end_unlock;
}
}
@@ -27024,7 +27324,7 @@ static int posixUnlock(sqlite3_file *id, int eFileLock, int handleNFSUnlock){
pInode->eFileLock = NO_LOCK;
}else{
rc = SQLITE_IOERR_UNLOCK;
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
pInode->eFileLock = NO_LOCK;
pFile->eFileLock = NO_LOCK;
}
@@ -27299,7 +27599,7 @@ static int dotlockLock(sqlite3_file *id, int eFileLock) {
} else {
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
}
}
return rc;
@@ -27326,7 +27626,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
assert( pFile );
OSTRACE(("UNLOCK %d %d was %d pid=%d (dotlock)\n", pFile->h, eFileLock,
- pFile->eFileLock, getpid()));
+ pFile->eFileLock, osGetpid(0)));
assert( eFileLock<=SHARED_LOCK );
/* no-op if possible */
@@ -27353,7 +27653,7 @@ static int dotlockUnlock(sqlite3_file *id, int eFileLock) {
rc = SQLITE_IOERR_UNLOCK;
}
if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
}
return rc;
}
@@ -27389,10 +27689,9 @@ static int dotlockClose(sqlite3_file *id) {
** still works when you do this, but concurrency is reduced since
** only a single process can be reading the database at a time.
**
-** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off or if
-** compiling for VXWORKS.
+** Omit this section if SQLITE_ENABLE_LOCKING_STYLE is turned off
*/
-#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
+#if SQLITE_ENABLE_LOCKING_STYLE
/*
** Retry flock() calls that fail with EINTR
@@ -27440,7 +27739,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
/* unlock failed with an error */
lrc = SQLITE_IOERR_UNLOCK;
if( IS_LOCK_ERROR(lrc) ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
rc = lrc;
}
}
@@ -27450,7 +27749,7 @@ static int flockCheckReservedLock(sqlite3_file *id, int *pResOut){
/* someone else might have it reserved */
lrc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
if( IS_LOCK_ERROR(lrc) ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
rc = lrc;
}
}
@@ -27516,7 +27815,7 @@ static int flockLock(sqlite3_file *id, int eFileLock) {
/* didn't get, must be busy */
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_LOCK);
if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
}
} else {
/* got it, set the type and return ok */
@@ -27545,7 +27844,7 @@ static int flockUnlock(sqlite3_file *id, int eFileLock) {
assert( pFile );
OSTRACE(("UNLOCK %d %d was %d pid=%d (flock)\n", pFile->h, eFileLock,
- pFile->eFileLock, getpid()));
+ pFile->eFileLock, osGetpid(0)));
assert( eFileLock<=SHARED_LOCK );
/* no-op if possible */
@@ -27606,7 +27905,7 @@ static int flockClose(sqlite3_file *id) {
** to a non-zero value otherwise *pResOut is set to zero. The return value
** is set to SQLITE_OK unless an I/O error occurs during lock checking.
*/
-static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
+static int semXCheckReservedLock(sqlite3_file *id, int *pResOut) {
int rc = SQLITE_OK;
int reserved = 0;
unixFile *pFile = (unixFile*)id;
@@ -27628,7 +27927,7 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
int tErrno = errno;
if( EAGAIN != tErrno ){
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_CHECKRESERVEDLOCK);
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
} else {
/* someone else has the lock when we are in NO_LOCK */
reserved = (pFile->eFileLock < SHARED_LOCK);
@@ -27673,7 +27972,7 @@ static int semCheckReservedLock(sqlite3_file *id, int *pResOut) {
** This routine will only increase a lock. Use the sqlite3OsUnlock()
** routine to lower a locking level.
*/
-static int semLock(sqlite3_file *id, int eFileLock) {
+static int semXLock(sqlite3_file *id, int eFileLock) {
unixFile *pFile = (unixFile*)id;
sem_t *pSem = pFile->pInode->pSem;
int rc = SQLITE_OK;
@@ -27706,14 +28005,14 @@ static int semLock(sqlite3_file *id, int eFileLock) {
** If the locking level of the file descriptor is already at or below
** the requested locking level, this routine is a no-op.
*/
-static int semUnlock(sqlite3_file *id, int eFileLock) {
+static int semXUnlock(sqlite3_file *id, int eFileLock) {
unixFile *pFile = (unixFile*)id;
sem_t *pSem = pFile->pInode->pSem;
assert( pFile );
assert( pSem );
OSTRACE(("UNLOCK %d %d was %d pid=%d (sem)\n", pFile->h, eFileLock,
- pFile->eFileLock, getpid()));
+ pFile->eFileLock, osGetpid(0)));
assert( eFileLock<=SHARED_LOCK );
/* no-op if possible */
@@ -27732,7 +28031,7 @@ static int semUnlock(sqlite3_file *id, int eFileLock) {
int rc, tErrno = errno;
rc = sqliteErrorFromPosixError(tErrno, SQLITE_IOERR_UNLOCK);
if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
}
return rc;
}
@@ -27743,10 +28042,10 @@ static int semUnlock(sqlite3_file *id, int eFileLock) {
/*
** Close a file.
*/
-static int semClose(sqlite3_file *id) {
+static int semXClose(sqlite3_file *id) {
if( id ){
unixFile *pFile = (unixFile*)id;
- semUnlock(id, NO_LOCK);
+ semXUnlock(id, NO_LOCK);
assert( pFile );
unixEnterMutex();
releaseInodeInfo(pFile);
@@ -27834,7 +28133,7 @@ static int afpSetLock(
setLockFlag ? SQLITE_IOERR_LOCK : SQLITE_IOERR_UNLOCK);
#endif /* SQLITE_IGNORE_AFP_LOCK_ERRORS */
if( IS_LOCK_ERROR(rc) ){
- pFile->lastErrno = tErrno;
+ storeLastErrno(pFile, tErrno);
}
return rc;
} else {
@@ -27927,7 +28226,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
assert( pFile );
OSTRACE(("LOCK %d %s was %s(%s,%d) pid=%d (afp)\n", pFile->h,
azFileLock(eFileLock), azFileLock(pFile->eFileLock),
- azFileLock(pInode->eFileLock), pInode->nShared , getpid()));
+ azFileLock(pInode->eFileLock), pInode->nShared , osGetpid(0)));
/* If there is already a lock of this type or more restrictive on the
** unixFile, do nothing. Don't use the afp_end_lock: exit path, as
@@ -28017,7 +28316,7 @@ static int afpLock(sqlite3_file *id, int eFileLock){
lrc2 = afpSetLock(context->dbPath, pFile, PENDING_BYTE, 1, 0);
if( IS_LOCK_ERROR(lrc1) ) {
- pFile->lastErrno = lrc1Errno;
+ storeLastErrno(pFile, lrc1Errno);
rc = lrc1;
goto afp_end_lock;
} else if( IS_LOCK_ERROR(lrc2) ){
@@ -28113,7 +28412,7 @@ static int afpUnlock(sqlite3_file *id, int eFileLock) {
assert( pFile );
OSTRACE(("UNLOCK %d %d was %d(%d,%d) pid=%d (afp)\n", pFile->h, eFileLock,
pFile->eFileLock, pFile->pInode->eFileLock, pFile->pInode->nShared,
- getpid()));
+ osGetpid(0)));
assert( eFileLock<=SHARED_LOCK );
if( pFile->eFileLock<=eFileLock ){
@@ -28304,9 +28603,9 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
SimulateIOError( newOffset-- );
if( newOffset!=offset ){
if( newOffset == -1 ){
- ((unixFile*)id)->lastErrno = errno;
+ storeLastErrno((unixFile*)id, errno);
}else{
- ((unixFile*)id)->lastErrno = 0;
+ storeLastErrno((unixFile*)id, 0);
}
return -1;
}
@@ -28316,7 +28615,7 @@ static int seekAndRead(unixFile *id, sqlite3_int64 offset, void *pBuf, int cnt){
if( got<0 ){
if( errno==EINTR ){ got = 1; continue; }
prior = 0;
- ((unixFile*)id)->lastErrno = errno;
+ storeLastErrno((unixFile*)id, errno);
break;
}else if( got>0 ){
cnt -= got;
@@ -28381,7 +28680,7 @@ static int unixRead(
/* lastErrno set by seekAndRead */
return SQLITE_IOERR_READ;
}else{
- pFile->lastErrno = 0; /* not a system error */
+ storeLastErrno(pFile, 0); /* not a system error */
/* Unread parts of the buffer must be zero-filled */
memset(&((char*)pBuf)[got], 0, amt-got);
return SQLITE_IOERR_SHORT_READ;
@@ -28410,9 +28709,9 @@ static int seekAndWriteFd(
TIMER_START;
#if defined(USE_PREAD)
- do{ rc = osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
+ do{ rc = (int)osPwrite(fd, pBuf, nBuf, iOff); }while( rc<0 && errno==EINTR );
#elif defined(USE_PREAD64)
- do{ rc = osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
+ do{ rc = (int)osPwrite64(fd, pBuf, nBuf, iOff);}while( rc<0 && errno==EINTR);
#else
do{
i64 iSeek = lseek(fd, iOff, SEEK_SET);
@@ -28522,7 +28821,7 @@ static int unixWrite(
/* lastErrno set by seekAndWrite */
return SQLITE_IOERR_WRITE;
}else{
- pFile->lastErrno = 0; /* not a system error */
+ storeLastErrno(pFile, 0); /* not a system error */
return SQLITE_FULL;
}
}
@@ -28731,7 +29030,7 @@ static int unixSync(sqlite3_file *id, int flags){
rc = full_fsync(pFile->h, isFullsync, isDataOnly);
SimulateIOError( rc=1 );
if( rc ){
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
return unixLogError(SQLITE_IOERR_FSYNC, "full_fsync", pFile->zPath);
}
@@ -28775,7 +29074,7 @@ static int unixTruncate(sqlite3_file *id, i64 nByte){
rc = robust_ftruncate(pFile->h, nByte);
if( rc ){
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
}else{
#ifdef SQLITE_DEBUG
@@ -28815,7 +29114,7 @@ static int unixFileSize(sqlite3_file *id, i64 *pSize){
rc = osFstat(((unixFile*)id)->h, &buf);
SimulateIOError( rc=1 );
if( rc!=0 ){
- ((unixFile*)id)->lastErrno = errno;
+ storeLastErrno((unixFile*)id, errno);
return SQLITE_IOERR_FSTAT;
}
*pSize = buf.st_size;
@@ -28851,7 +29150,9 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
i64 nSize; /* Required file size */
struct stat buf; /* Used to hold return values of fstat() */
- if( osFstat(pFile->h, &buf) ) return SQLITE_IOERR_FSTAT;
+ if( osFstat(pFile->h, &buf) ){
+ return SQLITE_IOERR_FSTAT;
+ }
nSize = ((nByte+pFile->szChunk-1) / pFile->szChunk) * pFile->szChunk;
if( nSize>(i64)buf.st_size ){
@@ -28898,7 +29199,7 @@ static int fcntlSizeHint(unixFile *pFile, i64 nByte){
int rc;
if( pFile->szChunk<=0 ){
if( robust_ftruncate(pFile->h, nByte) ){
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
return unixLogError(SQLITE_IOERR_TRUNCATE, "ftruncate", pFile->zPath);
}
}
@@ -28936,11 +29237,15 @@ static int unixGetTempname(int nBuf, char *zBuf);
static int unixFileControl(sqlite3_file *id, int op, void *pArg){
unixFile *pFile = (unixFile*)id;
switch( op ){
+ case SQLITE_FCNTL_WAL_BLOCK: {
+ /* pFile->ctrlFlags |= UNIXFILE_BLOCK; // Deferred feature */
+ return SQLITE_OK;
+ }
case SQLITE_FCNTL_LOCKSTATE: {
*(int*)pArg = pFile->eFileLock;
return SQLITE_OK;
}
- case SQLITE_LAST_ERRNO: {
+ case SQLITE_FCNTL_LAST_ERRNO: {
*(int*)pArg = pFile->lastErrno;
return SQLITE_OK;
}
@@ -28968,7 +29273,7 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
return SQLITE_OK;
}
case SQLITE_FCNTL_TEMPFILENAME: {
- char *zTFile = sqlite3_malloc( pFile->pVfs->mxPathname );
+ char *zTFile = sqlite3_malloc64( pFile->pVfs->mxPathname );
if( zTFile ){
unixGetTempname(pFile->pVfs->mxPathname, zTFile);
*(char**)pArg = zTFile;
@@ -29009,8 +29314,8 @@ static int unixFileControl(sqlite3_file *id, int op, void *pArg){
}
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
- case SQLITE_SET_LOCKPROXYFILE:
- case SQLITE_GET_LOCKPROXYFILE: {
+ case SQLITE_FCNTL_SET_LOCKPROXYFILE:
+ case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
return proxyFileControl(id,op,pArg);
}
#endif /* SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__) */
@@ -29150,7 +29455,9 @@ static int unixDeviceCharacteristics(sqlite3_file *id){
** Instead, it should be called via macro osGetpagesize().
*/
static int unixGetpagesize(void){
-#if defined(_BSD_SOURCE)
+#if OS_VXWORKS
+ return 1024;
+#elif defined(_BSD_SOURCE)
return getpagesize();
#else
return (int)sysconf(_SC_PAGESIZE);
@@ -29243,15 +29550,17 @@ struct unixShm {
** otherwise.
*/
static int unixShmSystemLock(
- unixShmNode *pShmNode, /* Apply locks to this open shared-memory segment */
+ unixFile *pFile, /* Open connection to the WAL file */
int lockType, /* F_UNLCK, F_RDLCK, or F_WRLCK */
int ofst, /* First byte of the locking range */
int n /* Number of bytes to lock */
){
- struct flock f; /* The posix advisory locking structure */
- int rc = SQLITE_OK; /* Result code form fcntl() */
+ unixShmNode *pShmNode; /* Apply locks to this open shared-memory segment */
+ struct flock f; /* The posix advisory locking structure */
+ int rc = SQLITE_OK; /* Result code form fcntl() */
/* Access to the unixShmNode object is serialized by the caller */
+ pShmNode = pFile->pInode->pShmNode;
assert( sqlite3_mutex_held(pShmNode->mutex) || pShmNode->nRef==0 );
/* Shared locks never span more than one byte */
@@ -29261,6 +29570,7 @@ static int unixShmSystemLock(
assert( n>=1 && n<SQLITE_SHM_NLOCK );
if( pShmNode->h>=0 ){
+ int lkType;
/* Initialize the locking parameters */
memset(&f, 0, sizeof(f));
f.l_type = lockType;
@@ -29268,8 +29578,10 @@ static int unixShmSystemLock(
f.l_start = ofst;
f.l_len = n;
- rc = osFcntl(pShmNode->h, F_SETLK, &f);
+ lkType = (pFile->ctrlFlags & UNIXFILE_BLOCK)!=0 ? F_SETLKW : F_SETLK;
+ rc = osFcntl(pShmNode->h, lkType, &f);
rc = (rc!=(-1)) ? SQLITE_OK : SQLITE_BUSY;
+ pFile->ctrlFlags &= ~UNIXFILE_BLOCK;
}
/* Update the global lock state and do debug tracing */
@@ -29402,7 +29714,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
int nShmFilename; /* Size of the SHM filename in bytes */
/* Allocate space for the new unixShm object. */
- p = sqlite3_malloc( sizeof(*p) );
+ p = sqlite3_malloc64( sizeof(*p) );
if( p==0 ) return SQLITE_NOMEM;
memset(p, 0, sizeof(*p));
assert( pDbFd->pShm==0 );
@@ -29415,6 +29727,9 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
pShmNode = pInode->pShmNode;
if( pShmNode==0 ){
struct stat sStat; /* fstat() info for database file */
+#ifndef SQLITE_SHM_DIRECTORY
+ const char *zBasePath = pDbFd->zPath;
+#endif
/* Call fstat() to figure out the permissions on the database file. If
** a new *-shm file is created, an attempt will be made to create it
@@ -29428,9 +29743,9 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
#ifdef SQLITE_SHM_DIRECTORY
nShmFilename = sizeof(SQLITE_SHM_DIRECTORY) + 31;
#else
- nShmFilename = 6 + (int)strlen(pDbFd->zPath);
+ nShmFilename = 6 + (int)strlen(zBasePath);
#endif
- pShmNode = sqlite3_malloc( sizeof(*pShmNode) + nShmFilename );
+ pShmNode = sqlite3_malloc64( sizeof(*pShmNode) + nShmFilename );
if( pShmNode==0 ){
rc = SQLITE_NOMEM;
goto shm_open_err;
@@ -29442,7 +29757,7 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
SQLITE_SHM_DIRECTORY "/sqlite-shm-%x-%x",
(u32)sStat.st_ino, (u32)sStat.st_dev);
#else
- sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", pDbFd->zPath);
+ sqlite3_snprintf(nShmFilename, zShmFilename, "%s-shm", zBasePath);
sqlite3FileSuffix3(pDbFd->zPath, zShmFilename);
#endif
pShmNode->h = -1;
@@ -29476,13 +29791,13 @@ static int unixOpenSharedMemory(unixFile *pDbFd){
** If not, truncate the file to zero length.
*/
rc = SQLITE_OK;
- if( unixShmSystemLock(pShmNode, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
+ if( unixShmSystemLock(pDbFd, F_WRLCK, UNIX_SHM_DMS, 1)==SQLITE_OK ){
if( robust_ftruncate(pShmNode->h, 0) ){
rc = unixLogError(SQLITE_IOERR_SHMOPEN, "ftruncate", zShmFilename);
}
}
if( rc==SQLITE_OK ){
- rc = unixShmSystemLock(pShmNode, F_RDLCK, UNIX_SHM_DMS, 1);
+ rc = unixShmSystemLock(pDbFd, F_RDLCK, UNIX_SHM_DMS, 1);
}
if( rc ) goto shm_open_err;
}
@@ -29640,7 +29955,7 @@ static int unixShmMap(
goto shmpage_out;
}
}else{
- pMem = sqlite3_malloc(szRegion);
+ pMem = sqlite3_malloc64(szRegion);
if( pMem==0 ){
rc = SQLITE_NOMEM;
goto shmpage_out;
@@ -29714,7 +30029,7 @@ static int unixShmLock(
/* Unlock the system-level locks */
if( (mask & allMask)==0 ){
- rc = unixShmSystemLock(pShmNode, F_UNLCK, ofst+UNIX_SHM_BASE, n);
+ rc = unixShmSystemLock(pDbFd, F_UNLCK, ofst+UNIX_SHM_BASE, n);
}else{
rc = SQLITE_OK;
}
@@ -29742,7 +30057,7 @@ static int unixShmLock(
/* Get shared locks at the system level, if necessary */
if( rc==SQLITE_OK ){
if( (allShared & mask)==0 ){
- rc = unixShmSystemLock(pShmNode, F_RDLCK, ofst+UNIX_SHM_BASE, n);
+ rc = unixShmSystemLock(pDbFd, F_RDLCK, ofst+UNIX_SHM_BASE, n);
}else{
rc = SQLITE_OK;
}
@@ -29767,7 +30082,7 @@ static int unixShmLock(
** also mark the local connection as being locked.
*/
if( rc==SQLITE_OK ){
- rc = unixShmSystemLock(pShmNode, F_WRLCK, ofst+UNIX_SHM_BASE, n);
+ rc = unixShmSystemLock(pDbFd, F_WRLCK, ofst+UNIX_SHM_BASE, n);
if( rc==SQLITE_OK ){
assert( (p->sharedMask & mask)==0 );
p->exclMask |= mask;
@@ -29776,7 +30091,7 @@ static int unixShmLock(
}
sqlite3_mutex_leave(pShmNode->mutex);
OSTRACE(("SHM-LOCK shmid-%d, pid-%d got %03x,%03x\n",
- p->id, getpid(), p->sharedMask, p->exclMask));
+ p->id, osGetpid(0), p->sharedMask, p->exclMask));
return rc;
}
@@ -29835,7 +30150,9 @@ static int unixShmUnmap(
assert( pShmNode->nRef>0 );
pShmNode->nRef--;
if( pShmNode->nRef==0 ){
- if( deleteFlag && pShmNode->h>=0 ) osUnlink(pShmNode->zFilename);
+ if( deleteFlag && pShmNode->h>=0 ){
+ osUnlink(pShmNode->zFilename);
+ }
unixShmPurge(pDbFd);
}
unixLeaveMutex();
@@ -30112,7 +30429,7 @@ static int unixUnfetch(sqlite3_file *fd, i64 iOff, void *p){
** * An I/O method finder function called FINDER that returns a pointer
** to the METHOD object in the previous bullet.
*/
-#define IOMETHODS(FINDER, METHOD, VERSION, CLOSE, LOCK, UNLOCK, CKLOCK, SHMMAP) \
+#define IOMETHODS(FINDER,METHOD,VERSION,CLOSE,LOCK,UNLOCK,CKLOCK,SHMMAP) \
static const sqlite3_io_methods METHOD = { \
VERSION, /* iVersion */ \
CLOSE, /* xClose */ \
@@ -30177,7 +30494,7 @@ IOMETHODS(
0 /* xShmMap method */
)
-#if SQLITE_ENABLE_LOCKING_STYLE && !OS_VXWORKS
+#if SQLITE_ENABLE_LOCKING_STYLE
IOMETHODS(
flockIoFinder, /* Finder function name */
flockIoMethods, /* sqlite3_io_methods object name */
@@ -30195,10 +30512,10 @@ IOMETHODS(
semIoFinder, /* Finder function name */
semIoMethods, /* sqlite3_io_methods object name */
1, /* shared memory is disabled */
- semClose, /* xClose method */
- semLock, /* xLock method */
- semUnlock, /* xUnlock method */
- semCheckReservedLock, /* xCheckReservedLock method */
+ semXClose, /* xClose method */
+ semXLock, /* xLock method */
+ semXUnlock, /* xUnlock method */
+ semXCheckReservedLock, /* xCheckReservedLock method */
0 /* xShmMap method */
)
#endif
@@ -30322,15 +30639,13 @@ static const sqlite3_io_methods
#endif /* defined(__APPLE__) && SQLITE_ENABLE_LOCKING_STYLE */
-#if OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE
-/*
-** This "finder" function attempts to determine the best locking strategy
-** for the database file "filePath". It then returns the sqlite3_io_methods
-** object that implements that strategy.
-**
-** This is for VXWorks only.
+#if OS_VXWORKS
+/*
+** This "finder" function for VxWorks checks to see if posix advisory
+** locking works. If it does, then that is what is used. If it does not
+** work, then fallback to named semaphore locking.
*/
-static const sqlite3_io_methods *autolockIoFinderImpl(
+static const sqlite3_io_methods *vxworksIoFinderImpl(
const char *filePath, /* name of the database file */
unixFile *pNew /* the open file object */
){
@@ -30356,9 +30671,9 @@ static const sqlite3_io_methods *autolockIoFinderImpl(
}
}
static const sqlite3_io_methods
- *(*const autolockIoFinder)(const char*,unixFile*) = autolockIoFinderImpl;
+ *(*const vxworksIoFinder)(const char*,unixFile*) = vxworksIoFinderImpl;
-#endif /* OS_VXWORKS && SQLITE_ENABLE_LOCKING_STYLE */
+#endif /* OS_VXWORKS */
/*
** An abstract type for a pointer to an IO method finder function:
@@ -30477,7 +30792,7 @@ static int fillInUnixFile(
** the afpLockingContext.
*/
afpLockingContext *pCtx;
- pNew->lockingContext = pCtx = sqlite3_malloc( sizeof(*pCtx) );
+ pNew->lockingContext = pCtx = sqlite3_malloc64( sizeof(*pCtx) );
if( pCtx==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -30507,7 +30822,7 @@ static int fillInUnixFile(
int nFilename;
assert( zFilename!=0 );
nFilename = (int)strlen(zFilename) + 6;
- zLockFile = (char *)sqlite3_malloc(nFilename);
+ zLockFile = (char *)sqlite3_malloc64(nFilename);
if( zLockFile==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -30540,7 +30855,7 @@ static int fillInUnixFile(
}
#endif
- pNew->lastErrno = 0;
+ storeLastErrno(pNew, 0);
#if OS_VXWORKS
if( rc!=SQLITE_OK ){
if( h>=0 ) robust_close(pNew, h, __LINE__);
@@ -30871,8 +31186,8 @@ static int unixOpen(
** the same instant might all reset the PRNG. But multiple resets
** are harmless.
*/
- if( randomnessPid!=getpid() ){
- randomnessPid = getpid();
+ if( randomnessPid!=osGetpid(0) ){
+ randomnessPid = osGetpid(0);
sqlite3_randomness(0,0);
}
@@ -30884,7 +31199,7 @@ static int unixOpen(
if( pUnused ){
fd = pUnused->fd;
}else{
- pUnused = sqlite3_malloc(sizeof(*pUnused));
+ pUnused = sqlite3_malloc64(sizeof(*pUnused));
if( !pUnused ){
return SQLITE_NOMEM;
}
@@ -30988,13 +31303,16 @@ static int unixOpen(
#if defined(__APPLE__) || SQLITE_ENABLE_LOCKING_STYLE
if( fstatfs(fd, &fsInfo) == -1 ){
- ((unixFile*)pFile)->lastErrno = errno;
+ storeLastErrno(p, errno);
robust_close(p, fd, __LINE__);
return SQLITE_IOERR_ACCESS;
}
if (0 == strncmp("msdos", fsInfo.f_fstypename, 5)) {
((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
}
+ if (0 == strncmp("exfat", fsInfo.f_fstypename, 5)) {
+ ((unixFile*)pFile)->fsFlags |= SQLITE_FSFLAGS_IS_MSDOS;
+ }
#endif
/* Set up appropriate ctrlFlags */
@@ -31017,19 +31335,6 @@ static int unixOpen(
if( envforce!=NULL ){
useProxy = atoi(envforce)>0;
}else{
- if( statfs(zPath, &fsInfo) == -1 ){
- /* In theory, the close(fd) call is sub-optimal. If the file opened
- ** with fd is a database file, and there are other connections open
- ** on that file that are currently holding advisory locks on it,
- ** then the call to close() will cancel those locks. In practice,
- ** we're assuming that statfs() doesn't fail very often. At least
- ** not while other file descriptors opened by the same process on
- ** the same file are working. */
- p->lastErrno = errno;
- robust_close(p, fd, __LINE__);
- rc = SQLITE_IOERR_ACCESS;
- goto open_finished;
- }
useProxy = !(fsInfo.f_flags&MNT_LOCAL);
}
if( useProxy ){
@@ -31273,8 +31578,8 @@ static int unixRandomness(sqlite3_vfs *NotUsed, int nBuf, char *zBuf){
** tests repeatable.
*/
memset(zBuf, 0, nBuf);
- randomnessPid = getpid();
-#if !defined(SQLITE_TEST)
+ randomnessPid = osGetpid(0);
+#if !defined(SQLITE_TEST) && !defined(SQLITE_OMIT_RANDOMNESS)
{
int fd, got;
fd = robust_open("/dev/urandom", O_RDONLY, 0);
@@ -31455,9 +31760,10 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
**
** C APIs
**
-** sqlite3_file_control(db, dbname, SQLITE_SET_LOCKPROXYFILE,
+** sqlite3_file_control(db, dbname, SQLITE_FCNTL_SET_LOCKPROXYFILE,
** <proxy_path> | ":auto:");
-** sqlite3_file_control(db, dbname, SQLITE_GET_LOCKPROXYFILE, &<proxy_path>);
+** sqlite3_file_control(db, dbname, SQLITE_FCNTL_GET_LOCKPROXYFILE,
+** &<proxy_path>);
**
**
** SQL pragmas
@@ -31550,7 +31856,7 @@ static int unixGetLastError(sqlite3_vfs *NotUsed, int NotUsed2, char *NotUsed3){
** setting the environment variable SQLITE_FORCE_PROXY_LOCKING to 1 will
** force proxy locking to be used for every database file opened, and 0
** will force automatic proxy locking to be disabled for all database
-** files (explicitly calling the SQLITE_SET_LOCKPROXYFILE pragma or
+** files (explicitly calling the SQLITE_FCNTL_SET_LOCKPROXYFILE pragma or
** sqlite_file_control API is not affected by SQLITE_FORCE_PROXY_LOCKING).
*/
@@ -31571,6 +31877,7 @@ struct proxyLockingContext {
char *lockProxyPath; /* Name of the proxy lock file */
char *dbPath; /* Name of the open file */
int conchHeld; /* 1 if the conch is held, -1 if lockless */
+ int nFails; /* Number of conch taking failures */
void *oldLockingContext; /* Original lockingcontext to restore on close */
sqlite3_io_methods const *pOldMethod; /* Original I/O methods for close */
};
@@ -31592,7 +31899,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
{
if( !confstr(_CS_DARWIN_USER_TEMP_DIR, lPath, maxLen) ){
OSTRACE(("GETLOCKPATH failed %s errno=%d pid=%d\n",
- lPath, errno, getpid()));
+ lPath, errno, osGetpid(0)));
return SQLITE_IOERR_LOCK;
}
len = strlcat(lPath, "sqliteplocks", maxLen);
@@ -31614,7 +31921,7 @@ static int proxyGetLockPath(const char *dbPath, char *lPath, size_t maxLen){
}
lPath[i+len]='\0';
strlcat(lPath, ":auto:", maxLen);
- OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, getpid()));
+ OSTRACE(("GETLOCKPATH proxy lock path=%s pid=%d\n", lPath, osGetpid(0)));
return SQLITE_OK;
}
@@ -31641,7 +31948,7 @@ static int proxyCreateLockPath(const char *lockPath){
if( err!=EEXIST ) {
OSTRACE(("CREATELOCKPATH FAILED creating %s, "
"'%s' proxy lock path=%s pid=%d\n",
- buf, strerror(err), lockPath, getpid()));
+ buf, strerror(err), lockPath, osGetpid(0)));
return err;
}
}
@@ -31650,7 +31957,7 @@ static int proxyCreateLockPath(const char *lockPath){
}
buf[i] = lockPath[i];
}
- OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, getpid()));
+ OSTRACE(("CREATELOCKPATH proxy lock path=%s pid=%d\n", lockPath, osGetpid(0)));
return 0;
}
@@ -31684,7 +31991,7 @@ static int proxyCreateUnixFile(
if( pUnused ){
fd = pUnused->fd;
}else{
- pUnused = sqlite3_malloc(sizeof(*pUnused));
+ pUnused = sqlite3_malloc64(sizeof(*pUnused));
if( !pUnused ){
return SQLITE_NOMEM;
}
@@ -31717,7 +32024,7 @@ static int proxyCreateUnixFile(
}
}
- pNew = (unixFile *)sqlite3_malloc(sizeof(*pNew));
+ pNew = (unixFile *)sqlite3_malloc64(sizeof(*pNew));
if( pNew==NULL ){
rc = SQLITE_NOMEM;
goto end_create_proxy;
@@ -31750,8 +32057,10 @@ SQLITE_API int sqlite3_hostid_num = 0;
#define PROXY_HOSTIDLEN 16 /* conch file host id length */
+#ifdef HAVE_GETHOSTUUID
/* Not always defined in the headers as it ought to be */
extern int gethostuuid(uuid_t id, const struct timespec *wait);
+#endif
/* get the host ID via gethostuuid(), pHostID must point to PROXY_HOSTIDLEN
** bytes of writable memory.
@@ -31759,10 +32068,9 @@ extern int gethostuuid(uuid_t id, const struct timespec *wait);
static int proxyGetHostID(unsigned char *pHostID, int *pError){
assert(PROXY_HOSTIDLEN == sizeof(uuid_t));
memset(pHostID, 0, PROXY_HOSTIDLEN);
-#if defined(__MAX_OS_X_VERSION_MIN_REQUIRED)\
- && __MAC_OS_X_VERSION_MIN_REQUIRED<1050
+#ifdef HAVE_GETHOSTUUID
{
- static const struct timespec timeout = {1, 0}; /* 1 sec timeout */
+ struct timespec timeout = {1, 0}; /* 1 sec timeout */
if( gethostuuid(pHostID, &timeout) ){
int err = errno;
if( pError ){
@@ -31877,7 +32185,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
*/
struct stat buf;
if( osFstat(conchFile->h, &buf) ){
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
return SQLITE_IOERR_LOCK;
}
@@ -31897,7 +32205,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
char tBuf[PROXY_MAXCONCHLEN];
int len = osPread(conchFile->h, tBuf, PROXY_MAXCONCHLEN, 0);
if( len<0 ){
- pFile->lastErrno = errno;
+ storeLastErrno(pFile, errno);
return SQLITE_IOERR_LOCK;
}
if( len>PROXY_PATHINDEX && tBuf[0]==(char)PROXY_CONCHVERSION){
@@ -31917,7 +32225,7 @@ static int proxyConchLock(unixFile *pFile, uuid_t myHostID, int lockType){
if( 0==proxyBreakConchLock(pFile, myHostID) ){
rc = SQLITE_OK;
if( lockType==EXCLUSIVE_LOCK ){
- rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
+ rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, SHARED_LOCK);
}
if( !rc ){
rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, lockType);
@@ -31955,11 +32263,12 @@ static int proxyTakeConch(unixFile *pFile){
int forceNewLockPath = 0;
OSTRACE(("TAKECONCH %d for %s pid=%d\n", conchFile->h,
- (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"), getpid()));
+ (pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
+ osGetpid(0)));
rc = proxyGetHostID(myHostID, &pError);
if( (rc&0xff)==SQLITE_IOERR ){
- pFile->lastErrno = pError;
+ storeLastErrno(pFile, pError);
goto end_takeconch;
}
rc = proxyConchLock(pFile, myHostID, SHARED_LOCK);
@@ -31970,7 +32279,7 @@ static int proxyTakeConch(unixFile *pFile){
readLen = seekAndRead((unixFile*)conchFile, 0, readBuf, PROXY_MAXCONCHLEN);
if( readLen<0 ){
/* I/O error: lastErrno set by seekAndRead */
- pFile->lastErrno = conchFile->lastErrno;
+ storeLastErrno(pFile, conchFile->lastErrno);
rc = SQLITE_IOERR_READ;
goto end_takeconch;
}else if( readLen<=(PROXY_HEADERLEN+PROXY_HOSTIDLEN) ||
@@ -32043,7 +32352,7 @@ static int proxyTakeConch(unixFile *pFile){
rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
}
}else{
- rc = conchFile->pMethod->xLock((sqlite3_file*)conchFile, EXCLUSIVE_LOCK);
+ rc = proxyConchLock(pFile, myHostID, EXCLUSIVE_LOCK);
}
if( rc==SQLITE_OK ){
char writeBuffer[PROXY_MAXCONCHLEN];
@@ -32052,7 +32361,8 @@ static int proxyTakeConch(unixFile *pFile){
writeBuffer[0] = (char)PROXY_CONCHVERSION;
memcpy(&writeBuffer[PROXY_HEADERLEN], myHostID, PROXY_HOSTIDLEN);
if( pCtx->lockProxyPath!=NULL ){
- strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath, MAXPATHLEN);
+ strlcpy(&writeBuffer[PROXY_PATHINDEX], pCtx->lockProxyPath,
+ MAXPATHLEN);
}else{
strlcpy(&writeBuffer[PROXY_PATHINDEX], tempLockPath, MAXPATHLEN);
}
@@ -32164,7 +32474,7 @@ static int proxyReleaseConch(unixFile *pFile){
conchFile = pCtx->conchFile;
OSTRACE(("RELEASECONCH %d for %s pid=%d\n", conchFile->h,
(pCtx->lockProxyPath ? pCtx->lockProxyPath : ":auto:"),
- getpid()));
+ osGetpid(0)));
if( pCtx->conchHeld>0 ){
rc = conchFile->pMethod->xUnlock((sqlite3_file*)conchFile, NO_LOCK);
}
@@ -32176,7 +32486,7 @@ static int proxyReleaseConch(unixFile *pFile){
/*
** Given the name of a database file, compute the name of its conch file.
-** Store the conch filename in memory obtained from sqlite3_malloc().
+** Store the conch filename in memory obtained from sqlite3_malloc64().
** Make *pConchPath point to the new name. Return SQLITE_OK on success
** or SQLITE_NOMEM if unable to obtain memory.
**
@@ -32192,7 +32502,7 @@ static int proxyCreateConchPathname(char *dbPath, char **pConchPath){
/* Allocate space for the conch filename and initialize the name to
** the name of the original database file. */
- *pConchPath = conchPath = (char *)sqlite3_malloc(len + 8);
+ *pConchPath = conchPath = (char *)sqlite3_malloc64(len + 8);
if( conchPath==0 ){
return SQLITE_NOMEM;
}
@@ -32264,7 +32574,8 @@ static int proxyGetDbPathForUnixFile(unixFile *pFile, char *dbPath){
/* afp style keeps a reference to the db path in the filePath field
** of the struct */
assert( (int)strlen((char*)pFile->lockingContext)<=MAXPATHLEN );
- strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath, MAXPATHLEN);
+ strlcpy(dbPath, ((afpLockingContext *)pFile->lockingContext)->dbPath,
+ MAXPATHLEN);
} else
#endif
if( pFile->pMethod == &dotlockIoMethods ){
@@ -32305,9 +32616,9 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
}
OSTRACE(("TRANSPROXY %d for %s pid=%d\n", pFile->h,
- (lockPath ? lockPath : ":auto:"), getpid()));
+ (lockPath ? lockPath : ":auto:"), osGetpid(0)));
- pCtx = sqlite3_malloc( sizeof(*pCtx) );
+ pCtx = sqlite3_malloc64( sizeof(*pCtx) );
if( pCtx==0 ){
return SQLITE_NOMEM;
}
@@ -32377,7 +32688,7 @@ static int proxyTransformUnixFile(unixFile *pFile, const char *path) {
*/
static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
switch( op ){
- case SQLITE_GET_LOCKPROXYFILE: {
+ case SQLITE_FCNTL_GET_LOCKPROXYFILE: {
unixFile *pFile = (unixFile*)id;
if( pFile->pMethod == &proxyIoMethods ){
proxyLockingContext *pCtx = (proxyLockingContext*)pFile->lockingContext;
@@ -32392,13 +32703,16 @@ static int proxyFileControl(sqlite3_file *id, int op, void *pArg){
}
return SQLITE_OK;
}
- case SQLITE_SET_LOCKPROXYFILE: {
+ case SQLITE_FCNTL_SET_LOCKPROXYFILE: {
unixFile *pFile = (unixFile*)id;
int rc = SQLITE_OK;
int isProxyStyle = (pFile->pMethod == &proxyIoMethods);
if( pArg==NULL || (const char *)pArg==0 ){
if( isProxyStyle ){
- /* turn off proxy locking - not supported */
+ /* turn off proxy locking - not supported. If support is added for
+ ** switching proxy locking mode off then it will need to fail if
+ ** the journal mode is WAL mode.
+ */
rc = SQLITE_ERROR /*SQLITE_PROTOCOL? SQLITE_MISUSE?*/;
}else{
/* turn off proxy locking - already off - NOOP */
@@ -32589,7 +32903,7 @@ static int proxyClose(sqlite3_file *id) {
** necessarily been initialized when this routine is called, and so they
** should not be used.
*/
-SQLITE_API int sqlite3_os_init(void){
+SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){
/*
** The following macro defines an initializer for an sqlite3_vfs object.
** The name of the VFS is NAME. The pAppData is a pointer to a pointer
@@ -32643,8 +32957,10 @@ SQLITE_API int sqlite3_os_init(void){
** array cannot be const.
*/
static sqlite3_vfs aVfs[] = {
-#if SQLITE_ENABLE_LOCKING_STYLE && (OS_VXWORKS || defined(__APPLE__))
+#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
UNIXVFS("unix", autolockIoFinder ),
+#elif OS_VXWORKS
+ UNIXVFS("unix", vxworksIoFinder ),
#else
UNIXVFS("unix", posixIoFinder ),
#endif
@@ -32654,11 +32970,11 @@ SQLITE_API int sqlite3_os_init(void){
#if OS_VXWORKS
UNIXVFS("unix-namedsem", semIoFinder ),
#endif
-#if SQLITE_ENABLE_LOCKING_STYLE
+#if SQLITE_ENABLE_LOCKING_STYLE || OS_VXWORKS
UNIXVFS("unix-posix", posixIoFinder ),
-#if !OS_VXWORKS
- UNIXVFS("unix-flock", flockIoFinder ),
#endif
+#if SQLITE_ENABLE_LOCKING_STYLE
+ UNIXVFS("unix-flock", flockIoFinder ),
#endif
#if SQLITE_ENABLE_LOCKING_STYLE && defined(__APPLE__)
UNIXVFS("unix-afp", afpIoFinder ),
@@ -32686,7 +33002,7 @@ SQLITE_API int sqlite3_os_init(void){
** to release dynamically allocated objects. But not on unix.
** This routine is a no-op for unix.
*/
-SQLITE_API int sqlite3_os_end(void){
+SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){
return SQLITE_OK;
}
@@ -32746,16 +33062,6 @@ SQLITE_API int sqlite3_os_end(void){
# error "The MEMORY_DEBUG macro is obsolete. Use SQLITE_DEBUG instead."
#endif
-#if defined(SQLITE_TEST) && defined(SQLITE_DEBUG)
-# ifndef SQLITE_DEBUG_OS_TRACE
-# define SQLITE_DEBUG_OS_TRACE 0
-# endif
- int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
-# define OSTRACE(X) if( sqlite3OSTrace ) sqlite3DebugPrintf X
-#else
-# define OSTRACE(X)
-#endif
-
/*
** Macros for performance tracing. Normally turned off. Only works
** on i486 hardware.
@@ -33099,8 +33405,10 @@ WINBASEAPI LPVOID WINAPI MapViewOfFile(HANDLE, DWORD, DWORD, DWORD, SIZE_T);
#endif /* SQLITE_OS_WINRT */
/*
-** This file mapping API is common to both Win32 and WinRT.
+** These file mapping APIs are common to both Win32 and WinRT.
*/
+
+WINBASEAPI BOOL WINAPI FlushViewOfFile(LPCVOID, SIZE_T);
WINBASEAPI BOOL WINAPI UnmapViewOfFile(LPCVOID);
#endif /* SQLITE_WIN32_FILEMAPPING_API */
@@ -33968,6 +34276,32 @@ static struct win_syscall {
SQLITE_WIN32_VOLATILE*, LONG,LONG))aSyscall[76].pCurrent)
#endif /* defined(InterlockedCompareExchange) */
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
+ { "UuidCreate", (SYSCALL)UuidCreate, 0 },
+#else
+ { "UuidCreate", (SYSCALL)0, 0 },
+#endif
+
+#define osUuidCreate ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[77].pCurrent)
+
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
+ { "UuidCreateSequential", (SYSCALL)UuidCreateSequential, 0 },
+#else
+ { "UuidCreateSequential", (SYSCALL)0, 0 },
+#endif
+
+#define osUuidCreateSequential \
+ ((RPC_STATUS(RPC_ENTRY*)(UUID*))aSyscall[78].pCurrent)
+
+#if !defined(SQLITE_NO_SYNC) && SQLITE_MAX_MMAP_SIZE>0
+ { "FlushViewOfFile", (SYSCALL)FlushViewOfFile, 0 },
+#else
+ { "FlushViewOfFile", (SYSCALL)0, 0 },
+#endif
+
+#define osFlushViewOfFile \
+ ((BOOL(WINAPI*)(LPCVOID,SIZE_T))aSyscall[79].pCurrent)
+
}; /* End of the overrideable system calls */
/*
@@ -34061,7 +34395,7 @@ static const char *winNextSystemCall(sqlite3_vfs *p, const char *zName){
** "pnLargest" argument, if non-zero, will be used to return the size of the
** largest committed free block in the heap, in bytes.
*/
-SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){
+SQLITE_API int SQLITE_STDCALL sqlite3_win32_compact_heap(LPUINT pnLargest){
int rc = SQLITE_OK;
UINT nLargest = 0;
HANDLE hHeap;
@@ -34101,7 +34435,7 @@ SQLITE_API int sqlite3_win32_compact_heap(LPUINT pnLargest){
** the sqlite3_memory_used() function does not return zero, SQLITE_BUSY will
** be returned and no changes will be made to the Win32 native heap.
*/
-SQLITE_API int sqlite3_win32_reset_heap(){
+SQLITE_API int SQLITE_STDCALL sqlite3_win32_reset_heap(){
int rc;
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
MUTEX_LOGIC( sqlite3_mutex *pMem; ) /* The memsys static mutex */
@@ -34146,7 +34480,7 @@ SQLITE_API int sqlite3_win32_reset_heap(){
** (if available).
*/
-SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
+SQLITE_API void SQLITE_STDCALL sqlite3_win32_write_debug(const char *zBuf, int nBuf){
char zDbgBuf[SQLITE_WIN32_DBG_BUF_SIZE];
int nMin = MIN(nBuf, (SQLITE_WIN32_DBG_BUF_SIZE - 1)); /* may be negative. */
if( nMin<-1 ) nMin = -1; /* all negative values become -1. */
@@ -34186,7 +34520,7 @@ SQLITE_API void sqlite3_win32_write_debug(const char *zBuf, int nBuf){
static HANDLE sleepObj = NULL;
#endif
-SQLITE_API void sqlite3_win32_sleep(DWORD milliseconds){
+SQLITE_API void SQLITE_STDCALL sqlite3_win32_sleep(DWORD milliseconds){
#if SQLITE_OS_WINRT
if ( sleepObj==NULL ){
sleepObj = osCreateEventExW(NULL, NULL, CREATE_EVENT_MANUAL_RESET,
@@ -34235,7 +34569,7 @@ SQLITE_PRIVATE DWORD sqlite3Win32Wait(HANDLE hObject){
** This function determines if the machine is running a version of Windows
** based on the NT kernel.
*/
-SQLITE_API int sqlite3_win32_is_nt(void){
+SQLITE_API int SQLITE_STDCALL sqlite3_win32_is_nt(void){
#if SQLITE_OS_WINRT
/*
** NOTE: The WinRT sub-platform is always assumed to be based on the NT
@@ -34589,7 +34923,7 @@ static char *winUnicodeToMbcs(LPCWSTR zWideFilename){
** Convert multibyte character string to UTF-8. Space to hold the
** returned string is obtained from sqlite3_malloc().
*/
-SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
+SQLITE_API char *SQLITE_STDCALL sqlite3_win32_mbcs_to_utf8(const char *zFilename){
char *zFilenameUtf8;
LPWSTR zTmpWide;
@@ -34606,7 +34940,7 @@ SQLITE_API char *sqlite3_win32_mbcs_to_utf8(const char *zFilename){
** Convert UTF-8 to multibyte character string. Space to hold the
** returned string is obtained from sqlite3_malloc().
*/
-SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
+SQLITE_API char *SQLITE_STDCALL sqlite3_win32_utf8_to_mbcs(const char *zFilename){
char *zFilenameMbcs;
LPWSTR zTmpWide;
@@ -34626,7 +34960,7 @@ SQLITE_API char *sqlite3_win32_utf8_to_mbcs(const char *zFilename){
** argument is the name of the directory to use. The return value will be
** SQLITE_OK if successful.
*/
-SQLITE_API int sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
+SQLITE_API int SQLITE_STDCALL sqlite3_win32_set_directory(DWORD type, LPCWSTR zValue){
char **ppDirectory = 0;
#ifndef SQLITE_OMIT_AUTOINIT
int rc = sqlite3_initialize();
@@ -34851,11 +35185,11 @@ static int winRetryIoerr(int *pnRetry, DWORD *pError){
/*
** Log a I/O error retry episode.
*/
-static void winLogIoerr(int nRetry){
+static void winLogIoerr(int nRetry, int lineno){
if( nRetry ){
- sqlite3_log(SQLITE_IOERR,
- "delayed %dms for lock/sharing conflict",
- winIoerrRetryDelay*nRetry*(nRetry+1)/2
+ sqlite3_log(SQLITE_NOTICE,
+ "delayed %dms for lock/sharing conflict at line %d",
+ winIoerrRetryDelay*nRetry*(nRetry+1)/2, lineno
);
}
}
@@ -35335,7 +35669,8 @@ static int winClose(sqlite3_file *id){
assert( pFile->pShm==0 );
#endif
assert( pFile->h!=NULL && pFile->h!=INVALID_HANDLE_VALUE );
- OSTRACE(("CLOSE file=%p\n", pFile->h));
+ OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
#if SQLITE_MAX_MMAP_SIZE>0
winUnmapfile(pFile);
@@ -35364,7 +35699,8 @@ static int winClose(sqlite3_file *id){
pFile->h = NULL;
}
OpenCounter(-1);
- OSTRACE(("CLOSE file=%p, rc=%s\n", pFile->h, rc ? "ok" : "failed"));
+ OSTRACE(("CLOSE pid=%lu, pFile=%p, file=%p, rc=%s\n",
+ osGetCurrentProcessId(), pFile, pFile->h, rc ? "ok" : "failed"));
return rc ? SQLITE_OK
: winLogError(SQLITE_IOERR_CLOSE, osGetLastError(),
"winClose", pFile->zPath);
@@ -35392,7 +35728,8 @@ static int winRead(
assert( amt>0 );
assert( offset>=0 );
SimulateIOError(return SQLITE_IOERR_READ);
- OSTRACE(("READ file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
+ OSTRACE(("READ pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
+ "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
pFile->h, pBuf, amt, offset, pFile->locktype));
#if SQLITE_MAX_MMAP_SIZE>0
@@ -35401,7 +35738,8 @@ static int winRead(
if( offset<pFile->mmapSize ){
if( offset+amt <= pFile->mmapSize ){
memcpy(pBuf, &((u8 *)(pFile->pMapRegion))[offset], amt);
- OSTRACE(("READ-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
+ OSTRACE(("READ-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return SQLITE_OK;
}else{
int nCopy = (int)(pFile->mmapSize - offset);
@@ -35415,7 +35753,8 @@ static int winRead(
#if SQLITE_OS_WINCE || defined(SQLITE_WIN32_NO_OVERLAPPED)
if( winSeekFile(pFile, offset) ){
- OSTRACE(("READ file=%p, rc=SQLITE_FULL\n", pFile->h));
+ OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return SQLITE_FULL;
}
while( !osReadFile(pFile->h, pBuf, amt, &nRead, 0) ){
@@ -35429,19 +35768,22 @@ static int winRead(
DWORD lastErrno;
if( winRetryIoerr(&nRetry, &lastErrno) ) continue;
pFile->lastErrno = lastErrno;
- OSTRACE(("READ file=%p, rc=SQLITE_IOERR_READ\n", pFile->h));
+ OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_READ\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return winLogError(SQLITE_IOERR_READ, pFile->lastErrno,
"winRead", pFile->zPath);
}
- winLogIoerr(nRetry);
+ winLogIoerr(nRetry, __LINE__);
if( nRead<(DWORD)amt ){
/* Unread parts of the buffer must be zero-filled */
memset(&((char*)pBuf)[nRead], 0, amt-nRead);
- OSTRACE(("READ file=%p, rc=SQLITE_IOERR_SHORT_READ\n", pFile->h));
+ OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_SHORT_READ\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return SQLITE_IOERR_SHORT_READ;
}
- OSTRACE(("READ file=%p, rc=SQLITE_OK\n", pFile->h));
+ OSTRACE(("READ pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return SQLITE_OK;
}
@@ -35464,7 +35806,8 @@ static int winWrite(
SimulateIOError(return SQLITE_IOERR_WRITE);
SimulateDiskfullError(return SQLITE_FULL);
- OSTRACE(("WRITE file=%p, buffer=%p, amount=%d, offset=%lld, lock=%d\n",
+ OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, buffer=%p, amount=%d, "
+ "offset=%lld, lock=%d\n", osGetCurrentProcessId(), pFile,
pFile->h, pBuf, amt, offset, pFile->locktype));
#if SQLITE_MAX_MMAP_SIZE>0
@@ -35473,7 +35816,8 @@ static int winWrite(
if( offset<pFile->mmapSize ){
if( offset+amt <= pFile->mmapSize ){
memcpy(&((u8 *)(pFile->pMapRegion))[offset], pBuf, amt);
- OSTRACE(("WRITE-MMAP file=%p, rc=SQLITE_OK\n", pFile->h));
+ OSTRACE(("WRITE-MMAP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return SQLITE_OK;
}else{
int nCopy = (int)(pFile->mmapSize - offset);
@@ -35536,17 +35880,20 @@ static int winWrite(
if( rc ){
if( ( pFile->lastErrno==ERROR_HANDLE_DISK_FULL )
|| ( pFile->lastErrno==ERROR_DISK_FULL )){
- OSTRACE(("WRITE file=%p, rc=SQLITE_FULL\n", pFile->h));
+ OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_FULL\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return winLogError(SQLITE_FULL, pFile->lastErrno,
"winWrite1", pFile->zPath);
}
- OSTRACE(("WRITE file=%p, rc=SQLITE_IOERR_WRITE\n", pFile->h));
+ OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_WRITE\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return winLogError(SQLITE_IOERR_WRITE, pFile->lastErrno,
"winWrite2", pFile->zPath);
}else{
- winLogIoerr(nRetry);
+ winLogIoerr(nRetry, __LINE__);
}
- OSTRACE(("WRITE file=%p, rc=SQLITE_OK\n", pFile->h));
+ OSTRACE(("WRITE pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return SQLITE_OK;
}
@@ -35560,8 +35907,8 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
assert( pFile );
SimulateIOError(return SQLITE_IOERR_TRUNCATE);
- OSTRACE(("TRUNCATE file=%p, size=%lld, lock=%d\n",
- pFile->h, nByte, pFile->locktype));
+ OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, size=%lld, lock=%d\n",
+ osGetCurrentProcessId(), pFile, pFile->h, nByte, pFile->locktype));
/* If the user has configured a chunk-size for this file, truncate the
** file so that it consists of an integer number of chunks (i.e. the
@@ -35593,7 +35940,8 @@ static int winTruncate(sqlite3_file *id, sqlite3_int64 nByte){
}
#endif
- OSTRACE(("TRUNCATE file=%p, rc=%s\n", pFile->h, sqlite3ErrName(rc)));
+ OSTRACE(("TRUNCATE pid=%lu, pFile=%p, file=%p, rc=%s\n",
+ osGetCurrentProcessId(), pFile, pFile->h, sqlite3ErrName(rc)));
return rc;
}
@@ -35617,7 +35965,7 @@ static int winSync(sqlite3_file *id, int flags){
BOOL rc;
#endif
#if !defined(NDEBUG) || !defined(SQLITE_NO_SYNC) || \
- (defined(SQLITE_TEST) && defined(SQLITE_DEBUG))
+ defined(SQLITE_HAVE_OS_TRACE)
/*
** Used when SQLITE_NO_SYNC is not defined and by the assert() and/or
** OSTRACE() macros.
@@ -35638,8 +35986,9 @@ static int winSync(sqlite3_file *id, int flags){
*/
SimulateDiskfullError( return SQLITE_FULL );
- OSTRACE(("SYNC file=%p, flags=%x, lock=%d\n",
- pFile->h, flags, pFile->locktype));
+ OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, flags=%x, lock=%d\n",
+ osGetCurrentProcessId(), pFile, pFile->h, flags,
+ pFile->locktype));
#ifndef SQLITE_TEST
UNUSED_PARAMETER(flags);
@@ -35654,19 +36003,38 @@ static int winSync(sqlite3_file *id, int flags){
** no-op
*/
#ifdef SQLITE_NO_SYNC
- OSTRACE(("SYNC-NOP file=%p, rc=SQLITE_OK\n", pFile->h));
+ OSTRACE(("SYNC-NOP pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return SQLITE_OK;
#else
+#if SQLITE_MAX_MMAP_SIZE>0
+ if( pFile->pMapRegion ){
+ if( osFlushViewOfFile(pFile->pMapRegion, 0) ){
+ OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
+ "rc=SQLITE_OK\n", osGetCurrentProcessId(),
+ pFile, pFile->pMapRegion));
+ }else{
+ pFile->lastErrno = osGetLastError();
+ OSTRACE(("SYNC-MMAP pid=%lu, pFile=%p, pMapRegion=%p, "
+ "rc=SQLITE_IOERR_MMAP\n", osGetCurrentProcessId(),
+ pFile, pFile->pMapRegion));
+ return winLogError(SQLITE_IOERR_MMAP, pFile->lastErrno,
+ "winSync1", pFile->zPath);
+ }
+ }
+#endif
rc = osFlushFileBuffers(pFile->h);
SimulateIOError( rc=FALSE );
if( rc ){
- OSTRACE(("SYNC file=%p, rc=SQLITE_OK\n", pFile->h));
+ OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_OK\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return SQLITE_OK;
}else{
pFile->lastErrno = osGetLastError();
- OSTRACE(("SYNC file=%p, rc=SQLITE_IOERR_FSYNC\n", pFile->h));
+ OSTRACE(("SYNC pid=%lu, pFile=%p, file=%p, rc=SQLITE_IOERR_FSYNC\n",
+ osGetCurrentProcessId(), pFile, pFile->h));
return winLogError(SQLITE_IOERR_FSYNC, pFile->lastErrno,
- "winSync", pFile->zPath);
+ "winSync2", pFile->zPath);
}
#endif
}
@@ -36274,7 +36642,7 @@ struct winShmNode {
int nRef; /* Number of winShm objects pointing to this */
winShm *pFirst; /* All winShm objects pointing to this */
winShmNode *pNext; /* Next in list of all winShmNode objects */
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 nextShmId; /* Next available winShm.id value */
#endif
};
@@ -36305,7 +36673,7 @@ struct winShm {
u8 hasMutex; /* True if holding the winShmNode mutex */
u16 sharedMask; /* Mask of shared locks held */
u16 exclMask; /* Mask of exclusive locks held */
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
u8 id; /* Id of this connection with its winShmNode */
#endif
};
@@ -36496,7 +36864,7 @@ static int winOpenSharedMemory(winFile *pDbFd){
/* Make the new connection a child of the winShmNode */
p->pShmNode = pShmNode;
-#ifdef SQLITE_DEBUG
+#if defined(SQLITE_DEBUG) || defined(SQLITE_HAVE_OS_TRACE)
p->id = pShmNode->nextShmId++;
#endif
pShmNode->nRef++;
@@ -36716,16 +37084,16 @@ static int winShmMap(
void volatile **pp /* OUT: Mapped memory */
){
winFile *pDbFd = (winFile*)fd;
- winShm *p = pDbFd->pShm;
+ winShm *pShm = pDbFd->pShm;
winShmNode *pShmNode;
int rc = SQLITE_OK;
- if( !p ){
+ if( !pShm ){
rc = winOpenSharedMemory(pDbFd);
if( rc!=SQLITE_OK ) return rc;
- p = pDbFd->pShm;
+ pShm = pDbFd->pShm;
}
- pShmNode = p->pShmNode;
+ pShmNode = pShm->pShmNode;
sqlite3_mutex_enter(pShmNode->mutex);
assert( szRegion==pShmNode->szRegion || pShmNode->nRegion==0 );
@@ -36765,7 +37133,7 @@ static int winShmMap(
}
/* Map the requested memory region into this processes address space. */
- apNew = (struct ShmRegion *)sqlite3_realloc(
+ apNew = (struct ShmRegion *)sqlite3_realloc64(
pShmNode->aRegion, (iRegion+1)*sizeof(apNew[0])
);
if( !apNew ){
@@ -37637,7 +38005,7 @@ static int winOpen(
}
}
#endif
- winLogIoerr(cnt);
+ winLogIoerr(cnt, __LINE__);
OSTRACE(("OPEN file=%p, name=%s, access=%lx, rc=%s\n", h, zUtf8Name,
dwDesiredAccess, (h==INVALID_HANDLE_VALUE) ? "failed" : "ok"));
@@ -37821,7 +38189,7 @@ static int winDelete(
if( rc && rc!=SQLITE_IOERR_DELETE_NOENT ){
rc = winLogError(SQLITE_IOERR_DELETE, lastErrno, "winDelete", zFilename);
}else{
- winLogIoerr(cnt);
+ winLogIoerr(cnt, __LINE__);
}
sqlite3_free(zConverted);
OSTRACE(("DELETE name=%s, rc=%s\n", zFilename, sqlite3ErrName(rc)));
@@ -37871,7 +38239,7 @@ static int winAccess(
attr = sAttrData.dwFileAttributes;
}
}else{
- winLogIoerr(cnt);
+ winLogIoerr(cnt, __LINE__);
if( lastErrno!=ERROR_FILE_NOT_FOUND && lastErrno!=ERROR_PATH_NOT_FOUND ){
sqlite3_free(zConverted);
return winLogError(SQLITE_IOERR_ACCESS, lastErrno, "winAccess",
@@ -38212,7 +38580,7 @@ static void winDlClose(sqlite3_vfs *pVfs, void *pHandle){
static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
int n = 0;
UNUSED_PARAMETER(pVfs);
-#if defined(SQLITE_TEST)
+#if defined(SQLITE_TEST) || defined(SQLITE_OMIT_RANDOMNESS)
n = nBuf;
memset(zBuf, 0, nBuf);
#else
@@ -38246,7 +38614,23 @@ static int winRandomness(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
memcpy(&zBuf[n], &i, sizeof(i));
n += sizeof(i);
}
+#if !SQLITE_OS_WINCE && !SQLITE_OS_WINRT && SQLITE_WIN32_USE_UUID
+ if( sizeof(UUID)<=nBuf-n ){
+ UUID id;
+ memset(&id, 0, sizeof(UUID));
+ osUuidCreate(&id);
+ memcpy(zBuf, &id, sizeof(UUID));
+ n += sizeof(UUID);
+ }
+ if( sizeof(UUID)<=nBuf-n ){
+ UUID id;
+ memset(&id, 0, sizeof(UUID));
+ osUuidCreateSequential(&id);
+ memcpy(zBuf, &id, sizeof(UUID));
+ n += sizeof(UUID);
+ }
#endif
+#endif /* defined(SQLITE_TEST) || defined(SQLITE_ZERO_PRNG_SEED) */
return n;
}
@@ -38370,7 +38754,7 @@ static int winGetLastError(sqlite3_vfs *pVfs, int nBuf, char *zBuf){
/*
** Initialize and deinitialize the operating system interface.
*/
-SQLITE_API int sqlite3_os_init(void){
+SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void){
static sqlite3_vfs winVfs = {
3, /* iVersion */
sizeof(winFile), /* szOsFile */
@@ -38424,7 +38808,7 @@ SQLITE_API int sqlite3_os_init(void){
/* Double-check that the aSyscall[] array has been constructed
** correctly. See ticket [bb3a86e890c8e96ab] */
- assert( ArraySize(aSyscall)==77 );
+ assert( ArraySize(aSyscall)==80 );
/* get memory map allocation granularity */
memset(&winSysInfo, 0, sizeof(SYSTEM_INFO));
@@ -38445,7 +38829,7 @@ SQLITE_API int sqlite3_os_init(void){
return SQLITE_OK;
}
-SQLITE_API int sqlite3_os_end(void){
+SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void){
#if SQLITE_OS_WINRT
if( sleepObj!=NULL ){
osCloseHandle(sleepObj);
@@ -38801,7 +39185,7 @@ SQLITE_PRIVATE int sqlite3BitvecBuiltinTest(int sz, int *aOp){
** bits to act as the reference */
pBitvec = sqlite3BitvecCreate( sz );
pV = sqlite3MallocZero( (sz+7)/8 + 1 );
- pTmpSpace = sqlite3_malloc(BITVEC_SZ);
+ pTmpSpace = sqlite3_malloc64(BITVEC_SZ);
if( pBitvec==0 || pV==0 || pTmpSpace==0 ) goto bitvec_end;
/* NULL pBitvec tests */
@@ -38983,12 +39367,20 @@ static void pcacheUnpin(PgHdr *p){
}
/*
-** Compute the number of pages of cache requested.
+** Compute the number of pages of cache requested. p->szCache is the
+** cache size requested by the "PRAGMA cache_size" statement.
+**
+**
*/
static int numberOfCachePages(PCache *p){
if( p->szCache>=0 ){
+ /* IMPLEMENTATION-OF: R-42059-47211 If the argument N is positive then the
+ ** suggested cache size is set to N. */
return p->szCache;
}else{
+ /* IMPLEMENTATION-OF: R-61436-13639 If the argument N is negative, then
+ ** the number of cache pages is adjusted to use approximately abs(N*1024)
+ ** bytes of memory. */
return (int)((-1024*(i64)p->szCache)/(p->szPage+p->szExtra));
}
}
@@ -39728,7 +40120,6 @@ SQLITE_PRIVATE void sqlite3PCacheBufferSetup(void *pBuf, int sz, int n){
static void *pcache1Alloc(int nByte){
void *p = 0;
assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
- sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
if( nByte<=pcache1.szSlot ){
sqlite3_mutex_enter(pcache1.mutex);
p = (PgHdr1 *)pcache1.pFree;
@@ -39737,7 +40128,8 @@ static void *pcache1Alloc(int nByte){
pcache1.nFreeSlot--;
pcache1.bUnderPressure = pcache1.nFreeSlot<pcache1.nReserve;
assert( pcache1.nFreeSlot>=0 );
- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, 1);
+ sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
+ sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_USED, 1);
}
sqlite3_mutex_leave(pcache1.mutex);
}
@@ -39750,7 +40142,8 @@ static void *pcache1Alloc(int nByte){
if( p ){
int sz = sqlite3MallocSize(p);
sqlite3_mutex_enter(pcache1.mutex);
- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
+ sqlite3StatusSet(SQLITE_STATUS_PAGECACHE_SIZE, nByte);
+ sqlite3StatusUp(SQLITE_STATUS_PAGECACHE_OVERFLOW, sz);
sqlite3_mutex_leave(pcache1.mutex);
}
#endif
@@ -39768,7 +40161,7 @@ static int pcache1Free(void *p){
if( p>=pcache1.pStart && p<pcache1.pEnd ){
PgFreeslot *pSlot;
sqlite3_mutex_enter(pcache1.mutex);
- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_USED, -1);
+ sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_USED, 1);
pSlot = (PgFreeslot*)p;
pSlot->pNext = pcache1.pFree;
pcache1.pFree = pSlot;
@@ -39782,7 +40175,7 @@ static int pcache1Free(void *p){
nFreed = sqlite3MallocSize(p);
#ifndef SQLITE_DISABLE_PAGECACHE_OVERFLOW_STATS
sqlite3_mutex_enter(pcache1.mutex);
- sqlite3StatusAdd(SQLITE_STATUS_PAGECACHE_OVERFLOW, -nFreed);
+ sqlite3StatusDown(SQLITE_STATUS_PAGECACHE_OVERFLOW, nFreed);
sqlite3_mutex_leave(pcache1.mutex);
#endif
sqlite3_free(p);
@@ -40519,6 +40912,14 @@ SQLITE_PRIVATE void sqlite3PCacheSetDefault(void){
*/
SQLITE_PRIVATE int sqlite3HeaderSizePcache1(void){ return ROUND8(sizeof(PgHdr1)); }
+/*
+** Return the global mutex used by this PCACHE implementation. The
+** sqlite3_status() routine needs access to this mutex.
+*/
+SQLITE_PRIVATE sqlite3_mutex *sqlite3Pcache1Mutex(void){
+ return pcache1.mutex;
+}
+
#ifdef SQLITE_ENABLE_MEMORY_MANAGEMENT
/*
** This function is called to free superfluous dynamically allocated memory
@@ -44273,9 +44674,7 @@ static int pagerWalFrames(
){
int rc; /* Return code */
int nList; /* Number of pages in pList */
-#if defined(SQLITE_DEBUG) || defined(SQLITE_CHECK_PAGES)
PgHdr *p; /* For looping over pages */
-#endif
assert( pPager->pWal );
assert( pList );
@@ -44292,7 +44691,6 @@ static int pagerWalFrames(
** any pages with page numbers greater than nTruncate into the WAL file.
** They will never be read by any client. So remove them from the pDirty
** list here. */
- PgHdr *p;
PgHdr **ppNext = &pList;
nList = 0;
for(p=pList; (*ppNext = p)!=0; p=p->pDirty){
@@ -44312,7 +44710,6 @@ static int pagerWalFrames(
pPager->pageSize, pList, nTruncate, isCommit, pPager->walSyncFlags
);
if( rc==SQLITE_OK && pPager->pBackup ){
- PgHdr *p;
for(p=pList; p; p=p->pDirty){
sqlite3BackupUpdate(pPager->pBackup, p->pgno, (u8 *)p->pData);
}
@@ -48243,6 +48640,8 @@ SQLITE_PRIVATE int sqlite3PagerSetJournalMode(Pager *pPager, int eMode){
}
assert( state==pPager->eState );
}
+ }else if( eMode==PAGER_JOURNALMODE_OFF ){
+ sqlite3OsClose(pPager->jfd);
}
}
@@ -49025,7 +49424,7 @@ static int walIndexPage(Wal *pWal, int iPage, volatile u32 **ppPage){
if( pWal->nWiData<=iPage ){
int nByte = sizeof(u32*)*(iPage+1);
volatile u32 **apNew;
- apNew = (volatile u32 **)sqlite3_realloc((void *)pWal->apWiData, nByte);
+ apNew = (volatile u32 **)sqlite3_realloc64((void *)pWal->apWiData, nByte);
if( !apNew ){
*ppPage = 0;
return SQLITE_NOMEM;
@@ -49291,9 +49690,10 @@ static void walUnlockShared(Wal *pWal, int lockIdx){
SQLITE_SHM_UNLOCK | SQLITE_SHM_SHARED);
WALTRACE(("WAL%p: release SHARED-%s\n", pWal, walLockName(lockIdx)));
}
-static int walLockExclusive(Wal *pWal, int lockIdx, int n){
+static int walLockExclusive(Wal *pWal, int lockIdx, int n, int fBlock){
int rc;
if( pWal->exclusiveMode ) return SQLITE_OK;
+ if( fBlock ) sqlite3OsFileControl(pWal->pDbFd, SQLITE_FCNTL_WAL_BLOCK, 0);
rc = sqlite3OsShmLock(pWal->pDbFd, lockIdx, n,
SQLITE_SHM_LOCK | SQLITE_SHM_EXCLUSIVE);
WALTRACE(("WAL%p: acquire EXCLUSIVE-%s cnt=%d %s\n", pWal,
@@ -49579,7 +49979,7 @@ static int walIndexRecover(Wal *pWal){
assert( pWal->writeLock );
iLock = WAL_ALL_BUT_WRITE + pWal->ckptLock;
nLock = SQLITE_SHM_NLOCK - iLock;
- rc = walLockExclusive(pWal, iLock, nLock);
+ rc = walLockExclusive(pWal, iLock, nLock, 0);
if( rc ){
return rc;
}
@@ -49649,7 +50049,7 @@ static int walIndexRecover(Wal *pWal){
/* Malloc a buffer to read frames into. */
szFrame = szPage + WAL_FRAME_HDRSIZE;
- aFrame = (u8 *)sqlite3_malloc(szFrame);
+ aFrame = (u8 *)sqlite3_malloc64(szFrame);
if( !aFrame ){
rc = SQLITE_NOMEM;
goto recovery_error;
@@ -50042,7 +50442,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
nByte = sizeof(WalIterator)
+ (nSegment-1)*sizeof(struct WalSegment)
+ iLast*sizeof(ht_slot);
- p = (WalIterator *)sqlite3_malloc(nByte);
+ p = (WalIterator *)sqlite3_malloc64(nByte);
if( !p ){
return SQLITE_NOMEM;
}
@@ -50052,7 +50452,7 @@ static int walIteratorInit(Wal *pWal, WalIterator **pp){
/* Allocate temporary space used by the merge-sort routine. This block
** of memory will be freed before this function returns.
*/
- aTmp = (ht_slot *)sqlite3_malloc(
+ aTmp = (ht_slot *)sqlite3_malloc64(
sizeof(ht_slot) * (iLast>HASHTABLE_NPAGE?HASHTABLE_NPAGE:iLast)
);
if( !aTmp ){
@@ -50113,7 +50513,7 @@ static int walBusyLock(
){
int rc;
do {
- rc = walLockExclusive(pWal, lockIdx, n);
+ rc = walLockExclusive(pWal, lockIdx, n, 0);
}while( xBusy && rc==SQLITE_BUSY && xBusy(pBusyArg) );
return rc;
}
@@ -50232,6 +50632,14 @@ static int walCheckpoint(
mxSafeFrame = pWal->hdr.mxFrame;
mxPage = pWal->hdr.nPage;
for(i=1; i<WAL_NREADER; i++){
+ /* Thread-sanitizer reports that the following is an unsafe read,
+ ** as some other thread may be in the process of updating the value
+ ** of the aReadMark[] slot. The assumption here is that if that is
+ ** happening, the other client may only be increasing the value,
+ ** not decreasing it. So assuming either that either the "old" or
+ ** "new" version of the value is read, and not some arbitrary value
+ ** that would never be written by a real client, things are still
+ ** safe. */
u32 y = pInfo->aReadMark[i];
if( mxSafeFrame>y ){
assert( y<=pWal->hdr.mxFrame );
@@ -50546,7 +50954,7 @@ static int walIndexReadHdr(Wal *pWal, int *pChanged){
walUnlockShared(pWal, WAL_WRITE_LOCK);
rc = SQLITE_READONLY_RECOVERY;
}
- }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1)) ){
+ }else if( SQLITE_OK==(rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 1)) ){
pWal->writeLock = 1;
if( SQLITE_OK==(rc = walIndexPage(pWal, 0, &page0)) ){
badHdr = walIndexTryHdr(pWal, pChanged);
@@ -50752,7 +51160,7 @@ static int walTryBeginRead(Wal *pWal, int *pChanged, int useWal, int cnt){
&& (mxReadMark<pWal->hdr.mxFrame || mxI==0)
){
for(i=1; i<WAL_NREADER; i++){
- rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1);
+ rc = walLockExclusive(pWal, WAL_READ_LOCK(i), 1, 0);
if( rc==SQLITE_OK ){
mxReadMark = pInfo->aReadMark[i] = pWal->hdr.mxFrame;
mxI = i;
@@ -51008,7 +51416,7 @@ SQLITE_PRIVATE int sqlite3WalBeginWriteTransaction(Wal *pWal){
/* Only one writer allowed at a time. Get the write lock. Return
** SQLITE_BUSY if unable.
*/
- rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1);
+ rc = walLockExclusive(pWal, WAL_WRITE_LOCK, 1, 0);
if( rc ){
return rc;
}
@@ -51153,7 +51561,7 @@ static int walRestartLog(Wal *pWal){
if( pInfo->nBackfill>0 ){
u32 salt1;
sqlite3_randomness(4, &salt1);
- rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1);
+ rc = walLockExclusive(pWal, WAL_READ_LOCK(1), WAL_NREADER-1, 0);
if( rc==SQLITE_OK ){
/* If all readers are using WAL_READ_LOCK(0) (in other words if no
** readers are currently using the WAL), then the transactions
@@ -51478,7 +51886,7 @@ SQLITE_PRIVATE int sqlite3WalCheckpoint(
/* IMPLEMENTATION-OF: R-62028-47212 All calls obtain an exclusive
** "checkpoint" lock on the database file. */
- rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1);
+ rc = walLockExclusive(pWal, WAL_CKPT_LOCK, 1, 0);
if( rc ){
/* EVIDENCE-OF: R-10421-19736 If any other process is running a
** checkpoint operation at the same time, the lock cannot be obtained and
@@ -51953,6 +52361,7 @@ struct MemPage {
u8 hdrOffset; /* 100 for page 1. 0 otherwise */
u8 childPtrSize; /* 0 if leaf==1. 4 if leaf==0 */
u8 max1bytePayload; /* min(maxLocal,127) */
+ u8 bBusy; /* Prevent endless loops on corrupt database files */
u16 maxLocal; /* Copy of BtShared.maxLocal or BtShared.maxLeaf */
u16 minLocal; /* Copy of BtShared.minLocal or BtShared.minLeaf */
u16 cellOffset; /* Index in aData of first cell pointer */
@@ -52091,6 +52500,9 @@ struct BtShared {
#endif
u8 inTransaction; /* Transaction state */
u8 max1bytePayload; /* Maximum first byte of cell for a 1-byte payload */
+#ifdef SQLITE_HAS_CODEC
+ u8 optimalReserve; /* Desired amount of reserved space per page */
+#endif
u16 btsFlags; /* Boolean parameters. See BTS_* macros below */
u16 maxLocal; /* Maximum local payload in non-LEAFDATA tables */
u16 minLocal; /* Minimum local payload in non-LEAFDATA tables */
@@ -52477,6 +52889,7 @@ static void SQLITE_NOINLINE btreeLockCarefully(Btree *p){
** Exit the recursive mutex on a Btree.
*/
SQLITE_PRIVATE void sqlite3BtreeLeave(Btree *p){
+ assert( sqlite3_mutex_held(p->db->mutex) );
if( p->sharable ){
assert( p->wantToLock>0 );
p->wantToLock--;
@@ -52724,7 +53137,7 @@ static BtShared *SQLITE_WSD sqlite3SharedCacheList = 0;
** The shared cache setting effects only future calls to
** sqlite3_open(), sqlite3_open16(), or sqlite3_open_v2().
*/
-SQLITE_API int sqlite3_enable_shared_cache(int enable){
+SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int enable){
sqlite3GlobalConfig.sharedCacheEnabled = enable;
return SQLITE_OK;
}
@@ -52813,6 +53226,12 @@ static int hasSharedCacheTableLock(
for(p=sqliteHashFirst(&pSchema->idxHash); p; p=sqliteHashNext(p)){
Index *pIdx = (Index *)sqliteHashData(p);
if( pIdx->tnum==(int)iRoot ){
+ if( iTab ){
+ /* Two or more indexes share the same root page. There must
+ ** be imposter tables. So just return true. The assert is not
+ ** useful in that case. */
+ return 1;
+ }
iTab = pIdx->pTable->tnum;
}
}
@@ -53232,10 +53651,15 @@ static void btreeReleaseAllCursorPages(BtCursor *pCur){
static int saveCursorPosition(BtCursor *pCur){
int rc;
- assert( CURSOR_VALID==pCur->eState );
+ assert( CURSOR_VALID==pCur->eState || CURSOR_SKIPNEXT==pCur->eState );
assert( 0==pCur->pKey );
assert( cursorHoldsMutex(pCur) );
+ if( pCur->eState==CURSOR_SKIPNEXT ){
+ pCur->eState = CURSOR_VALID;
+ }else{
+ pCur->skipNext = 0;
+ }
rc = sqlite3BtreeKeySize(pCur, &pCur->nKey);
assert( rc==SQLITE_OK ); /* KeySize() cannot fail */
@@ -53306,7 +53730,7 @@ static int SQLITE_NOINLINE saveCursorsOnList(
){
do{
if( p!=pExcept && (0==iRoot || p->pgnoRoot==iRoot) ){
- if( p->eState==CURSOR_VALID ){
+ if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
int rc = saveCursorPosition(p);
if( SQLITE_OK!=rc ){
return rc;
@@ -53378,17 +53802,19 @@ static int btreeMoveto(
*/
static int btreeRestoreCursorPosition(BtCursor *pCur){
int rc;
+ int skipNext;
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState>=CURSOR_REQUIRESEEK );
if( pCur->eState==CURSOR_FAULT ){
return pCur->skipNext;
}
pCur->eState = CURSOR_INVALID;
- rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &pCur->skipNext);
+ rc = btreeMoveto(pCur, pCur->pKey, pCur->nKey, 0, &skipNext);
if( rc==SQLITE_OK ){
sqlite3_free(pCur->pKey);
pCur->pKey = 0;
assert( pCur->eState==CURSOR_VALID || pCur->eState==CURSOR_INVALID );
+ pCur->skipNext |= skipNext;
if( pCur->skipNext && pCur->eState==CURSOR_VALID ){
pCur->eState = CURSOR_SKIPNEXT;
}
@@ -53440,9 +53866,10 @@ SQLITE_PRIVATE int sqlite3BtreeCursorRestore(BtCursor *pCur, int *pDifferentRow)
*pDifferentRow = 1;
return rc;
}
- if( pCur->eState!=CURSOR_VALID || NEVER(pCur->skipNext!=0) ){
+ if( pCur->eState!=CURSOR_VALID ){
*pDifferentRow = 1;
}else{
+ assert( pCur->skipNext==0 );
*pDifferentRow = 0;
}
return SQLITE_OK;
@@ -54583,16 +55010,18 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
*/
if( isTempDb==0 && (isMemdb==0 || (vfsFlags&SQLITE_OPEN_URI)!=0) ){
if( vfsFlags & SQLITE_OPEN_SHAREDCACHE ){
+ int nFilename = sqlite3Strlen30(zFilename)+1;
int nFullPathname = pVfs->mxPathname+1;
- char *zFullPathname = sqlite3Malloc(nFullPathname);
+ char *zFullPathname = sqlite3Malloc(MAX(nFullPathname,nFilename));
MUTEX_LOGIC( sqlite3_mutex *mutexShared; )
+
p->sharable = 1;
if( !zFullPathname ){
sqlite3_free(p);
return SQLITE_NOMEM;
}
if( isMemdb ){
- memcpy(zFullPathname, zFilename, sqlite3Strlen30(zFilename)+1);
+ memcpy(zFullPathname, zFilename, nFilename);
}else{
rc = sqlite3OsFullPathname(pVfs, zFilename,
nFullPathname, zFullPathname);
@@ -54649,8 +55078,8 @@ SQLITE_PRIVATE int sqlite3BtreeOpen(
** the right size. This is to guard against size changes that result
** when compiling on a different architecture.
*/
- assert( sizeof(i64)==8 || sizeof(i64)==4 );
- assert( sizeof(u64)==8 || sizeof(u64)==4 );
+ assert( sizeof(i64)==8 );
+ assert( sizeof(u64)==8 );
assert( sizeof(u32)==4 );
assert( sizeof(u16)==2 );
assert( sizeof(Pgno)==4 );
@@ -55037,6 +55466,9 @@ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve,
BtShared *pBt = p->pBt;
assert( nReserve>=-1 && nReserve<=255 );
sqlite3BtreeEnter(p);
+#if SQLITE_HAS_CODEC
+ if( nReserve>pBt->optimalReserve ) pBt->optimalReserve = (u8)nReserve;
+#endif
if( pBt->btsFlags & BTS_PAGESIZE_FIXED ){
sqlite3BtreeLeave(p);
return SQLITE_READONLY;
@@ -55048,7 +55480,7 @@ SQLITE_PRIVATE int sqlite3BtreeSetPageSize(Btree *p, int pageSize, int nReserve,
if( pageSize>=512 && pageSize<=SQLITE_MAX_PAGE_SIZE &&
((pageSize-1)&pageSize)==0 ){
assert( (pageSize & 7)==0 );
- assert( !pBt->pPage1 && !pBt->pCursor );
+ assert( !pBt->pCursor );
pBt->pageSize = (u32)pageSize;
freeTempSpace(pBt);
}
@@ -55066,7 +55498,6 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){
return p->pBt->pageSize;
}
-#if defined(SQLITE_HAS_CODEC) || defined(SQLITE_DEBUG)
/*
** This function is similar to sqlite3BtreeGetReserve(), except that it
** may only be called if it is guaranteed that the b-tree mutex is already
@@ -55079,25 +55510,33 @@ SQLITE_PRIVATE int sqlite3BtreeGetPageSize(Btree *p){
** database handle that owns *p, causing undefined behavior.
*/
SQLITE_PRIVATE int sqlite3BtreeGetReserveNoMutex(Btree *p){
+ int n;
assert( sqlite3_mutex_held(p->pBt->mutex) );
- return p->pBt->pageSize - p->pBt->usableSize;
+ n = p->pBt->pageSize - p->pBt->usableSize;
+ return n;
}
-#endif /* SQLITE_HAS_CODEC || SQLITE_DEBUG */
-#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM)
/*
** Return the number of bytes of space at the end of every page that
** are intentually left unused. This is the "reserved" space that is
** sometimes used by extensions.
+**
+** If SQLITE_HAS_MUTEX is defined then the number returned is the
+** greater of the current reserved space and the maximum requested
+** reserve space.
*/
-SQLITE_PRIVATE int sqlite3BtreeGetReserve(Btree *p){
+SQLITE_PRIVATE int sqlite3BtreeGetOptimalReserve(Btree *p){
int n;
sqlite3BtreeEnter(p);
- n = p->pBt->pageSize - p->pBt->usableSize;
+ n = sqlite3BtreeGetReserveNoMutex(p);
+#ifdef SQLITE_HAS_CODEC
+ if( n<p->pBt->optimalReserve ) n = p->pBt->optimalReserve;
+#endif
sqlite3BtreeLeave(p);
return n;
}
+
/*
** Set the maximum page count for a database if mxPage is positive.
** No changes are made if mxPage is 0 or negative.
@@ -55128,7 +55567,6 @@ SQLITE_PRIVATE int sqlite3BtreeSecureDelete(Btree *p, int newFlag){
sqlite3BtreeLeave(p);
return b;
}
-#endif /* !defined(SQLITE_OMIT_PAGER_PRAGMAS) || !defined(SQLITE_OMIT_VACUUM) */
/*
** Change the 'auto-vacuum' property of the database. If the 'autoVacuum'
@@ -56248,7 +56686,7 @@ SQLITE_PRIVATE int sqlite3BtreeTripAllCursors(Btree *pBtree, int errCode, int wr
for(p=pBtree->pBt->pCursor; p; p=p->pNext){
int i;
if( writeOnly && (p->curFlags & BTCF_WriteFlag)==0 ){
- if( p->eState==CURSOR_VALID ){
+ if( p->eState==CURSOR_VALID || p->eState==CURSOR_SKIPNEXT ){
rc = saveCursorPosition(p);
if( rc!=SQLITE_OK ){
(void)sqlite3BtreeTripAllCursors(pBtree, rc, 0);
@@ -56654,6 +57092,8 @@ SQLITE_PRIVATE int sqlite3BtreeKeySize(BtCursor *pCur, i64 *pSize){
SQLITE_PRIVATE int sqlite3BtreeDataSize(BtCursor *pCur, u32 *pSize){
assert( cursorHoldsMutex(pCur) );
assert( pCur->eState==CURSOR_VALID );
+ assert( pCur->iPage>=0 );
+ assert( pCur->iPage<BTCURSOR_MAX_DEPTH );
assert( pCur->apPage[pCur->iPage]->intKeyLeaf==1 );
getCellInfo(pCur);
*pSize = pCur->info.nPayload;
@@ -57062,13 +57502,18 @@ static const void *fetchPayload(
BtCursor *pCur, /* Cursor pointing to entry to read from */
u32 *pAmt /* Write the number of available bytes here */
){
+ u32 amt;
assert( pCur!=0 && pCur->iPage>=0 && pCur->apPage[pCur->iPage]);
assert( pCur->eState==CURSOR_VALID );
assert( sqlite3_mutex_held(pCur->pBtree->db->mutex) );
assert( cursorHoldsMutex(pCur) );
assert( pCur->aiIdx[pCur->iPage]<pCur->apPage[pCur->iPage]->nCell );
assert( pCur->info.nSize>0 );
- *pAmt = pCur->info.nLocal;
+ assert( pCur->info.pPayload>pCur->apPage[pCur->iPage]->aData || CORRUPT_DB );
+ assert( pCur->info.pPayload<pCur->apPage[pCur->iPage]->aDataEnd ||CORRUPT_DB);
+ amt = (int)(pCur->apPage[pCur->iPage]->aDataEnd - pCur->info.pPayload);
+ if( pCur->info.nLocal<amt ) amt = pCur->info.nLocal;
+ *pAmt = amt;
return (void*)pCur->info.pPayload;
}
@@ -57132,7 +57577,7 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
return SQLITE_OK;
}
-#if 0
+#if SQLITE_DEBUG
/*
** Page pParent is an internal (non-leaf) tree page. This function
** asserts that page number iChild is the left-child if the iIdx'th
@@ -57141,6 +57586,8 @@ static int moveToChild(BtCursor *pCur, u32 newPgno){
** the page.
*/
static void assertParentIndex(MemPage *pParent, int iIdx, Pgno iChild){
+ if( CORRUPT_DB ) return; /* The conditions tested below might not be true
+ ** in a corrupt database */
assert( iIdx<=pParent->nCell );
if( iIdx==pParent->nCell ){
assert( get4byte(&pParent->aData[pParent->hdrOffset+8])==iChild );
@@ -57165,19 +57612,11 @@ static void moveToParent(BtCursor *pCur){
assert( pCur->eState==CURSOR_VALID );
assert( pCur->iPage>0 );
assert( pCur->apPage[pCur->iPage] );
-
- /* UPDATE: It is actually possible for the condition tested by the assert
- ** below to be untrue if the database file is corrupt. This can occur if
- ** one cursor has modified page pParent while a reference to it is held
- ** by a second cursor. Which can only happen if a single page is linked
- ** into more than one b-tree structure in a corrupt database. */
-#if 0
assertParentIndex(
pCur->apPage[pCur->iPage-1],
pCur->aiIdx[pCur->iPage-1],
pCur->apPage[pCur->iPage]->pgno
);
-#endif
testcase( pCur->aiIdx[pCur->iPage-1] > pCur->apPage[pCur->iPage-1]->nCell );
releasePage(pCur->apPage[pCur->iPage]);
@@ -59352,7 +59791,6 @@ static int balance_nonroot(
}else if( iParentIdx==i ){
nxDiv = i-2+bBulk;
}else{
- assert( bBulk==0 );
nxDiv = iParentIdx-1;
}
i = 2-bBulk;
@@ -60103,7 +60541,8 @@ static int balance(BtCursor *pCur){
** pSpace buffer passed to the latter call to balance_nonroot().
*/
u8 *pSpace = sqlite3PageMalloc(pCur->pBt->pageSize);
- rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1, pCur->hints);
+ rc = balance_nonroot(pParent, iIdx, pSpace, iPage==1,
+ pCur->hints&BTREE_BULKLOAD);
if( pFree ){
/* If pFree is not NULL, it points to the pSpace buffer used
** by a previous call to balance_nonroot(). Its contents are
@@ -60124,6 +60563,7 @@ static int balance(BtCursor *pCur){
/* The next iteration of the do-loop balances the parent page. */
releasePage(pPage);
pCur->iPage--;
+ assert( pCur->iPage>=0 );
}
}while( rc==SQLITE_OK );
@@ -60600,9 +61040,13 @@ static int clearDatabasePage(
if( pgno>btreePagecount(pBt) ){
return SQLITE_CORRUPT_BKPT;
}
-
rc = getAndInitPage(pBt, pgno, &pPage, 0);
if( rc ) return rc;
+ if( pPage->bBusy ){
+ rc = SQLITE_CORRUPT_BKPT;
+ goto cleardatabasepage_out;
+ }
+ pPage->bBusy = 1;
hdr = pPage->hdrOffset;
for(i=0; i<pPage->nCell; i++){
pCell = findCell(pPage, i);
@@ -60627,6 +61071,7 @@ static int clearDatabasePage(
}
cleardatabasepage_out:
+ pPage->bBusy = 0;
releasePage(pPage);
return rc;
}
@@ -61134,6 +61579,57 @@ static void checkList(
}
#endif /* SQLITE_OMIT_INTEGRITY_CHECK */
+/*
+** An implementation of a min-heap.
+**
+** aHeap[0] is the number of elements on the heap. aHeap[1] is the
+** root element. The daughter nodes of aHeap[N] are aHeap[N*2]
+** and aHeap[N*2+1].
+**
+** The heap property is this: Every node is less than or equal to both
+** of its daughter nodes. A consequence of the heap property is that the
+** root node aHeap[1] is always the minimum value currently in the heap.
+**
+** The btreeHeapInsert() routine inserts an unsigned 32-bit number onto
+** the heap, preserving the heap property. The btreeHeapPull() routine
+** removes the root element from the heap (the minimum value in the heap)
+** and then moves other nodes around as necessary to preserve the heap
+** property.
+**
+** This heap is used for cell overlap and coverage testing. Each u32
+** entry represents the span of a cell or freeblock on a btree page.
+** The upper 16 bits are the index of the first byte of a range and the
+** lower 16 bits are the index of the last byte of that range.
+*/
+static void btreeHeapInsert(u32 *aHeap, u32 x){
+ u32 j, i = ++aHeap[0];
+ aHeap[i] = x;
+ while( (j = i/2)>0 && aHeap[j]>aHeap[i] ){
+ x = aHeap[j];
+ aHeap[j] = aHeap[i];
+ aHeap[i] = x;
+ i = j;
+ }
+}
+static int btreeHeapPull(u32 *aHeap, u32 *pOut){
+ u32 j, i, x;
+ if( (x = aHeap[0])==0 ) return 0;
+ *pOut = aHeap[1];
+ aHeap[1] = aHeap[x];
+ aHeap[x] = 0xffffffff;
+ aHeap[0]--;
+ i = 1;
+ while( (j = i*2)<=aHeap[0] ){
+ if( aHeap[j]>aHeap[j+1] ) j++;
+ if( aHeap[i]<aHeap[j] ) break;
+ x = aHeap[i];
+ aHeap[i] = aHeap[j];
+ aHeap[j] = x;
+ i = j;
+ }
+ return 1;
+}
+
#ifndef SQLITE_OMIT_INTEGRITY_CHECK
/*
** Do various sanity checks on a single page of a tree. Return
@@ -61166,7 +61662,8 @@ static int checkTreePage(
u8 *data;
BtShared *pBt;
int usableSize;
- char *hit = 0;
+ u32 *heap = 0;
+ u32 x, prev = 0;
i64 nMinKey = 0;
i64 nMaxKey = 0;
const char *saved_zPfx = pCheck->zPfx;
@@ -61311,15 +61808,15 @@ static int checkTreePage(
*/
data = pPage->aData;
hdr = pPage->hdrOffset;
- hit = sqlite3PageMalloc( pBt->pageSize );
+ heap = (u32*)sqlite3PageMalloc( pBt->pageSize );
pCheck->zPfx = 0;
- if( hit==0 ){
+ if( heap==0 ){
pCheck->mallocFailed = 1;
}else{
int contentOffset = get2byteNotZero(&data[hdr+5]);
assert( contentOffset<=usableSize ); /* Enforced by btreeInitPage() */
- memset(hit+contentOffset, 0, usableSize-contentOffset);
- memset(hit, 1, contentOffset);
+ heap[0] = 0;
+ btreeHeapInsert(heap, contentOffset-1);
/* EVIDENCE-OF: R-37002-32774 The two-byte integer at offset 3 gives the
** number of cells on the page. */
nCell = get2byte(&data[hdr+3]);
@@ -61331,7 +61828,6 @@ static int checkTreePage(
for(i=0; i<nCell; i++){
int pc = get2byte(&data[cellStart+i*2]);
u32 size = 65536;
- int j;
if( pc<=usableSize-4 ){
size = cellSizePtr(pPage, &data[pc]);
}
@@ -61340,7 +61836,7 @@ static int checkTreePage(
checkAppendMsg(pCheck,
"Corruption detected in cell %d on page %d",i,iPage);
}else{
- for(j=pc+size-1; j>=pc; j--) hit[j]++;
+ btreeHeapInsert(heap, (pc<<16)|(pc+size-1));
}
}
/* EVIDENCE-OF: R-20690-50594 The second field of the b-tree page header
@@ -61352,7 +61848,7 @@ static int checkTreePage(
assert( i<=usableSize-4 ); /* Enforced by btreeInitPage() */
size = get2byte(&data[i+2]);
assert( i+size<=usableSize ); /* Enforced by btreeInitPage() */
- for(j=i+size-1; j>=i; j--) hit[j]++;
+ btreeHeapInsert(heap, (i<<16)|(i+size-1));
/* EVIDENCE-OF: R-58208-19414 The first 2 bytes of a freeblock are a
** big-endian integer which is the offset in the b-tree page of the next
** freeblock in the chain, or zero if the freeblock is the last on the
@@ -61364,27 +61860,33 @@ static int checkTreePage(
assert( j<=usableSize-4 ); /* Enforced by btreeInitPage() */
i = j;
}
- for(i=cnt=0; i<usableSize; i++){
- if( hit[i]==0 ){
- cnt++;
- }else if( hit[i]>1 ){
+ cnt = 0;
+ assert( heap[0]>0 );
+ assert( (heap[1]>>16)==0 );
+ btreeHeapPull(heap,&prev);
+ while( btreeHeapPull(heap,&x) ){
+ if( (prev&0xffff)+1>(x>>16) ){
checkAppendMsg(pCheck,
- "Multiple uses for byte %d of page %d", i, iPage);
+ "Multiple uses for byte %u of page %d", x>>16, iPage);
break;
+ }else{
+ cnt += (x>>16) - (prev&0xffff) - 1;
+ prev = x;
}
}
+ cnt += usableSize - (prev&0xffff) - 1;
/* EVIDENCE-OF: R-43263-13491 The total number of bytes in all fragments
** is stored in the fifth field of the b-tree page header.
** EVIDENCE-OF: R-07161-27322 The one-byte integer at offset 7 gives the
** number of fragmented free bytes within the cell content area.
*/
- if( cnt!=data[hdr+7] ){
+ if( heap[0]==0 && cnt!=data[hdr+7] ){
checkAppendMsg(pCheck,
"Fragmentation of %d bytes reported as %d on page %d",
cnt, data[hdr+7], iPage);
}
}
- sqlite3PageFree(hit);
+ sqlite3PageFree(heap);
releasePage(pPage);
end_of_check:
@@ -61448,8 +61950,7 @@ SQLITE_PRIVATE char *sqlite3BtreeIntegrityCheck(
}
i = PENDING_BYTE_PAGE(pBt);
if( i<=sCheck.nPage ) setPageReferenced(&sCheck, i);
- sqlite3StrAccumInit(&sCheck.errMsg, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
- sCheck.errMsg.useMalloc = 2;
+ sqlite3StrAccumInit(&sCheck.errMsg, 0, zErr, sizeof(zErr), SQLITE_MAX_LENGTH);
/* Check the integrity of the freelist
*/
@@ -61766,14 +62267,23 @@ SQLITE_PRIVATE int sqlite3BtreeSetVersion(Btree *pBtree, int iVersion){
}
/*
-** set the mask of hint flags for cursor pCsr. Currently the only valid
-** values are 0 and BTREE_BULKLOAD.
+** set the mask of hint flags for cursor pCsr.
*/
SQLITE_PRIVATE void sqlite3BtreeCursorHints(BtCursor *pCsr, unsigned int mask){
- assert( mask==BTREE_BULKLOAD || mask==0 );
+ assert( mask==BTREE_BULKLOAD || mask==BTREE_SEEK_EQ || mask==0 );
pCsr->hints = mask;
}
+#ifdef SQLITE_DEBUG
+/*
+** Return true if the cursor has a hint specified. This routine is
+** only used from within assert() statements
+*/
+SQLITE_PRIVATE int sqlite3BtreeCursorHasHint(BtCursor *pCsr, unsigned int mask){
+ return (pCsr->hints & mask)!=0;
+}
+#endif
+
/*
** Return true if the given Btree is read-only.
*/
@@ -61932,7 +62442,7 @@ static int checkReadTransaction(sqlite3 *db, Btree *p){
** If an error occurs, NULL is returned and an error code and error message
** stored in database handle pDestDb.
*/
-SQLITE_API sqlite3_backup *sqlite3_backup_init(
+SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init(
sqlite3* pDestDb, /* Database to write to */
const char *zDestDb, /* Name of database within pDestDb */
sqlite3* pSrcDb, /* Database connection to read from */
@@ -62035,7 +62545,7 @@ static int backupOnePage(
** guaranteed that the shared-mutex is held by this thread, handle
** p->pSrc may not actually be the owner. */
int nSrcReserve = sqlite3BtreeGetReserveNoMutex(p->pSrc);
- int nDestReserve = sqlite3BtreeGetReserve(p->pDest);
+ int nDestReserve = sqlite3BtreeGetOptimalReserve(p->pDest);
#endif
int rc = SQLITE_OK;
i64 iOff;
@@ -62140,7 +62650,7 @@ static void attachBackupObject(sqlite3_backup *p){
/*
** Copy nPage pages from the source b-tree to the destination.
*/
-SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage){
int rc;
int destMode; /* Destination journal mode */
int pgszSrc = 0; /* Source page size */
@@ -62385,7 +62895,7 @@ SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage){
/*
** Release all resources associated with an sqlite3_backup* handle.
*/
-SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p){
sqlite3_backup **pp; /* Ptr to head of pagers backup list */
sqlite3 *pSrcDb; /* Source database connection */
int rc; /* Value to return */
@@ -62437,7 +62947,7 @@ SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p){
** Return the number of pages still to be backed up as of the most recent
** call to sqlite3_backup_step().
*/
-SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p){
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p){
#ifdef SQLITE_ENABLE_API_ARMOR
if( p==0 ){
(void)SQLITE_MISUSE_BKPT;
@@ -62451,7 +62961,7 @@ SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p){
** Return the total number of pages in the source database as of the most
** recent call to sqlite3_backup_step().
*/
-SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p){
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p){
#ifdef SQLITE_ENABLE_API_ARMOR
if( p==0 ){
(void)SQLITE_MISUSE_BKPT;
@@ -62776,10 +63286,11 @@ SQLITE_PRIVATE int sqlite3VdbeMemMakeWriteable(Mem *pMem){
pMem->z[pMem->n] = 0;
pMem->z[pMem->n+1] = 0;
pMem->flags |= MEM_Term;
+ }
+ pMem->flags &= ~MEM_Ephem;
#ifdef SQLITE_DEBUG
- pMem->pScopyFrom = 0;
+ pMem->pScopyFrom = 0;
#endif
- }
return SQLITE_OK;
}
@@ -63666,7 +64177,7 @@ struct ValueNewStat4Ctx {
** Otherwise, if the second argument is non-zero, then this function is
** being called indirectly by sqlite3Stat4ProbeSetValue(). If it has not
** already been allocated, allocate the UnpackedRecord structure that
-** that function will return to its caller here. Then return a pointer
+** that function will return to its caller here. Then return a pointer to
** an sqlite3_value within the UnpackedRecord.a[] array.
*/
static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
@@ -63711,6 +64222,113 @@ static sqlite3_value *valueNew(sqlite3 *db, struct ValueNewStat4Ctx *p){
}
/*
+** The expression object indicated by the second argument is guaranteed
+** to be a scalar SQL function. If
+**
+** * all function arguments are SQL literals,
+** * the SQLITE_FUNC_CONSTANT function flag is set, and
+** * the SQLITE_FUNC_NEEDCOLL function flag is not set,
+**
+** then this routine attempts to invoke the SQL function. Assuming no
+** error occurs, output parameter (*ppVal) is set to point to a value
+** object containing the result before returning SQLITE_OK.
+**
+** Affinity aff is applied to the result of the function before returning.
+** If the result is a text value, the sqlite3_value object uses encoding
+** enc.
+**
+** If the conditions above are not met, this function returns SQLITE_OK
+** and sets (*ppVal) to NULL. Or, if an error occurs, (*ppVal) is set to
+** NULL and an SQLite error code returned.
+*/
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+static int valueFromFunction(
+ sqlite3 *db, /* The database connection */
+ Expr *p, /* The expression to evaluate */
+ u8 enc, /* Encoding to use */
+ u8 aff, /* Affinity to use */
+ sqlite3_value **ppVal, /* Write the new value here */
+ struct ValueNewStat4Ctx *pCtx /* Second argument for valueNew() */
+){
+ sqlite3_context ctx; /* Context object for function invocation */
+ sqlite3_value **apVal = 0; /* Function arguments */
+ int nVal = 0; /* Size of apVal[] array */
+ FuncDef *pFunc = 0; /* Function definition */
+ sqlite3_value *pVal = 0; /* New value */
+ int rc = SQLITE_OK; /* Return code */
+ int nName; /* Size of function name in bytes */
+ ExprList *pList = 0; /* Function arguments */
+ int i; /* Iterator variable */
+
+ assert( pCtx!=0 );
+ assert( (p->flags & EP_TokenOnly)==0 );
+ pList = p->x.pList;
+ if( pList ) nVal = pList->nExpr;
+ nName = sqlite3Strlen30(p->u.zToken);
+ pFunc = sqlite3FindFunction(db, p->u.zToken, nName, nVal, enc, 0);
+ assert( pFunc );
+ if( (pFunc->funcFlags & SQLITE_FUNC_CONSTANT)==0
+ || (pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL)
+ ){
+ return SQLITE_OK;
+ }
+
+ if( pList ){
+ apVal = (sqlite3_value**)sqlite3DbMallocZero(db, sizeof(apVal[0]) * nVal);
+ if( apVal==0 ){
+ rc = SQLITE_NOMEM;
+ goto value_from_function_out;
+ }
+ for(i=0; i<nVal; i++){
+ rc = sqlite3ValueFromExpr(db, pList->a[i].pExpr, enc, aff, &apVal[i]);
+ if( apVal[i]==0 || rc!=SQLITE_OK ) goto value_from_function_out;
+ }
+ }
+
+ pVal = valueNew(db, pCtx);
+ if( pVal==0 ){
+ rc = SQLITE_NOMEM;
+ goto value_from_function_out;
+ }
+
+ assert( pCtx->pParse->rc==SQLITE_OK );
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.pOut = pVal;
+ ctx.pFunc = pFunc;
+ pFunc->xFunc(&ctx, nVal, apVal);
+ if( ctx.isError ){
+ rc = ctx.isError;
+ sqlite3ErrorMsg(pCtx->pParse, "%s", sqlite3_value_text(pVal));
+ }else{
+ sqlite3ValueApplyAffinity(pVal, aff, SQLITE_UTF8);
+ assert( rc==SQLITE_OK );
+ rc = sqlite3VdbeChangeEncoding(pVal, enc);
+ if( rc==SQLITE_OK && sqlite3VdbeMemTooBig(pVal) ){
+ rc = SQLITE_TOOBIG;
+ pCtx->pParse->nErr++;
+ }
+ }
+ pCtx->pParse->rc = rc;
+
+ value_from_function_out:
+ if( rc!=SQLITE_OK ){
+ pVal = 0;
+ }
+ if( apVal ){
+ for(i=0; i<nVal; i++){
+ sqlite3ValueFree(apVal[i]);
+ }
+ sqlite3DbFree(db, apVal);
+ }
+
+ *ppVal = pVal;
+ return rc;
+}
+#else
+# define valueFromFunction(a,b,c,d,e,f) SQLITE_OK
+#endif /* defined(SQLITE_ENABLE_STAT3_OR_STAT4) */
+
+/*
** Extract a value from the supplied expression in the manner described
** above sqlite3ValueFromExpr(). Allocate the sqlite3_value object
** using valueNew().
@@ -63742,6 +64360,12 @@ static int valueFromExpr(
while( (op = pExpr->op)==TK_UPLUS ) pExpr = pExpr->pLeft;
if( NEVER(op==TK_REGISTER) ) op = pExpr->op2;
+ /* Compressed expressions only appear when parsing the DEFAULT clause
+ ** on a table column definition, and hence only when pCtx==0. This
+ ** check ensures that an EP_TokenOnly expression is never passed down
+ ** into valueFromFunction(). */
+ assert( (pExpr->flags & EP_TokenOnly)==0 || pCtx==0 );
+
if( op==TK_CAST ){
u8 aff = sqlite3AffinityType(pExpr->u.zToken,0);
rc = valueFromExpr(db, pExpr->pLeft, enc, aff, ppVal, pCtx);
@@ -63818,6 +64442,12 @@ static int valueFromExpr(
}
#endif
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ else if( op==TK_FUNCTION && pCtx!=0 ){
+ rc = valueFromFunction(db, pExpr, enc, affinity, &pVal, pCtx);
+ }
+#endif
+
*ppVal = pVal;
return rc;
@@ -64104,7 +64734,7 @@ SQLITE_PRIVATE void sqlite3Stat4ProbeFree(UnpackedRecord *pRec){
Mem *aMem = pRec->aMem;
sqlite3 *db = aMem[0].db;
for(i=0; i<nCol; i++){
- if( aMem[i].szMalloc ) sqlite3DbFree(db, aMem[i].zMalloc);
+ sqlite3VdbeMemRelease(&aMem[i]);
}
sqlite3KeyInfoUnref(pRec->pKeyInfo);
sqlite3DbFree(db, pRec);
@@ -64207,7 +64837,7 @@ SQLITE_PRIVATE void sqlite3VdbeSetSql(Vdbe *p, const char *z, int n, int isPrepa
/*
** Return the SQL associated with a prepared statement
*/
-SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe *)pStmt;
return (p && p->isPrepareV2) ? p->zSql : 0;
}
@@ -65270,7 +65900,7 @@ static char *displayP4(Op *pOp, char *zTemp, int nTemp){
#ifndef SQLITE_OMIT_VIRTUALTABLE
case P4_VTAB: {
sqlite3_vtab *pVtab = pOp->p4.pVtab->pVtab;
- sqlite3_snprintf(nTemp, zTemp, "vtab:%p:%p", pVtab, pVtab->pModule);
+ sqlite3_snprintf(nTemp, zTemp, "vtab:%p", pVtab);
break;
}
#endif
@@ -65934,20 +66564,37 @@ SQLITE_PRIVATE void sqlite3VdbeFreeCursor(Vdbe *p, VdbeCursor *pCx){
else if( pCx->pVtabCursor ){
sqlite3_vtab_cursor *pVtabCursor = pCx->pVtabCursor;
const sqlite3_module *pModule = pVtabCursor->pVtab->pModule;
- p->inVtabMethod = 1;
+ assert( pVtabCursor->pVtab->nRef>0 );
+ pVtabCursor->pVtab->nRef--;
pModule->xClose(pVtabCursor);
- p->inVtabMethod = 0;
}
#endif
}
/*
+** Close all cursors in the current frame.
+*/
+static void closeCursorsInFrame(Vdbe *p){
+ if( p->apCsr ){
+ int i;
+ for(i=0; i<p->nCursor; i++){
+ VdbeCursor *pC = p->apCsr[i];
+ if( pC ){
+ sqlite3VdbeFreeCursor(p, pC);
+ p->apCsr[i] = 0;
+ }
+ }
+ }
+}
+
+/*
** Copy the values stored in the VdbeFrame structure to its Vdbe. This
** is used, for example, when a trigger sub-program is halted to restore
** control to the main program.
*/
SQLITE_PRIVATE int sqlite3VdbeFrameRestore(VdbeFrame *pFrame){
Vdbe *v = pFrame->v;
+ closeCursorsInFrame(v);
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
v->anExec = pFrame->anExec;
#endif
@@ -65982,17 +66629,7 @@ static void closeAllCursors(Vdbe *p){
p->nFrame = 0;
}
assert( p->nFrame==0 );
-
- if( p->apCsr ){
- int i;
- for(i=0; i<p->nCursor; i++){
- VdbeCursor *pC = p->apCsr[i];
- if( pC ){
- sqlite3VdbeFreeCursor(p, pC);
- p->apCsr[i] = 0;
- }
- }
- }
+ closeCursorsInFrame(p);
if( p->aMem ){
releaseMemArray(&p->aMem[1], p->nMem);
}
@@ -66295,7 +66932,7 @@ static int vdbeCommit(sqlite3 *db, Vdbe *p){
** doing this the directory is synced again before any individual
** transaction files are deleted.
*/
- rc = sqlite3OsDelete(pVfs, zMaster, 1);
+ rc = sqlite3OsDelete(pVfs, zMaster, needSync);
sqlite3DbFree(db, zMaster);
zMaster = 0;
if( rc ){
@@ -67525,7 +68162,8 @@ static void vdbeAssertFieldCountWithinLimits(
if( CORRUPT_DB ) return;
idx = getVarint32(aKey, szHdr);
- assert( szHdr<=nKey );
+ assert( nKey>=0 );
+ assert( szHdr<=(u32)nKey );
while( idx<szHdr ){
idx += getVarint32(aKey+idx, notUsed);
nField++;
@@ -67736,7 +68374,7 @@ static i64 vdbeRecordDecodeInt(u32 serial_type, const u8 *aKey){
** pPKey2->errCode is set to SQLITE_NOMEM and, if it is not NULL, the
** malloc-failed flag set on database handle (pPKey2->pKeyInfo->db).
*/
-static int vdbeRecordCompareWithSkip(
+SQLITE_PRIVATE int sqlite3VdbeRecordCompareWithSkip(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *pPKey2, /* Right key */
int bSkip /* If true, skip the first field */
@@ -67922,7 +68560,7 @@ SQLITE_PRIVATE int sqlite3VdbeRecordCompare(
int nKey1, const void *pKey1, /* Left key */
UnpackedRecord *pPKey2 /* Right key */
){
- return vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0);
+ return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 0);
}
@@ -68010,7 +68648,7 @@ static int vdbeRecordCompareInt(
}else if( pPKey2->nField>1 ){
/* The first fields of the two keys are equal. Compare the trailing
** fields. */
- res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
+ res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
}else{
/* The first fields of the two keys are equal and there are no trailing
** fields. Return pPKey2->default_rc in this case. */
@@ -68058,7 +68696,7 @@ static int vdbeRecordCompareString(
res = nStr - pPKey2->aMem[0].n;
if( res==0 ){
if( pPKey2->nField>1 ){
- res = vdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
+ res = sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, pPKey2, 1);
}else{
res = pPKey2->default_rc;
}
@@ -68362,7 +69000,7 @@ SQLITE_PRIVATE void sqlite3VtabImportErrmsg(Vdbe *p, sqlite3_vtab *pVtab){
** collating sequences are registered or if an authorizer function is
** added or changed.
*/
-SQLITE_API int sqlite3_expired(sqlite3_stmt *pStmt){
+SQLITE_API int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
return p==0 || p->expired;
}
@@ -68399,7 +69037,7 @@ static int vdbeSafetyNotNull(Vdbe *p){
** This routine sets the error code and string returned by
** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
*/
-SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){
+SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt){
int rc;
if( pStmt==0 ){
/* IMPLEMENTATION-OF: R-57228-12904 Invoking sqlite3_finalize() on a NULL
@@ -68425,7 +69063,7 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt){
** This routine sets the error code and string returned by
** sqlite3_errcode(), sqlite3_errmsg() and sqlite3_errmsg16().
*/
-SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){
+SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt){
int rc;
if( pStmt==0 ){
rc = SQLITE_OK;
@@ -68444,7 +69082,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt){
/*
** Set all the parameters in the compiled SQL statement to NULL.
*/
-SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
+SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt *pStmt){
int i;
int rc = SQLITE_OK;
Vdbe *p = (Vdbe*)pStmt;
@@ -68468,7 +69106,7 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt *pStmt){
** The following routines extract information from a Mem or sqlite3_value
** structure.
*/
-SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value *pVal){
Mem *p = (Mem*)pVal;
if( p->flags & (MEM_Blob|MEM_Str) ){
sqlite3VdbeMemExpandBlob(p);
@@ -68478,36 +69116,40 @@ SQLITE_API const void *sqlite3_value_blob(sqlite3_value *pVal){
return sqlite3_value_text(pVal);
}
}
-SQLITE_API int sqlite3_value_bytes(sqlite3_value *pVal){
+SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value *pVal){
return sqlite3ValueBytes(pVal, SQLITE_UTF8);
}
-SQLITE_API int sqlite3_value_bytes16(sqlite3_value *pVal){
+SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value *pVal){
return sqlite3ValueBytes(pVal, SQLITE_UTF16NATIVE);
}
-SQLITE_API double sqlite3_value_double(sqlite3_value *pVal){
+SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value *pVal){
return sqlite3VdbeRealValue((Mem*)pVal);
}
-SQLITE_API int sqlite3_value_int(sqlite3_value *pVal){
+SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value *pVal){
return (int)sqlite3VdbeIntValue((Mem*)pVal);
}
-SQLITE_API sqlite_int64 sqlite3_value_int64(sqlite3_value *pVal){
+SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value *pVal){
return sqlite3VdbeIntValue((Mem*)pVal);
}
-SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value *pVal){
+SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value *pVal){
return (const unsigned char *)sqlite3ValueText(pVal, SQLITE_UTF8);
}
#ifndef SQLITE_OMIT_UTF16
-SQLITE_API const void *sqlite3_value_text16(sqlite3_value* pVal){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value* pVal){
return sqlite3ValueText(pVal, SQLITE_UTF16NATIVE);
}
-SQLITE_API const void *sqlite3_value_text16be(sqlite3_value *pVal){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value *pVal){
return sqlite3ValueText(pVal, SQLITE_UTF16BE);
}
-SQLITE_API const void *sqlite3_value_text16le(sqlite3_value *pVal){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value *pVal){
return sqlite3ValueText(pVal, SQLITE_UTF16LE);
}
#endif /* SQLITE_OMIT_UTF16 */
-SQLITE_API int sqlite3_value_type(sqlite3_value* pVal){
+/* EVIDENCE-OF: R-12793-43283 Every value in SQLite has one of five
+** fundamental datatypes: 64-bit signed integer 64-bit IEEE floating
+** point number string BLOB NULL
+*/
+SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value* pVal){
static const u8 aType[] = {
SQLITE_BLOB, /* 0x00 */
SQLITE_NULL, /* 0x01 */
@@ -68583,7 +69225,7 @@ static int invokeValueDestructor(
if( pCtx ) sqlite3_result_error_toobig(pCtx);
return SQLITE_TOOBIG;
}
-SQLITE_API void sqlite3_result_blob(
+SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(
sqlite3_context *pCtx,
const void *z,
int n,
@@ -68593,7 +69235,7 @@ SQLITE_API void sqlite3_result_blob(
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n, 0, xDel);
}
-SQLITE_API void sqlite3_result_blob64(
+SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(
sqlite3_context *pCtx,
const void *z,
sqlite3_uint64 n,
@@ -68607,37 +69249,37 @@ SQLITE_API void sqlite3_result_blob64(
setResultStrOrError(pCtx, z, (int)n, 0, xDel);
}
}
-SQLITE_API void sqlite3_result_double(sqlite3_context *pCtx, double rVal){
+SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context *pCtx, double rVal){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetDouble(pCtx->pOut, rVal);
}
-SQLITE_API void sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context *pCtx, const char *z, int n){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
pCtx->isError = SQLITE_ERROR;
pCtx->fErrorOrAux = 1;
sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF8, SQLITE_TRANSIENT);
}
#ifndef SQLITE_OMIT_UTF16
-SQLITE_API void sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context *pCtx, const void *z, int n){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
pCtx->isError = SQLITE_ERROR;
pCtx->fErrorOrAux = 1;
sqlite3VdbeMemSetStr(pCtx->pOut, z, n, SQLITE_UTF16NATIVE, SQLITE_TRANSIENT);
}
#endif
-SQLITE_API void sqlite3_result_int(sqlite3_context *pCtx, int iVal){
+SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context *pCtx, int iVal){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetInt64(pCtx->pOut, (i64)iVal);
}
-SQLITE_API void sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){
+SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context *pCtx, i64 iVal){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetInt64(pCtx->pOut, iVal);
}
-SQLITE_API void sqlite3_result_null(sqlite3_context *pCtx){
+SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetNull(pCtx->pOut);
}
-SQLITE_API void sqlite3_result_text(
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text(
sqlite3_context *pCtx,
const char *z,
int n,
@@ -68646,7 +69288,7 @@ SQLITE_API void sqlite3_result_text(
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n, SQLITE_UTF8, xDel);
}
-SQLITE_API void sqlite3_result_text64(
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(
sqlite3_context *pCtx,
const char *z,
sqlite3_uint64 n,
@@ -68663,7 +69305,7 @@ SQLITE_API void sqlite3_result_text64(
}
}
#ifndef SQLITE_OMIT_UTF16
-SQLITE_API void sqlite3_result_text16(
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(
sqlite3_context *pCtx,
const void *z,
int n,
@@ -68672,7 +69314,7 @@ SQLITE_API void sqlite3_result_text16(
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n, SQLITE_UTF16NATIVE, xDel);
}
-SQLITE_API void sqlite3_result_text16be(
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(
sqlite3_context *pCtx,
const void *z,
int n,
@@ -68681,7 +69323,7 @@ SQLITE_API void sqlite3_result_text16be(
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
setResultStrOrError(pCtx, z, n, SQLITE_UTF16BE, xDel);
}
-SQLITE_API void sqlite3_result_text16le(
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(
sqlite3_context *pCtx,
const void *z,
int n,
@@ -68691,17 +69333,20 @@ SQLITE_API void sqlite3_result_text16le(
setResultStrOrError(pCtx, z, n, SQLITE_UTF16LE, xDel);
}
#endif /* SQLITE_OMIT_UTF16 */
-SQLITE_API void sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
+SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context *pCtx, sqlite3_value *pValue){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemCopy(pCtx->pOut, pValue);
}
-SQLITE_API void sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
+SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context *pCtx, int n){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetZeroBlob(pCtx->pOut, n);
}
-SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
pCtx->isError = errCode;
pCtx->fErrorOrAux = 1;
+#ifdef SQLITE_DEBUG
+ if( pCtx->pVdbe ) pCtx->pVdbe->rcApp = errCode;
+#endif
if( pCtx->pOut->flags & MEM_Null ){
sqlite3VdbeMemSetStr(pCtx->pOut, sqlite3ErrStr(errCode), -1,
SQLITE_UTF8, SQLITE_STATIC);
@@ -68709,7 +69354,7 @@ SQLITE_API void sqlite3_result_error_code(sqlite3_context *pCtx, int errCode){
}
/* Force an SQLITE_TOOBIG error. */
-SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
pCtx->isError = SQLITE_TOOBIG;
pCtx->fErrorOrAux = 1;
@@ -68718,7 +69363,7 @@ SQLITE_API void sqlite3_result_error_toobig(sqlite3_context *pCtx){
}
/* An SQLITE_NOMEM error. */
-SQLITE_API void sqlite3_result_error_nomem(sqlite3_context *pCtx){
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context *pCtx){
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
sqlite3VdbeMemSetNull(pCtx->pOut);
pCtx->isError = SQLITE_NOMEM;
@@ -68782,7 +69427,7 @@ static int sqlite3Step(Vdbe *p){
** or SQLITE_BUSY error.
*/
#ifdef SQLITE_OMIT_AUTORESET
- if( p->rc==SQLITE_BUSY || p->rc==SQLITE_LOCKED ){
+ if( (rc = p->rc&0xff)==SQLITE_BUSY || rc==SQLITE_LOCKED ){
sqlite3_reset((sqlite3_stmt*)p);
}else{
return SQLITE_MISUSE_BKPT;
@@ -68828,6 +69473,9 @@ static int sqlite3Step(Vdbe *p){
if( p->bIsReader ) db->nVdbeRead++;
p->pc = 0;
}
+#ifdef SQLITE_DEBUG
+ p->rcApp = SQLITE_OK;
+#endif
#ifndef SQLITE_OMIT_EXPLAIN
if( p->explain ){
rc = sqlite3VdbeList(p);
@@ -68872,7 +69520,7 @@ end_of_step:
assert( rc==SQLITE_ROW || rc==SQLITE_DONE || rc==SQLITE_ERROR
|| rc==SQLITE_BUSY || rc==SQLITE_MISUSE
);
- assert( p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE );
+ assert( (p->rc!=SQLITE_ROW && p->rc!=SQLITE_DONE) || p->rc==p->rcApp );
if( p->isPrepareV2 && rc!=SQLITE_ROW && rc!=SQLITE_DONE ){
/* If this statement was prepared using sqlite3_prepare_v2(), and an
** error has occurred, then return the error code in p->rc to the
@@ -68888,7 +69536,7 @@ end_of_step:
** sqlite3Step() to do most of the work. If a schema error occurs,
** call sqlite3Reprepare() and try again.
*/
-SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
+SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt *pStmt){
int rc = SQLITE_OK; /* Result from sqlite3Step() */
int rc2 = SQLITE_OK; /* Result from sqlite3Reprepare() */
Vdbe *v = (Vdbe*)pStmt; /* the prepared statement */
@@ -68939,7 +69587,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt *pStmt){
** Extract the user data from a sqlite3_context structure and return a
** pointer to it.
*/
-SQLITE_API void *sqlite3_user_data(sqlite3_context *p){
+SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context *p){
assert( p && p->pFunc );
return p->pFunc->pUserData;
}
@@ -68954,22 +69602,32 @@ SQLITE_API void *sqlite3_user_data(sqlite3_context *p){
** sqlite3_create_function16() routines that originally registered the
** application defined function.
*/
-SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context *p){
+SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context *p){
assert( p && p->pFunc );
return p->pOut->db;
}
/*
-** Return the current time for a statement
+** Return the current time for a statement. If the current time
+** is requested more than once within the same run of a single prepared
+** statement, the exact same time is returned for each invocation regardless
+** of the amount of time that elapses between invocations. In other words,
+** the time returned is always the time of the first call.
*/
SQLITE_PRIVATE sqlite3_int64 sqlite3StmtCurrentTime(sqlite3_context *p){
- Vdbe *v = p->pVdbe;
int rc;
- if( v->iCurrentTime==0 ){
- rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, &v->iCurrentTime);
- if( rc ) v->iCurrentTime = 0;
+#ifndef SQLITE_ENABLE_STAT3_OR_STAT4
+ sqlite3_int64 *piTime = &p->pVdbe->iCurrentTime;
+ assert( p->pVdbe!=0 );
+#else
+ sqlite3_int64 iTime = 0;
+ sqlite3_int64 *piTime = p->pVdbe!=0 ? &p->pVdbe->iCurrentTime : &iTime;
+#endif
+ if( *piTime==0 ){
+ rc = sqlite3OsCurrentTimeInt64(p->pOut->db->pVfs, piTime);
+ if( rc ) *piTime = 0;
}
- return v->iCurrentTime;
+ return *piTime;
}
/*
@@ -69020,7 +69678,7 @@ static SQLITE_NOINLINE void *createAggContext(sqlite3_context *p, int nByte){
** context is allocated on the first call. Subsequent calls return the
** same context that was returned on prior calls.
*/
-SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
+SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context *p, int nByte){
assert( p && p->pFunc && p->pFunc->xStep );
assert( sqlite3_mutex_held(p->pOut->db->mutex) );
testcase( nByte<0 );
@@ -69035,10 +69693,15 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context *p, int nByte){
** Return the auxiliary data pointer, if any, for the iArg'th argument to
** the user-function defined by pCtx.
*/
-SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
+SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
AuxData *pAuxData;
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
+#if SQLITE_ENABLE_STAT3_OR_STAT4
+ if( pCtx->pVdbe==0 ) return 0;
+#else
+ assert( pCtx->pVdbe!=0 );
+#endif
for(pAuxData=pCtx->pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
}
@@ -69051,7 +69714,7 @@ SQLITE_API void *sqlite3_get_auxdata(sqlite3_context *pCtx, int iArg){
** argument to the user-function defined by pCtx. Any previous value is
** deleted by calling the delete function specified when it was set.
*/
-SQLITE_API void sqlite3_set_auxdata(
+SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(
sqlite3_context *pCtx,
int iArg,
void *pAux,
@@ -69062,6 +69725,11 @@ SQLITE_API void sqlite3_set_auxdata(
assert( sqlite3_mutex_held(pCtx->pOut->db->mutex) );
if( iArg<0 ) goto failed;
+#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
+ if( pVdbe==0 ) goto failed;
+#else
+ assert( pVdbe!=0 );
+#endif
for(pAuxData=pVdbe->pAuxData; pAuxData; pAuxData=pAuxData->pNext){
if( pAuxData->iOp==pCtx->iOp && pAuxData->iArg==iArg ) break;
@@ -69101,7 +69769,7 @@ failed:
** implementations should keep their own counts within their aggregate
** context.
*/
-SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){
+SQLITE_API int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context *p){
assert( p && p->pMem && p->pFunc && p->pFunc->xStep );
return p->pMem->n;
}
@@ -69110,7 +69778,7 @@ SQLITE_API int sqlite3_aggregate_count(sqlite3_context *p){
/*
** Return the number of columns in the result set for the statement pStmt.
*/
-SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){
+SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt){
Vdbe *pVm = (Vdbe *)pStmt;
return pVm ? pVm->nResColumn : 0;
}
@@ -69119,7 +69787,7 @@ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt){
** Return the number of values available from the current row of the
** currently executing statement pStmt.
*/
-SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt){
+SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt){
Vdbe *pVm = (Vdbe *)pStmt;
if( pVm==0 || pVm->pResultSet==0 ) return 0;
return pVm->nResColumn;
@@ -69221,7 +69889,7 @@ static void columnMallocFailure(sqlite3_stmt *pStmt)
** The following routines are used to access elements of the current row
** in the result set.
*/
-SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt *pStmt, int i){
const void *val;
val = sqlite3_value_blob( columnMem(pStmt,i) );
/* Even though there is no encoding conversion, value_blob() might
@@ -69231,37 +69899,37 @@ SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt *pStmt, int i){
columnMallocFailure(pStmt);
return val;
}
-SQLITE_API int sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){
+SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt *pStmt, int i){
int val = sqlite3_value_bytes( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
-SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){
+SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt *pStmt, int i){
int val = sqlite3_value_bytes16( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
-SQLITE_API double sqlite3_column_double(sqlite3_stmt *pStmt, int i){
+SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt *pStmt, int i){
double val = sqlite3_value_double( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
-SQLITE_API int sqlite3_column_int(sqlite3_stmt *pStmt, int i){
+SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt *pStmt, int i){
int val = sqlite3_value_int( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
-SQLITE_API sqlite_int64 sqlite3_column_int64(sqlite3_stmt *pStmt, int i){
+SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt *pStmt, int i){
sqlite_int64 val = sqlite3_value_int64( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
-SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt *pStmt, int i){
+SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt *pStmt, int i){
const unsigned char *val = sqlite3_value_text( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
-SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){
+SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt *pStmt, int i){
Mem *pOut = columnMem(pStmt, i);
if( pOut->flags&MEM_Static ){
pOut->flags &= ~MEM_Static;
@@ -69271,13 +69939,13 @@ SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt *pStmt, int i){
return (sqlite3_value *)pOut;
}
#ifndef SQLITE_OMIT_UTF16
-SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt *pStmt, int i){
const void *val = sqlite3_value_text16( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return val;
}
#endif /* SQLITE_OMIT_UTF16 */
-SQLITE_API int sqlite3_column_type(sqlite3_stmt *pStmt, int i){
+SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt *pStmt, int i){
int iType = sqlite3_value_type( columnMem(pStmt,i) );
columnMallocFailure(pStmt);
return iType;
@@ -69341,12 +70009,12 @@ static const void *columnName(
** Return the name of the Nth column of the result set returned by SQL
** statement pStmt.
*/
-SQLITE_API const char *sqlite3_column_name(sqlite3_stmt *pStmt, int N){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_NAME);
}
#ifndef SQLITE_OMIT_UTF16
-SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_NAME);
}
@@ -69366,12 +70034,12 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt *pStmt, int N){
** Return the column declaration type (if applicable) of the 'i'th column
** of the result set of SQL statement pStmt.
*/
-SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DECLTYPE);
}
#ifndef SQLITE_OMIT_UTF16
-SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DECLTYPE);
}
@@ -69384,12 +70052,12 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt *pStmt, int N){
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
-SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_DATABASE);
}
#ifndef SQLITE_OMIT_UTF16
-SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_DATABASE);
}
@@ -69400,12 +70068,12 @@ SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt *pStmt, int N
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
-SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_TABLE);
}
#ifndef SQLITE_OMIT_UTF16
-SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_TABLE);
}
@@ -69416,12 +70084,12 @@ SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt *pStmt, int N){
** NULL is returned if the result column is an expression or constant or
** anything else which is not an unambiguous reference to a database column.
*/
-SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text, COLNAME_COLUMN);
}
#ifndef SQLITE_OMIT_UTF16
-SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt *pStmt, int N){
return columnName(
pStmt, N, (const void*(*)(Mem*))sqlite3_value_text16, COLNAME_COLUMN);
}
@@ -69522,7 +70190,7 @@ static int bindText(
/*
** Bind a blob value to an SQL statement variable.
*/
-SQLITE_API int sqlite3_bind_blob(
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(
sqlite3_stmt *pStmt,
int i,
const void *zData,
@@ -69531,7 +70199,7 @@ SQLITE_API int sqlite3_bind_blob(
){
return bindText(pStmt, i, zData, nData, xDel, 0);
}
-SQLITE_API int sqlite3_bind_blob64(
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(
sqlite3_stmt *pStmt,
int i,
const void *zData,
@@ -69545,7 +70213,7 @@ SQLITE_API int sqlite3_bind_blob64(
return bindText(pStmt, i, zData, (int)nData, xDel, 0);
}
}
-SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, i);
@@ -69555,10 +70223,10 @@ SQLITE_API int sqlite3_bind_double(sqlite3_stmt *pStmt, int i, double rValue){
}
return rc;
}
-SQLITE_API int sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt *p, int i, int iValue){
return sqlite3_bind_int64(p, i, (i64)iValue);
}
-SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValue){
int rc;
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, i);
@@ -69568,7 +70236,7 @@ SQLITE_API int sqlite3_bind_int64(sqlite3_stmt *pStmt, int i, sqlite_int64 iValu
}
return rc;
}
-SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
int rc;
Vdbe *p = (Vdbe*)pStmt;
rc = vdbeUnbind(p, i);
@@ -69577,7 +70245,7 @@ SQLITE_API int sqlite3_bind_null(sqlite3_stmt *pStmt, int i){
}
return rc;
}
-SQLITE_API int sqlite3_bind_text(
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(
sqlite3_stmt *pStmt,
int i,
const char *zData,
@@ -69586,7 +70254,7 @@ SQLITE_API int sqlite3_bind_text(
){
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF8);
}
-SQLITE_API int sqlite3_bind_text64(
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(
sqlite3_stmt *pStmt,
int i,
const char *zData,
@@ -69603,7 +70271,7 @@ SQLITE_API int sqlite3_bind_text64(
}
}
#ifndef SQLITE_OMIT_UTF16
-SQLITE_API int sqlite3_bind_text16(
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(
sqlite3_stmt *pStmt,
int i,
const void *zData,
@@ -69613,7 +70281,7 @@ SQLITE_API int sqlite3_bind_text16(
return bindText(pStmt, i, zData, nData, xDel, SQLITE_UTF16NATIVE);
}
#endif /* SQLITE_OMIT_UTF16 */
-SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_value *pValue){
int rc;
switch( sqlite3_value_type((sqlite3_value*)pValue) ){
case SQLITE_INTEGER: {
@@ -69644,7 +70312,7 @@ SQLITE_API int sqlite3_bind_value(sqlite3_stmt *pStmt, int i, const sqlite3_valu
}
return rc;
}
-SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
int rc;
Vdbe *p = (Vdbe *)pStmt;
rc = vdbeUnbind(p, i);
@@ -69659,7 +70327,7 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt *pStmt, int i, int n){
** Return the number of wildcards that can be potentially bound to.
** This routine is added to support DBD::SQLite.
*/
-SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
return p ? p->nVar : 0;
}
@@ -69670,7 +70338,7 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt *pStmt){
**
** The result is always UTF-8.
*/
-SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt *pStmt, int i){
Vdbe *p = (Vdbe*)pStmt;
if( p==0 || i<1 || i>p->nzVar ){
return 0;
@@ -69698,7 +70366,7 @@ SQLITE_PRIVATE int sqlite3VdbeParameterIndex(Vdbe *p, const char *zName, int nNa
}
return 0;
}
-SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt *pStmt, const char *zName){
return sqlite3VdbeParameterIndex((Vdbe*)pStmt, zName, sqlite3Strlen30(zName));
}
@@ -69732,7 +70400,7 @@ SQLITE_PRIVATE int sqlite3TransferBindings(sqlite3_stmt *pFromStmt, sqlite3_stmt
** an SQLITE_ERROR is returned. Nothing else can go wrong, so otherwise
** SQLITE_OK is returned.
*/
-SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
+SQLITE_API int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *pToStmt){
Vdbe *pFrom = (Vdbe*)pFromStmt;
Vdbe *pTo = (Vdbe*)pToStmt;
if( pFrom->nVar!=pTo->nVar ){
@@ -69754,7 +70422,7 @@ SQLITE_API int sqlite3_transfer_bindings(sqlite3_stmt *pFromStmt, sqlite3_stmt *
** the first argument to the sqlite3_prepare() that was used to create
** the statement in the first place.
*/
-SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){
+SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt *pStmt){
return pStmt ? ((Vdbe*)pStmt)->db : 0;
}
@@ -69762,14 +70430,14 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt *pStmt){
** Return true if the prepared statement is guaranteed to not modify the
** database.
*/
-SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
+SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt){
return pStmt ? ((Vdbe*)pStmt)->readOnly : 1;
}
/*
** Return true if the prepared statement is in need of being reset.
*/
-SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
+SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt *pStmt){
Vdbe *v = (Vdbe*)pStmt;
return v!=0 && v->pc>=0 && v->magic==VDBE_MAGIC_RUN;
}
@@ -69780,7 +70448,7 @@ SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt *pStmt){
** prepared statement for the database connection. Return NULL if there
** are no more.
*/
-SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
+SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
sqlite3_stmt *pNext;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(pDb) ){
@@ -69801,7 +70469,7 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt){
/*
** Return the value of a status counter for a prepared statement
*/
-SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
+SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
Vdbe *pVdbe = (Vdbe*)pStmt;
u32 v;
#ifdef SQLITE_ENABLE_API_ARMOR
@@ -69819,7 +70487,7 @@ SQLITE_API int sqlite3_stmt_status(sqlite3_stmt *pStmt, int op, int resetFlag){
/*
** Return status data for a single loop within query pStmt.
*/
-SQLITE_API int sqlite3_stmt_scanstatus(
+SQLITE_API int SQLITE_STDCALL sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt, /* Prepared statement being queried */
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Which metric to return */
@@ -69878,7 +70546,7 @@ SQLITE_API int sqlite3_stmt_scanstatus(
/*
** Zero all counters associated with the sqlite3_stmt_scanstatus() data.
*/
-SQLITE_API void sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){
+SQLITE_API void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt *pStmt){
Vdbe *p = (Vdbe*)pStmt;
memset(p->anExec, 0, p->nOp * sizeof(i64));
}
@@ -69970,9 +70638,8 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
char zBase[100]; /* Initial working space */
db = p->db;
- sqlite3StrAccumInit(&out, zBase, sizeof(zBase),
+ sqlite3StrAccumInit(&out, db, zBase, sizeof(zBase),
db->aLimit[SQLITE_LIMIT_LENGTH]);
- out.db = db;
if( db->nVdbeExec>1 ){
while( *zRawSql ){
const char *zStart = zRawSql;
@@ -69981,6 +70648,8 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
assert( (zRawSql - zStart) > 0 );
sqlite3StrAccumAppend(&out, zStart, (int)(zRawSql-zStart));
}
+ }else if( p->nVar==0 ){
+ sqlite3StrAccumAppend(&out, zRawSql, sqlite3Strlen30(zRawSql));
}else{
while( zRawSql[0] ){
n = findNextHostParameter(zRawSql, &nToken);
@@ -69997,10 +70666,12 @@ SQLITE_PRIVATE char *sqlite3VdbeExpandSql(
idx = nextIndex;
}
}else{
- assert( zRawSql[0]==':' || zRawSql[0]=='$' || zRawSql[0]=='@' );
+ assert( zRawSql[0]==':' || zRawSql[0]=='$' ||
+ zRawSql[0]=='@' || zRawSql[0]=='#' );
testcase( zRawSql[0]==':' );
testcase( zRawSql[0]=='$' );
testcase( zRawSql[0]=='@' );
+ testcase( zRawSql[0]=='#' );
idx = sqlite3VdbeParameterIndex(p, zRawSql, nToken);
assert( idx>0 );
}
@@ -70368,6 +71039,7 @@ static void applyAffinity(
if( 0==(pRec->flags&MEM_Str) && (pRec->flags&(MEM_Real|MEM_Int)) ){
sqlite3VdbeMemStringify(pRec, enc, 1);
}
+ pRec->flags &= ~(MEM_Real|MEM_Int);
}
}
@@ -70377,7 +71049,7 @@ static void applyAffinity(
** is appropriate. But only do the conversion if it is possible without
** loss of information and return the revised type of the argument.
*/
-SQLITE_API int sqlite3_value_numeric_type(sqlite3_value *pVal){
+SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value *pVal){
int eType = sqlite3_value_type(pVal);
if( eType==SQLITE_TEXT ){
Mem *pMem = (Mem*)pVal;
@@ -70675,6 +71347,21 @@ static int checkSavepointCount(sqlite3 *db){
}
#endif
+/*
+** Return the register of pOp->p2 after first preparing it to be
+** overwritten with an integer value.
+*/
+static Mem *out2Prerelease(Vdbe *p, VdbeOp *pOp){
+ Mem *pOut;
+ assert( pOp->p2>0 );
+ assert( pOp->p2<=(p->nMem-p->nCursor) );
+ pOut = &p->aMem[pOp->p2];
+ memAboutToChange(p, pOut);
+ if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut);
+ pOut->flags = MEM_Int;
+ return pOut;
+}
+
/*
** Execute as much of a VDBE program as we can.
@@ -70683,9 +71370,11 @@ static int checkSavepointCount(sqlite3 *db){
SQLITE_PRIVATE int sqlite3VdbeExec(
Vdbe *p /* The VDBE */
){
- int pc=0; /* The program counter */
Op *aOp = p->aOp; /* Copy of p->aOp */
- Op *pOp; /* Current operation */
+ Op *pOp = aOp; /* Current operation */
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
+ Op *pOrigOp; /* Value of pOp at the top of the loop */
+#endif
int rc = SQLITE_OK; /* Value to return */
sqlite3 *db = p->db; /* The database */
u8 resetSchemaOnFault = 0; /* Reset schema after an error if positive */
@@ -70761,23 +71450,22 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
}
sqlite3EndBenignMalloc();
#endif
- for(pc=p->pc; rc==SQLITE_OK; pc++){
- assert( pc>=0 && pc<p->nOp );
+ for(pOp=&aOp[p->pc]; rc==SQLITE_OK; pOp++){
+ assert( pOp>=aOp && pOp<&aOp[p->nOp]);
if( db->mallocFailed ) goto no_mem;
#ifdef VDBE_PROFILE
start = sqlite3Hwtime();
#endif
nVmStep++;
- pOp = &aOp[pc];
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
- if( p->anExec ) p->anExec[pc]++;
+ if( p->anExec ) p->anExec[(int)(pOp-aOp)]++;
#endif
/* Only allow tracing if SQLITE_DEBUG is defined.
*/
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeTrace ){
- sqlite3VdbePrintOp(stdout, pc, pOp);
+ sqlite3VdbePrintOp(stdout, (int)(pOp - aOp), pOp);
}
#endif
@@ -70794,23 +71482,9 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
}
#endif
- /* On any opcode with the "out2-prerelease" tag, free any
- ** external allocations out of mem[p2] and set mem[p2] to be
- ** an undefined integer. Opcodes will either fill in the integer
- ** value or convert mem[p2] to a different type.
- */
- assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
- if( pOp->opflags & OPFLG_OUT2_PRERELEASE ){
- assert( pOp->p2>0 );
- assert( pOp->p2<=(p->nMem-p->nCursor) );
- pOut = &aMem[pOp->p2];
- memAboutToChange(p, pOut);
- if( VdbeMemDynamic(pOut) ) sqlite3VdbeMemSetNull(pOut);
- pOut->flags = MEM_Int;
- }
-
/* Sanity checking on other operands */
#ifdef SQLITE_DEBUG
+ assert( pOp->opflags==sqlite3OpcodeProperty[pOp->opcode] );
if( (pOp->opflags & OPFLG_IN1)!=0 ){
assert( pOp->p1>0 );
assert( pOp->p1<=(p->nMem-p->nCursor) );
@@ -70843,6 +71517,9 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
memAboutToChange(p, &aMem[pOp->p3]);
}
#endif
+#if defined(SQLITE_DEBUG) || defined(VDBE_PROFILE)
+ pOrigOp = pOp;
+#endif
switch( pOp->opcode ){
@@ -70866,7 +71543,7 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
**
** Other keywords in the comment that follows each case are used to
** construct the OPFLG_INITIALIZER value that initializes opcodeProperty[].
-** Keywords include: in1, in2, in3, out2_prerelease, out2, out3. See
+** Keywords include: in1, in2, in3, out2, out3. See
** the mkopcodeh.awk script for additional information.
**
** Documentation about VDBE opcodes is generated by scanning this file
@@ -70894,7 +71571,8 @@ SQLITE_PRIVATE int sqlite3VdbeExec(
** to the current line should be indented for EXPLAIN output.
*/
case OP_Goto: { /* jump */
- pc = pOp->p2 - 1;
+jump_to_p2_and_check_for_interrupt:
+ pOp = &aOp[pOp->p2 - 1];
/* Opcodes that are used as the bottom of a loop (OP_Next, OP_Prev,
** OP_VNext, OP_RowSetNext, or OP_SorterNext) all jump here upon
@@ -70939,9 +71617,13 @@ case OP_Gosub: { /* jump */
assert( VdbeMemDynamic(pIn1)==0 );
memAboutToChange(p, pIn1);
pIn1->flags = MEM_Int;
- pIn1->u.i = pc;
+ pIn1->u.i = (int)(pOp-aOp);
REGISTER_TRACE(pOp->p1, pIn1);
- pc = pOp->p2 - 1;
+
+ /* Most jump operations do a goto to this spot in order to update
+ ** the pOp pointer. */
+jump_to_p2:
+ pOp = &aOp[pOp->p2 - 1];
break;
}
@@ -70953,7 +71635,7 @@ case OP_Gosub: { /* jump */
case OP_Return: { /* in1 */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags==MEM_Int );
- pc = (int)pIn1->u.i;
+ pOp = &aOp[pIn1->u.i];
pIn1->flags = MEM_Undefined;
break;
}
@@ -70977,7 +71659,7 @@ case OP_InitCoroutine: { /* jump */
assert( !VdbeMemDynamic(pOut) );
pOut->u.i = pOp->p3 - 1;
pOut->flags = MEM_Int;
- if( pOp->p2 ) pc = pOp->p2 - 1;
+ if( pOp->p2 ) goto jump_to_p2;
break;
}
@@ -70997,7 +71679,7 @@ case OP_EndCoroutine: { /* in1 */
pCaller = &aOp[pIn1->u.i];
assert( pCaller->opcode==OP_Yield );
assert( pCaller->p2>=0 && pCaller->p2<p->nOp );
- pc = pCaller->p2 - 1;
+ pOp = &aOp[pCaller->p2 - 1];
pIn1->flags = MEM_Undefined;
break;
}
@@ -71021,9 +71703,9 @@ case OP_Yield: { /* in1, jump */
assert( VdbeMemDynamic(pIn1)==0 );
pIn1->flags = MEM_Int;
pcDest = (int)pIn1->u.i;
- pIn1->u.i = pc;
+ pIn1->u.i = (int)(pOp - aOp);
REGISTER_TRACE(pOp->p1, pIn1);
- pc = pcDest;
+ pOp = &aOp[pcDest];
break;
}
@@ -71074,30 +71756,34 @@ case OP_HaltIfNull: { /* in3 */
case OP_Halt: {
const char *zType;
const char *zLogFmt;
+ VdbeFrame *pFrame;
+ int pcx;
+ pcx = (int)(pOp - aOp);
if( pOp->p1==SQLITE_OK && p->pFrame ){
/* Halt the sub-program. Return control to the parent frame. */
- VdbeFrame *pFrame = p->pFrame;
+ pFrame = p->pFrame;
p->pFrame = pFrame->pParent;
p->nFrame--;
sqlite3VdbeSetChanges(db, p->nChange);
- pc = sqlite3VdbeFrameRestore(pFrame);
+ pcx = sqlite3VdbeFrameRestore(pFrame);
lastRowid = db->lastRowid;
if( pOp->p2==OE_Ignore ){
- /* Instruction pc is the OP_Program that invoked the sub-program
+ /* Instruction pcx is the OP_Program that invoked the sub-program
** currently being halted. If the p2 instruction of this OP_Halt
** instruction is set to OE_Ignore, then the sub-program is throwing
** an IGNORE exception. In this case jump to the address specified
** as the p2 of the calling OP_Program. */
- pc = p->aOp[pc].p2-1;
+ pcx = p->aOp[pcx].p2-1;
}
aOp = p->aOp;
aMem = p->aMem;
+ pOp = &aOp[pcx];
break;
}
p->rc = pOp->p1;
p->errorAction = (u8)pOp->p2;
- p->pc = pc;
+ p->pc = pcx;
if( p->rc ){
if( pOp->p5 ){
static const char * const azType[] = { "NOT NULL", "UNIQUE", "CHECK",
@@ -71121,7 +71807,7 @@ case OP_Halt: {
}else{
sqlite3SetString(&p->zErrMsg, db, "%s constraint failed", zType);
}
- sqlite3_log(pOp->p1, zLogFmt, pc, p->zSql, p->zErrMsg);
+ sqlite3_log(pOp->p1, zLogFmt, pcx, p->zSql, p->zErrMsg);
}
rc = sqlite3VdbeHalt(p);
assert( rc==SQLITE_BUSY || rc==SQLITE_OK || rc==SQLITE_ERROR );
@@ -71140,7 +71826,8 @@ case OP_Halt: {
**
** The 32-bit integer value P1 is written into register P2.
*/
-case OP_Integer: { /* out2-prerelease */
+case OP_Integer: { /* out2 */
+ pOut = out2Prerelease(p, pOp);
pOut->u.i = pOp->p1;
break;
}
@@ -71151,7 +71838,8 @@ case OP_Integer: { /* out2-prerelease */
** P4 is a pointer to a 64-bit integer value.
** Write that value into register P2.
*/
-case OP_Int64: { /* out2-prerelease */
+case OP_Int64: { /* out2 */
+ pOut = out2Prerelease(p, pOp);
assert( pOp->p4.pI64!=0 );
pOut->u.i = *pOp->p4.pI64;
break;
@@ -71164,7 +71852,8 @@ case OP_Int64: { /* out2-prerelease */
** P4 is a pointer to a 64-bit floating point value.
** Write that value into register P2.
*/
-case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
+case OP_Real: { /* same as TK_FLOAT, out2 */
+ pOut = out2Prerelease(p, pOp);
pOut->flags = MEM_Real;
assert( !sqlite3IsNaN(*pOp->p4.pReal) );
pOut->u.r = *pOp->p4.pReal;
@@ -71176,12 +71865,13 @@ case OP_Real: { /* same as TK_FLOAT, out2-prerelease */
** Synopsis: r[P2]='P4'
**
** P4 points to a nul terminated UTF-8 string. This opcode is transformed
-** into a String before it is executed for the first time. During
+** into a String opcode before it is executed for the first time. During
** this transformation, the length of string P4 is computed and stored
** as the P1 parameter.
*/
-case OP_String8: { /* same as TK_STRING, out2-prerelease */
+case OP_String8: { /* same as TK_STRING, out2 */
assert( pOp->p4.z!=0 );
+ pOut = out2Prerelease(p, pOp);
pOp->opcode = OP_String;
pOp->p1 = sqlite3Strlen30(pOp->p4.z);
@@ -71208,18 +71898,31 @@ case OP_String8: { /* same as TK_STRING, out2-prerelease */
/* Fall through to the next case, OP_String */
}
-/* Opcode: String P1 P2 * P4 *
+/* Opcode: String P1 P2 P3 P4 P5
** Synopsis: r[P2]='P4' (len=P1)
**
** The string value P4 of length P1 (bytes) is stored in register P2.
+**
+** If P5!=0 and the content of register P3 is greater than zero, then
+** the datatype of the register P2 is converted to BLOB. The content is
+** the same sequence of bytes, it is merely interpreted as a BLOB instead
+** of a string, as if it had been CAST.
*/
-case OP_String: { /* out2-prerelease */
+case OP_String: { /* out2 */
assert( pOp->p4.z!=0 );
+ pOut = out2Prerelease(p, pOp);
pOut->flags = MEM_Str|MEM_Static|MEM_Term;
pOut->z = pOp->p4.z;
pOut->n = pOp->p1;
pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
+ if( pOp->p5 ){
+ assert( pOp->p3>0 );
+ assert( pOp->p3<=(p->nMem-p->nCursor) );
+ pIn3 = &aMem[pOp->p3];
+ assert( pIn3->flags & MEM_Int );
+ if( pIn3->u.i ) pOut->flags = MEM_Blob|MEM_Static|MEM_Term;
+ }
break;
}
@@ -71235,9 +71938,10 @@ case OP_String: { /* out2-prerelease */
** NULL values will not compare equal even if SQLITE_NULLEQ is set on
** OP_Ne or OP_Eq.
*/
-case OP_Null: { /* out2-prerelease */
+case OP_Null: { /* out2 */
int cnt;
u16 nullFlag;
+ pOut = out2Prerelease(p, pOp);
cnt = pOp->p3-pOp->p2;
assert( pOp->p3<=(p->nMem-p->nCursor) );
pOut->flags = nullFlag = pOp->p1 ? (MEM_Null|MEM_Cleared) : MEM_Null;
@@ -71272,8 +71976,9 @@ case OP_SoftNull: {
** P4 points to a blob of data P1 bytes long. Store this
** blob in register P2.
*/
-case OP_Blob: { /* out2-prerelease */
+case OP_Blob: { /* out2 */
assert( pOp->p1 <= SQLITE_MAX_LENGTH );
+ pOut = out2Prerelease(p, pOp);
sqlite3VdbeMemSetStr(pOut, pOp->p4.z, pOp->p1, 0, 0);
pOut->enc = encoding;
UPDATE_MAX_BLOBSIZE(pOut);
@@ -71288,7 +71993,7 @@ case OP_Blob: { /* out2-prerelease */
** If the parameter is named, then its name appears in P4.
** The P4 value is used by sqlite3_bind_parameter_name().
*/
-case OP_Variable: { /* out2-prerelease */
+case OP_Variable: { /* out2 */
Mem *pVar; /* Value being transferred */
assert( pOp->p1>0 && pOp->p1<=p->nVar );
@@ -71297,6 +72002,7 @@ case OP_Variable: { /* out2-prerelease */
if( sqlite3VdbeMemTooBig(pVar) ){
goto too_big;
}
+ pOut = out2Prerelease(p, pOp);
sqlite3VdbeMemShallowCopy(pOut, pVar, MEM_Static);
UPDATE_MAX_BLOBSIZE(pOut);
break;
@@ -71331,10 +72037,11 @@ case OP_Move: {
memAboutToChange(p, pOut);
sqlite3VdbeMemMove(pOut, pIn1);
#ifdef SQLITE_DEBUG
- if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<&aMem[p1+pOp->p3] ){
- pOut->pScopyFrom += p1 - pOp->p2;
+ if( pOut->pScopyFrom>=&aMem[p1] && pOut->pScopyFrom<pOut ){
+ pOut->pScopyFrom += pOp->p2 - p1;
}
#endif
+ Deephemeralize(pOut);
REGISTER_TRACE(p2++, pOut);
pIn1++;
pOut++;
@@ -71473,7 +72180,7 @@ case OP_ResultRow: {
/* Return SQLITE_ROW
*/
- p->pc = pc + 1;
+ p->pc = (int)(pOp - aOp) + 1;
rc = SQLITE_ROW;
goto vdbe_return;
}
@@ -71666,7 +72373,7 @@ arithmetic_result_is_null:
**
** The interface used by the implementation of the aforementioned functions
** to retrieve the collation sequence set by this opcode is not available
-** publicly, only to user functions defined in func.c.
+** publicly. Only built-in functions have access to this feature.
*/
case OP_CollSeq: {
assert( pOp->p4type==P4_COLLSEQ );
@@ -71719,7 +72426,7 @@ case OP_Function: {
assert( pOp->p4type==P4_FUNCDEF );
ctx.pFunc = pOp->p4.pFunc;
- ctx.iOp = pc;
+ ctx.iOp = (int)(pOp - aOp);
ctx.pVdbe = p;
MemSetTypeFlag(ctx.pOut, MEM_Null);
ctx.fErrorOrAux = 0;
@@ -71733,7 +72440,7 @@ case OP_Function: {
sqlite3SetString(&p->zErrMsg, db, "%s", sqlite3_value_text(ctx.pOut));
rc = ctx.isError;
}
- sqlite3VdbeDeleteAuxData(p, pc, pOp->p1);
+ sqlite3VdbeDeleteAuxData(p, (int)(pOp - aOp), pOp->p1);
}
/* Copy the result of the function into register P3 */
@@ -71862,8 +72569,7 @@ case OP_MustBeInt: { /* jump, in1 */
rc = SQLITE_MISMATCH;
goto abort_due_to_error;
}else{
- pc = pOp->p2 - 1;
- break;
+ goto jump_to_p2;
}
}
}
@@ -72049,7 +72755,7 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
}else{
VdbeBranchTaken(2,3);
if( pOp->p5 & SQLITE_JUMPIFNULL ){
- pc = pOp->p2-1;
+ goto jump_to_p2;
}
}
break;
@@ -72069,11 +72775,15 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
testcase( pIn1->flags & MEM_Int );
testcase( pIn1->flags & MEM_Real );
sqlite3VdbeMemStringify(pIn1, encoding, 1);
+ testcase( (flags1&MEM_Dyn) != (pIn1->flags&MEM_Dyn) );
+ flags1 = (pIn1->flags & ~MEM_TypeMask) | (flags1 & MEM_TypeMask);
}
if( (pIn3->flags & MEM_Str)==0 && (pIn3->flags & (MEM_Int|MEM_Real))!=0 ){
testcase( pIn3->flags & MEM_Int );
testcase( pIn3->flags & MEM_Real );
sqlite3VdbeMemStringify(pIn3, encoding, 1);
+ testcase( (flags3&MEM_Dyn) != (pIn3->flags&MEM_Dyn) );
+ flags3 = (pIn3->flags & ~MEM_TypeMask) | (flags3 & MEM_TypeMask);
}
}
assert( pOp->p4type==P4_COLLSEQ || pOp->p4.pColl==0 );
@@ -72097,6 +72807,12 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
default: res = res>=0; break;
}
+ /* Undo any changes made by applyAffinity() to the input registers. */
+ assert( (pIn1->flags & MEM_Dyn) == (flags1 & MEM_Dyn) );
+ pIn1->flags = flags1;
+ assert( (pIn3->flags & MEM_Dyn) == (flags3 & MEM_Dyn) );
+ pIn3->flags = flags3;
+
if( pOp->p5 & SQLITE_STOREP2 ){
pOut = &aMem[pOp->p2];
memAboutToChange(p, pOut);
@@ -72106,12 +72822,9 @@ case OP_Ge: { /* same as TK_GE, jump, in1, in3 */
}else{
VdbeBranchTaken(res!=0, (pOp->p5 & SQLITE_NULLEQ)?2:3);
if( res ){
- pc = pOp->p2-1;
+ goto jump_to_p2;
}
}
- /* Undo any changes made by applyAffinity() to the input registers. */
- pIn1->flags = flags1;
- pIn3->flags = flags3;
break;
}
@@ -72206,11 +72919,11 @@ case OP_Compare: {
*/
case OP_Jump: { /* jump */
if( iCompare<0 ){
- pc = pOp->p1 - 1; VdbeBranchTaken(0,3);
+ VdbeBranchTaken(0,3); pOp = &aOp[pOp->p1 - 1];
}else if( iCompare==0 ){
- pc = pOp->p2 - 1; VdbeBranchTaken(1,3);
+ VdbeBranchTaken(1,3); pOp = &aOp[pOp->p2 - 1];
}else{
- pc = pOp->p3 - 1; VdbeBranchTaken(2,3);
+ VdbeBranchTaken(2,3); pOp = &aOp[pOp->p3 - 1];
}
break;
}
@@ -72320,7 +73033,7 @@ case OP_Once: { /* jump */
assert( pOp->p1<p->nOnceFlag );
VdbeBranchTaken(p->aOnceFlag[pOp->p1]!=0, 2);
if( p->aOnceFlag[pOp->p1] ){
- pc = pOp->p2-1;
+ goto jump_to_p2;
}else{
p->aOnceFlag[pOp->p1] = 1;
}
@@ -72355,7 +73068,7 @@ case OP_IfNot: { /* jump, in1 */
}
VdbeBranchTaken(c!=0, 2);
if( c ){
- pc = pOp->p2-1;
+ goto jump_to_p2;
}
break;
}
@@ -72369,7 +73082,7 @@ case OP_IsNull: { /* same as TK_ISNULL, jump, in1 */
pIn1 = &aMem[pOp->p1];
VdbeBranchTaken( (pIn1->flags & MEM_Null)!=0, 2);
if( (pIn1->flags & MEM_Null)!=0 ){
- pc = pOp->p2 - 1;
+ goto jump_to_p2;
}
break;
}
@@ -72383,7 +73096,7 @@ case OP_NotNull: { /* same as TK_NOTNULL, jump, in1 */
pIn1 = &aMem[pOp->p1];
VdbeBranchTaken( (pIn1->flags & MEM_Null)==0, 2);
if( (pIn1->flags & MEM_Null)==0 ){
- pc = pOp->p2 - 1;
+ goto jump_to_p2;
}
break;
}
@@ -72597,7 +73310,7 @@ case OP_Column: {
}
}
- /* If after trying to extra new entries from the header, nHdrParsed is
+ /* If after trying to extract new entries from the header, nHdrParsed is
** still not up to p2, that means that the record has fewer than p2
** columns. So the result will be either the default value or a NULL.
*/
@@ -72721,7 +73434,7 @@ case OP_MakeRecord: {
u64 nData; /* Number of bytes of data space */
int nHdr; /* Number of bytes of header space */
i64 nByte; /* Data space required for this record */
- int nZero; /* Number of zero bytes at the end of the record */
+ i64 nZero; /* Number of zero bytes at the end of the record */
int nVarint; /* Number of bytes in a varint */
u32 serial_type; /* Type field */
Mem *pData0; /* First field to be combined into the record */
@@ -72813,7 +73526,7 @@ case OP_MakeRecord: {
if( nVarint<sqlite3VarintLen(nHdr) ) nHdr++;
}
nByte = nHdr+nData;
- if( nByte>db->aLimit[SQLITE_LIMIT_LENGTH] ){
+ if( nByte+nZero>db->aLimit[SQLITE_LIMIT_LENGTH] ){
goto too_big;
}
@@ -72864,7 +73577,7 @@ case OP_MakeRecord: {
** opened by cursor P1 in register P2
*/
#ifndef SQLITE_OMIT_BTREECOUNT
-case OP_Count: { /* out2-prerelease */
+case OP_Count: { /* out2 */
i64 nEntry;
BtCursor *pCrsr;
@@ -72872,6 +73585,7 @@ case OP_Count: { /* out2-prerelease */
assert( pCrsr );
nEntry = 0; /* Not needed. Only used to silence a warning. */
rc = sqlite3BtreeCount(pCrsr, &nEntry);
+ pOut = out2Prerelease(p, pOp);
pOut->u.i = nEntry;
break;
}
@@ -72985,7 +73699,7 @@ case OP_Savepoint: {
}
db->autoCommit = 1;
if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
- p->pc = pc;
+ p->pc = (int)(pOp - aOp);
db->autoCommit = 0;
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
@@ -73044,7 +73758,7 @@ case OP_Savepoint: {
db->nDeferredImmCons = pSavepoint->nDeferredImmCons;
}
- if( !isTransaction ){
+ if( !isTransaction || p1==SAVEPOINT_ROLLBACK ){
rc = sqlite3VtabSavepoint(db, p1, iSavepoint);
if( rc!=SQLITE_OK ) goto abort_due_to_error;
}
@@ -73104,7 +73818,7 @@ case OP_AutoCommit: {
}else{
db->autoCommit = (u8)desiredAutoCommit;
if( sqlite3VdbeHalt(p)==SQLITE_BUSY ){
- p->pc = pc;
+ p->pc = (int)(pOp - aOp);
db->autoCommit = (u8)(1-desiredAutoCommit);
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
@@ -73181,7 +73895,7 @@ case OP_Transaction: {
if( pBt ){
rc = sqlite3BtreeBeginTrans(pBt, pOp->p2);
if( rc==SQLITE_BUSY ){
- p->pc = pc;
+ p->pc = (int)(pOp - aOp);
p->rc = rc = SQLITE_BUSY;
goto vdbe_return;
}
@@ -73211,7 +73925,12 @@ case OP_Transaction: {
p->nStmtDefImmCons = db->nDeferredImmCons;
}
- /* Gather the schema version number for checking */
+ /* Gather the schema version number for checking:
+ ** IMPLEMENTATION-OF: R-32195-19465 The schema version is used by SQLite
+ ** each time a query is executed to ensure that the internal cache of the
+ ** schema used when compiling the SQL query matches the schema of the
+ ** database against which the compiled query is actually executed.
+ */
sqlite3BtreeGetMeta(pBt, BTREE_SCHEMA_VERSION, (u32 *)&iMeta);
iGen = db->aDb[pOp->p1].pSchema->iGeneration;
}else{
@@ -73255,7 +73974,7 @@ case OP_Transaction: {
** must be started or there must be an open cursor) before
** executing this instruction.
*/
-case OP_ReadCookie: { /* out2-prerelease */
+case OP_ReadCookie: { /* out2 */
int iMeta;
int iDb;
int iCookie;
@@ -73269,6 +73988,7 @@ case OP_ReadCookie: { /* out2-prerelease */
assert( DbMaskTest(p->btreeMask, iDb) );
sqlite3BtreeGetMeta(db->aDb[iDb].pBt, iCookie, (u32 *)&iMeta);
+ pOut = out2Prerelease(p, pOp);
pOut->u.i = iMeta;
break;
}
@@ -73379,31 +74099,29 @@ case OP_SetCookie: { /* in3 */
** See also OpenRead.
*/
case OP_ReopenIdx: {
+ int nField;
+ KeyInfo *pKeyInfo;
+ int p2;
+ int iDb;
+ int wrFlag;
+ Btree *pX;
VdbeCursor *pCur;
+ Db *pDb;
- assert( pOp->p5==0 );
+ assert( pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
assert( pOp->p4type==P4_KEYINFO );
pCur = p->apCsr[pOp->p1];
if( pCur && pCur->pgnoRoot==(u32)pOp->p2 ){
assert( pCur->iDb==pOp->p3 ); /* Guaranteed by the code generator */
- break;
+ goto open_cursor_set_hints;
}
/* If the cursor is not currently open or is open on a different
** index, then fall through into OP_OpenRead to force a reopen */
-}
case OP_OpenRead:
-case OP_OpenWrite: {
- int nField;
- KeyInfo *pKeyInfo;
- int p2;
- int iDb;
- int wrFlag;
- Btree *pX;
- VdbeCursor *pCur;
- Db *pDb;
+case OP_OpenWrite:
- assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR))==pOp->p5 );
- assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 );
+ assert( (pOp->p5&(OPFLAG_P2ISREG|OPFLAG_BULKCSR|OPFLAG_SEEKEQ))==pOp->p5 );
+ assert( pOp->opcode==OP_OpenWrite || pOp->p5==0 || pOp->p5==OPFLAG_SEEKEQ );
assert( p->bIsReader );
assert( pOp->opcode==OP_OpenRead || pOp->opcode==OP_ReopenIdx
|| p->readOnly==0 );
@@ -73466,14 +74184,17 @@ case OP_OpenWrite: {
pCur->pgnoRoot = p2;
rc = sqlite3BtreeCursor(pX, p2, wrFlag, pKeyInfo, pCur->pCursor);
pCur->pKeyInfo = pKeyInfo;
- assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
- sqlite3BtreeCursorHints(pCur->pCursor, (pOp->p5 & OPFLAG_BULKCSR));
-
/* Set the VdbeCursor.isTable variable. Previous versions of
** SQLite used to check if the root-page flags were sane at this point
** and report database corruption if they were not, but this check has
** since moved into the btree layer. */
pCur->isTable = pOp->p4type!=P4_KEYINFO;
+
+open_cursor_set_hints:
+ assert( OPFLAG_BULKCSR==BTREE_BULKLOAD );
+ assert( OPFLAG_SEEKEQ==BTREE_SEEK_EQ );
+ sqlite3BtreeCursorHints(pCur->pCursor,
+ (pOp->p5 & (OPFLAG_BULKCSR|OPFLAG_SEEKEQ)));
break;
}
@@ -73589,7 +74310,7 @@ case OP_SequenceTest: {
pC = p->apCsr[pOp->p1];
assert( pC->pSorter );
if( (pC->seqCount++)==0 ){
- pc = pOp->p2 - 1;
+ goto jump_to_p2;
}
break;
}
@@ -73734,6 +74455,22 @@ case OP_SeekGT: { /* jump, in3 */
#ifdef SQLITE_DEBUG
pC->seekOp = pOp->opcode;
#endif
+
+ /* For a cursor with the BTREE_SEEK_EQ hint, only the OP_SeekGE and
+ ** OP_SeekLE opcodes are allowed, and these must be immediately followed
+ ** by an OP_IdxGT or OP_IdxLT opcode, respectively, with the same key.
+ */
+#ifdef SQLITE_DEBUG
+ if( sqlite3BtreeCursorHasHint(pC->pCursor, BTREE_SEEK_EQ) ){
+ assert( pOp->opcode==OP_SeekGE || pOp->opcode==OP_SeekLE );
+ assert( pOp[1].opcode==OP_IdxLT || pOp[1].opcode==OP_IdxGT );
+ assert( pOp[1].p1==pOp[0].p1 );
+ assert( pOp[1].p2==pOp[0].p2 );
+ assert( pOp[1].p3==pOp[0].p3 );
+ assert( pOp[1].p4.i==pOp[0].p4.i );
+ }
+#endif
+
if( pC->isTable ){
/* The input value in P3 might be of any type: integer, real, string,
** blob, or NULL. But it needs to be an integer before we can do
@@ -73750,7 +74487,7 @@ case OP_SeekGT: { /* jump, in3 */
if( (pIn3->flags & MEM_Real)==0 ){
/* If the P3 value cannot be converted into any kind of a number,
** then the seek is not possible, so jump to P2 */
- pc = pOp->p2 - 1; VdbeBranchTaken(1,2);
+ VdbeBranchTaken(1,2); goto jump_to_p2;
break;
}
@@ -73841,7 +74578,7 @@ case OP_SeekGT: { /* jump, in3 */
assert( pOp->p2>0 );
VdbeBranchTaken(res!=0,2);
if( res ){
- pc = pOp->p2 - 1;
+ goto jump_to_p2;
}
break;
}
@@ -73935,6 +74672,7 @@ case OP_NoConflict: /* jump, in3 */
case OP_NotFound: /* jump, in3 */
case OP_Found: { /* jump, in3 */
int alreadyExists;
+ int takeJump;
int ii;
VdbeCursor *pC;
int res;
@@ -73957,7 +74695,7 @@ case OP_Found: { /* jump, in3 */
pIn3 = &aMem[pOp->p3];
assert( pC->pCursor!=0 );
assert( pC->isTable==0 );
- pFree = 0; /* Not needed. Only used to suppress a compiler warning. */
+ pFree = 0;
if( pOp->p4.i>0 ){
r.pKeyInfo = pC->pKeyInfo;
r.nField = (u16)pOp->p4.i;
@@ -73980,21 +74718,20 @@ case OP_Found: { /* jump, in3 */
sqlite3VdbeRecordUnpack(pC->pKeyInfo, pIn3->n, pIn3->z, pIdxKey);
}
pIdxKey->default_rc = 0;
+ takeJump = 0;
if( pOp->opcode==OP_NoConflict ){
/* For the OP_NoConflict opcode, take the jump if any of the
** input fields are NULL, since any key with a NULL will not
** conflict */
for(ii=0; ii<pIdxKey->nField; ii++){
if( pIdxKey->aMem[ii].flags & MEM_Null ){
- pc = pOp->p2 - 1; VdbeBranchTaken(1,2);
+ takeJump = 1;
break;
}
}
}
rc = sqlite3BtreeMovetoUnpacked(pC->pCursor, pIdxKey, 0, 0, &res);
- if( pOp->p4.i==0 ){
- sqlite3DbFree(db, pFree);
- }
+ sqlite3DbFree(db, pFree);
if( rc!=SQLITE_OK ){
break;
}
@@ -74005,10 +74742,10 @@ case OP_Found: { /* jump, in3 */
pC->cacheStatus = CACHE_STALE;
if( pOp->opcode==OP_Found ){
VdbeBranchTaken(alreadyExists!=0,2);
- if( alreadyExists ) pc = pOp->p2 - 1;
+ if( alreadyExists ) goto jump_to_p2;
}else{
- VdbeBranchTaken(alreadyExists==0,2);
- if( !alreadyExists ) pc = pOp->p2 - 1;
+ VdbeBranchTaken(takeJump||alreadyExists==0,2);
+ if( takeJump || !alreadyExists ) goto jump_to_p2;
}
break;
}
@@ -74057,10 +74794,8 @@ case OP_NotExists: { /* jump, in3 */
pC->cacheStatus = CACHE_STALE;
pC->deferredMoveto = 0;
VdbeBranchTaken(res!=0,2);
- if( res!=0 ){
- pc = pOp->p2 - 1;
- }
pC->seekResult = res;
+ if( res!=0 ) goto jump_to_p2;
break;
}
@@ -74072,9 +74807,10 @@ case OP_NotExists: { /* jump, in3 */
** The sequence number on the cursor is incremented after this
** instruction.
*/
-case OP_Sequence: { /* out2-prerelease */
+case OP_Sequence: { /* out2 */
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
assert( p->apCsr[pOp->p1]!=0 );
+ pOut = out2Prerelease(p, pOp);
pOut->u.i = p->apCsr[pOp->p1]->seqCount++;
break;
}
@@ -74095,7 +74831,7 @@ case OP_Sequence: { /* out2-prerelease */
** generated record number. This P3 mechanism is used to help implement the
** AUTOINCREMENT feature.
*/
-case OP_NewRowid: { /* out2-prerelease */
+case OP_NewRowid: { /* out2 */
i64 v; /* The new rowid */
VdbeCursor *pC; /* Cursor of table to get the new rowid */
int res; /* Result of an sqlite3BtreeLast() */
@@ -74105,6 +74841,7 @@ case OP_NewRowid: { /* out2-prerelease */
v = 0;
res = 0;
+ pOut = out2Prerelease(p, pOp);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
@@ -74418,9 +75155,7 @@ case OP_SorterCompare: {
res = 0;
rc = sqlite3VdbeSorterCompare(pC, pIn3, nKeyCol, &res);
VdbeBranchTaken(res!=0,2);
- if( res ){
- pc = pOp->p2-1;
- }
+ if( res ) goto jump_to_p2;
break;
};
@@ -74549,12 +75284,13 @@ case OP_RowData: {
** be a separate OP_VRowid opcode for use with virtual tables, but this
** one opcode now works for both table types.
*/
-case OP_Rowid: { /* out2-prerelease */
+case OP_Rowid: { /* out2 */
VdbeCursor *pC;
i64 v;
sqlite3_vtab *pVtab;
const sqlite3_module *pModule;
+ pOut = out2Prerelease(p, pOp);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
@@ -74607,7 +75343,7 @@ case OP_NullRow: {
break;
}
-/* Opcode: Last P1 P2 * * *
+/* Opcode: Last P1 P2 P3 * *
**
** The next use of the Rowid or Column or Prev instruction for P1
** will refer to the last entry in the database table or index.
@@ -74634,12 +75370,13 @@ case OP_Last: { /* jump */
pC->nullRow = (u8)res;
pC->deferredMoveto = 0;
pC->cacheStatus = CACHE_STALE;
+ pC->seekResult = pOp->p3;
#ifdef SQLITE_DEBUG
pC->seekOp = OP_Last;
#endif
if( pOp->p2>0 ){
VdbeBranchTaken(res!=0,2);
- if( res ) pc = pOp->p2 - 1;
+ if( res ) goto jump_to_p2;
}
break;
}
@@ -74703,9 +75440,7 @@ case OP_Rewind: { /* jump */
pC->nullRow = (u8)res;
assert( pOp->p2>0 && pOp->p2<p->nOp );
VdbeBranchTaken(res!=0,2);
- if( res ){
- pc = pOp->p2 - 1;
- }
+ if( res ) goto jump_to_p2;
break;
}
@@ -74816,11 +75551,11 @@ next_tail:
VdbeBranchTaken(res==0,2);
if( res==0 ){
pC->nullRow = 0;
- pc = pOp->p2 - 1;
p->aCounter[pOp->p5]++;
#ifdef SQLITE_TEST
sqlite3_search_count++;
#endif
+ goto jump_to_p2_and_check_for_interrupt;
}else{
pC->nullRow = 1;
}
@@ -74928,11 +75663,12 @@ case OP_IdxDelete: {
**
** See also: Rowid, MakeRecord.
*/
-case OP_IdxRowid: { /* out2-prerelease */
+case OP_IdxRowid: { /* out2 */
BtCursor *pCrsr;
VdbeCursor *pC;
i64 rowid;
+ pOut = out2Prerelease(p, pOp);
assert( pOp->p1>=0 && pOp->p1<p->nCursor );
pC = p->apCsr[pOp->p1];
assert( pC!=0 );
@@ -75045,9 +75781,7 @@ case OP_IdxGE: { /* jump */
res++;
}
VdbeBranchTaken(res>0,2);
- if( res>0 ){
- pc = pOp->p2 - 1 ;
- }
+ if( res>0 ) goto jump_to_p2;
break;
}
@@ -75071,32 +75805,18 @@ case OP_IdxGE: { /* jump */
**
** See also: Clear
*/
-case OP_Destroy: { /* out2-prerelease */
+case OP_Destroy: { /* out2 */
int iMoved;
- int iCnt;
- Vdbe *pVdbe;
int iDb;
assert( p->readOnly==0 );
-#ifndef SQLITE_OMIT_VIRTUALTABLE
- iCnt = 0;
- for(pVdbe=db->pVdbe; pVdbe; pVdbe = pVdbe->pNext){
- if( pVdbe->magic==VDBE_MAGIC_RUN && pVdbe->bIsReader
- && pVdbe->inVtabMethod<2 && pVdbe->pc>=0
- ){
- iCnt++;
- }
- }
-#else
- iCnt = db->nVdbeRead;
-#endif
+ pOut = out2Prerelease(p, pOp);
pOut->flags = MEM_Null;
- if( iCnt>1 ){
+ if( db->nVdbeRead > db->nVDestroy+1 ){
rc = SQLITE_LOCKED;
p->errorAction = OE_Abort;
}else{
iDb = pOp->p3;
- assert( iCnt==1 );
assert( DbMaskTest(p->btreeMask, iDb) );
iMoved = 0; /* Not needed. Only to silence a warning. */
rc = sqlite3BtreeDropTable(db->aDb[iDb].pBt, pOp->p1, &iMoved);
@@ -75199,12 +75919,13 @@ case OP_ResetSorter: {
**
** See documentation on OP_CreateTable for additional information.
*/
-case OP_CreateIndex: /* out2-prerelease */
-case OP_CreateTable: { /* out2-prerelease */
+case OP_CreateIndex: /* out2 */
+case OP_CreateTable: { /* out2 */
int pgno;
int flags;
Db *pDb;
+ pOut = out2Prerelease(p, pOp);
pgno = 0;
assert( pOp->p1>=0 && pOp->p1<db->nDb );
assert( DbMaskTest(p->btreeMask, pOp->p1) );
@@ -75430,12 +76151,12 @@ case OP_RowSetRead: { /* jump, in1, out3 */
){
/* The boolean index is empty */
sqlite3VdbeMemSetNull(pIn1);
- pc = pOp->p2 - 1;
VdbeBranchTaken(1,2);
+ goto jump_to_p2_and_check_for_interrupt;
}else{
/* A value was pulled from the index */
- sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val);
VdbeBranchTaken(0,2);
+ sqlite3VdbeMemSetInt64(&aMem[pOp->p3], val);
}
goto check_for_interrupt;
}
@@ -75486,10 +76207,7 @@ case OP_RowSetTest: { /* jump, in1, in3 */
if( iSet ){
exists = sqlite3RowSetTest(pIn1->u.pRowSet, iSet, pIn3->u.i);
VdbeBranchTaken(exists!=0,2);
- if( exists ){
- pc = pOp->p2 - 1;
- break;
- }
+ if( exists ) goto jump_to_p2;
}
if( iSet>=0 ){
sqlite3RowSetInsert(pIn1->u.pRowSet, pIn3->u.i);
@@ -75578,7 +76296,7 @@ case OP_Program: { /* jump */
pFrame->v = p;
pFrame->nChildMem = nMem;
pFrame->nChildCsr = pProgram->nCsr;
- pFrame->pc = pc;
+ pFrame->pc = (int)(pOp - aOp);
pFrame->aMem = p->aMem;
pFrame->nMem = p->nMem;
pFrame->apCsr = p->apCsr;
@@ -75601,7 +76319,7 @@ case OP_Program: { /* jump */
pFrame = pRt->u.pFrame;
assert( pProgram->nMem+pProgram->nCsr==pFrame->nChildMem );
assert( pProgram->nCsr==pFrame->nChildCsr );
- assert( pc==pFrame->pc );
+ assert( (int)(pOp - aOp)==pFrame->pc );
}
p->nFrame++;
@@ -75622,7 +76340,7 @@ case OP_Program: { /* jump */
#ifdef SQLITE_ENABLE_STMT_SCANSTATUS
p->anExec = 0;
#endif
- pc = -1;
+ pOp = &aOp[-1];
memset(p->aOnceFlag, 0, p->nOnceFlag);
break;
@@ -75640,9 +76358,10 @@ case OP_Program: { /* jump */
** the value of the P1 argument to the value of the P1 argument to the
** calling OP_Program instruction.
*/
-case OP_Param: { /* out2-prerelease */
+case OP_Param: { /* out2 */
VdbeFrame *pFrame;
Mem *pIn;
+ pOut = out2Prerelease(p, pOp);
pFrame = p->pFrame;
pIn = &pFrame->aMem[pOp->p1 + pFrame->aOp[pFrame->pc].p1];
sqlite3VdbeMemShallowCopy(pOut, pIn, MEM_Ephem);
@@ -75686,10 +76405,10 @@ case OP_FkCounter: {
case OP_FkIfZero: { /* jump */
if( pOp->p1 ){
VdbeBranchTaken(db->nDeferredCons==0 && db->nDeferredImmCons==0, 2);
- if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
+ if( db->nDeferredCons==0 && db->nDeferredImmCons==0 ) goto jump_to_p2;
}else{
VdbeBranchTaken(p->nFkConstraint==0 && db->nDeferredImmCons==0, 2);
- if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) pc = pOp->p2-1;
+ if( p->nFkConstraint==0 && db->nDeferredImmCons==0 ) goto jump_to_p2;
}
break;
}
@@ -75729,18 +76448,18 @@ case OP_MemMax: { /* in2 */
/* Opcode: IfPos P1 P2 * * *
** Synopsis: if r[P1]>0 goto P2
**
-** If the value of register P1 is 1 or greater, jump to P2.
+** Register P1 must contain an integer.
+** If the value of register P1 is 1 or greater, jump to P2 and
+** add the literal value P3 to register P1.
**
-** It is illegal to use this instruction on a register that does
-** not contain an integer. An assertion fault will result if you try.
+** If the initial value of register P1 is less than 1, then the
+** value is unchanged and control passes through to the next instruction.
*/
case OP_IfPos: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int );
VdbeBranchTaken( pIn1->u.i>0, 2);
- if( pIn1->u.i>0 ){
- pc = pOp->p2 - 1;
- }
+ if( pIn1->u.i>0 ) goto jump_to_p2;
break;
}
@@ -75755,26 +76474,56 @@ case OP_IfNeg: { /* jump, in1 */
assert( pIn1->flags&MEM_Int );
pIn1->u.i += pOp->p3;
VdbeBranchTaken(pIn1->u.i<0, 2);
- if( pIn1->u.i<0 ){
- pc = pOp->p2 - 1;
+ if( pIn1->u.i<0 ) goto jump_to_p2;
+ break;
+}
+
+/* Opcode: IfNotZero P1 P2 P3 * *
+** Synopsis: if r[P1]!=0 then r[P1]+=P3, goto P2
+**
+** Register P1 must contain an integer. If the content of register P1 is
+** initially nonzero, then add P3 to P1 and jump to P2. If register P1 is
+** initially zero, leave it unchanged and fall through.
+*/
+case OP_IfNotZero: { /* jump, in1 */
+ pIn1 = &aMem[pOp->p1];
+ assert( pIn1->flags&MEM_Int );
+ VdbeBranchTaken(pIn1->u.i<0, 2);
+ if( pIn1->u.i ){
+ pIn1->u.i += pOp->p3;
+ goto jump_to_p2;
}
break;
}
-/* Opcode: IfZero P1 P2 P3 * *
-** Synopsis: r[P1]+=P3, if r[P1]==0 goto P2
+/* Opcode: DecrJumpZero P1 P2 * * *
+** Synopsis: if (--r[P1])==0 goto P2
**
-** The register P1 must contain an integer. Add literal P3 to the
-** value in register P1. If the result is exactly 0, jump to P2.
+** Register P1 must hold an integer. Decrement the value in register P1
+** then jump to P2 if the new value is exactly zero.
*/
-case OP_IfZero: { /* jump, in1 */
+case OP_DecrJumpZero: { /* jump, in1 */
pIn1 = &aMem[pOp->p1];
assert( pIn1->flags&MEM_Int );
- pIn1->u.i += pOp->p3;
+ pIn1->u.i--;
VdbeBranchTaken(pIn1->u.i==0, 2);
- if( pIn1->u.i==0 ){
- pc = pOp->p2 - 1;
- }
+ if( pIn1->u.i==0 ) goto jump_to_p2;
+ break;
+}
+
+
+/* Opcode: JumpZeroIncr P1 P2 * * *
+** Synopsis: if (r[P1]++)==0 ) goto P2
+**
+** The register P1 must contain an integer. If register P1 is initially
+** zero, then jump to P2. Increment register P1 regardless of whether or
+** not the jump is taken.
+*/
+case OP_JumpZeroIncr: { /* jump, in1 */
+ pIn1 = &aMem[pOp->p1];
+ assert( pIn1->flags&MEM_Int );
+ VdbeBranchTaken(pIn1->u.i==0, 2);
+ if( (pIn1->u.i++)==0 ) goto jump_to_p2;
break;
}
@@ -75816,7 +76565,7 @@ case OP_AggStep: {
ctx.pOut = &t;
ctx.isError = 0;
ctx.pVdbe = p;
- ctx.iOp = pc;
+ ctx.iOp = (int)(pOp - aOp);
ctx.skipFlag = 0;
(ctx.pFunc->xStep)(&ctx, n, apVal); /* IMP: R-24505-23230 */
if( ctx.isError ){
@@ -75911,7 +76660,7 @@ case OP_Checkpoint: {
**
** Write a string containing the final journal-mode to register P2.
*/
-case OP_JournalMode: { /* out2-prerelease */
+case OP_JournalMode: { /* out2 */
Btree *pBt; /* Btree to change journal mode of */
Pager *pPager; /* Pager associated with pBt */
int eNew; /* New journal mode */
@@ -75920,6 +76669,7 @@ case OP_JournalMode: { /* out2-prerelease */
const char *zFilename; /* Name of database file for pPager */
#endif
+ pOut = out2Prerelease(p, pOp);
eNew = pOp->p3;
assert( eNew==PAGER_JOURNALMODE_DELETE
|| eNew==PAGER_JOURNALMODE_TRUNCATE
@@ -75995,7 +76745,6 @@ case OP_JournalMode: { /* out2-prerelease */
}
eNew = sqlite3PagerSetJournalMode(pPager, eNew);
- pOut = &aMem[pOp->p2];
pOut->flags = MEM_Str|MEM_Static|MEM_Term;
pOut->z = (char *)sqlite3JournalModename(eNew);
pOut->n = sqlite3Strlen30(pOut->z);
@@ -76036,8 +76785,8 @@ case OP_IncrVacuum: { /* jump */
rc = sqlite3BtreeIncrVacuum(pBt);
VdbeBranchTaken(rc==SQLITE_DONE,2);
if( rc==SQLITE_DONE ){
- pc = pOp->p2 - 1;
rc = SQLITE_OK;
+ goto jump_to_p2;
}
break;
}
@@ -76115,13 +76864,29 @@ case OP_VBegin: {
#endif /* SQLITE_OMIT_VIRTUALTABLE */
#ifndef SQLITE_OMIT_VIRTUALTABLE
-/* Opcode: VCreate P1 * * P4 *
+/* Opcode: VCreate P1 P2 * * *
**
-** P4 is the name of a virtual table in database P1. Call the xCreate method
-** for that table.
+** P2 is a register that holds the name of a virtual table in database
+** P1. Call the xCreate method for that table.
*/
case OP_VCreate: {
- rc = sqlite3VtabCallCreate(db, pOp->p1, pOp->p4.z, &p->zErrMsg);
+ Mem sMem; /* For storing the record being decoded */
+ const char *zTab; /* Name of the virtual table */
+
+ memset(&sMem, 0, sizeof(sMem));
+ sMem.db = db;
+ /* Because P2 is always a static string, it is impossible for the
+ ** sqlite3VdbeMemCopy() to fail */
+ assert( (aMem[pOp->p2].flags & MEM_Str)!=0 );
+ assert( (aMem[pOp->p2].flags & MEM_Static)!=0 );
+ rc = sqlite3VdbeMemCopy(&sMem, &aMem[pOp->p2]);
+ assert( rc==SQLITE_OK );
+ zTab = (const char*)sqlite3_value_text(&sMem);
+ assert( zTab || db->mallocFailed );
+ if( zTab ){
+ rc = sqlite3VtabCallCreate(db, pOp->p1, zTab, &p->zErrMsg);
+ }
+ sqlite3VdbeMemRelease(&sMem);
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -76133,9 +76898,9 @@ case OP_VCreate: {
** of that table.
*/
case OP_VDestroy: {
- p->inVtabMethod = 2;
+ db->nVDestroy++;
rc = sqlite3VtabCallDestroy(db, pOp->p1, pOp->p4.z);
- p->inVtabMethod = 0;
+ db->nVDestroy--;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -76151,14 +76916,17 @@ case OP_VOpen: {
VdbeCursor *pCur;
sqlite3_vtab_cursor *pVtabCursor;
sqlite3_vtab *pVtab;
- sqlite3_module *pModule;
+ const sqlite3_module *pModule;
assert( p->bIsReader );
pCur = 0;
pVtabCursor = 0;
pVtab = pOp->p4.pVtab->pVtab;
- pModule = (sqlite3_module *)pVtab->pModule;
- assert(pVtab && pModule);
+ if( pVtab==0 || NEVER(pVtab->pModule==0) ){
+ rc = SQLITE_LOCKED;
+ break;
+ }
+ pModule = pVtab->pModule;
rc = pModule->xOpen(pVtab, &pVtabCursor);
sqlite3VtabImportErrmsg(p, pVtab);
if( SQLITE_OK==rc ){
@@ -76169,9 +76937,11 @@ case OP_VOpen: {
pCur = allocateCursor(p, pOp->p1, 0, -1, 0);
if( pCur ){
pCur->pVtabCursor = pVtabCursor;
+ pVtab->nRef++;
}else{
- db->mallocFailed = 1;
+ assert( db->mallocFailed );
pModule->xClose(pVtabCursor);
+ goto no_mem;
}
}
break;
@@ -76227,27 +76997,19 @@ case OP_VFilter: { /* jump */
iQuery = (int)pQuery->u.i;
/* Invoke the xFilter method */
- {
- res = 0;
- apArg = p->apArg;
- for(i = 0; i<nArg; i++){
- apArg[i] = &pArgc[i+1];
- }
-
- p->inVtabMethod = 1;
- rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
- p->inVtabMethod = 0;
- sqlite3VtabImportErrmsg(p, pVtab);
- if( rc==SQLITE_OK ){
- res = pModule->xEof(pVtabCursor);
- }
- VdbeBranchTaken(res!=0,2);
- if( res ){
- pc = pOp->p2 - 1;
- }
+ res = 0;
+ apArg = p->apArg;
+ for(i = 0; i<nArg; i++){
+ apArg[i] = &pArgc[i+1];
+ }
+ rc = pModule->xFilter(pVtabCursor, iQuery, pOp->p4.z, nArg, apArg);
+ sqlite3VtabImportErrmsg(p, pVtab);
+ if( rc==SQLITE_OK ){
+ res = pModule->xEof(pVtabCursor);
}
pCur->nullRow = 0;
-
+ VdbeBranchTaken(res!=0,2);
+ if( res ) goto jump_to_p2;
break;
}
#endif /* SQLITE_OMIT_VIRTUALTABLE */
@@ -76326,9 +77088,7 @@ case OP_VNext: { /* jump */
** data is available) and the error code returned when xColumn or
** some other method is next invoked on the save virtual table cursor.
*/
- p->inVtabMethod = 1;
rc = pModule->xNext(pCur->pVtabCursor);
- p->inVtabMethod = 0;
sqlite3VtabImportErrmsg(p, pVtab);
if( rc==SQLITE_OK ){
res = pModule->xEof(pCur->pVtabCursor);
@@ -76336,7 +77096,7 @@ case OP_VNext: { /* jump */
VdbeBranchTaken(!res,2);
if( !res ){
/* If there is data, jump to P2 */
- pc = pOp->p2 - 1;
+ goto jump_to_p2_and_check_for_interrupt;
}
goto check_for_interrupt;
}
@@ -76403,7 +77163,7 @@ case OP_VRename: {
*/
case OP_VUpdate: {
sqlite3_vtab *pVtab;
- sqlite3_module *pModule;
+ const sqlite3_module *pModule;
int nArg;
int i;
sqlite_int64 rowid;
@@ -76415,7 +77175,11 @@ case OP_VUpdate: {
);
assert( p->readOnly==0 );
pVtab = pOp->p4.pVtab->pVtab;
- pModule = (sqlite3_module *)pVtab->pModule;
+ if( pVtab==0 || NEVER(pVtab->pModule==0) ){
+ rc = SQLITE_LOCKED;
+ break;
+ }
+ pModule = pVtab->pModule;
nArg = pOp->p2;
assert( pOp->p4type==P4_VTAB );
if( ALWAYS(pModule->xUpdate) ){
@@ -76455,7 +77219,8 @@ case OP_VUpdate: {
**
** Write the current number of pages in database P1 to memory cell P2.
*/
-case OP_Pagecount: { /* out2-prerelease */
+case OP_Pagecount: { /* out2 */
+ pOut = out2Prerelease(p, pOp);
pOut->u.i = sqlite3BtreeLastPage(db->aDb[pOp->p1].pBt);
break;
}
@@ -76471,10 +77236,11 @@ case OP_Pagecount: { /* out2-prerelease */
**
** Store the maximum page count after the change in register P2.
*/
-case OP_MaxPgcnt: { /* out2-prerelease */
+case OP_MaxPgcnt: { /* out2 */
unsigned int newMax;
Btree *pBt;
+ pOut = out2Prerelease(p, pOp);
pBt = db->aDb[pOp->p1].pBt;
newMax = 0;
if( pOp->p3 ){
@@ -76503,9 +77269,6 @@ case OP_Init: { /* jump */
char *zTrace;
char *z;
- if( pOp->p2 ){
- pc = pOp->p2 - 1;
- }
#ifndef SQLITE_OMIT_TRACE
if( db->xTrace
&& !p->doingRerun
@@ -76533,6 +77296,7 @@ case OP_Init: { /* jump */
}
#endif /* SQLITE_DEBUG */
#endif /* SQLITE_OMIT_TRACE */
+ if( pOp->p2 ) goto jump_to_p2;
break;
}
@@ -76564,8 +77328,8 @@ default: { /* This is really OP_Noop and OP_Explain */
#ifdef VDBE_PROFILE
{
u64 endTime = sqlite3Hwtime();
- if( endTime>start ) pOp->cycles += endTime - start;
- pOp->cnt++;
+ if( endTime>start ) pOrigOp->cycles += endTime - start;
+ pOrigOp->cnt++;
}
#endif
@@ -76575,16 +77339,16 @@ default: { /* This is really OP_Noop and OP_Explain */
** the evaluator loop. So we can leave it out when NDEBUG is defined.
*/
#ifndef NDEBUG
- assert( pc>=-1 && pc<p->nOp );
+ assert( pOp>=&aOp[-1] && pOp<&aOp[p->nOp-1] );
#ifdef SQLITE_DEBUG
if( db->flags & SQLITE_VdbeTrace ){
if( rc!=0 ) printf("rc=%d\n",rc);
- if( pOp->opflags & (OPFLG_OUT2_PRERELEASE|OPFLG_OUT2) ){
- registerTrace(pOp->p2, &aMem[pOp->p2]);
+ if( pOrigOp->opflags & (OPFLG_OUT2) ){
+ registerTrace(pOrigOp->p2, &aMem[pOrigOp->p2]);
}
- if( pOp->opflags & OPFLG_OUT3 ){
- registerTrace(pOp->p3, &aMem[pOp->p3]);
+ if( pOrigOp->opflags & OPFLG_OUT3 ){
+ registerTrace(pOrigOp->p3, &aMem[pOrigOp->p3]);
}
}
#endif /* SQLITE_DEBUG */
@@ -76599,7 +77363,7 @@ vdbe_error_halt:
p->rc = rc;
testcase( sqlite3GlobalConfig.xLog!=0 );
sqlite3_log(rc, "statement aborts at %d: [%s] %s",
- pc, p->zSql, p->zErrMsg);
+ (int)(pOp - aOp), p->zSql, p->zErrMsg);
sqlite3VdbeHalt(p);
if( rc==SQLITE_IOERR_NOMEM ) db->mallocFailed = 1;
rc = SQLITE_ERROR;
@@ -76762,7 +77526,7 @@ static int blobSeekToRow(Incrblob *p, sqlite3_int64 iRow, char **pzErr){
/*
** Open a blob handle.
*/
-SQLITE_API int sqlite3_blob_open(
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_open(
sqlite3* db, /* The database connection */
const char *zDb, /* The attached database containing the blob */
const char *zTable, /* The table containing the blob */
@@ -76812,12 +77576,17 @@ SQLITE_API int sqlite3_blob_open(
Incrblob *pBlob = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || ppBlob==0 || zTable==0 ){
+ if( ppBlob==0 ){
return SQLITE_MISUSE_BKPT;
}
#endif
- flags = !!flags; /* flags = (flags ? 1 : 0); */
*ppBlob = 0;
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) || zTable==0 ){
+ return SQLITE_MISUSE_BKPT;
+ }
+#endif
+ flags = !!flags; /* flags = (flags ? 1 : 0); */
sqlite3_mutex_enter(db->mutex);
@@ -76994,7 +77763,7 @@ blob_open_out:
** Close a blob handle that was previously created using
** sqlite3_blob_open().
*/
-SQLITE_API int sqlite3_blob_close(sqlite3_blob *pBlob){
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *pBlob){
Incrblob *p = (Incrblob *)pBlob;
int rc;
sqlite3 *db;
@@ -77031,7 +77800,7 @@ static int blobReadWrite(
sqlite3_mutex_enter(db->mutex);
v = (Vdbe*)p->pStmt;
- if( n<0 || iOffset<0 || (iOffset+n)>p->nByte ){
+ if( n<0 || iOffset<0 || ((sqlite3_int64)iOffset+n)>p->nByte ){
/* Request is out of range. Return a transient error. */
rc = SQLITE_ERROR;
}else if( v==0 ){
@@ -77063,14 +77832,14 @@ static int blobReadWrite(
/*
** Read data from a blob handle.
*/
-SQLITE_API int sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *pBlob, void *z, int n, int iOffset){
return blobReadWrite(pBlob, z, n, iOffset, sqlite3BtreeData);
}
/*
** Write data to a blob handle.
*/
-SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int iOffset){
return blobReadWrite(pBlob, (void *)z, n, iOffset, sqlite3BtreePutData);
}
@@ -77080,7 +77849,7 @@ SQLITE_API int sqlite3_blob_write(sqlite3_blob *pBlob, const void *z, int n, int
** The Incrblob.nByte field is fixed for the lifetime of the Incrblob
** so no mutex is required for access.
*/
-SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *pBlob){
Incrblob *p = (Incrblob *)pBlob;
return (p && p->pStmt) ? p->nByte : 0;
}
@@ -77095,7 +77864,7 @@ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *pBlob){
** subsequent calls to sqlite3_blob_xxx() functions (except blob_close())
** immediately return SQLITE_ABORT.
*/
-SQLITE_API int sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *pBlob, sqlite3_int64 iRow){
int rc;
Incrblob *p = (Incrblob *)pBlob;
sqlite3 *db;
@@ -77420,6 +78189,7 @@ struct MergeEngine {
** after the thread has finished are not dire. So we don't worry about
** memory barriers and such here.
*/
+typedef int (*SorterCompare)(SortSubtask*,int*,const void*,int,const void*,int);
struct SortSubtask {
SQLiteThread *pThread; /* Background thread, if any */
int bDone; /* Set if thread is finished but not joined */
@@ -77427,10 +78197,12 @@ struct SortSubtask {
UnpackedRecord *pUnpacked; /* Space to unpack a record */
SorterList list; /* List for thread to write to a PMA */
int nPMA; /* Number of PMAs currently in file */
+ SorterCompare xCompare; /* Compare function to use */
SorterFile file; /* Temp file for level-0 PMAs */
SorterFile file2; /* Space for other PMAs */
};
+
/*
** Main sorter structure. A single instance of this is allocated for each
** sorter cursor created by the VDBE.
@@ -77457,9 +78229,13 @@ struct VdbeSorter {
u8 bUseThreads; /* True to use background threads */
u8 iPrev; /* Previous thread used to flush PMA */
u8 nTask; /* Size of aTask[] array */
+ u8 typeMask;
SortSubtask aTask[1]; /* One or more subtasks */
};
+#define SORTER_TYPE_INTEGER 0x01
+#define SORTER_TYPE_TEXT 0x02
+
/*
** An instance of the following object is used to read records out of a
** PMA, in sorted order. The next key to be read is cached in nKey/aKey.
@@ -77871,33 +78647,163 @@ static int vdbePmaReaderInit(
return rc;
}
+/*
+** A version of vdbeSorterCompare() that assumes that it has already been
+** determined that the first field of key1 is equal to the first field of
+** key2.
+*/
+static int vdbeSorterCompareTail(
+ SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
+ int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
+ const void *pKey1, int nKey1, /* Left side of comparison */
+ const void *pKey2, int nKey2 /* Right side of comparison */
+){
+ UnpackedRecord *r2 = pTask->pUnpacked;
+ if( *pbKey2Cached==0 ){
+ sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
+ *pbKey2Cached = 1;
+ }
+ return sqlite3VdbeRecordCompareWithSkip(nKey1, pKey1, r2, 1);
+}
/*
** Compare key1 (buffer pKey1, size nKey1 bytes) with key2 (buffer pKey2,
** size nKey2 bytes). Use (pTask->pKeyInfo) for the collation sequences
** used by the comparison. Return the result of the comparison.
**
-** Before returning, object (pTask->pUnpacked) is populated with the
-** unpacked version of key2. Or, if pKey2 is passed a NULL pointer, then it
-** is assumed that the (pTask->pUnpacked) structure already contains the
-** unpacked key to use as key2.
+** If IN/OUT parameter *pbKey2Cached is true when this function is called,
+** it is assumed that (pTask->pUnpacked) contains the unpacked version
+** of key2. If it is false, (pTask->pUnpacked) is populated with the unpacked
+** version of key2 and *pbKey2Cached set to true before returning.
**
** If an OOM error is encountered, (pTask->pUnpacked->error_rc) is set
** to SQLITE_NOMEM.
*/
static int vdbeSorterCompare(
SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
+ int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
const void *pKey1, int nKey1, /* Left side of comparison */
const void *pKey2, int nKey2 /* Right side of comparison */
){
UnpackedRecord *r2 = pTask->pUnpacked;
- if( pKey2 ){
+ if( !*pbKey2Cached ){
sqlite3VdbeRecordUnpack(pTask->pSorter->pKeyInfo, nKey2, pKey2, r2);
+ *pbKey2Cached = 1;
}
return sqlite3VdbeRecordCompare(nKey1, pKey1, r2);
}
/*
+** A specially optimized version of vdbeSorterCompare() that assumes that
+** the first field of each key is a TEXT value and that the collation
+** sequence to compare them with is BINARY.
+*/
+static int vdbeSorterCompareText(
+ SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
+ int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
+ const void *pKey1, int nKey1, /* Left side of comparison */
+ const void *pKey2, int nKey2 /* Right side of comparison */
+){
+ const u8 * const p1 = (const u8 * const)pKey1;
+ const u8 * const p2 = (const u8 * const)pKey2;
+ const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */
+ const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */
+
+ int n1;
+ int n2;
+ int res;
+
+ getVarint32(&p1[1], n1); n1 = (n1 - 13) / 2;
+ getVarint32(&p2[1], n2); n2 = (n2 - 13) / 2;
+ res = memcmp(v1, v2, MIN(n1, n2));
+ if( res==0 ){
+ res = n1 - n2;
+ }
+
+ if( res==0 ){
+ if( pTask->pSorter->pKeyInfo->nField>1 ){
+ res = vdbeSorterCompareTail(
+ pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
+ );
+ }
+ }else{
+ if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
+ res = res * -1;
+ }
+ }
+
+ return res;
+}
+
+/*
+** A specially optimized version of vdbeSorterCompare() that assumes that
+** the first field of each key is an INTEGER value.
+*/
+static int vdbeSorterCompareInt(
+ SortSubtask *pTask, /* Subtask context (for pKeyInfo) */
+ int *pbKey2Cached, /* True if pTask->pUnpacked is pKey2 */
+ const void *pKey1, int nKey1, /* Left side of comparison */
+ const void *pKey2, int nKey2 /* Right side of comparison */
+){
+ const u8 * const p1 = (const u8 * const)pKey1;
+ const u8 * const p2 = (const u8 * const)pKey2;
+ const int s1 = p1[1]; /* Left hand serial type */
+ const int s2 = p2[1]; /* Right hand serial type */
+ const u8 * const v1 = &p1[ p1[0] ]; /* Pointer to value 1 */
+ const u8 * const v2 = &p2[ p2[0] ]; /* Pointer to value 2 */
+ int res; /* Return value */
+
+ assert( (s1>0 && s1<7) || s1==8 || s1==9 );
+ assert( (s2>0 && s2<7) || s2==8 || s2==9 );
+
+ if( s1>7 && s2>7 ){
+ res = s1 - s2;
+ }else{
+ if( s1==s2 ){
+ if( (*v1 ^ *v2) & 0x80 ){
+ /* The two values have different signs */
+ res = (*v1 & 0x80) ? -1 : +1;
+ }else{
+ /* The two values have the same sign. Compare using memcmp(). */
+ static const u8 aLen[] = {0, 1, 2, 3, 4, 6, 8 };
+ int i;
+ res = 0;
+ for(i=0; i<aLen[s1]; i++){
+ if( (res = v1[i] - v2[i]) ) break;
+ }
+ }
+ }else{
+ if( s2>7 ){
+ res = +1;
+ }else if( s1>7 ){
+ res = -1;
+ }else{
+ res = s1 - s2;
+ }
+ assert( res!=0 );
+
+ if( res>0 ){
+ if( *v1 & 0x80 ) res = -1;
+ }else{
+ if( *v2 & 0x80 ) res = +1;
+ }
+ }
+ }
+
+ if( res==0 ){
+ if( pTask->pSorter->pKeyInfo->nField>1 ){
+ res = vdbeSorterCompareTail(
+ pTask, pbKey2Cached, pKey1, nKey1, pKey2, nKey2
+ );
+ }
+ }else if( pTask->pSorter->pKeyInfo->aSortOrder[0] ){
+ res = res * -1;
+ }
+
+ return res;
+}
+
+/*
** Initialize the temporary index cursor just opened as a sorter cursor.
**
** Usually, the sorter module uses the value of (pCsr->pKeyInfo->nField)
@@ -77964,9 +78870,13 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
pSorter->pKeyInfo = pKeyInfo = (KeyInfo*)((u8*)pSorter + sz);
memcpy(pKeyInfo, pCsr->pKeyInfo, szKeyInfo);
pKeyInfo->db = 0;
- if( nField && nWorker==0 ) pKeyInfo->nField = nField;
+ if( nField && nWorker==0 ){
+ pKeyInfo->nXField += (pKeyInfo->nField - nField);
+ pKeyInfo->nField = nField;
+ }
pSorter->pgsz = pgsz = sqlite3BtreeGetPageSize(db->aDb[0].pBt);
pSorter->nTask = nWorker + 1;
+ pSorter->iPrev = nWorker-1;
pSorter->bUseThreads = (pSorter->nTask>1);
pSorter->db = db;
for(i=0; i<pSorter->nTask; i++){
@@ -77992,6 +78902,12 @@ SQLITE_PRIVATE int sqlite3VdbeSorterInit(
if( !pSorter->list.aMemory ) rc = SQLITE_NOMEM;
}
}
+
+ if( (pKeyInfo->nField+pKeyInfo->nXField)<13
+ && (pKeyInfo->aColl[0]==0 || pKeyInfo->aColl[0]==db->pDfltColl)
+ ){
+ pSorter->typeMask = SORTER_TYPE_INTEGER | SORTER_TYPE_TEXT;
+ }
}
return rc;
@@ -78016,30 +78932,24 @@ static void vdbeSorterRecordFree(sqlite3 *db, SorterRecord *pRecord){
*/
static void vdbeSortSubtaskCleanup(sqlite3 *db, SortSubtask *pTask){
sqlite3DbFree(db, pTask->pUnpacked);
- pTask->pUnpacked = 0;
#if SQLITE_MAX_WORKER_THREADS>0
/* pTask->list.aMemory can only be non-zero if it was handed memory
** from the main thread. That only occurs SQLITE_MAX_WORKER_THREADS>0 */
if( pTask->list.aMemory ){
sqlite3_free(pTask->list.aMemory);
- pTask->list.aMemory = 0;
}else
#endif
{
assert( pTask->list.aMemory==0 );
vdbeSorterRecordFree(0, pTask->list.pList);
}
- pTask->list.pList = 0;
if( pTask->file.pFd ){
sqlite3OsCloseFree(pTask->file.pFd);
- pTask->file.pFd = 0;
- pTask->file.iEof = 0;
}
if( pTask->file2.pFd ){
sqlite3OsCloseFree(pTask->file2.pFd);
- pTask->file2.pFd = 0;
- pTask->file2.iEof = 0;
}
+ memset(pTask, 0, sizeof(SortSubtask));
}
#ifdef SQLITE_DEBUG_SORTER_THREADS
@@ -78219,6 +79129,7 @@ SQLITE_PRIVATE void sqlite3VdbeSorterReset(sqlite3 *db, VdbeSorter *pSorter){
for(i=0; i<pSorter->nTask; i++){
SortSubtask *pTask = &pSorter->aTask[i];
vdbeSortSubtaskCleanup(db, pTask);
+ pTask->pSorter = pSorter;
}
if( pSorter->list.aMemory==0 ){
vdbeSorterRecordFree(0, pSorter->list.pList);
@@ -78280,6 +79191,7 @@ static int vdbeSorterOpenTempFile(
sqlite3_file **ppFd
){
int rc;
+ if( sqlite3FaultSim(202) ) return SQLITE_IOERR_ACCESS;
rc = sqlite3OsOpenMalloc(db->pVfs, 0, ppFd,
SQLITE_OPEN_TEMP_JOURNAL |
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE |
@@ -78327,22 +79239,23 @@ static void vdbeSorterMerge(
){
SorterRecord *pFinal = 0;
SorterRecord **pp = &pFinal;
- void *pVal2 = p2 ? SRVAL(p2) : 0;
+ int bCached = 0;
while( p1 && p2 ){
int res;
- res = vdbeSorterCompare(pTask, SRVAL(p1), p1->nVal, pVal2, p2->nVal);
+ res = pTask->xCompare(
+ pTask, &bCached, SRVAL(p1), p1->nVal, SRVAL(p2), p2->nVal
+ );
+
if( res<=0 ){
*pp = p1;
pp = &p1->u.pNext;
p1 = p1->u.pNext;
- pVal2 = 0;
}else{
*pp = p2;
- pp = &p2->u.pNext;
+ pp = &p2->u.pNext;
p2 = p2->u.pNext;
- if( p2==0 ) break;
- pVal2 = SRVAL(p2);
+ bCached = 0;
}
}
*pp = p1 ? p1 : p2;
@@ -78350,6 +79263,19 @@ static void vdbeSorterMerge(
}
/*
+** Return the SorterCompare function to compare values collected by the
+** sorter object passed as the only argument.
+*/
+static SorterCompare vdbeSorterGetCompare(VdbeSorter *p){
+ if( p->typeMask==SORTER_TYPE_INTEGER ){
+ return vdbeSorterCompareInt;
+ }else if( p->typeMask==SORTER_TYPE_TEXT ){
+ return vdbeSorterCompareText;
+ }
+ return vdbeSorterCompare;
+}
+
+/*
** Sort the linked list of records headed at pTask->pList. Return
** SQLITE_OK if successful, or an SQLite error code (i.e. SQLITE_NOMEM) if
** an error occurs.
@@ -78363,12 +79289,14 @@ static int vdbeSorterSort(SortSubtask *pTask, SorterList *pList){
rc = vdbeSortAllocUnpacked(pTask);
if( rc!=SQLITE_OK ) return rc;
+ p = pList->pList;
+ pTask->xCompare = vdbeSorterGetCompare(pTask->pSorter);
+
aSlot = (SorterRecord **)sqlite3MallocZero(64 * sizeof(SorterRecord *));
if( !aSlot ){
return SQLITE_NOMEM;
}
- p = pList->pList;
while( p ){
SorterRecord *pNext;
if( pList->aMemory ){
@@ -78582,13 +79510,12 @@ static int vdbeMergeEngineStep(
int i; /* Index of aTree[] to recalculate */
PmaReader *pReadr1; /* First PmaReader to compare */
PmaReader *pReadr2; /* Second PmaReader to compare */
- u8 *pKey2; /* To pReadr2->aKey, or 0 if record cached */
+ int bCached = 0;
/* Find the first two PmaReaders to compare. The one that was just
** advanced (iPrev) and the one next to it in the array. */
pReadr1 = &pMerger->aReadr[(iPrev & 0xFFFE)];
pReadr2 = &pMerger->aReadr[(iPrev | 0x0001)];
- pKey2 = pReadr2->aKey;
for(i=(pMerger->nTree+iPrev)/2; i>0; i=i/2){
/* Compare pReadr1 and pReadr2. Store the result in variable iRes. */
@@ -78598,8 +79525,8 @@ static int vdbeMergeEngineStep(
}else if( pReadr2->pFd==0 ){
iRes = -1;
}else{
- iRes = vdbeSorterCompare(pTask,
- pReadr1->aKey, pReadr1->nKey, pKey2, pReadr2->nKey
+ iRes = pTask->xCompare(pTask, &bCached,
+ pReadr1->aKey, pReadr1->nKey, pReadr2->aKey, pReadr2->nKey
);
}
@@ -78621,9 +79548,9 @@ static int vdbeMergeEngineStep(
if( iRes<0 || (iRes==0 && pReadr1<pReadr2) ){
pMerger->aTree[i] = (int)(pReadr1 - pMerger->aReadr);
pReadr2 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ];
- pKey2 = pReadr2->aKey;
+ bCached = 0;
}else{
- if( pReadr1->pFd ) pKey2 = 0;
+ if( pReadr1->pFd ) bCached = 0;
pMerger->aTree[i] = (int)(pReadr2 - pMerger->aReadr);
pReadr1 = &pMerger->aReadr[ pMerger->aTree[i ^ 0x0001] ];
}
@@ -78730,6 +79657,16 @@ SQLITE_PRIVATE int sqlite3VdbeSorterWrite(
int bFlush; /* True to flush contents of memory to PMA */
int nReq; /* Bytes of memory required */
int nPMA; /* Bytes of PMA space required */
+ int t; /* serial type of first record field */
+
+ getVarint32((const u8*)&pVal->z[1], t);
+ if( t>0 && t<10 && t!=7 ){
+ pSorter->typeMask &= SORTER_TYPE_INTEGER;
+ }else if( t>10 && (t & 0x01) ){
+ pSorter->typeMask &= SORTER_TYPE_TEXT;
+ }else{
+ pSorter->typeMask = 0;
+ }
assert( pSorter );
@@ -78995,10 +79932,12 @@ static void vdbeMergeEngineCompare(
}else if( p2->pFd==0 ){
iRes = i1;
}else{
+ SortSubtask *pTask = pMerger->pTask;
+ int bCached = 0;
int res;
- assert( pMerger->pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */
- res = vdbeSorterCompare(
- pMerger->pTask, p1->aKey, p1->nKey, p2->aKey, p2->nKey
+ assert( pTask->pUnpacked!=0 ); /* from vdbeSortSubtaskMain() */
+ res = pTask->xCompare(
+ pTask, &bCached, p1->aKey, p1->nKey, p2->aKey, p2->nKey
);
if( res<=0 ){
iRes = i1;
@@ -79022,11 +79961,12 @@ static void vdbeMergeEngineCompare(
#define INCRINIT_TASK 1
#define INCRINIT_ROOT 2
-/* Forward reference.
-** The vdbeIncrMergeInit() and vdbePmaReaderIncrMergeInit() routines call each
-** other (when building a merge tree).
+/*
+** Forward reference required as the vdbeIncrMergeInit() and
+** vdbePmaReaderIncrInit() routines are called mutually recursively when
+** building a merge tree.
*/
-static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode);
+static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode);
/*
** Initialize the MergeEngine object passed as the second argument. Once this
@@ -79073,7 +80013,7 @@ static int vdbeMergeEngineInit(
** better advantage of multi-processor hardware. */
rc = vdbePmaReaderNext(&pMerger->aReadr[nTree-i-1]);
}else{
- rc = vdbePmaReaderIncrMergeInit(&pMerger->aReadr[i], INCRINIT_NORMAL);
+ rc = vdbePmaReaderIncrInit(&pMerger->aReadr[i], INCRINIT_NORMAL);
}
if( rc!=SQLITE_OK ) return rc;
}
@@ -79085,17 +80025,15 @@ static int vdbeMergeEngineInit(
}
/*
-** Initialize the IncrMerge field of a PmaReader.
-**
-** If the PmaReader passed as the first argument is not an incremental-reader
-** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it serves
-** to open and/or initialize the temp file related fields of the IncrMerge
+** The PmaReader passed as the first argument is guaranteed to be an
+** incremental-reader (pReadr->pIncr!=0). This function serves to open
+** and/or initialize the temp file related fields of the IncrMerge
** object at (pReadr->pIncr).
**
** If argument eMode is set to INCRINIT_NORMAL, then all PmaReaders
-** in the sub-tree headed by pReadr are also initialized. Data is then loaded
-** into the buffers belonging to pReadr and it is set to
-** point to the first key in its range.
+** in the sub-tree headed by pReadr are also initialized. Data is then
+** loaded into the buffers belonging to pReadr and it is set to point to
+** the first key in its range.
**
** If argument eMode is set to INCRINIT_TASK, then pReadr is guaranteed
** to be a multi-threaded PmaReader and this function is being called in a
@@ -79122,59 +80060,62 @@ static int vdbeMergeEngineInit(
static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){
int rc = SQLITE_OK;
IncrMerger *pIncr = pReadr->pIncr;
+ SortSubtask *pTask = pIncr->pTask;
+ sqlite3 *db = pTask->pSorter->db;
/* eMode is always INCRINIT_NORMAL in single-threaded mode */
assert( SQLITE_MAX_WORKER_THREADS>0 || eMode==INCRINIT_NORMAL );
- if( pIncr ){
- SortSubtask *pTask = pIncr->pTask;
- sqlite3 *db = pTask->pSorter->db;
-
- rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode);
+ rc = vdbeMergeEngineInit(pTask, pIncr->pMerger, eMode);
- /* Set up the required files for pIncr. A multi-theaded IncrMerge object
- ** requires two temp files to itself, whereas a single-threaded object
- ** only requires a region of pTask->file2. */
- if( rc==SQLITE_OK ){
- int mxSz = pIncr->mxSz;
+ /* Set up the required files for pIncr. A multi-theaded IncrMerge object
+ ** requires two temp files to itself, whereas a single-threaded object
+ ** only requires a region of pTask->file2. */
+ if( rc==SQLITE_OK ){
+ int mxSz = pIncr->mxSz;
#if SQLITE_MAX_WORKER_THREADS>0
- if( pIncr->bUseThread ){
- rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd);
- if( rc==SQLITE_OK ){
- rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd);
- }
- }else
+ if( pIncr->bUseThread ){
+ rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[0].pFd);
+ if( rc==SQLITE_OK ){
+ rc = vdbeSorterOpenTempFile(db, mxSz, &pIncr->aFile[1].pFd);
+ }
+ }else
#endif
- /*if( !pIncr->bUseThread )*/{
- if( pTask->file2.pFd==0 ){
- assert( pTask->file2.iEof>0 );
- rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd);
- pTask->file2.iEof = 0;
- }
- if( rc==SQLITE_OK ){
- pIncr->aFile[1].pFd = pTask->file2.pFd;
- pIncr->iStartOff = pTask->file2.iEof;
- pTask->file2.iEof += mxSz;
- }
+ /*if( !pIncr->bUseThread )*/{
+ if( pTask->file2.pFd==0 ){
+ assert( pTask->file2.iEof>0 );
+ rc = vdbeSorterOpenTempFile(db, pTask->file2.iEof, &pTask->file2.pFd);
+ pTask->file2.iEof = 0;
+ }
+ if( rc==SQLITE_OK ){
+ pIncr->aFile[1].pFd = pTask->file2.pFd;
+ pIncr->iStartOff = pTask->file2.iEof;
+ pTask->file2.iEof += mxSz;
}
}
+ }
#if SQLITE_MAX_WORKER_THREADS>0
- if( rc==SQLITE_OK && pIncr->bUseThread ){
- /* Use the current thread to populate aFile[1], even though this
- ** PmaReader is multi-threaded. The reason being that this function
- ** is already running in background thread pIncr->pTask->thread. */
- assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK );
- rc = vdbeIncrPopulate(pIncr);
- }
+ if( rc==SQLITE_OK && pIncr->bUseThread ){
+ /* Use the current thread to populate aFile[1], even though this
+ ** PmaReader is multi-threaded. If this is an INCRINIT_TASK object,
+ ** then this function is already running in background thread
+ ** pIncr->pTask->thread.
+ **
+ ** If this is the INCRINIT_ROOT object, then it is running in the
+ ** main VDBE thread. But that is Ok, as that thread cannot return
+ ** control to the VDBE or proceed with anything useful until the
+ ** first results are ready from this merger object anyway.
+ */
+ assert( eMode==INCRINIT_ROOT || eMode==INCRINIT_TASK );
+ rc = vdbeIncrPopulate(pIncr);
+ }
#endif
- if( rc==SQLITE_OK
- && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK)
- ){
- rc = vdbePmaReaderNext(pReadr);
- }
+ if( rc==SQLITE_OK && (SQLITE_MAX_WORKER_THREADS==0 || eMode!=INCRINIT_TASK) ){
+ rc = vdbePmaReaderNext(pReadr);
}
+
return rc;
}
@@ -79183,7 +80124,7 @@ static int vdbePmaReaderIncrMergeInit(PmaReader *pReadr, int eMode){
** The main routine for vdbePmaReaderIncrMergeInit() operations run in
** background threads.
*/
-static void *vdbePmaReaderBgInit(void *pCtx){
+static void *vdbePmaReaderBgIncrInit(void *pCtx){
PmaReader *pReader = (PmaReader*)pCtx;
void *pRet = SQLITE_INT_TO_PTR(
vdbePmaReaderIncrMergeInit(pReader,INCRINIT_TASK)
@@ -79191,20 +80132,36 @@ static void *vdbePmaReaderBgInit(void *pCtx){
pReader->pIncr->pTask->bDone = 1;
return pRet;
}
+#endif
/*
-** Use a background thread to invoke vdbePmaReaderIncrMergeInit(INCRINIT_TASK)
-** on the PmaReader object passed as the first argument.
-**
-** This call will initialize the various fields of the pReadr->pIncr
-** structure and, if it is a multi-threaded IncrMerger, launch a
-** background thread to populate aFile[1].
+** If the PmaReader passed as the first argument is not an incremental-reader
+** (if pReadr->pIncr==0), then this function is a no-op. Otherwise, it invokes
+** the vdbePmaReaderIncrMergeInit() function with the parameters passed to
+** this routine to initialize the incremental merge.
+**
+** If the IncrMerger object is multi-threaded (IncrMerger.bUseThread==1),
+** then a background thread is launched to call vdbePmaReaderIncrMergeInit().
+** Or, if the IncrMerger is single threaded, the same function is called
+** using the current thread.
*/
-static int vdbePmaReaderBgIncrInit(PmaReader *pReadr){
- void *pCtx = (void*)pReadr;
- return vdbeSorterCreateThread(pReadr->pIncr->pTask, vdbePmaReaderBgInit, pCtx);
-}
+static int vdbePmaReaderIncrInit(PmaReader *pReadr, int eMode){
+ IncrMerger *pIncr = pReadr->pIncr; /* Incremental merger */
+ int rc = SQLITE_OK; /* Return code */
+ if( pIncr ){
+#if SQLITE_MAX_WORKER_THREADS>0
+ assert( pIncr->bUseThread==0 || eMode==INCRINIT_TASK );
+ if( pIncr->bUseThread ){
+ void *pCtx = (void*)pReadr;
+ rc = vdbeSorterCreateThread(pIncr->pTask, vdbePmaReaderBgIncrInit, pCtx);
+ }else
#endif
+ {
+ rc = vdbePmaReaderIncrMergeInit(pReadr, eMode);
+ }
+ }
+ return rc;
+}
/*
** Allocate a new MergeEngine object to merge the contents of nPMA level-0
@@ -79416,6 +80373,11 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){
MergeEngine *pMain = 0;
#if SQLITE_MAX_WORKER_THREADS
sqlite3 *db = pTask0->pSorter->db;
+ int i;
+ SorterCompare xCompare = vdbeSorterGetCompare(pSorter);
+ for(i=0; i<pSorter->nTask; i++){
+ pSorter->aTask[i].xCompare = xCompare;
+ }
#endif
rc = vdbeSorterMergeTreeBuild(pSorter, &pMain);
@@ -79444,15 +80406,21 @@ static int vdbeSorterSetupMerge(VdbeSorter *pSorter){
}
}
for(iTask=0; rc==SQLITE_OK && iTask<pSorter->nTask; iTask++){
+ /* Check that:
+ **
+ ** a) The incremental merge object is configured to use the
+ ** right task, and
+ ** b) If it is using task (nTask-1), it is configured to run
+ ** in single-threaded mode. This is important, as the
+ ** root merge (INCRINIT_ROOT) will be using the same task
+ ** object.
+ */
PmaReader *p = &pMain->aReadr[iTask];
- assert( p->pIncr==0 || p->pIncr->pTask==&pSorter->aTask[iTask] );
- if( p->pIncr ){
- if( iTask==pSorter->nTask-1 ){
- rc = vdbePmaReaderIncrMergeInit(p, INCRINIT_TASK);
- }else{
- rc = vdbePmaReaderBgIncrInit(p);
- }
- }
+ assert( p->pIncr==0 || (
+ (p->pIncr->pTask==&pSorter->aTask[iTask]) /* a */
+ && (iTask!=pSorter->nTask-1 || p->pIncr->bUseThread==0) /* b */
+ ));
+ rc = vdbePmaReaderIncrInit(p, INCRINIT_TASK);
}
}
pMain = 0;
@@ -80407,7 +81375,7 @@ static void incrAggFunctionDepth(Expr *pExpr, int N){
** SELECT a+b, c+d FROM t1 ORDER BY (a+b) COLLATE nocase;
**
** The nSubquery parameter specifies how many levels of subquery the
-** alias is removed from the original expression. The usually value is
+** alias is removed from the original expression. The usual value is
** zero but it might be more if the alias is contained within a subquery
** of the original expression. The Expr.op2 field of TK_AGG_FUNCTION
** structures must be increased by the nSubquery amount.
@@ -80427,7 +81395,6 @@ static void resolveAlias(
assert( iCol>=0 && iCol<pEList->nExpr );
pOrig = pEList->a[iCol].pExpr;
assert( pOrig!=0 );
- assert( pOrig->flags & EP_Resolved );
db = pParse->db;
pDup = sqlite3ExprDup(db, pOrig, 0);
if( pDup==0 ) return;
@@ -80575,9 +81542,10 @@ static int lookupName(
testcase( pNC->ncFlags & NC_PartIdx );
testcase( pNC->ncFlags & NC_IsCheck );
if( (pNC->ncFlags & (NC_PartIdx|NC_IsCheck))!=0 ){
- /* Silently ignore database qualifiers inside CHECK constraints and partial
- ** indices. Do not raise errors because that might break legacy and
- ** because it does not hurt anything to just ignore the database name. */
+ /* Silently ignore database qualifiers inside CHECK constraints and
+ ** partial indices. Do not raise errors because that might break
+ ** legacy and because it does not hurt anything to just ignore the
+ ** database name. */
zDb = 0;
}else{
for(i=0; i<db->nDb; i++){
@@ -80648,7 +81616,8 @@ static int lookupName(
if( pMatch ){
pExpr->iTable = pMatch->iCursor;
pExpr->pTab = pMatch->pTab;
- assert( (pMatch->jointype & JT_RIGHT)==0 ); /* RIGHT JOIN not (yet) supported */
+ /* RIGHT JOIN not (yet) supported */
+ assert( (pMatch->jointype & JT_RIGHT)==0 );
if( (pMatch->jointype & JT_LEFT)!=0 ){
ExprSetProperty(pExpr, EP_CanBeNull);
}
@@ -80969,7 +81938,8 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
pExpr->affinity = SQLITE_AFF_INTEGER;
break;
}
-#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT) && !defined(SQLITE_OMIT_SUBQUERY) */
+#endif /* defined(SQLITE_ENABLE_UPDATE_DELETE_LIMIT)
+ && !defined(SQLITE_OMIT_SUBQUERY) */
/* A lone identifier is the name of a column.
*/
@@ -81034,19 +82004,20 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
if( n==2 ){
pExpr->iTable = exprProbability(pList->a[1].pExpr);
if( pExpr->iTable<0 ){
- sqlite3ErrorMsg(pParse, "second argument to likelihood() must be a "
- "constant between 0.0 and 1.0");
+ sqlite3ErrorMsg(pParse,
+ "second argument to likelihood() must be a "
+ "constant between 0.0 and 1.0");
pNC->nErr++;
}
}else{
- /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is equivalent to
- ** likelihood(X, 0.0625).
- ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is short-hand for
- ** likelihood(X,0.0625).
- ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand for
- ** likelihood(X,0.9375).
- ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent to
- ** likelihood(X,0.9375). */
+ /* EVIDENCE-OF: R-61304-29449 The unlikely(X) function is
+ ** equivalent to likelihood(X, 0.0625).
+ ** EVIDENCE-OF: R-01283-11636 The unlikely(X) function is
+ ** short-hand for likelihood(X,0.0625).
+ ** EVIDENCE-OF: R-36850-34127 The likely(X) function is short-hand
+ ** for likelihood(X,0.9375).
+ ** EVIDENCE-OF: R-53436-40973 The likely(X) function is equivalent
+ ** to likelihood(X,0.9375). */
/* TUNING: unlikely() probability is 0.0625. likely() is 0.9375 */
pExpr->iTable = pDef->zName[0]=='u' ? 8388608 : 125829120;
}
@@ -81063,7 +82034,9 @@ static int resolveExprStep(Walker *pWalker, Expr *pExpr){
return WRC_Prune;
}
#endif
- if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ) ExprSetProperty(pExpr,EP_Constant);
+ if( pDef->funcFlags & SQLITE_FUNC_CONSTANT ){
+ ExprSetProperty(pExpr,EP_ConstFunc);
+ }
}
if( is_agg && (pNC->ncFlags & NC_AllowAgg)==0 ){
sqlite3ErrorMsg(pParse, "misuse of aggregate function %.*s()", nId,zId);
@@ -81315,9 +82288,11 @@ static int resolveCompoundOrderBy(
if( pItem->pExpr==pE ){
pItem->pExpr = pNew;
}else{
- assert( pItem->pExpr->op==TK_COLLATE );
- assert( pItem->pExpr->pLeft==pE );
- pItem->pExpr->pLeft = pNew;
+ Expr *pParent = pItem->pExpr;
+ assert( pParent->op==TK_COLLATE );
+ while( pParent->pLeft->op==TK_COLLATE ) pParent = pParent->pLeft;
+ assert( pParent->pLeft==pE );
+ pParent->pLeft = pNew;
}
sqlite3ExprDelete(db, pE);
pItem->u.x.iOrderByCol = (u16)iCol;
@@ -81374,7 +82349,8 @@ SQLITE_PRIVATE int sqlite3ResolveOrderGroupBy(
resolveOutOfRangeError(pParse, zType, i+1, pEList->nExpr);
return 1;
}
- resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr, zType,0);
+ resolveAlias(pParse, pEList, pItem->u.x.iOrderByCol-1, pItem->pExpr,
+ zType,0);
}
}
return 0;
@@ -81507,6 +82483,20 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
sqlite3ResolveExprNames(&sNC, p->pOffset) ){
return WRC_Abort;
}
+
+ /* If the SF_Converted flags is set, then this Select object was
+ ** was created by the convertCompoundSelectToSubquery() function.
+ ** In this case the ORDER BY clause (p->pOrderBy) should be resolved
+ ** as if it were part of the sub-query, not the parent. This block
+ ** moves the pOrderBy down to the sub-query. It will be moved back
+ ** after the names have been resolved. */
+ if( p->selFlags & SF_Converted ){
+ Select *pSub = p->pSrc->a[0].pSelect;
+ assert( p->pSrc->nSrc==1 && p->pOrderBy );
+ assert( pSub->pPrior && pSub->pOrderBy==0 );
+ pSub->pOrderBy = p->pOrderBy;
+ p->pOrderBy = 0;
+ }
/* Recursively resolve names in all subqueries
*/
@@ -81589,12 +82579,30 @@ static int resolveSelectStep(Walker *pWalker, Select *p){
sNC.pNext = 0;
sNC.ncFlags |= NC_AllowAgg;
+ /* If this is a converted compound query, move the ORDER BY clause from
+ ** the sub-query back to the parent query. At this point each term
+ ** within the ORDER BY clause has been transformed to an integer value.
+ ** These integers will be replaced by copies of the corresponding result
+ ** set expressions by the call to resolveOrderGroupBy() below. */
+ if( p->selFlags & SF_Converted ){
+ Select *pSub = p->pSrc->a[0].pSelect;
+ p->pOrderBy = pSub->pOrderBy;
+ pSub->pOrderBy = 0;
+ }
+
/* Process the ORDER BY clause for singleton SELECT statements.
** The ORDER BY clause for compounds SELECT statements is handled
** below, after all of the result-sets for all of the elements of
** the compound have been resolved.
+ **
+ ** If there is an ORDER BY clause on a term of a compound-select other
+ ** than the right-most term, then that is a syntax error. But the error
+ ** is not detected until much later, and so we need to go ahead and
+ ** resolve those symbols on the incorrect ORDER BY for consistency.
*/
- if( !isCompound && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER") ){
+ if( isCompound<=nCompound /* Defer right-most ORDER BY of a compound */
+ && resolveOrderGroupBy(&sNC, p, p->pOrderBy, "ORDER")
+ ){
return WRC_Abort;
}
if( db->mallocFailed ){
@@ -81864,10 +82872,11 @@ SQLITE_PRIVATE char sqlite3ExprAffinity(Expr *pExpr){
SQLITE_PRIVATE Expr *sqlite3ExprAddCollateToken(
Parse *pParse, /* Parsing context */
Expr *pExpr, /* Add the "COLLATE" clause to this expression */
- const Token *pCollName /* Name of collating sequence */
+ const Token *pCollName, /* Name of collating sequence */
+ int dequote /* True to dequote pCollName */
){
if( pCollName->n>0 ){
- Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, 1);
+ Expr *pNew = sqlite3ExprAlloc(pParse->db, TK_COLLATE, pCollName, dequote);
if( pNew ){
pNew->pLeft = pExpr;
pNew->flags |= EP_Collate|EP_Skip;
@@ -81881,7 +82890,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprAddCollateString(Parse *pParse, Expr *pExpr, con
assert( zC!=0 );
s.z = zC;
s.n = sqlite3Strlen30(s.z);
- return sqlite3ExprAddCollateToken(pParse, pExpr, &s);
+ return sqlite3ExprAddCollateToken(pParse, pExpr, &s, 0);
}
/*
@@ -81927,9 +82936,9 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
pColl = sqlite3GetCollSeq(pParse, ENC(db), 0, p->u.zToken);
break;
}
- if( p->pTab!=0
- && (op==TK_AGG_COLUMN || op==TK_COLUMN
+ if( (op==TK_AGG_COLUMN || op==TK_COLUMN
|| op==TK_REGISTER || op==TK_TRIGGER)
+ && p->pTab!=0
){
/* op==TK_REGISTER && p->pTab!=0 happens when pExpr was originally
** a TK_COLUMN but was previously evaluated and cached in a register */
@@ -81941,10 +82950,25 @@ SQLITE_PRIVATE CollSeq *sqlite3ExprCollSeq(Parse *pParse, Expr *pExpr){
break;
}
if( p->flags & EP_Collate ){
- if( ALWAYS(p->pLeft) && (p->pLeft->flags & EP_Collate)!=0 ){
+ if( p->pLeft && (p->pLeft->flags & EP_Collate)!=0 ){
p = p->pLeft;
}else{
- p = p->pRight;
+ Expr *pNext = p->pRight;
+ /* The Expr.x union is never used at the same time as Expr.pRight */
+ assert( p->x.pList==0 || p->pRight==0 );
+ /* p->flags holds EP_Collate and p->pLeft->flags does not. And
+ ** p->x.pSelect cannot. So if p->x.pLeft exists, it must hold at
+ ** least one EP_Collate. Thus the following two ALWAYS. */
+ if( p->x.pList!=0 && ALWAYS(!ExprHasProperty(p, EP_xIsSelect)) ){
+ int i;
+ for(i=0; ALWAYS(i<p->x.pList->nExpr); i++){
+ if( ExprHasProperty(p->x.pList->a[i].pExpr, EP_Collate) ){
+ pNext = p->x.pList->a[i].pExpr;
+ break;
+ }
+ }
+ }
+ p = pNext;
}
}else{
break;
@@ -82150,6 +83174,9 @@ static void heightOfSelect(Select *p, int *pnHeight){
** Expr.pSelect member has a height of 1. Any other expression
** has a height equal to the maximum height of any other
** referenced Expr plus one.
+**
+** Also propagate EP_Propagate flags up from Expr.x.pList to Expr.flags,
+** if appropriate.
*/
static void exprSetHeight(Expr *p){
int nHeight = 0;
@@ -82157,8 +83184,9 @@ static void exprSetHeight(Expr *p){
heightOfExpr(p->pRight, &nHeight);
if( ExprHasProperty(p, EP_xIsSelect) ){
heightOfSelect(p->x.pSelect, &nHeight);
- }else{
+ }else if( p->x.pList ){
heightOfExprList(p->x.pList, &nHeight);
+ p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
}
p->nHeight = nHeight + 1;
}
@@ -82167,8 +83195,12 @@ static void exprSetHeight(Expr *p){
** Set the Expr.nHeight variable using the exprSetHeight() function. If
** the height is greater than the maximum allowed expression depth,
** leave an error in pParse.
+**
+** Also propagate all EP_Propagate flags from the Expr.x.pList into
+** Expr.flags.
*/
-SQLITE_PRIVATE void sqlite3ExprSetHeight(Parse *pParse, Expr *p){
+SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
+ if( pParse->nErr ) return;
exprSetHeight(p);
sqlite3ExprCheckHeight(pParse, p->nHeight);
}
@@ -82182,8 +83214,17 @@ SQLITE_PRIVATE int sqlite3SelectExprHeight(Select *p){
heightOfSelect(p, &nHeight);
return nHeight;
}
-#else
- #define exprSetHeight(y)
+#else /* ABOVE: Height enforcement enabled. BELOW: Height enforcement off */
+/*
+** Propagate all EP_Propagate flags from the Expr.x.pList into
+** Expr.flags.
+*/
+SQLITE_PRIVATE void sqlite3ExprSetHeightAndFlags(Parse *pParse, Expr *p){
+ if( p && p->x.pList && !ExprHasProperty(p, EP_xIsSelect) ){
+ p->flags |= EP_Propagate & sqlite3ExprListFlags(p->x.pList);
+ }
+}
+#define exprSetHeight(y)
#endif /* SQLITE_MAX_EXPR_DEPTH>0 */
/*
@@ -82285,11 +83326,11 @@ SQLITE_PRIVATE void sqlite3ExprAttachSubtrees(
}else{
if( pRight ){
pRoot->pRight = pRight;
- pRoot->flags |= EP_Collate & pRight->flags;
+ pRoot->flags |= EP_Propagate & pRight->flags;
}
if( pLeft ){
pRoot->pLeft = pLeft;
- pRoot->flags |= EP_Collate & pLeft->flags;
+ pRoot->flags |= EP_Propagate & pLeft->flags;
}
exprSetHeight(pRoot);
}
@@ -82389,7 +83430,7 @@ SQLITE_PRIVATE Expr *sqlite3ExprFunction(Parse *pParse, ExprList *pList, Token *
}
pNew->x.pList = pList;
assert( !ExprHasProperty(pNew, EP_xIsSelect) );
- sqlite3ExprSetHeight(pParse, pNew);
+ sqlite3ExprSetHeightAndFlags(pParse, pNew);
return pNew;
}
@@ -83005,6 +84046,22 @@ SQLITE_PRIVATE void sqlite3ExprListDelete(sqlite3 *db, ExprList *pList){
}
/*
+** Return the bitwise-OR of all Expr.flags fields in the given
+** ExprList.
+*/
+SQLITE_PRIVATE u32 sqlite3ExprListFlags(const ExprList *pList){
+ int i;
+ u32 m = 0;
+ if( pList ){
+ for(i=0; i<pList->nExpr; i++){
+ Expr *pExpr = pList->a[i].pExpr;
+ if( ALWAYS(pExpr) ) m |= pExpr->flags;
+ }
+ }
+ return m;
+}
+
+/*
** These routines are Walker callbacks used to check expressions to
** see if they are "constant" for some definition of constant. The
** Walker.eCode value determines the type of "constant" we are looking
@@ -83044,7 +84101,7 @@ static int exprNodeIsConstant(Walker *pWalker, Expr *pExpr){
** and either pWalker->eCode==4 or 5 or the function has the
** SQLITE_FUNC_CONST flag. */
case TK_FUNCTION:
- if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_Constant) ){
+ if( pWalker->eCode>=4 || ExprHasProperty(pExpr,EP_ConstFunc) ){
return WRC_Continue;
}else{
pWalker->eCode = 0;
@@ -83438,7 +84495,7 @@ SQLITE_PRIVATE int sqlite3FindInIndex(Parse *pParse, Expr *pX, u32 inFlags, int
** ephemeral table.
*/
p = (ExprHasProperty(pX, EP_xIsSelect) ? pX->x.pSelect : 0);
- if( ALWAYS(pParse->nErr==0) && isCandidateForInOpt(p) ){
+ if( pParse->nErr==0 && isCandidateForInOpt(p) ){
sqlite3 *db = pParse->db; /* Database connection */
Table *pTab; /* Table <table>. */
Expr *pExpr; /* Expression <column> */
@@ -83763,6 +84820,7 @@ SQLITE_PRIVATE int sqlite3CodeSubselect(
pSel->pLimit = sqlite3PExpr(pParse, TK_INTEGER, 0, 0,
&sqlite3IntTokens[1]);
pSel->iLimit = 0;
+ pSel->selFlags &= ~SF_MultiValue;
if( sqlite3Select(pParse, pSel, &dest) ){
return 0;
}
@@ -84051,7 +85109,8 @@ SQLITE_PRIVATE void sqlite3ExprCacheStore(Parse *pParse, int iTab, int iCol, int
int idxLru;
struct yColCache *p;
- assert( iReg>0 ); /* Register numbers are always positive */
+ /* Unless an error has occurred, register numbers are always positive. */
+ assert( iReg>0 || pParse->nErr || pParse->db->mallocFailed );
assert( iCol>=-1 && iCol<32768 ); /* Finite column numbers */
/* The SQLITE_ColumnCache flag disables the column cache. This is used
@@ -85127,7 +86186,7 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 m
break;
}
case TK_ID: {
- sqlite3TreeViewLine(pView,"ID %Q", pExpr->u.zToken);
+ sqlite3TreeViewLine(pView,"ID \"%w\"", pExpr->u.zToken);
break;
}
#ifndef SQLITE_OMIT_CAST
@@ -85762,7 +86821,7 @@ SQLITE_PRIVATE int sqlite3ExprCompare(Expr *pA, Expr *pB, int iTab){
if( sqlite3ExprCompare(pA->pLeft, pB->pLeft, iTab) ) return 2;
if( sqlite3ExprCompare(pA->pRight, pB->pRight, iTab) ) return 2;
if( sqlite3ExprListCompare(pA->x.pList, pB->x.pList, iTab) ) return 2;
- if( ALWAYS((combinedFlags & EP_Reduced)==0) ){
+ if( ALWAYS((combinedFlags & EP_Reduced)==0) && pA->op!=TK_STRING ){
if( pA->iColumn!=pB->iColumn ) return 2;
if( pA->iTable!=pB->iTable
&& (pA->iTable!=iTab || NEVER(pB->iTable>=0)) ) return 2;
@@ -86294,6 +87353,7 @@ static void renameParentFunc(
n = sqlite3GetToken(z, &token);
}while( token==TK_SPACE );
+ if( token==TK_ILLEGAL ) break;
zParent = sqlite3DbStrNDup(db, (const char *)z, n);
if( zParent==0 ) break;
sqlite3Dequote(zParent);
@@ -86858,7 +87918,10 @@ SQLITE_PRIVATE void sqlite3AlterFinishAddColumn(Parse *pParse, Token *pColDef){
*/
if( pDflt ){
sqlite3_value *pVal = 0;
- if( sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal) ){
+ int rc;
+ rc = sqlite3ValueFromExpr(db, pDflt, SQLITE_UTF8, SQLITE_AFF_NONE, &pVal);
+ assert( rc==SQLITE_OK || rc==SQLITE_NOMEM );
+ if( rc!=SQLITE_OK ){
db->mallocFailed = 1;
return;
}
@@ -88517,14 +89580,17 @@ static int analysisLoader(void *pData, int argc, char **argv, char **NotUsed){
z = argv[2];
if( pIndex ){
+ tRowcnt *aiRowEst = 0;
int nCol = pIndex->nKeyCol+1;
#ifdef SQLITE_ENABLE_STAT3_OR_STAT4
- tRowcnt * const aiRowEst = pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(
- sizeof(tRowcnt) * nCol
- );
- if( aiRowEst==0 ) pInfo->db->mallocFailed = 1;
-#else
- tRowcnt * const aiRowEst = 0;
+ /* Index.aiRowEst may already be set here if there are duplicate
+ ** sqlite_stat1 entries for this index. In that case just clobber
+ ** the old data with the new instead of allocating a new array. */
+ if( pIndex->aiRowEst==0 ){
+ pIndex->aiRowEst = (tRowcnt*)sqlite3MallocZero(sizeof(tRowcnt) * nCol);
+ if( pIndex->aiRowEst==0 ) pInfo->db->mallocFailed = 1;
+ }
+ aiRowEst = pIndex->aiRowEst;
#endif
pIndex->bUnordered = 0;
decodeIntArray((char*)z, nCol, aiRowEst, pIndex->aiRowLogEst, pIndex);
@@ -89080,7 +90146,7 @@ static void attachFunc(
case SQLITE_NULL:
/* No key specified. Use the key from the main database */
sqlite3CodecGetKey(db, 0, (void**)&zKey, &nKey);
- if( nKey>0 || sqlite3BtreeGetReserve(db->aDb[0].pBt)>0 ){
+ if( nKey>0 || sqlite3BtreeGetOptimalReserve(db->aDb[0].pBt)>0 ){
rc = sqlite3CodecAttach(db, db->nDb-1, zKey, nKey);
}
break;
@@ -89187,7 +90253,7 @@ static void detachFunc(
sqlite3BtreeClose(pDb->pBt);
pDb->pBt = 0;
pDb->pSchema = 0;
- sqlite3ResetAllSchemasOfConnection(db);
+ sqlite3CollapseDatabaseArray(db);
return;
detach_error:
@@ -89221,7 +90287,6 @@ static void codeAttach(
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pDbname)) ||
SQLITE_OK!=(rc = resolveAttachExpr(&sName, pKey))
){
- pParse->nErr++;
goto attach_end;
}
@@ -89543,7 +90608,7 @@ SQLITE_PRIVATE int sqlite3FixTriggerStep(
** Setting the auth function to NULL disables this hook. The default
** setting of the auth function is NULL.
*/
-SQLITE_API int sqlite3_set_authorizer(
+SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer(
sqlite3 *db,
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
void *pArg
@@ -89880,9 +90945,11 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
assert( pParse->pToplevel==0 );
db = pParse->db;
- if( db->mallocFailed ) return;
if( pParse->nested ) return;
- if( pParse->nErr ) return;
+ if( db->mallocFailed || pParse->nErr ){
+ if( pParse->rc==SQLITE_OK ) pParse->rc = SQLITE_ERROR;
+ return;
+ }
/* Begin by generating some termination code at the end of the
** vdbe program
@@ -89964,7 +91031,7 @@ SQLITE_PRIVATE void sqlite3FinishCoding(Parse *pParse){
/* Get the VDBE program ready for execution
*/
- if( v && ALWAYS(pParse->nErr==0) && !db->mallocFailed ){
+ if( v && pParse->nErr==0 && !db->mallocFailed ){
assert( pParse->iCacheLevel==0 ); /* Disables and re-enables match */
/* A minimum of one cursor is required if autoincrement is used
* See ticket [a696379c1f08866] */
@@ -90046,10 +91113,6 @@ SQLITE_PRIVATE Table *sqlite3FindTable(sqlite3 *db, const char *zName, const cha
Table *p = 0;
int i;
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) || zName==0 ) return 0;
-#endif
-
/* All mutexes are required for schema access. Make sure we hold them. */
assert( zDatabase!=0 || sqlite3BtreeHoldsAllMutexes(db) );
#if SQLITE_USER_AUTHENTICATION
@@ -90503,14 +91566,12 @@ SQLITE_PRIVATE int sqlite3TwoPartName(
if( ALWAYS(pName2!=0) && pName2->n>0 ){
if( db->init.busy ) {
sqlite3ErrorMsg(pParse, "corrupt database");
- pParse->nErr++;
return -1;
}
*pUnqual = pName2;
iDb = sqlite3FindDb(db, pName1);
if( iDb<0 ){
sqlite3ErrorMsg(pParse, "unknown database %T", pName1);
- pParse->nErr++;
return -1;
}
}else{
@@ -90669,7 +91730,7 @@ SQLITE_PRIVATE void sqlite3StartTable(
if( !noErr ){
sqlite3ErrorMsg(pParse, "table %T already exists", pName);
}else{
- assert( !db->init.busy );
+ assert( !db->init.busy || CORRUPT_DB );
sqlite3CodeVerifySchema(pParse, iDb);
}
goto begin_table_error;
@@ -90958,7 +92019,8 @@ SQLITE_PRIVATE void sqlite3AddColumnType(Parse *pParse, Token *pType){
p = pParse->pNewTable;
if( p==0 || NEVER(p->nCol<1) ) return;
pCol = &p->aCol[p->nCol-1];
- assert( pCol->zType==0 );
+ assert( pCol->zType==0 || CORRUPT_DB );
+ sqlite3DbFree(pParse->db, pCol->zType);
pCol->zType = sqlite3NameFromToken(pParse->db, pType);
pCol->affinity = sqlite3AffinityType(pCol->zType, &pCol->szEst);
}
@@ -91469,11 +92531,14 @@ static void convertToWithoutRowidTable(Parse *pParse, Table *pTab){
assert( pPk!=0 );
nPk = pPk->nKeyCol;
- /* Make sure every column of the PRIMARY KEY is NOT NULL */
- for(i=0; i<nPk; i++){
- pTab->aCol[pPk->aiColumn[i]].notNull = 1;
+ /* Make sure every column of the PRIMARY KEY is NOT NULL. (Except,
+ ** do not enforce this for imposter tables.) */
+ if( !db->init.imposterTable ){
+ for(i=0; i<nPk; i++){
+ pTab->aCol[pPk->aiColumn[i]].notNull = 1;
+ }
+ pPk->uniqNotNull = 1;
}
- pPk->uniqNotNull = 1;
/* The root page of the PRIMARY KEY is the table root page */
pPk->tnum = pTab->tnum;
@@ -92189,6 +93254,7 @@ SQLITE_PRIVATE void sqlite3DropTable(Parse *pParse, SrcList *pName, int isView,
}
assert( pParse->nErr==0 );
assert( pName->nSrc==1 );
+ if( sqlite3ReadSchema(pParse) ) goto exit_drop_table;
if( noErr ) db->suppressErr++;
pTab = sqlite3LocateTableItem(pParse, isView, &pName->a[0]);
if( noErr ) db->suppressErr--;
@@ -92502,7 +93568,8 @@ static void sqlite3RefillIndex(Parse *pParse, Index *pIndex, int memRootPage){
addr2 = sqlite3VdbeCurrentAddr(v);
}
sqlite3VdbeAddOp3(v, OP_SorterData, iSorter, regRecord, iIdx);
- sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 1);
+ sqlite3VdbeAddOp3(v, OP_Last, iIdx, 0, -1);
+ sqlite3VdbeAddOp3(v, OP_IdxInsert, iIdx, regRecord, 0);
sqlite3VdbeChangeP5(v, OPFLAG_USESEEKRESULT);
sqlite3ReleaseTempReg(pParse, regRecord);
sqlite3VdbeAddOp2(v, OP_SorterNext, iSorter, addr2); VdbeCoverage(v);
@@ -92595,8 +93662,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
char *zExtra = 0; /* Extra space after the Index object */
Index *pPk = 0; /* PRIMARY KEY index for WITHOUT ROWID tables */
- assert( pParse->nErr==0 ); /* Never called with prior errors */
- if( db->mallocFailed || IN_DECLARE_VTAB ){
+ if( db->mallocFailed || IN_DECLARE_VTAB || pParse->nErr>0 ){
goto exit_create_index;
}
if( SQLITE_OK!=sqlite3ReadSchema(pParse) ){
@@ -92922,6 +93988,7 @@ SQLITE_PRIVATE Index *sqlite3CreateIndex(
pIdx->onError = pIndex->onError;
}
}
+ pRet = pIdx;
goto exit_create_index;
}
}
@@ -93514,7 +94581,6 @@ SQLITE_PRIVATE void sqlite3SrcListIndexedBy(Parse *pParse, SrcList *p, Token *pI
SQLITE_PRIVATE void sqlite3SrcListShiftJoinType(SrcList *p){
if( p ){
int i;
- assert( p->a || p->nSrc==0 );
for(i=p->nSrc-1; i>0; i--){
p->a[i].jointype = p->a[i-1].jointype;
}
@@ -93761,8 +94827,7 @@ SQLITE_PRIVATE void sqlite3UniqueConstraint(
StrAccum errMsg;
Table *pTab = pIdx->pTable;
- sqlite3StrAccumInit(&errMsg, 0, 0, 200);
- errMsg.db = pParse->db;
+ sqlite3StrAccumInit(&errMsg, pParse->db, 0, 0, 200);
for(j=0; j<pIdx->nKeyCol; j++){
char *zCol = pTab->aCol[pIdx->aiColumn[j]].zName;
if( j ) sqlite3StrAccumAppend(&errMsg, ", ", 2);
@@ -94708,7 +95773,7 @@ SQLITE_PRIVATE Expr *sqlite3LimitWhere(
pInClause->x.pSelect = pSelect;
pInClause->flags |= EP_xIsSelect;
- sqlite3ExprSetHeight(pParse, pInClause);
+ sqlite3ExprSetHeightAndFlags(pParse, pInClause);
return pInClause;
/* something went wrong. clean up anything allocated. */
@@ -95381,7 +96446,9 @@ SQLITE_PRIVATE void sqlite3ResolvePartIdxLabel(Parse *pParse, int iLabel){
** Return the collating function associated with a function.
*/
static CollSeq *sqlite3GetFuncCollSeq(sqlite3_context *context){
- VdbeOp *pOp = &context->pVdbe->aOp[context->iOp-1];
+ VdbeOp *pOp;
+ assert( context->pVdbe!=0 );
+ pOp = &context->pVdbe->aOp[context->iOp-1];
assert( pOp->opcode==OP_CollSeq );
assert( pOp->p4type==P4_COLLSEQ );
return pOp->p4.pColl;
@@ -95589,13 +96656,13 @@ static void printfFunc(
StrAccum str;
const char *zFormat;
int n;
+ sqlite3 *db = sqlite3_context_db_handle(context);
if( argc>=1 && (zFormat = (const char*)sqlite3_value_text(argv[0]))!=0 ){
x.nArg = argc-1;
x.nUsed = 0;
x.apArg = argv+1;
- sqlite3StrAccumInit(&str, 0, 0, SQLITE_MAX_LENGTH);
- str.db = sqlite3_context_db_handle(context);
+ sqlite3StrAccumInit(&str, db, 0, 0, db->aLimit[SQLITE_LIMIT_LENGTH]);
sqlite3XPrintf(&str, SQLITE_PRINTF_SQLFUNC, zFormat, &x);
n = str.nChar;
sqlite3_result_text(context, sqlite3StrAccumFinish(&str), n,
@@ -95650,6 +96717,14 @@ static void substrFunc(
}
}
}
+#ifdef SQLITE_SUBSTR_COMPATIBILITY
+ /* If SUBSTR_COMPATIBILITY is defined then substr(X,0,N) work the same as
+ ** as substr(X,1,N) - it returns the first N characters of X. This
+ ** is essentially a back-out of the bug-fix in check-in [5fc125d362df4b8]
+ ** from 2009-02-02 for compatibility of applications that exploited the
+ ** old buggy behavior. */
+ if( p1==0 ) p1 = 1; /* <rdar://problem/6778339> */
+#endif
if( argc==3 ){
p2 = sqlite3_value_int(argv[2]);
if( p2<0 ){
@@ -95737,7 +96812,7 @@ static void roundFunc(sqlite3_context *context, int argc, sqlite3_value **argv){
#endif
/*
-** Allocate nByte bytes of space using sqlite3_malloc(). If the
+** Allocate nByte bytes of space using sqlite3Malloc(). If the
** allocation fails, call sqlite3_result_error_nomem() to notify
** the database handle that malloc() has failed and return NULL.
** If nByte is larger than the maximum string or blob length, then
@@ -96111,7 +97186,7 @@ static int patternCompare(
/*
** The sqlite3_strglob() interface.
*/
-SQLITE_API int sqlite3_strglob(const char *zGlobPattern, const char *zString){
+SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlobPattern, const char *zString){
return patternCompare((u8*)zGlobPattern, (u8*)zString, &globInfo, 0)==0;
}
@@ -96406,7 +97481,7 @@ static void charFunc(
){
unsigned char *z, *zOut;
int i;
- zOut = z = sqlite3_malloc( argc*4+1 );
+ zOut = z = sqlite3_malloc64( argc*4+1 );
if( z==0 ){
sqlite3_result_error_nomem(context);
return;
@@ -96554,7 +97629,7 @@ static void replaceFunc(
return;
}
zOld = zOut;
- zOut = sqlite3_realloc(zOut, (int)nOut);
+ zOut = sqlite3_realloc64(zOut, (int)nOut);
if( zOut==0 ){
sqlite3_result_error_nomem(context);
sqlite3_free(zOld);
@@ -96916,8 +97991,7 @@ static void groupConcatStep(
if( pAccum ){
sqlite3 *db = sqlite3_context_db_handle(context);
- int firstTerm = pAccum->useMalloc==0;
- pAccum->useMalloc = 2;
+ int firstTerm = pAccum->mxAlloc==0;
pAccum->mxAlloc = db->aLimit[SQLITE_LIMIT_LENGTH];
if( !firstTerm ){
if( argc==2 ){
@@ -97001,6 +98075,11 @@ SQLITE_PRIVATE void sqlite3RegisterLikeFunctions(sqlite3 *db, int caseSensitive)
** then set aWc[0] through aWc[2] to the wildcard characters and
** return TRUE. If the function is not a LIKE-style function then
** return FALSE.
+**
+** *pIsNocase is set to true if uppercase and lowercase are equivalent for
+** the function (default for LIKE). If the function makes the distinction
+** between uppercase and lowercase (as does GLOB) then *pIsNocase is set to
+** false.
*/
SQLITE_PRIVATE int sqlite3IsLikeFunction(sqlite3 *db, Expr *pExpr, int *pIsNocase, char *aWc){
FuncDef *pDef;
@@ -98332,7 +99411,8 @@ static Trigger *fkActionTrigger(
iFromCol = aiCol ? aiCol[i] : pFKey->aCol[0].iFrom;
assert( iFromCol>=0 );
- tToCol.z = pIdx ? pTab->aCol[pIdx->aiColumn[i]].zName : "oid";
+ assert( pIdx!=0 || (pTab->iPKey>=0 && pTab->iPKey<pTab->nCol) );
+ tToCol.z = pTab->aCol[pIdx ? pIdx->aiColumn[i] : pTab->iPKey].zName;
tFromCol.z = pFKey->pFrom->aCol[iFromCol].zName;
tToCol.n = sqlite3Strlen30(tToCol.z);
@@ -98344,10 +99424,10 @@ static Trigger *fkActionTrigger(
** parent table are used for the comparison. */
pEq = sqlite3PExpr(pParse, TK_EQ,
sqlite3PExpr(pParse, TK_DOT,
- sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
- sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
+ sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)
, 0),
- sqlite3PExpr(pParse, TK_ID, 0, 0, &tFromCol)
+ sqlite3ExprAlloc(db, TK_ID, &tFromCol, 0)
, 0);
pWhere = sqlite3ExprAnd(db, pWhere, pEq);
@@ -98359,12 +99439,12 @@ static Trigger *fkActionTrigger(
if( pChanges ){
pEq = sqlite3PExpr(pParse, TK_IS,
sqlite3PExpr(pParse, TK_DOT,
- sqlite3PExpr(pParse, TK_ID, 0, 0, &tOld),
- sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
+ sqlite3ExprAlloc(db, TK_ID, &tOld, 0),
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0),
0),
sqlite3PExpr(pParse, TK_DOT,
- sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
- sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol),
+ sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0),
0),
0);
pWhen = sqlite3ExprAnd(db, pWhen, pEq);
@@ -98374,8 +99454,8 @@ static Trigger *fkActionTrigger(
Expr *pNew;
if( action==OE_Cascade ){
pNew = sqlite3PExpr(pParse, TK_DOT,
- sqlite3PExpr(pParse, TK_ID, 0, 0, &tNew),
- sqlite3PExpr(pParse, TK_ID, 0, 0, &tToCol)
+ sqlite3ExprAlloc(db, TK_ID, &tNew, 0),
+ sqlite3ExprAlloc(db, TK_ID, &tToCol, 0)
, 0);
}else if( action==OE_SetDflt ){
Expr *pDflt = pFKey->pFrom->aCol[iFromCol].pDflt;
@@ -98422,13 +99502,12 @@ static Trigger *fkActionTrigger(
pTrigger = (Trigger *)sqlite3DbMallocZero(db,
sizeof(Trigger) + /* struct Trigger */
sizeof(TriggerStep) + /* Single step in trigger program */
- nFrom + 1 /* Space for pStep->target.z */
+ nFrom + 1 /* Space for pStep->zTarget */
);
if( pTrigger ){
pStep = pTrigger->step_list = (TriggerStep *)&pTrigger[1];
- pStep->target.z = (char *)&pStep[1];
- pStep->target.n = nFrom;
- memcpy((char *)pStep->target.z, zFrom, nFrom);
+ pStep->zTarget = (char *)&pStep[1];
+ memcpy((char *)pStep->zTarget, zFrom, nFrom);
pStep->pWhere = sqlite3ExprDup(db, pWhere, EXPRDUP_REDUCE);
pStep->pExprList = sqlite3ExprListDup(db, pList, EXPRDUP_REDUCE);
@@ -98893,20 +99972,23 @@ static int xferOptimization(
/*
** This routine is called to handle SQL of the following forms:
**
-** insert into TABLE (IDLIST) values(EXPRLIST)
+** insert into TABLE (IDLIST) values(EXPRLIST),(EXPRLIST),...
** insert into TABLE (IDLIST) select
+** insert into TABLE (IDLIST) default values
**
** The IDLIST following the table name is always optional. If omitted,
-** then a list of all columns for the table is substituted. The IDLIST
-** appears in the pColumn parameter. pColumn is NULL if IDLIST is omitted.
+** then a list of all (non-hidden) columns for the table is substituted.
+** The IDLIST appears in the pColumn parameter. pColumn is NULL if IDLIST
+** is omitted.
**
-** The pList parameter holds EXPRLIST in the first form of the INSERT
-** statement above, and pSelect is NULL. For the second form, pList is
-** NULL and pSelect is a pointer to the select statement used to generate
-** data for the insert.
+** For the pSelect parameter holds the values to be inserted for the
+** first two forms shown above. A VALUES clause is really just short-hand
+** for a SELECT statement that omits the FROM clause and everything else
+** that follows. If the pSelect parameter is NULL, that means that the
+** DEFAULT VALUES form of the INSERT statement is intended.
**
** The code generated follows one of four templates. For a simple
-** insert with data coming from a VALUES clause, the code executes
+** insert with data coming from a single-row VALUES clause, the code executes
** once straight down through. Pseudo-code follows (we call this
** the "1st template"):
**
@@ -99013,7 +100095,7 @@ SQLITE_PRIVATE void sqlite3Insert(
u8 useTempTable = 0; /* Store SELECT results in intermediate table */
u8 appendFlag = 0; /* True if the insert is likely to be an append */
u8 withoutRowid; /* 0 for normal table. 1 for WITHOUT ROWID table */
- u8 bIdListInOrder = 1; /* True if IDLIST is in table order */
+ u8 bIdListInOrder; /* True if IDLIST is in table order */
ExprList *pList = 0; /* List of VALUES() to be inserted */
/* Register allocations */
@@ -99038,8 +100120,8 @@ SQLITE_PRIVATE void sqlite3Insert(
}
/* If the Select object is really just a simple VALUES() list with a
- ** single row values (the common case) then keep that one row of values
- ** and go ahead and discard the Select object
+ ** single row (the common case) then keep that one row of values
+ ** and discard the other (unused) parts of the pSelect object
*/
if( pSelect && (pSelect->selFlags & SF_Values)!=0 && pSelect->pPrior==0 ){
pList = pSelect->pEList;
@@ -99147,6 +100229,7 @@ SQLITE_PRIVATE void sqlite3Insert(
** is appears in the original table. (The index of the INTEGER
** PRIMARY KEY in the original table is pTab->iPKey.)
*/
+ bIdListInOrder = (pTab->tabFlags & TF_OOOHidden)==0;
if( pColumn ){
for(i=0; i<pColumn->nId; i++){
pColumn->a[i].idx = -1;
@@ -99182,7 +100265,8 @@ SQLITE_PRIVATE void sqlite3Insert(
** co-routine is the common header to the 3rd and 4th templates.
*/
if( pSelect ){
- /* Data is coming from a SELECT. Generate a co-routine to run the SELECT */
+ /* Data is coming from a SELECT or from a multi-row VALUES clause.
+ ** Generate a co-routine to run the SELECT. */
int regYield; /* Register holding co-routine entry-point */
int addrTop; /* Top of the co-routine */
int rc; /* Result code */
@@ -99195,8 +100279,7 @@ SQLITE_PRIVATE void sqlite3Insert(
dest.nSdst = pTab->nCol;
rc = sqlite3Select(pParse, pSelect, &dest);
regFromSelect = dest.iSdst;
- assert( pParse->nErr==0 || rc );
- if( rc || db->mallocFailed ) goto insert_cleanup;
+ if( rc || db->mallocFailed || pParse->nErr ) goto insert_cleanup;
sqlite3VdbeAddOp1(v, OP_EndCoroutine, regYield);
sqlite3VdbeJumpHere(v, addrTop - 1); /* label B: */
assert( pSelect->pEList );
@@ -99244,8 +100327,8 @@ SQLITE_PRIVATE void sqlite3Insert(
sqlite3ReleaseTempReg(pParse, regTempRowid);
}
}else{
- /* This is the case if the data for the INSERT is coming from a VALUES
- ** clause
+ /* This is the case if the data for the INSERT is coming from a
+ ** single-row VALUES clause
*/
NameContext sNC;
memset(&sNC, 0, sizeof(sNC));
@@ -100316,6 +101399,7 @@ static int xferOptimization(
int onError, /* How to handle constraint errors */
int iDbDest /* The database of pDest */
){
+ sqlite3 *db = pParse->db;
ExprList *pEList; /* The result set of the SELECT */
Table *pSrc; /* The table in the FROM clause of SELECT */
Index *pSrcIdx, *pDestIdx; /* Source and destination indices */
@@ -100463,11 +101547,11 @@ static int xferOptimization(
** the extra complication to make this rule less restrictive is probably
** not worth the effort. Ticket [6284df89debdfa61db8073e062908af0c9b6118e]
*/
- if( (pParse->db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
+ if( (db->flags & SQLITE_ForeignKeys)!=0 && pDest->pFKey!=0 ){
return 0;
}
#endif
- if( (pParse->db->flags & SQLITE_CountRows)!=0 ){
+ if( (db->flags & SQLITE_CountRows)!=0 ){
return 0; /* xfer opt does not play well with PRAGMA count_changes */
}
@@ -100478,7 +101562,7 @@ static int xferOptimization(
#ifdef SQLITE_TEST
sqlite3_xferopt_count++;
#endif
- iDbSrc = sqlite3SchemaToIndex(pParse->db, pSrc->pSchema);
+ iDbSrc = sqlite3SchemaToIndex(db, pSrc->pSchema);
v = sqlite3GetVdbe(pParse);
sqlite3CodeVerifySchema(pParse, iDbSrc);
iSrc = pParse->nTab++;
@@ -100488,14 +101572,18 @@ static int xferOptimization(
regRowid = sqlite3GetTempReg(pParse);
sqlite3OpenTable(pParse, iDest, iDbDest, pDest, OP_OpenWrite);
assert( HasRowid(pDest) || destHasUniqueIdx );
- if( (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */
+ if( (db->flags & SQLITE_Vacuum)==0 && (
+ (pDest->iPKey<0 && pDest->pIndex!=0) /* (1) */
|| destHasUniqueIdx /* (2) */
|| (onError!=OE_Abort && onError!=OE_Rollback) /* (3) */
- ){
+ )){
/* In some circumstances, we are able to run the xfer optimization
- ** only if the destination table is initially empty. This code makes
- ** that determination. Conditions under which the destination must
- ** be empty:
+ ** only if the destination table is initially empty. Unless the
+ ** SQLITE_Vacuum flag is set, this block generates code to make
+ ** that determination. If SQLITE_Vacuum is set, then the destination
+ ** table is always empty.
+ **
+ ** Conditions under which the destination must be empty:
**
** (1) There is no INTEGER PRIMARY KEY but there are indices.
** (If the destination is not initially empty, the rowid fields
@@ -100538,6 +101626,7 @@ static int xferOptimization(
sqlite3TableLock(pParse, iDbSrc, pSrc->tnum, 0, pSrc->zName);
}
for(pDestIdx=pDest->pIndex; pDestIdx; pDestIdx=pDestIdx->pNext){
+ u8 useSeekResult = 0;
for(pSrcIdx=pSrc->pIndex; ALWAYS(pSrcIdx); pSrcIdx=pSrcIdx->pNext){
if( xferCompatibleIndex(pDestIdx, pSrcIdx) ) break;
}
@@ -100551,7 +101640,33 @@ static int xferOptimization(
VdbeComment((v, "%s", pDestIdx->zName));
addr1 = sqlite3VdbeAddOp2(v, OP_Rewind, iSrc, 0); VdbeCoverage(v);
sqlite3VdbeAddOp2(v, OP_RowKey, iSrc, regData);
+ if( db->flags & SQLITE_Vacuum ){
+ /* This INSERT command is part of a VACUUM operation, which guarantees
+ ** that the destination table is empty. If all indexed columns use
+ ** collation sequence BINARY, then it can also be assumed that the
+ ** index will be populated by inserting keys in strictly sorted
+ ** order. In this case, instead of seeking within the b-tree as part
+ ** of every OP_IdxInsert opcode, an OP_Last is added before the
+ ** OP_IdxInsert to seek to the point within the b-tree where each key
+ ** should be inserted. This is faster.
+ **
+ ** If any of the indexed columns use a collation sequence other than
+ ** BINARY, this optimization is disabled. This is because the user
+ ** might change the definition of a collation sequence and then run
+ ** a VACUUM command. In that case keys may not be written in strictly
+ ** sorted order. */
+ for(i=0; i<pSrcIdx->nColumn; i++){
+ char *zColl = pSrcIdx->azColl[i];
+ assert( zColl!=0 );
+ if( sqlite3_stricmp("BINARY", zColl) ) break;
+ }
+ if( i==pSrcIdx->nColumn ){
+ useSeekResult = OPFLAG_USESEEKRESULT;
+ sqlite3VdbeAddOp3(v, OP_Last, iDest, 0, -1);
+ }
+ }
sqlite3VdbeAddOp3(v, OP_IdxInsert, iDest, regData, 1);
+ sqlite3VdbeChangeP5(v, useSeekResult);
sqlite3VdbeAddOp2(v, OP_Next, iSrc, addr1+1); VdbeCoverage(v);
sqlite3VdbeJumpHere(v, addr1);
sqlite3VdbeAddOp2(v, OP_Close, iSrc, 0);
@@ -100601,7 +101716,7 @@ static int xferOptimization(
** argument to xCallback(). If xCallback=NULL then no callback
** is invoked, even for queries.
*/
-SQLITE_API int sqlite3_exec(
+SQLITE_API int SQLITE_STDCALL sqlite3_exec(
sqlite3 *db, /* The database on which the SQL executes */
const char *zSql, /* The SQL to be executed */
sqlite3_callback xCallback, /* Invoke this callback routine */
@@ -101670,7 +102785,7 @@ static int sqlite3LoadExtension(
const char *zEntry;
char *zAltEntry = 0;
void **aHandle;
- int nMsg = 300 + sqlite3Strlen30(zFile);
+ u64 nMsg = 300 + sqlite3Strlen30(zFile);
int ii;
/* Shared library endings to try if zFile cannot be loaded as written */
@@ -101713,7 +102828,7 @@ static int sqlite3LoadExtension(
#endif
if( handle==0 ){
if( pzErrMsg ){
- *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
+ *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
if( zErrmsg ){
sqlite3_snprintf(nMsg, zErrmsg,
"unable to open shared library [%s]", zFile);
@@ -101739,7 +102854,7 @@ static int sqlite3LoadExtension(
if( xInit==0 && zProc==0 ){
int iFile, iEntry, c;
int ncFile = sqlite3Strlen30(zFile);
- zAltEntry = sqlite3_malloc(ncFile+30);
+ zAltEntry = sqlite3_malloc64(ncFile+30);
if( zAltEntry==0 ){
sqlite3OsDlClose(pVfs, handle);
return SQLITE_NOMEM;
@@ -101761,7 +102876,7 @@ static int sqlite3LoadExtension(
if( xInit==0 ){
if( pzErrMsg ){
nMsg += sqlite3Strlen30(zEntry);
- *pzErrMsg = zErrmsg = sqlite3_malloc(nMsg);
+ *pzErrMsg = zErrmsg = sqlite3_malloc64(nMsg);
if( zErrmsg ){
sqlite3_snprintf(nMsg, zErrmsg,
"no entry point [%s] in shared library [%s]", zEntry, zFile);
@@ -101796,7 +102911,7 @@ static int sqlite3LoadExtension(
db->aExtension[db->nExtension++] = handle;
return SQLITE_OK;
}
-SQLITE_API int sqlite3_load_extension(
+SQLITE_API int SQLITE_STDCALL sqlite3_load_extension(
sqlite3 *db, /* Load the extension into this database connection */
const char *zFile, /* Name of the shared library containing extension */
const char *zProc, /* Entry point. Use "sqlite3_extension_init" if 0 */
@@ -101827,7 +102942,7 @@ SQLITE_PRIVATE void sqlite3CloseExtensions(sqlite3 *db){
** Enable or disable extension loading. Extension loading is disabled by
** default so as not to open security holes in older applications.
*/
-SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff){
+SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff){
sqlite3_mutex_enter(db->mutex);
if( onoff ){
db->flags |= SQLITE_LoadExtension;
@@ -101860,7 +102975,7 @@ static const sqlite3_api_routines sqlite3Apis = { 0 };
*/
typedef struct sqlite3AutoExtList sqlite3AutoExtList;
static SQLITE_WSD struct sqlite3AutoExtList {
- int nExt; /* Number of entries in aExt[] */
+ u32 nExt; /* Number of entries in aExt[] */
void (**aExt)(void); /* Pointers to the extension init functions */
} sqlite3Autoext = { 0, 0 };
@@ -101884,7 +102999,7 @@ static SQLITE_WSD struct sqlite3AutoExtList {
** Register a statically linked extension that is automatically
** loaded by every new database connection.
*/
-SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){
+SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xInit)(void)){
int rc = SQLITE_OK;
#ifndef SQLITE_OMIT_AUTOINIT
rc = sqlite3_initialize();
@@ -101893,7 +103008,7 @@ SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){
}else
#endif
{
- int i;
+ u32 i;
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
@@ -101903,9 +103018,9 @@ SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){
if( wsdAutoext.aExt[i]==xInit ) break;
}
if( i==wsdAutoext.nExt ){
- int nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
+ u64 nByte = (wsdAutoext.nExt+1)*sizeof(wsdAutoext.aExt[0]);
void (**aNew)(void);
- aNew = sqlite3_realloc(wsdAutoext.aExt, nByte);
+ aNew = sqlite3_realloc64(wsdAutoext.aExt, nByte);
if( aNew==0 ){
rc = SQLITE_NOMEM;
}else{
@@ -101929,7 +103044,7 @@ SQLITE_API int sqlite3_auto_extension(void (*xInit)(void)){
** Return 1 if xInit was found on the list and removed. Return 0 if xInit
** was not on the list.
*/
-SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){
+SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xInit)(void)){
#if SQLITE_THREADSAFE
sqlite3_mutex *mutex = sqlite3MutexAlloc(SQLITE_MUTEX_STATIC_MASTER);
#endif
@@ -101937,7 +103052,7 @@ SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){
int n = 0;
wsdAutoextInit;
sqlite3_mutex_enter(mutex);
- for(i=wsdAutoext.nExt-1; i>=0; i--){
+ for(i=(int)wsdAutoext.nExt-1; i>=0; i--){
if( wsdAutoext.aExt[i]==xInit ){
wsdAutoext.nExt--;
wsdAutoext.aExt[i] = wsdAutoext.aExt[wsdAutoext.nExt];
@@ -101952,7 +103067,7 @@ SQLITE_API int sqlite3_cancel_auto_extension(void (*xInit)(void)){
/*
** Reset the automatic extension loading mechanism.
*/
-SQLITE_API void sqlite3_reset_auto_extension(void){
+SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void){
#ifndef SQLITE_OMIT_AUTOINIT
if( sqlite3_initialize()==SQLITE_OK )
#endif
@@ -101975,7 +103090,7 @@ SQLITE_API void sqlite3_reset_auto_extension(void){
** If anything goes wrong, set an error in the database connection.
*/
SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
- int i;
+ u32 i;
int go = 1;
int rc;
int (*xInit)(sqlite3*,char**,const sqlite3_api_routines*);
@@ -102034,11 +103149,18 @@ SQLITE_PRIVATE void sqlite3AutoLoadExtensions(sqlite3 *db){
#endif
/***************************************************************************
-** The next block of code, including the PragTyp_XXXX macro definitions and
-** the aPragmaName[] object is composed of generated code. DO NOT EDIT.
-**
-** To add new pragmas, edit the code in ../tool/mkpragmatab.tcl and rerun
-** that script. Then copy/paste the output in place of the following:
+** The "pragma.h" include file is an automatically generated file that
+** that includes the PragType_XXXX macro definitions and the aPragmaName[]
+** object. This ensures that the aPragmaName[] table is arranged in
+** lexicographical order to facility a binary search of the pragma name.
+** Do not edit pragma.h directly. Edit and rerun the script in at
+** ../tool/mkpragmatab.tcl. */
+/************** Include pragma.h in the middle of pragma.c *******************/
+/************** Begin file pragma.h ******************************************/
+/* DO NOT EDIT!
+** This file is automatically generated by the script at
+** ../tool/mkpragmatab.tcl. To update the set of pragmas, edit
+** that script and rerun it.
*/
#define PragTyp_HEADER_VALUE 0
#define PragTyp_AUTO_VACUUM 1
@@ -102273,6 +103395,10 @@ static const struct sPragmaNames {
/* ePragTyp: */ PragTyp_INDEX_LIST,
/* ePragFlag: */ PragFlag_NeedSchema,
/* iArg: */ 0 },
+ { /* zName: */ "index_xinfo",
+ /* ePragTyp: */ PragTyp_INDEX_INFO,
+ /* ePragFlag: */ PragFlag_NeedSchema,
+ /* iArg: */ 1 },
#endif
#if !defined(SQLITE_OMIT_INTEGRITY_CHECK)
{ /* zName: */ "integrity_check",
@@ -102489,9 +103615,10 @@ static const struct sPragmaNames {
/* iArg: */ SQLITE_WriteSchema|SQLITE_RecoveryMode },
#endif
};
-/* Number of pragmas: 58 on by default, 71 total. */
-/* End of the automatically generated pragma table.
-***************************************************************************/
+/* Number of pragmas: 59 on by default, 72 total. */
+
+/************** End of pragma.h **********************************************/
+/************** Continuing where we left off in pragma.c *********************/
/*
** Interpret the given string as a safety level. Return 0 for OFF,
@@ -102627,15 +103754,15 @@ static int changeTempStorage(Parse *pParse, const char *zStorageType){
*/
static void returnSingleInt(Parse *pParse, const char *zLabel, i64 value){
Vdbe *v = sqlite3GetVdbe(pParse);
- int mem = ++pParse->nMem;
+ int nMem = ++pParse->nMem;
i64 *pI64 = sqlite3DbMallocRaw(pParse->db, sizeof(value));
if( pI64 ){
memcpy(pI64, &value, sizeof(value));
}
- sqlite3VdbeAddOp4(v, OP_Int64, 0, mem, 0, (char*)pI64, P4_INT64);
+ sqlite3VdbeAddOp4(v, OP_Int64, 0, nMem, 0, (char*)pI64, P4_INT64);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, zLabel, SQLITE_STATIC);
- sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, nMem, 1);
}
@@ -102744,6 +103871,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3 *db = pParse->db; /* The database connection */
Db *pDb; /* The specific database being pragmaed */
Vdbe *v = sqlite3GetVdbe(pParse); /* Prepared statement */
+ const struct sPragmaNames *pPragma;
if( v==0 ) return;
sqlite3VdbeRunOnlyOnce(v);
@@ -102779,6 +103907,17 @@ SQLITE_PRIVATE void sqlite3Pragma(
/* Send an SQLITE_FCNTL_PRAGMA file-control to the underlying VFS
** connection. If it returns SQLITE_OK, then assume that the VFS
** handled the pragma and generate a no-op prepared statement.
+ **
+ ** IMPLEMENTATION-OF: R-12238-55120 Whenever a PRAGMA statement is parsed,
+ ** an SQLITE_FCNTL_PRAGMA file control is sent to the open sqlite3_file
+ ** object corresponding to the database file to which the pragma
+ ** statement refers.
+ **
+ ** IMPLEMENTATION-OF: R-29875-31678 The argument to the SQLITE_FCNTL_PRAGMA
+ ** file control is an array of pointers to strings (char**) in which the
+ ** second element of the array is the name of the pragma and the third
+ ** element is the argument to the pragma or NULL if the pragma has no
+ ** argument.
*/
aFcntl[0] = 0;
aFcntl[1] = zLeft;
@@ -102788,11 +103927,11 @@ SQLITE_PRIVATE void sqlite3Pragma(
rc = sqlite3_file_control(db, zDb, SQLITE_FCNTL_PRAGMA, (void*)aFcntl);
if( rc==SQLITE_OK ){
if( aFcntl[0] ){
- int mem = ++pParse->nMem;
- sqlite3VdbeAddOp4(v, OP_String8, 0, mem, 0, aFcntl[0], 0);
+ int nMem = ++pParse->nMem;
+ sqlite3VdbeAddOp4(v, OP_String8, 0, nMem, 0, aFcntl[0], 0);
sqlite3VdbeSetNumCols(v, 1);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "result", SQLITE_STATIC);
- sqlite3VdbeAddOp2(v, OP_ResultRow, mem, 1);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, nMem, 1);
sqlite3_free(aFcntl[0]);
}
goto pragma_out;
@@ -102821,14 +103960,15 @@ SQLITE_PRIVATE void sqlite3Pragma(
}
}
if( lwr>upr ) goto pragma_out;
+ pPragma = &aPragmaNames[mid];
/* Make sure the database schema is loaded if the pragma requires that */
- if( (aPragmaNames[mid].mPragFlag & PragFlag_NeedSchema)!=0 ){
+ if( (pPragma->mPragFlag & PragFlag_NeedSchema)!=0 ){
if( sqlite3ReadSchema(pParse) ) goto pragma_out;
}
/* Jump to the appropriate pragma handler */
- switch( aPragmaNames[mid].ePragTyp ){
+ switch( pPragma->ePragTyp ){
#if !defined(SQLITE_OMIT_PAGER_PRAGMAS) && !defined(SQLITE_OMIT_DEPRECATED)
/*
@@ -103396,7 +104536,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
sqlite3ErrorMsg(pParse,
"Safety level may not be changed inside a transaction");
}else{
- pDb->safety_level = getSafetyLevel(zRight,0,1)+1;
+ int iLevel = (getSafetyLevel(zRight,0,1)+1) & PAGER_SYNCHRONOUS_MASK;
+ if( iLevel==0 ) iLevel = 1;
+ pDb->safety_level = iLevel;
setAllPagerFlags(db);
}
}
@@ -103407,10 +104549,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
#ifndef SQLITE_OMIT_FLAG_PRAGMAS
case PragTyp_FLAG: {
if( zRight==0 ){
- returnSingleInt(pParse, aPragmaNames[mid].zName,
- (db->flags & aPragmaNames[mid].iArg)!=0 );
+ returnSingleInt(pParse, pPragma->zName, (db->flags & pPragma->iArg)!=0 );
}else{
- int mask = aPragmaNames[mid].iArg; /* Mask of bits to set or clear. */
+ int mask = pPragma->iArg; /* Mask of bits to set or clear. */
if( db->autoCommit==0 ){
/* Foreign key support may not be enabled or disabled while not
** in auto-commit mode. */
@@ -103492,7 +104633,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
}else if( pPk==0 ){
k = 1;
}else{
- for(k=1; ALWAYS(k<=pTab->nCol) && pPk->aiColumn[k-1]!=i; k++){}
+ for(k=1; k<=pTab->nCol && pPk->aiColumn[k-1]!=i; k++){}
}
sqlite3VdbeAddOp2(v, OP_Integer, k, 6);
sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 6);
@@ -103539,20 +104680,42 @@ SQLITE_PRIVATE void sqlite3Pragma(
pIdx = sqlite3FindIndex(db, zRight, zDb);
if( pIdx ){
int i;
+ int mx;
+ if( pPragma->iArg ){
+ /* PRAGMA index_xinfo (newer version with more rows and columns) */
+ mx = pIdx->nColumn;
+ pParse->nMem = 6;
+ }else{
+ /* PRAGMA index_info (legacy version) */
+ mx = pIdx->nKeyCol;
+ pParse->nMem = 3;
+ }
pTab = pIdx->pTable;
- sqlite3VdbeSetNumCols(v, 3);
- pParse->nMem = 3;
+ sqlite3VdbeSetNumCols(v, pParse->nMem);
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seqno", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "cid", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "name", SQLITE_STATIC);
- for(i=0; i<pIdx->nKeyCol; i++){
+ if( pPragma->iArg ){
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "desc", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "coll", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 5, COLNAME_NAME, "key", SQLITE_STATIC);
+ }
+ for(i=0; i<mx; i++){
i16 cnum = pIdx->aiColumn[i];
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
sqlite3VdbeAddOp2(v, OP_Integer, cnum, 2);
- assert( pTab->nCol>cnum );
- sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
+ if( cnum<0 ){
+ sqlite3VdbeAddOp2(v, OP_Null, 0, 3);
+ }else{
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 3, 0, pTab->aCol[cnum].zName, 0);
+ }
+ if( pPragma->iArg ){
+ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->aSortOrder[i], 4);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 5, 0, pIdx->azColl[i], 0);
+ sqlite3VdbeAddOp2(v, OP_Integer, i<pIdx->nKeyCol, 6);
+ }
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, pParse->nMem);
}
}
}
@@ -103565,17 +104728,22 @@ SQLITE_PRIVATE void sqlite3Pragma(
pTab = sqlite3FindTable(db, zRight, zDb);
if( pTab ){
v = sqlite3GetVdbe(pParse);
- sqlite3VdbeSetNumCols(v, 3);
- pParse->nMem = 3;
+ sqlite3VdbeSetNumCols(v, 5);
+ pParse->nMem = 5;
sqlite3CodeVerifySchema(pParse, iDb);
sqlite3VdbeSetColName(v, 0, COLNAME_NAME, "seq", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 1, COLNAME_NAME, "name", SQLITE_STATIC);
sqlite3VdbeSetColName(v, 2, COLNAME_NAME, "unique", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 3, COLNAME_NAME, "origin", SQLITE_STATIC);
+ sqlite3VdbeSetColName(v, 4, COLNAME_NAME, "partial", SQLITE_STATIC);
for(pIdx=pTab->pIndex, i=0; pIdx; pIdx=pIdx->pNext, i++){
+ const char *azOrigin[] = { "c", "u", "pk" };
sqlite3VdbeAddOp2(v, OP_Integer, i, 1);
sqlite3VdbeAddOp4(v, OP_String8, 0, 2, 0, pIdx->zName, 0);
sqlite3VdbeAddOp2(v, OP_Integer, IsUniqueIndex(pIdx), 3);
- sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 3);
+ sqlite3VdbeAddOp4(v, OP_String8, 0, 4, 0, azOrigin[pIdx->idxType], 0);
+ sqlite3VdbeAddOp2(v, OP_Integer, pIdx->pPartIdxWhere!=0, 5);
+ sqlite3VdbeAddOp2(v, OP_ResultRow, 1, 5);
}
}
}
@@ -104145,9 +105313,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
** applications for any purpose.
*/
case PragTyp_HEADER_VALUE: {
- int iCookie = aPragmaNames[mid].iArg; /* Which cookie to read or write */
+ int iCookie = pPragma->iArg; /* Which cookie to read or write */
sqlite3VdbeUsesBtree(v, iDb);
- if( zRight && (aPragmaNames[mid].mPragFlag & PragFlag_ReadOnly)==0 ){
+ if( zRight && (pPragma->mPragFlag & PragFlag_ReadOnly)==0 ){
/* Write the specified cookie value */
static const VdbeOpList setCookie[] = {
{ OP_Transaction, 0, 1, 0}, /* 0 */
@@ -104249,8 +105417,9 @@ SQLITE_PRIVATE void sqlite3Pragma(
/*
** PRAGMA shrink_memory
**
- ** This pragma attempts to free as much memory as possible from the
- ** current database connection.
+ ** IMPLEMENTATION-OF: R-23445-46109 This pragma causes the database
+ ** connection on which it is invoked to free up as much memory as it
+ ** can, by calling sqlite3_db_release_memory().
*/
case PragTyp_SHRINK_MEMORY: {
sqlite3_db_release_memory(db);
@@ -104267,7 +105436,7 @@ SQLITE_PRIVATE void sqlite3Pragma(
** disables the timeout.
*/
/*case PragTyp_BUSY_TIMEOUT*/ default: {
- assert( aPragmaNames[mid].ePragTyp==PragTyp_BUSY_TIMEOUT );
+ assert( pPragma->ePragTyp==PragTyp_BUSY_TIMEOUT );
if( zRight ){
sqlite3_busy_timeout(db, sqlite3Atoi(zRight));
}
@@ -104279,8 +105448,12 @@ SQLITE_PRIVATE void sqlite3Pragma(
** PRAGMA soft_heap_limit
** PRAGMA soft_heap_limit = N
**
- ** Call sqlite3_soft_heap_limit64(N). Return the result. If N is omitted,
- ** use -1.
+ ** IMPLEMENTATION-OF: R-26343-45930 This pragma invokes the
+ ** sqlite3_soft_heap_limit64() interface with the argument N, if N is
+ ** specified and is a non-negative integer.
+ ** IMPLEMENTATION-OF: R-64451-07163 The soft_heap_limit pragma always
+ ** returns the same integer that would be returned by the
+ ** sqlite3_soft_heap_limit64(-1) C-language function.
*/
case PragTyp_SOFT_HEAP_LIMIT: {
sqlite3_int64 N;
@@ -104466,7 +105639,7 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
if( argv==0 ) return 0; /* Might happen if EMPTY_RESULT_CALLBACKS are on */
if( argv[1]==0 ){
corruptSchema(pData, argv[0], 0);
- }else if( argv[2] && argv[2][0] ){
+ }else if( sqlite3_strnicmp(argv[2],"create ",7)==0 ){
/* Call the parser to process a CREATE TABLE, INDEX or VIEW.
** But because db->init.busy is set to 1, no VDBE code is generated
** or executed. All the parser does is build the internal data
@@ -104497,8 +105670,8 @@ SQLITE_PRIVATE int sqlite3InitCallback(void *pInit, int argc, char **argv, char
}
}
sqlite3_finalize(pStmt);
- }else if( argv[0]==0 ){
- corruptSchema(pData, 0, 0);
+ }else if( argv[0]==0 || (argv[2]!=0 && argv[2][0]!=0) ){
+ corruptSchema(pData, argv[0], 0);
}else{
/* If the SQL column is blank it means this is an index that
** was created to be the PRIMARY KEY or to fulfill a UNIQUE
@@ -105176,7 +106349,7 @@ SQLITE_PRIVATE int sqlite3Reprepare(Vdbe *p){
** and the statement is automatically recompiled if an schema change
** occurs.
*/
-SQLITE_API int sqlite3_prepare(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
@@ -105188,7 +106361,7 @@ SQLITE_API int sqlite3_prepare(
assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
return rc;
}
-SQLITE_API int sqlite3_prepare_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2(
sqlite3 *db, /* Database handle. */
const char *zSql, /* UTF-8 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
@@ -105264,7 +106437,7 @@ static int sqlite3Prepare16(
** and the statement is automatically recompiled if an schema change
** occurs.
*/
-SQLITE_API int sqlite3_prepare16(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare16(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-16 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
@@ -105276,7 +106449,7 @@ SQLITE_API int sqlite3_prepare16(
assert( rc==SQLITE_OK || ppStmt==0 || *ppStmt==0 ); /* VERIFY: F13021 */
return rc;
}
-SQLITE_API int sqlite3_prepare16_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2(
sqlite3 *db, /* Database handle. */
const void *zSql, /* UTF-16 encoded SQL statement. */
int nBytes, /* Length of zSql in bytes. */
@@ -105405,7 +106578,6 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
Select standin;
sqlite3 *db = pParse->db;
pNew = sqlite3DbMallocZero(db, sizeof(*pNew) );
- assert( db->mallocFailed || !pOffset || pLimit ); /* OFFSET implies LIMIT */
if( pNew==0 ){
assert( db->mallocFailed );
pNew = &standin;
@@ -105425,7 +106597,7 @@ SQLITE_PRIVATE Select *sqlite3SelectNew(
pNew->op = TK_SELECT;
pNew->pLimit = pLimit;
pNew->pOffset = pOffset;
- assert( pOffset==0 || pLimit!=0 );
+ assert( pOffset==0 || pLimit!=0 || pParse->nErr>0 || db->mallocFailed!=0 );
pNew->addrOpenEphm[0] = -1;
pNew->addrOpenEphm[1] = -1;
if( db->mallocFailed ) {
@@ -105857,20 +107029,17 @@ static void pushOntoSorter(
}
sqlite3VdbeAddOp2(v, op, pSort->iECursor, regRecord);
if( pSelect->iLimit ){
- int addr1, addr2;
+ int addr;
int iLimit;
if( pSelect->iOffset ){
iLimit = pSelect->iOffset+1;
}else{
iLimit = pSelect->iLimit;
}
- addr1 = sqlite3VdbeAddOp1(v, OP_IfZero, iLimit); VdbeCoverage(v);
- sqlite3VdbeAddOp2(v, OP_AddImm, iLimit, -1);
- addr2 = sqlite3VdbeAddOp0(v, OP_Goto);
- sqlite3VdbeJumpHere(v, addr1);
+ addr = sqlite3VdbeAddOp3(v, OP_IfNotZero, iLimit, 0, -1); VdbeCoverage(v);
sqlite3VdbeAddOp1(v, OP_Last, pSort->iECursor);
sqlite3VdbeAddOp1(v, OP_Delete, pSort->iECursor);
- sqlite3VdbeJumpHere(v, addr2);
+ sqlite3VdbeJumpHere(v, addr);
}
}
@@ -106267,7 +107436,7 @@ static void selectInnerLoop(
** the output for us.
*/
if( pSort==0 && p->iLimit ){
- sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v);
}
}
@@ -106678,7 +107847,7 @@ static const char *columnTypeImpl(
** of the SELECT statement. Return the declaration type and origin
** data for the result-set column of the sub-select.
*/
- if( iCol>=0 && ALWAYS(iCol<pS->pEList->nExpr) ){
+ if( iCol>=0 && iCol<pS->pEList->nExpr ){
/* If iCol is less than zero, then the expression requests the
** rowid of the sub-select or view. This expression is legal (see
** test case misc2.2.2) - it always evaluates to NULL.
@@ -106998,12 +108167,14 @@ static void selectAddColumnTypeAndCollation(
a = pSelect->pEList->a;
for(i=0, pCol=pTab->aCol; i<pTab->nCol; i++, pCol++){
p = a[i].pExpr;
- pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
+ if( pCol->zType==0 ){
+ pCol->zType = sqlite3DbStrDup(db, columnType(&sNC, p,0,0,0, &pCol->szEst));
+ }
szAll += pCol->szEst;
pCol->affinity = sqlite3ExprAffinity(p);
if( pCol->affinity==0 ) pCol->affinity = SQLITE_AFF_NONE;
pColl = sqlite3ExprCollSeq(pParse, p);
- if( pColl ){
+ if( pColl && pCol->zColl==0 ){
pCol->zColl = sqlite3DbStrDup(db, pColl->zName);
}
}
@@ -107120,7 +108291,7 @@ static void computeLimitRegisters(Parse *pParse, Select *p, int iBreak){
sqlite3ExprCode(pParse, p->pLimit, iLimit);
sqlite3VdbeAddOp1(v, OP_MustBeInt, iLimit); VdbeCoverage(v);
VdbeComment((v, "LIMIT counter"));
- sqlite3VdbeAddOp2(v, OP_IfZero, iLimit, iBreak); VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_IfNot, iLimit, iBreak); VdbeCoverage(v);
}
if( p->pOffset ){
p->iOffset = iOffset = ++pParse->nMem;
@@ -107339,7 +108510,7 @@ static void generateWithRecursiveQuery(
selectInnerLoop(pParse, p, p->pEList, iCurrent,
0, 0, pDest, addrCont, addrBreak);
if( regLimit ){
- sqlite3VdbeAddOp3(v, OP_IfZero, regLimit, addrBreak, -1);
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, regLimit, addrBreak);
VdbeCoverage(v);
}
sqlite3VdbeResolveLabel(v, addrCont);
@@ -107405,8 +108576,7 @@ static int multiSelectValues(
int nExpr = p->pEList->nExpr;
int nRow = 1;
int rc = 0;
- assert( p->pNext==0 );
- assert( p->selFlags & SF_AllValues );
+ assert( p->selFlags & SF_MultiValue );
do{
assert( p->selFlags & SF_Values );
assert( p->op==TK_ALL || (p->op==TK_SELECT && p->pPrior==0) );
@@ -107515,7 +108685,7 @@ static int multiSelect(
/* Special handling for a compound-select that originates as a VALUES clause.
*/
- if( p->selFlags & SF_AllValues ){
+ if( p->selFlags & SF_MultiValue ){
rc = multiSelectValues(pParse, p, &dest);
goto multi_select_end;
}
@@ -107564,7 +108734,7 @@ static int multiSelect(
p->iLimit = pPrior->iLimit;
p->iOffset = pPrior->iOffset;
if( p->iLimit ){
- addr = sqlite3VdbeAddOp1(v, OP_IfZero, p->iLimit); VdbeCoverage(v);
+ addr = sqlite3VdbeAddOp1(v, OP_IfNot, p->iLimit); VdbeCoverage(v);
VdbeComment((v, "Jump ahead if LIMIT reached"));
}
explainSetInteger(iSub2, pParse->iNextSelectId);
@@ -107900,7 +109070,7 @@ static int generateOutputSubroutine(
*/
case SRT_Set: {
int r1;
- assert( pIn->nSdst==1 );
+ assert( pIn->nSdst==1 || pParse->nErr>0 );
pDest->affSdst =
sqlite3CompareAffinity(p->pEList->a[0].pExpr, pDest->affSdst);
r1 = sqlite3GetTempReg(pParse);
@@ -107926,7 +109096,7 @@ static int generateOutputSubroutine(
** of the scan loop.
*/
case SRT_Mem: {
- assert( pIn->nSdst==1 );
+ assert( pIn->nSdst==1 || pParse->nErr>0 ); testcase( pIn->nSdst!=1 );
sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSDParm, 1);
/* The LIMIT clause will jump out of the loop for us */
break;
@@ -107941,7 +109111,7 @@ static int generateOutputSubroutine(
pDest->iSdst = sqlite3GetTempRange(pParse, pIn->nSdst);
pDest->nSdst = pIn->nSdst;
}
- sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pDest->nSdst);
+ sqlite3ExprCodeMove(pParse, pIn->iSdst, pDest->iSdst, pIn->nSdst);
sqlite3VdbeAddOp1(v, OP_Yield, pDest->iSDParm);
break;
}
@@ -107965,7 +109135,7 @@ static int generateOutputSubroutine(
/* Jump to the end of the loop if the LIMIT is reached.
*/
if( p->iLimit ){
- sqlite3VdbeAddOp3(v, OP_IfZero, p->iLimit, iBreak, -1); VdbeCoverage(v);
+ sqlite3VdbeAddOp2(v, OP_DecrJumpZero, p->iLimit, iBreak); VdbeCoverage(v);
}
/* Generate the subroutine return
@@ -108157,8 +109327,10 @@ static int multiSelectOrderBy(
if( aPermute ){
struct ExprList_item *pItem;
for(i=0, pItem=pOrderBy->a; i<nOrderBy; i++, pItem++){
- assert( pItem->u.x.iOrderByCol>0
- && pItem->u.x.iOrderByCol<=p->pEList->nExpr );
+ assert( pItem->u.x.iOrderByCol>0 );
+ /* assert( pItem->u.x.iOrderByCol<=p->pEList->nExpr ) is also true
+ ** but only for well-formed SELECT statements. */
+ testcase( pItem->u.x.iOrderByCol > p->pEList->nExpr );
aPermute[i] = pItem->u.x.iOrderByCol - 1;
}
pKeyMerge = multiSelectOrderByKeyInfo(pParse, p, 1);
@@ -108368,7 +109540,7 @@ static int multiSelectOrderBy(
/*** TBD: Insert subroutine calls to close cursors on incomplete
**** subqueries ****/
explainComposite(pParse, p->op, iSub1, iSub2, 0);
- return SQLITE_OK;
+ return pParse->nErr!=0;
}
#endif
@@ -108488,7 +109660,10 @@ static void substSelect(
**
** (1) The subquery and the outer query do not both use aggregates.
**
-** (2) The subquery is not an aggregate or the outer query is not a join.
+** (2) The subquery is not an aggregate or (2a) the outer query is not a join
+** and (2b) the outer query does not use subqueries other than the one
+** FROM-clause subquery that is a candidate for flattening. (2b is
+** due to ticket [2f7170d73bf9abf80] from 2015-02-09.)
**
** (3) The subquery is not the right operand of a left outer join
** (Originally ticket #306. Strengthened by ticket #3300)
@@ -108625,8 +109800,17 @@ static int flattenSubquery(
iParent = pSubitem->iCursor;
pSub = pSubitem->pSelect;
assert( pSub!=0 );
- if( isAgg && subqueryIsAgg ) return 0; /* Restriction (1) */
- if( subqueryIsAgg && pSrc->nSrc>1 ) return 0; /* Restriction (2) */
+ if( subqueryIsAgg ){
+ if( isAgg ) return 0; /* Restriction (1) */
+ if( pSrc->nSrc>1 ) return 0; /* Restriction (2a) */
+ if( (p->pWhere && ExprHasProperty(p->pWhere,EP_Subquery))
+ || (sqlite3ExprListFlags(p->pEList) & EP_Subquery)!=0
+ || (sqlite3ExprListFlags(p->pOrderBy) & EP_Subquery)!=0
+ ){
+ return 0; /* Restriction (2b) */
+ }
+ }
+
pSubSrc = pSub->pSrc;
assert( pSubSrc );
/* Prior to version 3.1.2, when LIMIT and OFFSET had to be simple constants,
@@ -109168,7 +110352,10 @@ static int convertCompoundSelectToSubquery(Walker *pWalker, Select *p){
pNew->pOrderBy = 0;
p->pPrior = 0;
p->pNext = 0;
+ p->pWith = 0;
p->selFlags &= ~SF_Compound;
+ assert( (p->selFlags & SF_Converted)==0 );
+ p->selFlags |= SF_Converted;
assert( pNew->pPrior!=0 );
pNew->pPrior->pNext = pNew;
pNew->pLimit = 0;
@@ -109320,7 +110507,7 @@ static int withExpand(
for(pLeft=pSel; pLeft->pPrior; pLeft=pLeft->pPrior);
pEList = pLeft->pEList;
if( pCte->pCols ){
- if( pEList->nExpr!=pCte->pCols->nExpr ){
+ if( pEList && pEList->nExpr!=pCte->pCols->nExpr ){
sqlite3ErrorMsg(pParse, "table %s has %d values for %d columns",
pCte->zName, pEList->nExpr, pCte->pCols->nExpr
);
@@ -109447,7 +110634,7 @@ static int selectExpander(Walker *pWalker, Select *p){
/* A sub-query in the FROM clause of a SELECT */
assert( pSel!=0 );
assert( pFrom->pTab==0 );
- sqlite3WalkSelect(pWalker, pSel);
+ if( sqlite3WalkSelect(pWalker, pSel) ) return WRC_Abort;
pFrom->pTab = pTab = sqlite3DbMallocZero(db, sizeof(Table));
if( pTab==0 ) return WRC_Abort;
pTab->nRef = 1;
@@ -109704,7 +110891,7 @@ static void sqlite3SelectExpand(Parse *pParse, Select *pSelect){
sqlite3WalkSelect(&w, pSelect);
}
w.xSelectCallback = selectExpander;
- if( (pSelect->selFlags & SF_AllValues)==0 ){
+ if( (pSelect->selFlags & SF_MultiValue)==0 ){
w.xSelectCallback2 = selectPopWith;
}
sqlite3WalkSelect(&w, pSelect);
@@ -109890,7 +111077,8 @@ static void updateAccumulator(Parse *pParse, AggInfo *pAggInfo){
}
if( pF->iDistinct>=0 ){
addrNext = sqlite3VdbeMakeLabel(v);
- assert( nArg==1 );
+ testcase( nArg==0 ); /* Error condition */
+ testcase( nArg>1 ); /* Also an error */
codeDistinct(pParse, pF->iDistinct, addrNext, 1, regAgg);
}
if( pF->pFunc->funcFlags & SQLITE_FUNC_NEEDCOLL ){
@@ -110046,6 +111234,13 @@ SQLITE_PRIVATE int sqlite3Select(
}
isAgg = (p->selFlags & SF_Aggregate)!=0;
assert( pEList!=0 );
+#if SELECTTRACE_ENABLED
+ if( sqlite3SelectTrace & 0x100 ){
+ SELECTTRACE(0x100,pParse,p, ("after name resolution:\n"));
+ sqlite3TreeViewSelect(0, p, 0);
+ }
+#endif
+
/* Begin generating code.
*/
@@ -110758,10 +111953,9 @@ SQLITE_PRIVATE int sqlite3Select(
*/
sqlite3VdbeResolveLabel(v, iEnd);
- /* The SELECT was successfully coded. Set the return code to 0
- ** to indicate no errors.
- */
- rc = 0;
+ /* The SELECT has been coded. If there is an error in the Parse structure,
+ ** set the return code to 1. Otherwise 0. */
+ rc = (pParse->nErr>0);
/* Control jumps to here if an error is encountered above, or upon
** successful coding of the SELECT.
@@ -110791,9 +111985,9 @@ select_end:
SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 moreToFollow){
int n = 0;
pView = sqlite3TreeViewPush(pView, moreToFollow);
- sqlite3TreeViewLine(pView, "SELECT%s%s",
+ sqlite3TreeViewLine(pView, "SELECT%s%s (0x%p)",
((p->selFlags & SF_Distinct) ? " DISTINCT" : ""),
- ((p->selFlags & SF_Aggregate) ? " agg_flag" : "")
+ ((p->selFlags & SF_Aggregate) ? " agg_flag" : ""), p
);
if( p->pSrc && p->pSrc->nSrc ) n++;
if( p->pWhere ) n++;
@@ -110812,7 +112006,7 @@ SQLITE_PRIVATE void sqlite3TreeViewSelect(TreeView *pView, const Select *p, u8 m
struct SrcList_item *pItem = &p->pSrc->a[i];
StrAccum x;
char zLine[100];
- sqlite3StrAccumInit(&x, zLine, sizeof(zLine), 0);
+ sqlite3StrAccumInit(&x, 0, zLine, sizeof(zLine), 0);
sqlite3XPrintf(&x, 0, "{%d,*}", pItem->iCursor);
if( pItem->zDatabase ){
sqlite3XPrintf(&x, 0, " %s.%s", pItem->zDatabase, pItem->zName);
@@ -110971,7 +112165,7 @@ static int sqlite3_get_table_cb(void *pArg, int nCol, char **argv, char **colv){
z = 0;
}else{
int n = sqlite3Strlen30(argv[i])+1;
- z = sqlite3_malloc( n );
+ z = sqlite3_malloc64( n );
if( z==0 ) goto malloc_failed;
memcpy(z, argv[i], n);
}
@@ -110996,7 +112190,7 @@ malloc_failed:
** Instead, the entire table should be passed to sqlite3_free_table() when
** the calling procedure is finished using it.
*/
-SQLITE_API int sqlite3_get_table(
+SQLITE_API int SQLITE_STDCALL sqlite3_get_table(
sqlite3 *db, /* The database on which the SQL executes */
const char *zSql, /* The SQL to be executed */
char ***pazResult, /* Write the result table here */
@@ -111020,7 +112214,7 @@ SQLITE_API int sqlite3_get_table(
res.nData = 1;
res.nAlloc = 20;
res.rc = SQLITE_OK;
- res.azResult = sqlite3_malloc(sizeof(char*)*res.nAlloc );
+ res.azResult = sqlite3_malloc64(sizeof(char*)*res.nAlloc );
if( res.azResult==0 ){
db->errCode = SQLITE_NOMEM;
return SQLITE_NOMEM;
@@ -111048,7 +112242,7 @@ SQLITE_API int sqlite3_get_table(
}
if( res.nAlloc>res.nData ){
char **azNew;
- azNew = sqlite3_realloc( res.azResult, sizeof(char*)*res.nData );
+ azNew = sqlite3_realloc64( res.azResult, sizeof(char*)*res.nData );
if( azNew==0 ){
sqlite3_free_table(&res.azResult[1]);
db->errCode = SQLITE_NOMEM;
@@ -111065,7 +112259,7 @@ SQLITE_API int sqlite3_get_table(
/*
** This routine frees the space the sqlite3_get_table() malloced.
*/
-SQLITE_API void sqlite3_free_table(
+SQLITE_API void SQLITE_STDCALL sqlite3_free_table(
char **azResult /* Result returned from sqlite3_get_table() */
){
if( azResult ){
@@ -111276,7 +112470,6 @@ SQLITE_PRIVATE void sqlite3BeginTrigger(
/* Do not create a trigger on a system table */
if( sqlite3StrNICmp(pTab->zName, "sqlite_", 7)==0 ){
sqlite3ErrorMsg(pParse, "cannot create trigger on system table");
- pParse->nErr++;
goto trigger_cleanup;
}
@@ -111456,12 +112649,12 @@ static TriggerStep *triggerStepAllocate(
){
TriggerStep *pTriggerStep;
- pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n);
+ pTriggerStep = sqlite3DbMallocZero(db, sizeof(TriggerStep) + pName->n + 1);
if( pTriggerStep ){
char *z = (char*)&pTriggerStep[1];
memcpy(z, pName->z, pName->n);
- pTriggerStep->target.z = z;
- pTriggerStep->target.n = pName->n;
+ sqlite3Dequote(z);
+ pTriggerStep->zTarget = z;
pTriggerStep->op = op;
}
return pTriggerStep;
@@ -111744,7 +112937,7 @@ SQLITE_PRIVATE Trigger *sqlite3TriggersExist(
}
/*
-** Convert the pStep->target token into a SrcList and return a pointer
+** Convert the pStep->zTarget string into a SrcList and return a pointer
** to that SrcList.
**
** This routine adds a specific database name, if needed, to the target when
@@ -111757,17 +112950,17 @@ static SrcList *targetSrcList(
Parse *pParse, /* The parsing context */
TriggerStep *pStep /* The trigger containing the target token */
){
+ sqlite3 *db = pParse->db;
int iDb; /* Index of the database to use */
SrcList *pSrc; /* SrcList to be returned */
- pSrc = sqlite3SrcListAppend(pParse->db, 0, &pStep->target, 0);
+ pSrc = sqlite3SrcListAppend(db, 0, 0, 0);
if( pSrc ){
assert( pSrc->nSrc>0 );
- assert( pSrc->a!=0 );
- iDb = sqlite3SchemaToIndex(pParse->db, pStep->pTrig->pSchema);
+ pSrc->a[pSrc->nSrc-1].zName = sqlite3DbStrDup(db, pStep->zTarget);
+ iDb = sqlite3SchemaToIndex(db, pStep->pTrig->pSchema);
if( iDb==0 || iDb>=2 ){
- sqlite3 *db = pParse->db;
- assert( iDb<pParse->db->nDb );
+ assert( iDb<db->nDb );
pSrc->a[pSrc->nSrc-1].zDatabase = sqlite3DbStrDup(db, db->aDb[iDb].zName);
}
}
@@ -111879,6 +113072,7 @@ static void transferParseError(Parse *pTo, Parse *pFrom){
if( pTo->nErr==0 ){
pTo->zErrMsg = pFrom->zErrMsg;
pTo->nErr = pFrom->nErr;
+ pTo->rc = pFrom->rc;
}else{
sqlite3DbFree(pFrom->db, pFrom->zErrMsg);
}
@@ -113163,7 +114357,7 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
** cause problems for the call to BtreeSetPageSize() below. */
sqlite3BtreeCommit(pTemp);
- nRes = sqlite3BtreeGetReserve(pMain);
+ nRes = sqlite3BtreeGetOptimalReserve(pMain);
/* A VACUUM cannot change the pagesize of an encrypted database. */
#ifdef SQLITE_HAS_CODEC
@@ -113229,6 +114423,8 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
** an "INSERT INTO vacuum_db.xxx SELECT * FROM main.xxx;" to copy
** the contents to the temporary database.
*/
+ assert( (db->flags & SQLITE_Vacuum)==0 );
+ db->flags |= SQLITE_Vacuum;
rc = execExecSql(db, pzErrMsg,
"SELECT 'INSERT INTO vacuum_db.' || quote(name) "
"|| ' SELECT * FROM main.' || quote(name) || ';'"
@@ -113236,6 +114432,8 @@ SQLITE_PRIVATE int sqlite3RunVacuum(char **pzErrMsg, sqlite3 *db){
"WHERE type = 'table' AND name!='sqlite_sequence' "
" AND coalesce(rootpage,1)>0"
);
+ assert( (db->flags & SQLITE_Vacuum)!=0 );
+ db->flags &= ~SQLITE_Vacuum;
if( rc!=SQLITE_OK ) goto end_of_vacuum;
/* Copy over the sequence table
@@ -113374,6 +114572,8 @@ end_of_vacuum:
struct VtabCtx {
VTable *pVTable; /* The virtual table being constructed */
Table *pTab; /* The Table object to which the virtual table belongs */
+ VtabCtx *pPrior; /* Parent context (if any) */
+ int bDeclared; /* True after sqlite3_declare_vtab() is called */
};
/*
@@ -113425,7 +114625,7 @@ static int createModule(
/*
** External API function used to create a new virtual-table module.
*/
-SQLITE_API int sqlite3_create_module(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_module(
sqlite3 *db, /* Database in which module is registered */
const char *zName, /* Name assigned to this module */
const sqlite3_module *pModule, /* The definition of the module */
@@ -113440,7 +114640,7 @@ SQLITE_API int sqlite3_create_module(
/*
** External API function used to create a new virtual-table module.
*/
-SQLITE_API int sqlite3_create_module_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2(
sqlite3 *db, /* Database in which module is registered */
const char *zName, /* Name assigned to this module */
const sqlite3_module *pModule, /* The definition of the module */
@@ -113739,6 +114939,7 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
char *zStmt;
char *zWhere;
int iDb;
+ int iReg;
Vdbe *v;
/* Compute the complete text of the CREATE VIRTUAL TABLE statement */
@@ -113773,8 +114974,10 @@ SQLITE_PRIVATE void sqlite3VtabFinishParse(Parse *pParse, Token *pEnd){
sqlite3VdbeAddOp2(v, OP_Expire, 0, 0);
zWhere = sqlite3MPrintf(db, "name='%q' AND type='table'", pTab->zName);
sqlite3VdbeAddParseSchemaOp(v, iDb, zWhere);
- sqlite3VdbeAddOp4(v, OP_VCreate, iDb, 0, 0,
- pTab->zName, sqlite3Strlen30(pTab->zName) + 1);
+
+ iReg = ++pParse->nMem;
+ sqlite3VdbeAddOp4(v, OP_String8, 0, iReg, 0, pTab->zName, 0);
+ sqlite3VdbeAddOp2(v, OP_VCreate, iDb, iReg);
}
/* If we are rereading the sqlite_master table create the in-memory
@@ -113817,7 +115020,7 @@ SQLITE_PRIVATE void sqlite3VtabArgExtend(Parse *pParse, Token *p){
pArg->z = p->z;
pArg->n = p->n;
}else{
- assert(pArg->z < p->z);
+ assert(pArg->z <= p->z);
pArg->n = (int)(&p->z[p->n] - pArg->z);
}
}
@@ -113834,15 +115037,27 @@ static int vtabCallConstructor(
int (*xConstruct)(sqlite3*,void*,int,const char*const*,sqlite3_vtab**,char**),
char **pzErr
){
- VtabCtx sCtx, *pPriorCtx;
+ VtabCtx sCtx;
VTable *pVTable;
int rc;
const char *const*azArg = (const char *const*)pTab->azModuleArg;
int nArg = pTab->nModuleArg;
char *zErr = 0;
- char *zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
+ char *zModuleName;
int iDb;
+ VtabCtx *pCtx;
+
+ /* Check that the virtual-table is not already being initialized */
+ for(pCtx=db->pVtabCtx; pCtx; pCtx=pCtx->pPrior){
+ if( pCtx->pTab==pTab ){
+ *pzErr = sqlite3MPrintf(db,
+ "vtable constructor called recursively: %s", pTab->zName
+ );
+ return SQLITE_LOCKED;
+ }
+ }
+ zModuleName = sqlite3MPrintf(db, "%s", pTab->zName);
if( !zModuleName ){
return SQLITE_NOMEM;
}
@@ -113863,11 +115078,13 @@ static int vtabCallConstructor(
assert( xConstruct );
sCtx.pTab = pTab;
sCtx.pVTable = pVTable;
- pPriorCtx = db->pVtabCtx;
+ sCtx.pPrior = db->pVtabCtx;
+ sCtx.bDeclared = 0;
db->pVtabCtx = &sCtx;
rc = xConstruct(db, pMod->pAux, nArg, azArg, &pVTable->pVtab, &zErr);
- db->pVtabCtx = pPriorCtx;
+ db->pVtabCtx = sCtx.pPrior;
if( rc==SQLITE_NOMEM ) db->mallocFailed = 1;
+ assert( sCtx.pTab==pTab );
if( SQLITE_OK!=rc ){
if( zErr==0 ){
@@ -113883,13 +115100,14 @@ static int vtabCallConstructor(
memset(pVTable->pVtab, 0, sizeof(pVTable->pVtab[0]));
pVTable->pVtab->pModule = pMod->pModule;
pVTable->nRef = 1;
- if( sCtx.pTab ){
+ if( sCtx.bDeclared==0 ){
const char *zFormat = "vtable constructor did not declare schema: %s";
*pzErr = sqlite3MPrintf(db, zFormat, pTab->zName);
sqlite3VtabUnlock(pVTable);
rc = SQLITE_ERROR;
}else{
int iCol;
+ u8 oooHidden = 0;
/* If everything went according to plan, link the new VTable structure
** into the linked list headed by pTab->pVTable. Then loop through the
** columns of the table to see if any of them contain the token "hidden".
@@ -113902,7 +115120,10 @@ static int vtabCallConstructor(
char *zType = pTab->aCol[iCol].zType;
int nType;
int i = 0;
- if( !zType ) continue;
+ if( !zType ){
+ pTab->tabFlags |= oooHidden;
+ continue;
+ }
nType = sqlite3Strlen30(zType);
if( sqlite3StrNICmp("hidden", zType, 6)||(zType[6] && zType[6]!=' ') ){
for(i=0; i<nType; i++){
@@ -113925,6 +115146,9 @@ static int vtabCallConstructor(
zType[i-1] = '\0';
}
pTab->aCol[iCol].colFlags |= COLFLAG_HIDDEN;
+ oooHidden = TF_OOOHidden;
+ }else{
+ pTab->tabFlags |= oooHidden;
}
}
}
@@ -114052,22 +115276,26 @@ SQLITE_PRIVATE int sqlite3VtabCallCreate(sqlite3 *db, int iDb, const char *zTab,
** valid to call this function from within the xCreate() or xConnect() of a
** virtual table module.
*/
-SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
+SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
+ VtabCtx *pCtx;
Parse *pParse;
-
int rc = SQLITE_OK;
Table *pTab;
char *zErr = 0;
#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
+ if( !sqlite3SafetyCheckOk(db) || zCreateTable==0 ){
+ return SQLITE_MISUSE_BKPT;
+ }
#endif
sqlite3_mutex_enter(db->mutex);
- if( !db->pVtabCtx || !(pTab = db->pVtabCtx->pTab) ){
+ pCtx = db->pVtabCtx;
+ if( !pCtx || pCtx->bDeclared ){
sqlite3Error(db, SQLITE_MISUSE);
sqlite3_mutex_leave(db->mutex);
return SQLITE_MISUSE_BKPT;
}
+ pTab = pCtx->pTab;
assert( (pTab->tabFlags & TF_Virtual)!=0 );
pParse = sqlite3StackAllocZero(db, sizeof(*pParse));
@@ -114090,7 +115318,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3 *db, const char *zCreateTable){
pParse->pNewTable->nCol = 0;
pParse->pNewTable->aCol = 0;
}
- db->pVtabCtx->pTab = 0;
+ pCtx->bDeclared = 1;
}else{
sqlite3ErrorWithMsg(db, SQLITE_ERROR, (zErr ? "%s" : 0), zErr);
sqlite3DbFree(db, zErr);
@@ -114125,11 +115353,15 @@ SQLITE_PRIVATE int sqlite3VtabCallDestroy(sqlite3 *db, int iDb, const char *zTab
pTab = sqlite3FindTable(db, zTab, db->aDb[iDb].zName);
if( ALWAYS(pTab!=0 && pTab->pVTable!=0) ){
- VTable *p = vtabDisconnectAll(db, pTab);
-
- assert( rc==SQLITE_OK );
+ VTable *p;
+ for(p=pTab->pVTable; p; p=p->pNext){
+ assert( p->pVtab );
+ if( p->pVtab->nRef>0 ){
+ return SQLITE_LOCKED;
+ }
+ }
+ p = vtabDisconnectAll(db, pTab);
rc = p->pMod->pModule->xDestroy(p->pVtab);
-
/* Remove the sqlite3_vtab* from the aVTrans[] array, if applicable */
if( rc==SQLITE_OK ){
assert( pTab->pVTable==p && p->pNext==0 );
@@ -114280,7 +115512,7 @@ SQLITE_PRIVATE int sqlite3VtabSavepoint(sqlite3 *db, int op, int iSavepoint){
int rc = SQLITE_OK;
assert( op==SAVEPOINT_RELEASE||op==SAVEPOINT_ROLLBACK||op==SAVEPOINT_BEGIN );
- assert( iSavepoint>=0 );
+ assert( iSavepoint>=-1 );
if( db->aVTrans ){
int i;
for(i=0; rc==SQLITE_OK && i<db->nVTrans; i++){
@@ -114398,7 +115630,7 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
if( pTab==pToplevel->apVtabLock[i] ) return;
}
n = (pToplevel->nVtabLock+1)*sizeof(pToplevel->apVtabLock[0]);
- apVtabLock = sqlite3_realloc(pToplevel->apVtabLock, n);
+ apVtabLock = sqlite3_realloc64(pToplevel->apVtabLock, n);
if( apVtabLock ){
pToplevel->apVtabLock = apVtabLock;
pToplevel->apVtabLock[pToplevel->nVtabLock++] = pTab;
@@ -114414,7 +115646,7 @@ SQLITE_PRIVATE void sqlite3VtabMakeWritable(Parse *pParse, Table *pTab){
** The results of this routine are undefined unless it is called from
** within an xUpdate method.
*/
-SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){
+SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *db){
static const unsigned char aMap[] = {
SQLITE_ROLLBACK, SQLITE_ABORT, SQLITE_FAIL, SQLITE_IGNORE, SQLITE_REPLACE
};
@@ -114432,7 +115664,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *db){
** the SQLite core with additional information about the behavior
** of the virtual table being implemented.
*/
-SQLITE_API int sqlite3_vtab_config(sqlite3 *db, int op, ...){
+SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3 *db, int op, ...){
va_list ap;
int rc = SQLITE_OK;
@@ -114558,6 +115790,8 @@ struct WhereLevel {
int addrCont; /* Jump here to continue with the next loop cycle */
int addrFirst; /* First instruction of interior of the loop */
int addrBody; /* Beginning of the body of this loop */
+ int iLikeRepCntr; /* LIKE range processing counter register */
+ int addrLikeRep; /* LIKE range processing address */
u8 iFrom; /* Which entry in the FROM clause */
u8 op, p3, p5; /* Opcode, P3 & P5 of the opcode that ends the loop */
int p1, p2; /* Operands of the opcode used to ends the loop */
@@ -114742,7 +115976,7 @@ struct WhereTerm {
} u;
LogEst truthProb; /* Probability of truth for this expression */
u16 eOperator; /* A WO_xx value describing <op> */
- u8 wtFlags; /* TERM_xxx bit flags. See below */
+ u16 wtFlags; /* TERM_xxx bit flags. See below */
u8 nChild; /* Number of children that must disable us */
WhereClause *pWC; /* The clause this term is part of */
Bitmask prereqRight; /* Bitmask of tables used by pExpr->pRight */
@@ -114764,6 +115998,9 @@ struct WhereTerm {
#else
# define TERM_VNULL 0x00 /* Disabled if not using stat3 */
#endif
+#define TERM_LIKEOPT 0x100 /* Virtual terms from the LIKE optimization */
+#define TERM_LIKECOND 0x200 /* Conditionally this LIKE operator term */
+#define TERM_LIKE 0x400 /* The original LIKE operator */
/*
** An instance of the WhereScan object is used as an iterator for locating
@@ -115139,7 +116376,7 @@ static void whereClauseClear(WhereClause *pWC){
** calling this routine. Such pointers may be reinitialized by referencing
** the pWC->a[] array.
*/
-static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
+static int whereClauseInsert(WhereClause *pWC, Expr *p, u16 wtFlags){
WhereTerm *pTerm;
int idx;
testcase( wtFlags & TERM_VIRTUAL );
@@ -115192,13 +116429,14 @@ static int whereClauseInsert(WhereClause *pWC, Expr *p, u8 wtFlags){
** all terms of the WHERE clause.
*/
static void whereSplit(WhereClause *pWC, Expr *pExpr, u8 op){
+ Expr *pE2 = sqlite3ExprSkipCollate(pExpr);
pWC->op = op;
- if( pExpr==0 ) return;
- if( pExpr->op!=op ){
+ if( pE2==0 ) return;
+ if( pE2->op!=op ){
whereClauseInsert(pWC, pExpr, 0);
}else{
- whereSplit(pWC, pExpr->pLeft, op);
- whereSplit(pWC, pExpr->pRight, op);
+ whereSplit(pWC, pE2->pLeft, op);
+ whereSplit(pWC, pE2->pRight, op);
}
}
@@ -115564,7 +116802,11 @@ static void exprAnalyzeAll(
** so and false if not.
**
** In order for the operator to be optimizible, the RHS must be a string
-** literal that does not begin with a wildcard.
+** literal that does not begin with a wildcard. The LHS must be a column
+** that may only be NULL, a string, or a BLOB, never a number. (This means
+** that virtual tables cannot participate in the LIKE optimization.) If the
+** collating sequence for the column on the LHS must be appropriate for
+** the operator.
*/
static int isLikeOrGlob(
Parse *pParse, /* Parsing and code generating context */
@@ -115593,7 +116835,7 @@ static int isLikeOrGlob(
pLeft = pList->a[1].pExpr;
if( pLeft->op!=TK_COLUMN
|| sqlite3ExprAffinity(pLeft)!=SQLITE_AFF_TEXT
- || IsVirtual(pLeft->pTab)
+ || IsVirtual(pLeft->pTab) /* Value might be numeric */
){
/* IMP: R-02065-49465 The left-hand side of the LIKE or GLOB operator must
** be the name of an indexed column with TEXT affinity. */
@@ -115703,6 +116945,79 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
pWC->a[iParent].nChild++;
}
+/*
+** Return the N-th AND-connected subterm of pTerm. Or if pTerm is not
+** a conjunction, then return just pTerm when N==0. If N is exceeds
+** the number of available subterms, return NULL.
+*/
+static WhereTerm *whereNthSubterm(WhereTerm *pTerm, int N){
+ if( pTerm->eOperator!=WO_AND ){
+ return N==0 ? pTerm : 0;
+ }
+ if( N<pTerm->u.pAndInfo->wc.nTerm ){
+ return &pTerm->u.pAndInfo->wc.a[N];
+ }
+ return 0;
+}
+
+/*
+** Subterms pOne and pTwo are contained within WHERE clause pWC. The
+** two subterms are in disjunction - they are OR-ed together.
+**
+** If these two terms are both of the form: "A op B" with the same
+** A and B values but different operators and if the operators are
+** compatible (if one is = and the other is <, for example) then
+** add a new virtual AND term to pWC that is the combination of the
+** two.
+**
+** Some examples:
+**
+** x<y OR x=y --> x<=y
+** x=y OR x=y --> x=y
+** x<=y OR x<y --> x<=y
+**
+** The following is NOT generated:
+**
+** x<y OR x>y --> x!=y
+*/
+static void whereCombineDisjuncts(
+ SrcList *pSrc, /* the FROM clause */
+ WhereClause *pWC, /* The complete WHERE clause */
+ WhereTerm *pOne, /* First disjunct */
+ WhereTerm *pTwo /* Second disjunct */
+){
+ u16 eOp = pOne->eOperator | pTwo->eOperator;
+ sqlite3 *db; /* Database connection (for malloc) */
+ Expr *pNew; /* New virtual expression */
+ int op; /* Operator for the combined expression */
+ int idxNew; /* Index in pWC of the next virtual term */
+
+ if( (pOne->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
+ if( (pTwo->eOperator & (WO_EQ|WO_LT|WO_LE|WO_GT|WO_GE))==0 ) return;
+ if( (eOp & (WO_EQ|WO_LT|WO_LE))!=eOp
+ && (eOp & (WO_EQ|WO_GT|WO_GE))!=eOp ) return;
+ assert( pOne->pExpr->pLeft!=0 && pOne->pExpr->pRight!=0 );
+ assert( pTwo->pExpr->pLeft!=0 && pTwo->pExpr->pRight!=0 );
+ if( sqlite3ExprCompare(pOne->pExpr->pLeft, pTwo->pExpr->pLeft, -1) ) return;
+ if( sqlite3ExprCompare(pOne->pExpr->pRight, pTwo->pExpr->pRight, -1) )return;
+ /* If we reach this point, it means the two subterms can be combined */
+ if( (eOp & (eOp-1))!=0 ){
+ if( eOp & (WO_LT|WO_LE) ){
+ eOp = WO_LE;
+ }else{
+ assert( eOp & (WO_GT|WO_GE) );
+ eOp = WO_GE;
+ }
+ }
+ db = pWC->pWInfo->pParse->db;
+ pNew = sqlite3ExprDup(db, pOne->pExpr, 0);
+ if( pNew==0 ) return;
+ for(op=TK_EQ; eOp!=(WO_EQ<<(op-TK_EQ)); op++){ assert( op<TK_GE ); }
+ pNew->op = op;
+ idxNew = whereClauseInsert(pWC, pNew, TERM_VIRTUAL|TERM_DYNAMIC);
+ exprAnalyze(pSrc, pWC, idxNew);
+}
+
#if !defined(SQLITE_OMIT_OR_OPTIMIZATION) && !defined(SQLITE_OMIT_SUBQUERY)
/*
** Analyze a term that consists of two or more OR-connected
@@ -115727,6 +117042,7 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
** (C) t1.x=t2.y OR (t1.x=t2.z AND t1.y=15)
** (D) x=expr1 OR (y>11 AND y<22 AND z LIKE '*hello*')
** (E) (p.a=1 AND q.b=2 AND r.c=3) OR (p.x=4 AND q.y=5 AND r.z=6)
+** (F) x>A OR (x=A AND y>=B)
**
** CASE 1:
**
@@ -115743,6 +117059,16 @@ static void markTermAsChild(WhereClause *pWC, int iChild, int iParent){
**
** CASE 2:
**
+** If there are exactly two disjuncts one side has x>A and the other side
+** has x=A (for the same x and A) then add a new virtual conjunct term to the
+** WHERE clause of the form "x>=A". Example:
+**
+** x>A OR (x=A AND y>B) adds: x>=A
+**
+** The added conjunct can sometimes be helpful in query planning.
+**
+** CASE 3:
+**
** If all subterms are indexable by a single table T, then set
**
** WhereTerm.eOperator = WO_OR
@@ -115869,12 +117195,26 @@ static void exprAnalyzeOrTerm(
}
/*
- ** Record the set of tables that satisfy case 2. The set might be
+ ** Record the set of tables that satisfy case 3. The set might be
** empty.
*/
pOrInfo->indexable = indexable;
pTerm->eOperator = indexable==0 ? 0 : WO_OR;
+ /* For a two-way OR, attempt to implementation case 2.
+ */
+ if( indexable && pOrWc->nTerm==2 ){
+ int iOne = 0;
+ WhereTerm *pOne;
+ while( (pOne = whereNthSubterm(&pOrWc->a[0],iOne++))!=0 ){
+ int iTwo = 0;
+ WhereTerm *pTwo;
+ while( (pTwo = whereNthSubterm(&pOrWc->a[1],iTwo++))!=0 ){
+ whereCombineDisjuncts(pSrc, pWC, pOne, pTwo);
+ }
+ }
+ }
+
/*
** chngToIN holds a set of tables that *might* satisfy case 1. But
** we have to do some additional checking to see if case 1 really
@@ -116004,7 +117344,7 @@ static void exprAnalyzeOrTerm(
}else{
sqlite3ExprListDelete(db, pList);
}
- pTerm->eOperator = WO_NOOP; /* case 1 trumps case 2 */
+ pTerm->eOperator = WO_NOOP; /* case 1 trumps case 3 */
}
}
}
@@ -116042,7 +117382,7 @@ static void exprAnalyze(
Bitmask extraRight = 0; /* Extra dependencies on LEFT JOIN */
Expr *pStr1 = 0; /* RHS of LIKE/GLOB operator */
int isComplete = 0; /* RHS of LIKE/GLOB ends with wildcard */
- int noCase = 0; /* LIKE/GLOB distinguishes case */
+ int noCase = 0; /* uppercase equivalent to lowercase */
int op; /* Top-level operator. pExpr->op */
Parse *pParse = pWInfo->pParse; /* Parsing context */
sqlite3 *db = pParse->db; /* Database connection */
@@ -116180,12 +117520,15 @@ static void exprAnalyze(
/* Add constraints to reduce the search space on a LIKE or GLOB
** operator.
**
- ** A like pattern of the form "x LIKE 'abc%'" is changed into constraints
+ ** A like pattern of the form "x LIKE 'aBc%'" is changed into constraints
**
- ** x>='abc' AND x<'abd' AND x LIKE 'abc%'
+ ** x>='ABC' AND x<'abd' AND x LIKE 'aBc%'
**
** The last character of the prefix "abc" is incremented to form the
- ** termination condition "abd".
+ ** termination condition "abd". If case is not significant (the default
+ ** for LIKE) then the lower-bound is made all uppercase and the upper-
+ ** bound is made all lowercase so that the bounds also work when comparing
+ ** BLOBs.
*/
if( pWC->op==TK_AND
&& isLikeOrGlob(pParse, pExpr, &pStr1, &isComplete, &noCase)
@@ -116196,10 +117539,26 @@ static void exprAnalyze(
Expr *pNewExpr2;
int idxNew1;
int idxNew2;
- Token sCollSeqName; /* Name of collating sequence */
+ const char *zCollSeqName; /* Name of collating sequence */
+ const u16 wtFlags = TERM_LIKEOPT | TERM_VIRTUAL | TERM_DYNAMIC;
pLeft = pExpr->x.pList->a[1].pExpr;
pStr2 = sqlite3ExprDup(db, pStr1, 0);
+
+ /* Convert the lower bound to upper-case and the upper bound to
+ ** lower-case (upper-case is less than lower-case in ASCII) so that
+ ** the range constraints also work for BLOBs
+ */
+ if( noCase && !pParse->db->mallocFailed ){
+ int i;
+ char c;
+ pTerm->wtFlags |= TERM_LIKE;
+ for(i=0; (c = pStr1->u.zToken[i])!=0; i++){
+ pStr1->u.zToken[i] = sqlite3Toupper(c);
+ pStr2->u.zToken[i] = sqlite3Tolower(c);
+ }
+ }
+
if( !db->mallocFailed ){
u8 c, *pC; /* Last character before the first wildcard */
pC = (u8*)&pStr2->u.zToken[sqlite3Strlen30(pStr2->u.zToken)-1];
@@ -116216,22 +117575,21 @@ static void exprAnalyze(
}
*pC = c + 1;
}
- sCollSeqName.z = noCase ? "NOCASE" : "BINARY";
- sCollSeqName.n = 6;
+ zCollSeqName = noCase ? "NOCASE" : "BINARY";
pNewExpr1 = sqlite3ExprDup(db, pLeft, 0);
- pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
- sqlite3ExprAddCollateToken(pParse,pNewExpr1,&sCollSeqName),
+ pNewExpr1 = sqlite3PExpr(pParse, TK_GE,
+ sqlite3ExprAddCollateString(pParse,pNewExpr1,zCollSeqName),
pStr1, 0);
transferJoinMarkings(pNewExpr1, pExpr);
- idxNew1 = whereClauseInsert(pWC, pNewExpr1, TERM_VIRTUAL|TERM_DYNAMIC);
+ idxNew1 = whereClauseInsert(pWC, pNewExpr1, wtFlags);
testcase( idxNew1==0 );
exprAnalyze(pSrc, pWC, idxNew1);
pNewExpr2 = sqlite3ExprDup(db, pLeft, 0);
pNewExpr2 = sqlite3PExpr(pParse, TK_LT,
- sqlite3ExprAddCollateToken(pParse,pNewExpr2,&sCollSeqName),
+ sqlite3ExprAddCollateString(pParse,pNewExpr2,zCollSeqName),
pStr2, 0);
transferJoinMarkings(pNewExpr2, pExpr);
- idxNew2 = whereClauseInsert(pWC, pNewExpr2, TERM_VIRTUAL|TERM_DYNAMIC);
+ idxNew2 = whereClauseInsert(pWC, pNewExpr2, wtFlags);
testcase( idxNew2==0 );
exprAnalyze(pSrc, pWC, idxNew2);
pTerm = &pWC->a[idxTerm];
@@ -116349,7 +117707,7 @@ static int findIndexCol(
&& p->iTable==iBase
){
CollSeq *pColl = sqlite3ExprCollSeq(pParse, pList->a[i].pExpr);
- if( ALWAYS(pColl) && 0==sqlite3StrICmp(pColl->zName, zColl) ){
+ if( pColl && 0==sqlite3StrICmp(pColl->zName, zColl) ){
return i;
}
}
@@ -116549,12 +117907,16 @@ static void constructAutomaticIndex(
pLoop = pLevel->pWLoop;
idxCols = 0;
for(pTerm=pWC->a; pTerm<pWCEnd; pTerm++){
+ Expr *pExpr = pTerm->pExpr;
+ assert( !ExprHasProperty(pExpr, EP_FromJoin) /* prereq always non-zero */
+ || pExpr->iRightJoinTable!=pSrc->iCursor /* for the right-hand */
+ || pLoop->prereq!=0 ); /* table of a LEFT JOIN */
if( pLoop->prereq==0
&& (pTerm->wtFlags & TERM_VIRTUAL)==0
- && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
- && sqlite3ExprIsTableConstant(pTerm->pExpr, pSrc->iCursor) ){
+ && !ExprHasProperty(pExpr, EP_FromJoin)
+ && sqlite3ExprIsTableConstant(pExpr, pSrc->iCursor) ){
pPartial = sqlite3ExprAnd(pParse->db, pPartial,
- sqlite3ExprDup(pParse->db, pTerm->pExpr, 0));
+ sqlite3ExprDup(pParse->db, pExpr, 0));
}
if( termCanDriveIndex(pTerm, pSrc, notReady) ){
int iCol = pTerm->u.leftColumn;
@@ -116619,7 +117981,7 @@ static void constructAutomaticIndex(
idxCols |= cMask;
pIdx->aiColumn[n] = pTerm->u.leftColumn;
pColl = sqlite3BinaryCompareCollSeq(pParse, pX->pLeft, pX->pRight);
- pIdx->azColl[n] = ALWAYS(pColl) ? pColl->zName : "BINARY";
+ pIdx->azColl[n] = pColl ? pColl->zName : "BINARY";
n++;
}
}
@@ -116841,11 +118203,14 @@ static int vtabBestIndex(Parse *pParse, Table *pTab, sqlite3_index_info *p){
** Estimate the location of a particular key among all keys in an
** index. Store the results in aStat as follows:
**
-** aStat[0] Est. number of rows less than pVal
-** aStat[1] Est. number of rows equal to pVal
+** aStat[0] Est. number of rows less than pRec
+** aStat[1] Est. number of rows equal to pRec
**
** Return the index of the sample that is the smallest sample that
-** is greater than or equal to pRec.
+** is greater than or equal to pRec. Note that this index is not an index
+** into the aSample[] array - it is an index into a virtual set of samples
+** based on the contents of aSample[] and the number of fields in record
+** pRec.
*/
static int whereKeyStats(
Parse *pParse, /* Database connection */
@@ -116856,67 +118221,158 @@ static int whereKeyStats(
){
IndexSample *aSample = pIdx->aSample;
int iCol; /* Index of required stats in anEq[] etc. */
+ int i; /* Index of first sample >= pRec */
+ int iSample; /* Smallest sample larger than or equal to pRec */
int iMin = 0; /* Smallest sample not yet tested */
- int i = pIdx->nSample; /* Smallest sample larger than or equal to pRec */
int iTest; /* Next sample to test */
int res; /* Result of comparison operation */
+ int nField; /* Number of fields in pRec */
+ tRowcnt iLower = 0; /* anLt[] + anEq[] of largest sample pRec is > */
#ifndef SQLITE_DEBUG
UNUSED_PARAMETER( pParse );
#endif
assert( pRec!=0 );
- iCol = pRec->nField - 1;
assert( pIdx->nSample>0 );
- assert( pRec->nField>0 && iCol<pIdx->nSampleCol );
+ assert( pRec->nField>0 && pRec->nField<=pIdx->nSampleCol );
+
+ /* Do a binary search to find the first sample greater than or equal
+ ** to pRec. If pRec contains a single field, the set of samples to search
+ ** is simply the aSample[] array. If the samples in aSample[] contain more
+ ** than one fields, all fields following the first are ignored.
+ **
+ ** If pRec contains N fields, where N is more than one, then as well as the
+ ** samples in aSample[] (truncated to N fields), the search also has to
+ ** consider prefixes of those samples. For example, if the set of samples
+ ** in aSample is:
+ **
+ ** aSample[0] = (a, 5)
+ ** aSample[1] = (a, 10)
+ ** aSample[2] = (b, 5)
+ ** aSample[3] = (c, 100)
+ ** aSample[4] = (c, 105)
+ **
+ ** Then the search space should ideally be the samples above and the
+ ** unique prefixes [a], [b] and [c]. But since that is hard to organize,
+ ** the code actually searches this set:
+ **
+ ** 0: (a)
+ ** 1: (a, 5)
+ ** 2: (a, 10)
+ ** 3: (a, 10)
+ ** 4: (b)
+ ** 5: (b, 5)
+ ** 6: (c)
+ ** 7: (c, 100)
+ ** 8: (c, 105)
+ ** 9: (c, 105)
+ **
+ ** For each sample in the aSample[] array, N samples are present in the
+ ** effective sample array. In the above, samples 0 and 1 are based on
+ ** sample aSample[0]. Samples 2 and 3 on aSample[1] etc.
+ **
+ ** Often, sample i of each block of N effective samples has (i+1) fields.
+ ** Except, each sample may be extended to ensure that it is greater than or
+ ** equal to the previous sample in the array. For example, in the above,
+ ** sample 2 is the first sample of a block of N samples, so at first it
+ ** appears that it should be 1 field in size. However, that would make it
+ ** smaller than sample 1, so the binary search would not work. As a result,
+ ** it is extended to two fields. The duplicates that this creates do not
+ ** cause any problems.
+ */
+ nField = pRec->nField;
+ iCol = 0;
+ iSample = pIdx->nSample * nField;
do{
- iTest = (iMin+i)/2;
- res = sqlite3VdbeRecordCompare(aSample[iTest].n, aSample[iTest].p, pRec);
+ int iSamp; /* Index in aSample[] of test sample */
+ int n; /* Number of fields in test sample */
+
+ iTest = (iMin+iSample)/2;
+ iSamp = iTest / nField;
+ if( iSamp>0 ){
+ /* The proposed effective sample is a prefix of sample aSample[iSamp].
+ ** Specifically, the shortest prefix of at least (1 + iTest%nField)
+ ** fields that is greater than the previous effective sample. */
+ for(n=(iTest % nField) + 1; n<nField; n++){
+ if( aSample[iSamp-1].anLt[n-1]!=aSample[iSamp].anLt[n-1] ) break;
+ }
+ }else{
+ n = iTest + 1;
+ }
+
+ pRec->nField = n;
+ res = sqlite3VdbeRecordCompare(aSample[iSamp].n, aSample[iSamp].p, pRec);
if( res<0 ){
+ iLower = aSample[iSamp].anLt[n-1] + aSample[iSamp].anEq[n-1];
+ iMin = iTest+1;
+ }else if( res==0 && n<nField ){
+ iLower = aSample[iSamp].anLt[n-1];
iMin = iTest+1;
+ res = -1;
}else{
- i = iTest;
+ iSample = iTest;
+ iCol = n-1;
}
- }while( res && iMin<i );
+ }while( res && iMin<iSample );
+ i = iSample / nField;
#ifdef SQLITE_DEBUG
/* The following assert statements check that the binary search code
** above found the right answer. This block serves no purpose other
** than to invoke the asserts. */
- if( res==0 ){
- /* If (res==0) is true, then sample $i must be equal to pRec */
- assert( i<pIdx->nSample );
- assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
- || pParse->db->mallocFailed );
- }else{
- /* Otherwise, pRec must be smaller than sample $i and larger than
- ** sample ($i-1). */
- assert( i==pIdx->nSample
- || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
- || pParse->db->mallocFailed );
- assert( i==0
- || sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
- || pParse->db->mallocFailed );
+ if( pParse->db->mallocFailed==0 ){
+ if( res==0 ){
+ /* If (res==0) is true, then pRec must be equal to sample i. */
+ assert( i<pIdx->nSample );
+ assert( iCol==nField-1 );
+ pRec->nField = nField;
+ assert( 0==sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)
+ || pParse->db->mallocFailed
+ );
+ }else{
+ /* Unless i==pIdx->nSample, indicating that pRec is larger than
+ ** all samples in the aSample[] array, pRec must be smaller than the
+ ** (iCol+1) field prefix of sample i. */
+ assert( i<=pIdx->nSample && i>=0 );
+ pRec->nField = iCol+1;
+ assert( i==pIdx->nSample
+ || sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)>0
+ || pParse->db->mallocFailed );
+
+ /* if i==0 and iCol==0, then record pRec is smaller than all samples
+ ** in the aSample[] array. Otherwise, if (iCol>0) then pRec must
+ ** be greater than or equal to the (iCol) field prefix of sample i.
+ ** If (i>0), then pRec must also be greater than sample (i-1). */
+ if( iCol>0 ){
+ pRec->nField = iCol;
+ assert( sqlite3VdbeRecordCompare(aSample[i].n, aSample[i].p, pRec)<=0
+ || pParse->db->mallocFailed );
+ }
+ if( i>0 ){
+ pRec->nField = nField;
+ assert( sqlite3VdbeRecordCompare(aSample[i-1].n, aSample[i-1].p, pRec)<0
+ || pParse->db->mallocFailed );
+ }
+ }
}
#endif /* ifdef SQLITE_DEBUG */
- /* At this point, aSample[i] is the first sample that is greater than
- ** or equal to pVal. Or if i==pIdx->nSample, then all samples are less
- ** than pVal. If aSample[i]==pVal, then res==0.
- */
if( res==0 ){
+ /* Record pRec is equal to sample i */
+ assert( iCol==nField-1 );
aStat[0] = aSample[i].anLt[iCol];
aStat[1] = aSample[i].anEq[iCol];
}else{
- tRowcnt iLower, iUpper, iGap;
- if( i==0 ){
- iLower = 0;
- iUpper = aSample[0].anLt[iCol];
+ /* At this point, the (iCol+1) field prefix of aSample[i] is the first
+ ** sample that is greater than pRec. Or, if i==pIdx->nSample then pRec
+ ** is larger than all samples in the array. */
+ tRowcnt iUpper, iGap;
+ if( i>=pIdx->nSample ){
+ iUpper = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]);
}else{
- i64 nRow0 = sqlite3LogEstToInt(pIdx->aiRowLogEst[0]);
- iUpper = i>=pIdx->nSample ? nRow0 : aSample[i].anLt[iCol];
- iLower = aSample[i-1].anEq[iCol] + aSample[i-1].anLt[iCol];
+ iUpper = aSample[i].anLt[iCol];
}
- aStat[1] = pIdx->aAvgEq[iCol];
+
if( iLower>=iUpper ){
iGap = 0;
}else{
@@ -116928,7 +118384,11 @@ static int whereKeyStats(
iGap = iGap/3;
}
aStat[0] = iLower + iGap;
+ aStat[1] = pIdx->aAvgEq[iCol];
}
+
+ /* Restore the pRec->nField value before returning. */
+ pRec->nField = nField;
return i;
}
#endif /* SQLITE_ENABLE_STAT3_OR_STAT4 */
@@ -117402,20 +118862,43 @@ static int whereInScanEst(
** but joins might run a little slower. The trick is to disable as much
** as we can without disabling too much. If we disabled in (1), we'd get
** the wrong answer. See ticket #813.
+**
+** If all the children of a term are disabled, then that term is also
+** automatically disabled. In this way, terms get disabled if derived
+** virtual terms are tested first. For example:
+**
+** x GLOB 'abc*' AND x>='abc' AND x<'acd'
+** \___________/ \______/ \_____/
+** parent child1 child2
+**
+** Only the parent term was in the original WHERE clause. The child1
+** and child2 terms were added by the LIKE optimization. If both of
+** the virtual child terms are valid, then testing of the parent can be
+** skipped.
+**
+** Usually the parent term is marked as TERM_CODED. But if the parent
+** term was originally TERM_LIKE, then the parent gets TERM_LIKECOND instead.
+** The TERM_LIKECOND marking indicates that the term should be coded inside
+** a conditional such that is only evaluated on the second pass of a
+** LIKE-optimization loop, when scanning BLOBs instead of strings.
*/
static void disableTerm(WhereLevel *pLevel, WhereTerm *pTerm){
- if( pTerm
+ int nLoop = 0;
+ while( pTerm
&& (pTerm->wtFlags & TERM_CODED)==0
&& (pLevel->iLeftJoin==0 || ExprHasProperty(pTerm->pExpr, EP_FromJoin))
&& (pLevel->notReady & pTerm->prereqAll)==0
){
- pTerm->wtFlags |= TERM_CODED;
- if( pTerm->iParent>=0 ){
- WhereTerm *pOther = &pTerm->pWC->a[pTerm->iParent];
- if( (--pOther->nChild)==0 ){
- disableTerm(pLevel, pOther);
- }
+ if( nLoop && (pTerm->wtFlags & TERM_LIKE)!=0 ){
+ pTerm->wtFlags |= TERM_LIKECOND;
+ }else{
+ pTerm->wtFlags |= TERM_CODED;
}
+ if( pTerm->iParent<0 ) break;
+ pTerm = &pTerm->pWC->a[pTerm->iParent];
+ pTerm->nChild--;
+ if( pTerm->nChild!=0 ) break;
+ nLoop++;
}
}
@@ -117794,8 +119277,7 @@ static int explainOneScan(
|| ((flags&WHERE_VIRTUALTABLE)==0 && (pLoop->u.btree.nEq>0))
|| (wctrlFlags&(WHERE_ORDERBY_MIN|WHERE_ORDERBY_MAX));
- sqlite3StrAccumInit(&str, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
- str.db = db;
+ sqlite3StrAccumInit(&str, db, zBuf, sizeof(zBuf), SQLITE_MAX_LENGTH);
sqlite3StrAccumAppendAll(&str, isSearch ? "SEARCH" : "SCAN");
if( pItem->pSelect ){
sqlite3XPrintf(&str, 0, " SUBQUERY %d", pItem->iSelectId);
@@ -117899,7 +119381,34 @@ static void addScanStatus(
# define addScanStatus(a, b, c, d) ((void)d)
#endif
-
+/*
+** If the most recently coded instruction is a constant range contraint
+** that originated from the LIKE optimization, then change the P3 to be
+** pLoop->iLikeRepCntr and set P5.
+**
+** The LIKE optimization trys to evaluate "x LIKE 'abc%'" as a range
+** expression: "x>='ABC' AND x<'abd'". But this requires that the range
+** scan loop run twice, once for strings and a second time for BLOBs.
+** The OP_String opcodes on the second pass convert the upper and lower
+** bound string contants to blobs. This routine makes the necessary changes
+** to the OP_String opcodes for that to happen.
+*/
+static void whereLikeOptimizationStringFixup(
+ Vdbe *v, /* prepared statement under construction */
+ WhereLevel *pLevel, /* The loop that contains the LIKE operator */
+ WhereTerm *pTerm /* The upper or lower bound just coded */
+){
+ if( pTerm->wtFlags & TERM_LIKEOPT ){
+ VdbeOp *pOp;
+ assert( pLevel->iLikeRepCntr>0 );
+ pOp = sqlite3VdbeGetOp(v, -1);
+ assert( pOp!=0 );
+ assert( pOp->opcode==OP_String8
+ || pTerm->pWC->pWInfo->pParse->db->mallocFailed );
+ pOp->p3 = pLevel->iLikeRepCntr;
+ pOp->p5 = 1;
+ }
+}
/*
** Generate code for the start of the iLevel-th loop in the WHERE clause
@@ -118229,10 +119738,25 @@ static Bitmask codeOneLoopStart(
if( pLoop->wsFlags & WHERE_BTM_LIMIT ){
pRangeStart = pLoop->aLTerm[j++];
nExtraReg = 1;
+ /* Like optimization range constraints always occur in pairs */
+ assert( (pRangeStart->wtFlags & TERM_LIKEOPT)==0 ||
+ (pLoop->wsFlags & WHERE_TOP_LIMIT)!=0 );
}
if( pLoop->wsFlags & WHERE_TOP_LIMIT ){
pRangeEnd = pLoop->aLTerm[j++];
nExtraReg = 1;
+ if( (pRangeEnd->wtFlags & TERM_LIKEOPT)!=0 ){
+ assert( pRangeStart!=0 ); /* LIKE opt constraints */
+ assert( pRangeStart->wtFlags & TERM_LIKEOPT ); /* occur in pairs */
+ pLevel->iLikeRepCntr = ++pParse->nMem;
+ testcase( bRev );
+ testcase( pIdx->aSortOrder[nEq]==SQLITE_SO_DESC );
+ sqlite3VdbeAddOp2(v, OP_Integer,
+ bRev ^ (pIdx->aSortOrder[nEq]==SQLITE_SO_DESC),
+ pLevel->iLikeRepCntr);
+ VdbeComment((v, "LIKE loop counter"));
+ pLevel->addrLikeRep = sqlite3VdbeCurrentAddr(v);
+ }
if( pRangeStart==0
&& (j = pIdx->aiColumn[nEq])>=0
&& pIdx->pTable->aCol[j].notNull==0
@@ -118275,6 +119799,7 @@ static Bitmask codeOneLoopStart(
if( pRangeStart ){
Expr *pRight = pRangeStart->pExpr->pRight;
sqlite3ExprCode(pParse, pRight, regBase+nEq);
+ whereLikeOptimizationStringFixup(v, pLevel, pRangeStart);
if( (pRangeStart->wtFlags & TERM_VNULL)==0
&& sqlite3ExprCanBeNull(pRight)
){
@@ -118320,6 +119845,7 @@ static Bitmask codeOneLoopStart(
Expr *pRight = pRangeEnd->pExpr->pRight;
sqlite3ExprCacheRemove(pParse, regBase+nEq, 1);
sqlite3ExprCode(pParse, pRight, regBase+nEq);
+ whereLikeOptimizationStringFixup(v, pLevel, pRangeEnd);
if( (pRangeEnd->wtFlags & TERM_VNULL)==0
&& sqlite3ExprCanBeNull(pRight)
){
@@ -118547,7 +120073,8 @@ static Bitmask codeOneLoopStart(
*/
wctrlFlags = WHERE_OMIT_OPEN_CLOSE
| WHERE_FORCE_TABLE
- | WHERE_ONETABLE_ONLY;
+ | WHERE_ONETABLE_ONLY
+ | WHERE_NO_AUTOINDEX;
for(ii=0; ii<pOrWc->nTerm; ii++){
WhereTerm *pOrTerm = &pOrWc->a[ii];
if( pOrTerm->leftCursor==iCur || (pOrTerm->eOperator & WO_AND)!=0 ){
@@ -118709,6 +120236,7 @@ static Bitmask codeOneLoopStart(
*/
for(pTerm=pWC->a, j=pWC->nTerm; j>0; j--, pTerm++){
Expr *pE;
+ int skipLikeAddr = 0;
testcase( pTerm->wtFlags & TERM_VIRTUAL );
testcase( pTerm->wtFlags & TERM_CODED );
if( pTerm->wtFlags & (TERM_VIRTUAL|TERM_CODED) ) continue;
@@ -118723,7 +120251,13 @@ static Bitmask codeOneLoopStart(
if( pLevel->iLeftJoin && !ExprHasProperty(pE, EP_FromJoin) ){
continue;
}
+ if( pTerm->wtFlags & TERM_LIKECOND ){
+ assert( pLevel->iLikeRepCntr>0 );
+ skipLikeAddr = sqlite3VdbeAddOp1(v, OP_IfNot, pLevel->iLikeRepCntr);
+ VdbeCoverage(v);
+ }
sqlite3ExprIfFalse(pParse, pE, addrCont, SQLITE_JUMPIFNULL);
+ if( skipLikeAddr ) sqlite3VdbeJumpHere(v, skipLikeAddr);
pTerm->wtFlags |= TERM_CODED;
}
@@ -118942,6 +120476,13 @@ static void whereLoopDelete(sqlite3 *db, WhereLoop *p){
*/
static void whereInfoFree(sqlite3 *db, WhereInfo *pWInfo){
if( ALWAYS(pWInfo) ){
+ int i;
+ for(i=0; i<pWInfo->nLevel; i++){
+ WhereLevel *pLevel = &pWInfo->a[i];
+ if( pLevel->pWLoop && (pLevel->pWLoop->wsFlags & WHERE_IN_ABLE) ){
+ sqlite3DbFree(db, pLevel->u.in.aInLoop);
+ }
+ }
whereClauseClear(&pWInfo->sWC);
while( pWInfo->pLoops ){
WhereLoop *p = pWInfo->pLoops;
@@ -119388,6 +120929,10 @@ static int whereLoopAddBtreeIndex(
}
if( pTerm->prereqRight & pNew->maskSelf ) continue;
+ /* Do not allow the upper bound of a LIKE optimization range constraint
+ ** to mix with a lower range bound from some other source */
+ if( pTerm->wtFlags & TERM_LIKEOPT && pTerm->eOperator==WO_LT ) continue;
+
pNew->wsFlags = saved_wsFlags;
pNew->u.btree.nEq = saved_nEq;
pNew->nLTerm = saved_nLTerm;
@@ -119417,7 +120962,7 @@ static int whereLoopAddBtreeIndex(
}else if( eOp & (WO_EQ) ){
pNew->wsFlags |= WHERE_COLUMN_EQ;
if( iCol<0 || (nInMul==0 && pNew->u.btree.nEq==pProbe->nKeyCol-1) ){
- if( iCol>=0 && !IsUniqueIndex(pProbe) ){
+ if( iCol>=0 && pProbe->uniqNotNull==0 ){
pNew->wsFlags |= WHERE_UNQ_WANTED;
}else{
pNew->wsFlags |= WHERE_ONEROW;
@@ -119431,6 +120976,17 @@ static int whereLoopAddBtreeIndex(
pNew->wsFlags |= WHERE_COLUMN_RANGE|WHERE_BTM_LIMIT;
pBtm = pTerm;
pTop = 0;
+ if( pTerm->wtFlags & TERM_LIKEOPT ){
+ /* Range contraints that come from the LIKE optimization are
+ ** always used in pairs. */
+ pTop = &pTerm[1];
+ assert( (pTop-(pTerm->pWC->a))<pTerm->pWC->nTerm );
+ assert( pTop->wtFlags & TERM_LIKEOPT );
+ assert( pTop->eOperator==WO_LT );
+ if( whereLoopResize(db, pNew, pNew->nLTerm+1) ) break; /* OOM */
+ pNew->aLTerm[pNew->nLTerm++] = pTop;
+ pNew->wsFlags |= WHERE_TOP_LIMIT;
+ }
}else{
assert( eOp & (WO_LT|WO_LE) );
testcase( eOp & WO_LT );
@@ -119632,8 +121188,9 @@ static int whereUsablePartialIndex(int iTab, WhereClause *pWC, Expr *pWhere){
int i;
WhereTerm *pTerm;
for(i=0, pTerm=pWC->a; i<pWC->nTerm; i++, pTerm++){
- if( sqlite3ExprImpliesExpr(pTerm->pExpr, pWhere, iTab)
- && !ExprHasProperty(pTerm->pExpr, EP_FromJoin)
+ Expr *pExpr = pTerm->pExpr;
+ if( sqlite3ExprImpliesExpr(pExpr, pWhere, iTab)
+ && (!ExprHasProperty(pExpr, EP_FromJoin) || pExpr->iRightJoinTable==iTab)
){
return 1;
}
@@ -119740,6 +121297,7 @@ static int whereLoopAddBtree(
#ifndef SQLITE_OMIT_AUTOMATIC_INDEX
/* Automatic indexes */
if( !pBuilder->pOrSet
+ && (pWInfo->wctrlFlags & WHERE_NO_AUTOINDEX)==0
&& (pWInfo->pParse->db->flags & SQLITE_AutoIndex)!=0
&& pSrc->pIndex==0
&& !pSrc->viaCoroutine
@@ -120623,10 +122181,10 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
/* Seed the search with a single WherePath containing zero WhereLoops.
**
- ** TUNING: Do not let the number of iterations go above 25. If the cost
- ** of computing an automatic index is not paid back within the first 25
+ ** TUNING: Do not let the number of iterations go above 28. If the cost
+ ** of computing an automatic index is not paid back within the first 28
** rows, then do not use the automatic index. */
- aFrom[0].nRow = MIN(pParse->nQueryLoop, 46); assert( 46==sqlite3LogEst(25) );
+ aFrom[0].nRow = MIN(pParse->nQueryLoop, 48); assert( 48==sqlite3LogEst(28) );
nFrom = 1;
assert( aFrom[0].isOrdered==0 );
if( nOrderBy ){
@@ -120864,7 +122422,7 @@ static int wherePathSolver(WhereInfo *pWInfo, LogEst nRowEst){
pWInfo->revMask = pFrom->revLoop;
}
if( (pWInfo->wctrlFlags & WHERE_SORTBYGROUP)
- && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr
+ && pWInfo->nOBSat==pWInfo->pOrderBy->nExpr && nLoop>0
){
Bitmask revMask = 0;
int nOrder = wherePathSatisfiesOrderBy(pWInfo, pWInfo->pOrderBy,
@@ -121269,7 +122827,6 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
}
#ifdef WHERETRACE_ENABLED /* !=0 */
if( sqlite3WhereTrace ){
- int ii;
sqlite3DebugPrintf("---- Solution nRow=%d", pWInfo->nRowOut);
if( pWInfo->nOBSat>0 ){
sqlite3DebugPrintf(" ORDERBY=%d,0x%llx", pWInfo->nOBSat, pWInfo->revMask);
@@ -121424,6 +122981,12 @@ SQLITE_PRIVATE WhereInfo *sqlite3WhereBegin(
if( op ){
sqlite3VdbeAddOp3(v, op, iIndexCur, pIx->tnum, iDb);
sqlite3VdbeSetP4KeyInfo(pParse, pIx);
+ if( (pLoop->wsFlags & WHERE_CONSTRAINT)!=0
+ && (pLoop->wsFlags & (WHERE_COLUMN_RANGE|WHERE_SKIPSCAN))==0
+ && (pWInfo->wctrlFlags&WHERE_ORDERBY_MIN)==0
+ ){
+ sqlite3VdbeChangeP5(v, OPFLAG_SEEKEQ); /* Hint to COMDB2 */
+ }
VdbeComment((v, "%s", pIx->zName));
}
}
@@ -121516,7 +123079,6 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
VdbeCoverageIf(v, pIn->eEndLoopOp==OP_NextIfOpen);
sqlite3VdbeJumpHere(v, pIn->addrInTop-1);
}
- sqlite3DbFree(db, pLevel->u.in.aInLoop);
}
sqlite3VdbeResolveLabel(v, pLevel->addrBrk);
if( pLevel->addrSkip ){
@@ -121525,6 +123087,16 @@ SQLITE_PRIVATE void sqlite3WhereEnd(WhereInfo *pWInfo){
sqlite3VdbeJumpHere(v, pLevel->addrSkip);
sqlite3VdbeJumpHere(v, pLevel->addrSkip-2);
}
+ if( pLevel->addrLikeRep ){
+ int op;
+ if( sqlite3VdbeGetOp(v, pLevel->addrLikeRep-1)->p1 ){
+ op = OP_DecrJumpZero;
+ }else{
+ op = OP_JumpZeroIncr;
+ }
+ sqlite3VdbeAddOp2(v, op, pLevel->iLikeRepCntr, pLevel->addrLikeRep);
+ VdbeCoverage(v);
+ }
if( pLevel->iLeftJoin ){
addr = sqlite3VdbeAddOp1(v, OP_IfPos, pLevel->iLeftJoin); VdbeCoverage(v);
assert( (pLoop->wsFlags & WHERE_IDX_ONLY)==0
@@ -121718,6 +123290,28 @@ struct TrigEvent { int a; IdList * b; };
struct AttachKey { int type; Token key; };
+ /*
+ ** For a compound SELECT statement, make sure p->pPrior->pNext==p for
+ ** all elements in the list. And make sure list length does not exceed
+ ** SQLITE_LIMIT_COMPOUND_SELECT.
+ */
+ static void parserDoubleLinkSelect(Parse *pParse, Select *p){
+ if( p->pPrior ){
+ Select *pNext = 0, *pLoop;
+ int mxSelect, cnt = 0;
+ for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
+ pLoop->pNext = pNext;
+ pLoop->selFlags |= SF_Compound;
+ }
+ if( (p->selFlags & SF_MultiValue)==0 &&
+ (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0 &&
+ cnt>mxSelect
+ ){
+ sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
+ }
+ }
+ }
+
/* This is a utility routine used to set the ExprSpan.zStart and
** ExprSpan.zEnd values of pOut so that the span covers the complete
** range of text beginning with pStart and going to the end of pEnd.
@@ -124034,27 +125628,10 @@ static void yy_reduce(
break;
case 112: /* select ::= with selectnowith */
{
- Select *p = yymsp[0].minor.yy3, *pNext, *pLoop;
+ Select *p = yymsp[0].minor.yy3;
if( p ){
- int cnt = 0, mxSelect;
p->pWith = yymsp[-1].minor.yy59;
- if( p->pPrior ){
- u16 allValues = SF_Values;
- pNext = 0;
- for(pLoop=p; pLoop; pNext=pLoop, pLoop=pLoop->pPrior, cnt++){
- pLoop->pNext = pNext;
- pLoop->selFlags |= SF_Compound;
- allValues &= pLoop->selFlags;
- }
- if( allValues ){
- p->selFlags |= SF_AllValues;
- }else if(
- (mxSelect = pParse->db->aLimit[SQLITE_LIMIT_COMPOUND_SELECT])>0
- && cnt>mxSelect
- ){
- sqlite3ErrorMsg(pParse, "too many terms in compound SELECT");
- }
- }
+ parserDoubleLinkSelect(pParse, p);
}else{
sqlite3WithDelete(pParse->db, yymsp[-1].minor.yy59);
}
@@ -124072,12 +125649,14 @@ static void yy_reduce(
SrcList *pFrom;
Token x;
x.n = 0;
+ parserDoubleLinkSelect(pParse, pRhs);
pFrom = sqlite3SrcListAppendFromTerm(pParse,0,0,0,&x,pRhs,0,0);
pRhs = sqlite3SelectNew(pParse,0,pFrom,0,0,0,0,0,0,0);
}
if( pRhs ){
pRhs->op = (u8)yymsp[-1].minor.yy328;
pRhs->pPrior = yymsp[-2].minor.yy3;
+ pRhs->selFlags &= ~SF_MultiValue;
if( yymsp[-1].minor.yy328!=TK_ALL ) pParse->hasCompound = 1;
}else{
sqlite3SelectDelete(pParse->db, yymsp[-2].minor.yy3);
@@ -124124,13 +125703,16 @@ static void yy_reduce(
break;
case 121: /* values ::= values COMMA LP exprlist RP */
{
- Select *pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values,0,0);
+ Select *pRight, *pLeft = yymsp[-4].minor.yy3;
+ pRight = sqlite3SelectNew(pParse,yymsp[-1].minor.yy14,0,0,0,0,0,SF_Values|SF_MultiValue,0,0);
+ if( ALWAYS(pLeft) ) pLeft->selFlags &= ~SF_MultiValue;
if( pRight ){
pRight->op = TK_ALL;
- pRight->pPrior = yymsp[-4].minor.yy3;
+ pLeft = yymsp[-4].minor.yy3;
+ pRight->pPrior = pLeft;
yygotominor.yy3 = pRight;
}else{
- yygotominor.yy3 = yymsp[-4].minor.yy3;
+ yygotominor.yy3 = pLeft;
}
}
break;
@@ -124415,7 +125997,7 @@ static void yy_reduce(
break;
case 193: /* expr ::= expr COLLATE ID|STRING */
{
- yygotominor.yy346.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy346.pExpr, &yymsp[0].minor.yy0);
+ yygotominor.yy346.pExpr = sqlite3ExprAddCollateToken(pParse, yymsp[-2].minor.yy346.pExpr, &yymsp[0].minor.yy0, 1);
yygotominor.yy346.zStart = yymsp[-2].minor.yy346.zStart;
yygotominor.yy346.zEnd = &yymsp[0].minor.yy0.z[yymsp[0].minor.yy0.n];
}
@@ -124578,7 +126160,7 @@ static void yy_reduce(
yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0);
if( yygotominor.yy346.pExpr ){
yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy14;
- sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
+ sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy346.pExpr);
}else{
sqlite3ExprListDelete(pParse->db, yymsp[-1].minor.yy14);
}
@@ -124593,8 +126175,8 @@ static void yy_reduce(
yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_SELECT, 0, 0, 0);
if( yygotominor.yy346.pExpr ){
yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3;
- ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect);
- sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
+ ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect|EP_Subquery);
+ sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy346.pExpr);
}else{
sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3);
}
@@ -124607,8 +126189,8 @@ static void yy_reduce(
yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-4].minor.yy346.pExpr, 0, 0);
if( yygotominor.yy346.pExpr ){
yygotominor.yy346.pExpr->x.pSelect = yymsp[-1].minor.yy3;
- ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect);
- sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
+ ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect|EP_Subquery);
+ sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy346.pExpr);
}else{
sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3);
}
@@ -124623,8 +126205,8 @@ static void yy_reduce(
yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_IN, yymsp[-3].minor.yy346.pExpr, 0, 0);
if( yygotominor.yy346.pExpr ){
yygotominor.yy346.pExpr->x.pSelect = sqlite3SelectNew(pParse, 0,pSrc,0,0,0,0,0,0,0);
- ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect);
- sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
+ ExprSetProperty(yygotominor.yy346.pExpr, EP_xIsSelect|EP_Subquery);
+ sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy346.pExpr);
}else{
sqlite3SrcListDelete(pParse->db, pSrc);
}
@@ -124638,8 +126220,8 @@ static void yy_reduce(
Expr *p = yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_EXISTS, 0, 0, 0);
if( p ){
p->x.pSelect = yymsp[-1].minor.yy3;
- ExprSetProperty(p, EP_xIsSelect);
- sqlite3ExprSetHeight(pParse, p);
+ ExprSetProperty(p, EP_xIsSelect|EP_Subquery);
+ sqlite3ExprSetHeightAndFlags(pParse, p);
}else{
sqlite3SelectDelete(pParse->db, yymsp[-1].minor.yy3);
}
@@ -124652,7 +126234,7 @@ static void yy_reduce(
yygotominor.yy346.pExpr = sqlite3PExpr(pParse, TK_CASE, yymsp[-3].minor.yy132, 0, 0);
if( yygotominor.yy346.pExpr ){
yygotominor.yy346.pExpr->x.pList = yymsp[-1].minor.yy132 ? sqlite3ExprListAppend(pParse,yymsp[-2].minor.yy14,yymsp[-1].minor.yy132) : yymsp[-2].minor.yy14;
- sqlite3ExprSetHeight(pParse, yygotominor.yy346.pExpr);
+ sqlite3ExprSetHeightAndFlags(pParse, yygotominor.yy346.pExpr);
}else{
sqlite3ExprListDelete(pParse->db, yymsp[-2].minor.yy14);
sqlite3ExprDelete(pParse->db, yymsp[-1].minor.yy132);
@@ -124695,7 +126277,7 @@ static void yy_reduce(
break;
case 244: /* idxlist ::= idxlist COMMA nm collate sortorder */
{
- Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
+ Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0, 1);
yygotominor.yy14 = sqlite3ExprListAppend(pParse,yymsp[-4].minor.yy14, p);
sqlite3ExprListSetName(pParse,yygotominor.yy14,&yymsp[-2].minor.yy0,1);
sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index");
@@ -124704,7 +126286,7 @@ static void yy_reduce(
break;
case 245: /* idxlist ::= nm collate sortorder */
{
- Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0);
+ Expr *p = sqlite3ExprAddCollateToken(pParse, 0, &yymsp[-1].minor.yy0, 1);
yygotominor.yy14 = sqlite3ExprListAppend(pParse,0, p);
sqlite3ExprListSetName(pParse, yygotominor.yy14, &yymsp[-2].minor.yy0, 1);
sqlite3ExprListCheckLength(pParse, yygotominor.yy14, "index");
@@ -125894,10 +127476,7 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
sqlite3 *db = pParse->db; /* The database connection */
int mxSqlLen; /* Max length of an SQL string */
-
-#ifdef SQLITE_ENABLE_API_ARMOR
- if( zSql==0 || pzErrMsg==0 ) return SQLITE_MISUSE_BKPT;
-#endif
+ assert( zSql!=0 );
mxSqlLen = db->aLimit[SQLITE_LIMIT_SQL_LENGTH];
if( db->nVdbeActive==0 ){
db->u1.isInterrupted = 0;
@@ -125937,10 +127516,8 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
break;
}
case TK_ILLEGAL: {
- sqlite3DbFree(db, *pzErrMsg);
- *pzErrMsg = sqlite3MPrintf(db, "unrecognized token: \"%T\"",
+ sqlite3ErrorMsg(pParse, "unrecognized token: \"%T\"",
&pParse->sLastToken);
- nErr++;
goto abort_parse;
}
case TK_SEMI: {
@@ -125958,17 +127535,22 @@ SQLITE_PRIVATE int sqlite3RunParser(Parse *pParse, const char *zSql, char **pzEr
}
}
abort_parse:
- if( zSql[i]==0 && nErr==0 && pParse->rc==SQLITE_OK ){
+ assert( nErr==0 );
+ if( zSql[i]==0 && pParse->rc==SQLITE_OK && db->mallocFailed==0 ){
if( lastTokenParsed!=TK_SEMI ){
sqlite3Parser(pEngine, TK_SEMI, pParse->sLastToken, pParse);
pParse->zTail = &zSql[i];
}
- sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
+ if( pParse->rc==SQLITE_OK && db->mallocFailed==0 ){
+ sqlite3Parser(pEngine, 0, pParse->sLastToken, pParse);
+ }
}
#ifdef YYTRACKMAXSTACKDEPTH
+ sqlite3_mutex_enter(sqlite3MallocMutex());
sqlite3StatusSet(SQLITE_STATUS_PARSER_STACK,
sqlite3ParserStackPeak(pEngine)
);
+ sqlite3_mutex_leave(sqlite3MallocMutex());
#endif /* YYDEBUG */
sqlite3ParserFree(pEngine, sqlite3_free);
db->lookaside.bEnabled = enableLookaside;
@@ -126022,9 +127604,7 @@ abort_parse:
pParse->pZombieTab = p->pNextZombie;
sqlite3DeleteTable(db, p);
}
- if( nErr>0 && pParse->rc==SQLITE_OK ){
- pParse->rc = SQLITE_ERROR;
- }
+ assert( nErr==0 || pParse->rc!=SQLITE_OK );
return nErr;
}
@@ -126132,7 +127712,7 @@ SQLITE_PRIVATE const char sqlite3IsEbcdicIdChar[];
** to recognize the end of a trigger can be omitted. All we have to do
** is look for a semicolon that is not part of an string or comment.
*/
-SQLITE_API int sqlite3_complete(const char *zSql){
+SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *zSql){
u8 state = 0; /* Current state, using numbers defined in header comment */
u8 token; /* Value of the next token */
@@ -126297,10 +127877,10 @@ SQLITE_API int sqlite3_complete(const char *zSql){
** above, except that the parameter is required to be UTF-16 encoded, not
** UTF-8.
*/
-SQLITE_API int sqlite3_complete16(const void *zSql){
+SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *zSql){
sqlite3_value *pVal;
char const *zSql8;
- int rc = SQLITE_NOMEM;
+ int rc;
#ifndef SQLITE_OMIT_AUTOINIT
rc = sqlite3_initialize();
@@ -126447,24 +128027,36 @@ SQLITE_API const char sqlite3_version[] = SQLITE_VERSION;
/* IMPLEMENTATION-OF: R-53536-42575 The sqlite3_libversion() function returns
** a pointer to the to the sqlite3_version[] string constant.
*/
-SQLITE_API const char *sqlite3_libversion(void){ return sqlite3_version; }
+SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void){ return sqlite3_version; }
/* IMPLEMENTATION-OF: R-63124-39300 The sqlite3_sourceid() function returns a
** pointer to a string constant whose value is the same as the
** SQLITE_SOURCE_ID C preprocessor macro.
*/
-SQLITE_API const char *sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
+SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void){ return SQLITE_SOURCE_ID; }
/* IMPLEMENTATION-OF: R-35210-63508 The sqlite3_libversion_number() function
** returns an integer equal to SQLITE_VERSION_NUMBER.
*/
-SQLITE_API int sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
+SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void){ return SQLITE_VERSION_NUMBER; }
/* IMPLEMENTATION-OF: R-20790-14025 The sqlite3_threadsafe() function returns
** zero if and only if SQLite was compiled with mutexing code omitted due to
** the SQLITE_THREADSAFE compile-time option being set to 0.
*/
-SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
+SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
+
+/*
+** When compiling the test fixture or with debugging enabled (on Win32),
+** this variable being set to non-zero will cause OSTRACE macros to emit
+** extra diagnostic information.
+*/
+#ifdef SQLITE_HAVE_OS_TRACE
+# ifndef SQLITE_DEBUG_OS_TRACE
+# define SQLITE_DEBUG_OS_TRACE 0
+# endif
+ int sqlite3OSTrace = SQLITE_DEBUG_OS_TRACE;
+#endif
#if !defined(SQLITE_OMIT_TRACE) && defined(SQLITE_ENABLE_IOTRACE)
/*
@@ -126473,7 +128065,7 @@ SQLITE_API int sqlite3_threadsafe(void){ return SQLITE_THREADSAFE; }
** I/O active are written using this function. These messages
** are intended for debugging activity only.
*/
-/* not-private */ void (*sqlite3IoTrace)(const char*, ...) = 0;
+SQLITE_API void (SQLITE_CDECL *sqlite3IoTrace)(const char*, ...) = 0;
#endif
/*
@@ -126525,7 +128117,7 @@ SQLITE_API char *sqlite3_data_directory = 0;
** * Recursive calls to this routine from thread X return immediately
** without blocking.
*/
-SQLITE_API int sqlite3_initialize(void){
+SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void){
MUTEX_LOGIC( sqlite3_mutex *pMaster; ) /* The main static mutex */
int rc; /* Result code */
#ifdef SQLITE_EXTRA_INIT
@@ -126539,6 +128131,11 @@ SQLITE_API int sqlite3_initialize(void){
}
#endif
+ /* If the following assert() fails on some obscure processor/compiler
+ ** combination, the work-around is to set the correct pointer
+ ** size at compile-time using -DSQLITE_PTRSIZE=n compile-time option */
+ assert( SQLITE_PTRSIZE==sizeof(char*) );
+
/* If SQLite is already completely initialized, then this call
** to sqlite3_initialize() should be a no-op. But the initialization
** must be complete. So isInit must not be set until the very end
@@ -126681,7 +128278,7 @@ SQLITE_API int sqlite3_initialize(void){
** on when SQLite is already shut down. If SQLite is already shut down
** when this routine is invoked, then this routine is a harmless no-op.
*/
-SQLITE_API int sqlite3_shutdown(void){
+SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void){
#ifdef SQLITE_OMIT_WSD
int rc = sqlite3_wsd_init(4096, 24);
if( rc!=SQLITE_OK ){
@@ -126735,7 +128332,7 @@ SQLITE_API int sqlite3_shutdown(void){
** threadsafe. Failure to heed these warnings can lead to unpredictable
** behavior.
*/
-SQLITE_API int sqlite3_config(int op, ...){
+SQLITE_API int SQLITE_CDECL sqlite3_config(int op, ...){
va_list ap;
int rc = SQLITE_OK;
@@ -126751,26 +128348,28 @@ SQLITE_API int sqlite3_config(int op, ...){
*/
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-54466-46756 */
case SQLITE_CONFIG_SINGLETHREAD: {
- /* Disable all mutexing */
- sqlite3GlobalConfig.bCoreMutex = 0;
- sqlite3GlobalConfig.bFullMutex = 0;
+ /* EVIDENCE-OF: R-02748-19096 This option sets the threading mode to
+ ** Single-thread. */
+ sqlite3GlobalConfig.bCoreMutex = 0; /* Disable mutex on core */
+ sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */
break;
}
#endif
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-20520-54086 */
case SQLITE_CONFIG_MULTITHREAD: {
- /* Disable mutexing of database connections */
- /* Enable mutexing of core data structures */
- sqlite3GlobalConfig.bCoreMutex = 1;
- sqlite3GlobalConfig.bFullMutex = 0;
+ /* EVIDENCE-OF: R-14374-42468 This option sets the threading mode to
+ ** Multi-thread. */
+ sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */
+ sqlite3GlobalConfig.bFullMutex = 0; /* Disable mutex on connections */
break;
}
#endif
#if defined(SQLITE_THREADSAFE) && SQLITE_THREADSAFE>0 /* IMP: R-59593-21810 */
case SQLITE_CONFIG_SERIALIZED: {
- /* Enable all mutexing */
- sqlite3GlobalConfig.bCoreMutex = 1;
- sqlite3GlobalConfig.bFullMutex = 1;
+ /* EVIDENCE-OF: R-41220-51800 This option sets the threading mode to
+ ** Serialized. */
+ sqlite3GlobalConfig.bCoreMutex = 1; /* Enable mutex on core */
+ sqlite3GlobalConfig.bFullMutex = 1; /* Enable mutex on connections */
break;
}
#endif
@@ -126882,7 +128481,8 @@ SQLITE_API int sqlite3_config(int op, ...){
case SQLITE_CONFIG_HEAP: {
/* EVIDENCE-OF: R-19854-42126 There are three arguments to
** SQLITE_CONFIG_HEAP: An 8-byte aligned pointer to the memory, the
- ** number of bytes in the memory buffer, and the minimum allocation size. */
+ ** number of bytes in the memory buffer, and the minimum allocation size.
+ */
sqlite3GlobalConfig.pHeap = va_arg(ap, void*);
sqlite3GlobalConfig.nHeap = va_arg(ap, int);
sqlite3GlobalConfig.mnReq = va_arg(ap, int);
@@ -126987,7 +128587,9 @@ SQLITE_API int sqlite3_config(int op, ...){
** compile-time maximum mmap size set by the SQLITE_MAX_MMAP_SIZE
** compile-time option.
*/
- if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ) mxMmap = SQLITE_MAX_MMAP_SIZE;
+ if( mxMmap<0 || mxMmap>SQLITE_MAX_MMAP_SIZE ){
+ mxMmap = SQLITE_MAX_MMAP_SIZE;
+ }
if( szMmap<0 ) szMmap = SQLITE_DEFAULT_MMAP_SIZE;
if( szMmap>mxMmap) szMmap = mxMmap;
sqlite3GlobalConfig.mxMmap = mxMmap;
@@ -127087,7 +128689,7 @@ static int setupLookaside(sqlite3 *db, void *pBuf, int sz, int cnt){
/*
** Return the mutex associated with a database connection.
*/
-SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){
+SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
@@ -127101,7 +128703,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3 *db){
** Free up as much memory as we can from the given database
** connection.
*/
-SQLITE_API int sqlite3_db_release_memory(sqlite3 *db){
+SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3 *db){
int i;
#ifdef SQLITE_ENABLE_API_ARMOR
@@ -127124,7 +128726,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3 *db){
/*
** Configuration settings for an individual database connection
*/
-SQLITE_API int sqlite3_db_config(sqlite3 *db, int op, ...){
+SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3 *db, int op, ...){
va_list ap;
int rc;
va_start(ap, op);
@@ -127243,7 +128845,7 @@ static int nocaseCollatingFunc(
/*
** Return the ROWID of the most recent insert
*/
-SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){
+SQLITE_API sqlite_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
@@ -127256,7 +128858,7 @@ SQLITE_API sqlite_int64 sqlite3_last_insert_rowid(sqlite3 *db){
/*
** Return the number of changes in the most recent call to sqlite3_exec().
*/
-SQLITE_API int sqlite3_changes(sqlite3 *db){
+SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
@@ -127269,7 +128871,7 @@ SQLITE_API int sqlite3_changes(sqlite3 *db){
/*
** Return the number of changes since the database handle was opened.
*/
-SQLITE_API int sqlite3_total_changes(sqlite3 *db){
+SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
@@ -127411,8 +129013,8 @@ static int sqlite3Close(sqlite3 *db, int forceZombie){
** unclosed resources, and arranges for deallocation when the last
** prepare statement or sqlite3_backup closes.
*/
-SQLITE_API int sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); }
-SQLITE_API int sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); }
+SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3 *db){ return sqlite3Close(db,0); }
+SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3 *db){ return sqlite3Close(db,1); }
/*
@@ -127595,7 +129197,7 @@ SQLITE_PRIVATE void sqlite3RollbackAll(sqlite3 *db, int tripCode){
** Return a static string containing the name corresponding to the error code
** specified in the argument.
*/
-#if (defined(SQLITE_DEBUG) && SQLITE_OS_WIN) || defined(SQLITE_TEST)
+#if defined(SQLITE_NEED_ERR_NAME)
SQLITE_PRIVATE const char *sqlite3ErrName(int rc){
const char *zName = 0;
int i, origRc = rc;
@@ -127819,13 +129421,13 @@ SQLITE_PRIVATE int sqlite3InvokeBusyHandler(BusyHandler *p){
** This routine sets the busy callback for an Sqlite database to the
** given callback function with the given argument.
*/
-SQLITE_API int sqlite3_busy_handler(
+SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(
sqlite3 *db,
int (*xBusy)(void*,int),
void *pArg
){
#ifdef SQLITE_ENABLE_API_ARMOR
- if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE;
+ if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
sqlite3_mutex_enter(db->mutex);
db->busyHandler.xFunc = xBusy;
@@ -127842,7 +129444,7 @@ SQLITE_API int sqlite3_busy_handler(
** given callback function with the given argument. The progress callback will
** be invoked every nOps opcodes.
*/
-SQLITE_API void sqlite3_progress_handler(
+SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(
sqlite3 *db,
int nOps,
int (*xProgress)(void*),
@@ -127873,7 +129475,7 @@ SQLITE_API void sqlite3_progress_handler(
** This routine installs a default busy handler that waits for the
** specified number of milliseconds before returning 0.
*/
-SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
+SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3 *db, int ms){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
@@ -127889,7 +129491,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3 *db, int ms){
/*
** Cause any pending operation to stop at its earliest opportunity.
*/
-SQLITE_API void sqlite3_interrupt(sqlite3 *db){
+SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
@@ -128006,7 +129608,7 @@ SQLITE_PRIVATE int sqlite3CreateFunc(
/*
** Create new user functions.
*/
-SQLITE_API int sqlite3_create_function(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_function(
sqlite3 *db,
const char *zFunc,
int nArg,
@@ -128020,7 +129622,7 @@ SQLITE_API int sqlite3_create_function(
xFinal, 0);
}
-SQLITE_API int sqlite3_create_function_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2(
sqlite3 *db,
const char *zFunc,
int nArg,
@@ -128063,7 +129665,7 @@ SQLITE_API int sqlite3_create_function_v2(
}
#ifndef SQLITE_OMIT_UTF16
-SQLITE_API int sqlite3_create_function16(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_function16(
sqlite3 *db,
const void *zFunctionName,
int nArg,
@@ -128103,7 +129705,7 @@ SQLITE_API int sqlite3_create_function16(
** A global function must exist in order for name resolution to work
** properly.
*/
-SQLITE_API int sqlite3_overload_function(
+SQLITE_API int SQLITE_STDCALL sqlite3_overload_function(
sqlite3 *db,
const char *zName,
int nArg
@@ -128135,7 +129737,7 @@ SQLITE_API int sqlite3_overload_function(
** trace is a pointer to a function that is invoked at the start of each
** SQL statement.
*/
-SQLITE_API void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){
+SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), void *pArg){
void *pOld;
#ifdef SQLITE_ENABLE_API_ARMOR
@@ -128159,7 +129761,7 @@ SQLITE_API void *sqlite3_trace(sqlite3 *db, void (*xTrace)(void*,const char*), v
** profile is a pointer to a function that is invoked at the conclusion of
** each SQL statement that is run.
*/
-SQLITE_API void *sqlite3_profile(
+SQLITE_API void *SQLITE_STDCALL sqlite3_profile(
sqlite3 *db,
void (*xProfile)(void*,const char*,sqlite_uint64),
void *pArg
@@ -128186,7 +129788,7 @@ SQLITE_API void *sqlite3_profile(
** If the invoked function returns non-zero, then the commit becomes a
** rollback.
*/
-SQLITE_API void *sqlite3_commit_hook(
+SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook(
sqlite3 *db, /* Attach the hook to this database */
int (*xCallback)(void*), /* Function to invoke on each commit */
void *pArg /* Argument to the function */
@@ -128211,7 +129813,7 @@ SQLITE_API void *sqlite3_commit_hook(
** Register a callback to be invoked each time a row is updated,
** inserted or deleted using this database connection.
*/
-SQLITE_API void *sqlite3_update_hook(
+SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook(
sqlite3 *db, /* Attach the hook to this database */
void (*xCallback)(void*,int,char const *,char const *,sqlite_int64),
void *pArg /* Argument to the function */
@@ -128236,7 +129838,7 @@ SQLITE_API void *sqlite3_update_hook(
** Register a callback to be invoked each time a transaction is rolled
** back by this database connection.
*/
-SQLITE_API void *sqlite3_rollback_hook(
+SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(
sqlite3 *db, /* Attach the hook to this database */
void (*xCallback)(void*), /* Callback function */
void *pArg /* Argument to the function */
@@ -128290,7 +129892,7 @@ SQLITE_PRIVATE int sqlite3WalDefaultHook(
** using sqlite3_wal_hook() disables the automatic checkpoint mechanism
** configured by this function.
*/
-SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){
+SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){
#ifdef SQLITE_OMIT_WAL
UNUSED_PARAMETER(db);
UNUSED_PARAMETER(nFrame);
@@ -128311,7 +129913,7 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int nFrame){
** Register a callback to be invoked each time a transaction is written
** into the write-ahead-log by this database connection.
*/
-SQLITE_API void *sqlite3_wal_hook(
+SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook(
sqlite3 *db, /* Attach the hook to this db handle */
int(*xCallback)(void *, sqlite3*, const char*, int),
void *pArg /* First argument passed to xCallback() */
@@ -128338,7 +129940,7 @@ SQLITE_API void *sqlite3_wal_hook(
/*
** Checkpoint database zDb.
*/
-SQLITE_API int sqlite3_wal_checkpoint_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2(
sqlite3 *db, /* Database handle */
const char *zDb, /* Name of attached database (or NULL) */
int eMode, /* SQLITE_CHECKPOINT_* value */
@@ -128393,7 +129995,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
** to contains a zero-length string, all attached databases are
** checkpointed.
*/
-SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
+SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb){
/* EVIDENCE-OF: R-41613-20553 The sqlite3_wal_checkpoint(D,X) is equivalent to
** sqlite3_wal_checkpoint_v2(D,X,SQLITE_CHECKPOINT_PASSIVE,0,0). */
return sqlite3_wal_checkpoint_v2(db,zDb,SQLITE_CHECKPOINT_PASSIVE,0,0);
@@ -128482,7 +130084,7 @@ SQLITE_PRIVATE int sqlite3TempInMemory(const sqlite3 *db){
** Return UTF-8 encoded English language explanation of the most recent
** error.
*/
-SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3 *db){
const char *z;
if( !db ){
return sqlite3ErrStr(SQLITE_NOMEM);
@@ -128510,7 +130112,7 @@ SQLITE_API const char *sqlite3_errmsg(sqlite3 *db){
** Return UTF-16 encoded English language explanation of the most recent
** error.
*/
-SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){
+SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3 *db){
static const u16 outOfMem[] = {
'o', 'u', 't', ' ', 'o', 'f', ' ', 'm', 'e', 'm', 'o', 'r', 'y', 0
};
@@ -128555,7 +130157,7 @@ SQLITE_API const void *sqlite3_errmsg16(sqlite3 *db){
** Return the most recent error code generated by an SQLite routine. If NULL is
** passed to this function, we assume a malloc() failed during sqlite3_open().
*/
-SQLITE_API int sqlite3_errcode(sqlite3 *db){
+SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db){
if( db && !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE_BKPT;
}
@@ -128564,7 +130166,7 @@ SQLITE_API int sqlite3_errcode(sqlite3 *db){
}
return db->errCode & db->errMask;
}
-SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){
+SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db){
if( db && !sqlite3SafetyCheckSickOrOk(db) ){
return SQLITE_MISUSE_BKPT;
}
@@ -128579,7 +130181,7 @@ SQLITE_API int sqlite3_extended_errcode(sqlite3 *db){
** argument. For now, this simply calls the internal sqlite3ErrStr()
** function.
*/
-SQLITE_API const char *sqlite3_errstr(int rc){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int rc){
return sqlite3ErrStr(rc);
}
@@ -128727,7 +130329,7 @@ static const int aHardLimit[] = {
** It merely prevents new constructs that exceed the limit
** from forming.
*/
-SQLITE_API int sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
+SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3 *db, int limitId, int newLimit){
int oldLimit;
#ifdef SQLITE_ENABLE_API_ARMOR
@@ -128820,18 +130422,30 @@ SQLITE_PRIVATE int sqlite3ParseUri(
int eState; /* Parser state when parsing URI */
int iIn; /* Input character index */
int iOut = 0; /* Output character index */
- int nByte = nUri+2; /* Bytes of space to allocate */
+ u64 nByte = nUri+2; /* Bytes of space to allocate */
/* Make sure the SQLITE_OPEN_URI flag is set to indicate to the VFS xOpen
** method that there may be extra parameters following the file-name. */
flags |= SQLITE_OPEN_URI;
for(iIn=0; iIn<nUri; iIn++) nByte += (zUri[iIn]=='&');
- zFile = sqlite3_malloc(nByte);
+ zFile = sqlite3_malloc64(nByte);
if( !zFile ) return SQLITE_NOMEM;
iIn = 5;
-#ifndef SQLITE_ALLOW_URI_AUTHORITY
+#ifdef SQLITE_ALLOW_URI_AUTHORITY
+ if( strncmp(zUri+5, "///", 3)==0 ){
+ iIn = 7;
+ /* The following condition causes URIs with five leading / characters
+ ** like file://///host/path to be converted into UNCs like //host/path.
+ ** The correct URI for that UNC has only two or four leading / characters
+ ** file://host/path or file:////host/path. But 5 leading slashes is a
+ ** common error, we are told, so we handle it as a special case. */
+ if( strncmp(zUri+7, "///", 3)==0 ){ iIn++; }
+ }else if( strncmp(zUri+5, "//localhost/", 12)==0 ){
+ iIn = 16;
+ }
+#else
/* Discard the scheme and authority segments of the URI. */
if( zUri[5]=='/' && zUri[6]=='/' ){
iIn = 7;
@@ -128981,7 +130595,7 @@ SQLITE_PRIVATE int sqlite3ParseUri(
}
}else{
- zFile = sqlite3_malloc(nUri+2);
+ zFile = sqlite3_malloc64(nUri+2);
if( !zFile ) return SQLITE_NOMEM;
memcpy(zFile, zUri, nUri);
zFile[nUri] = '\0';
@@ -129118,6 +130732,9 @@ static int openDatabase(
#if !defined(SQLITE_DEFAULT_AUTOMATIC_INDEX) || SQLITE_DEFAULT_AUTOMATIC_INDEX
| SQLITE_AutoIndex
#endif
+#if SQLITE_DEFAULT_CKPTFULLFSYNC
+ | SQLITE_CkptFullFSync
+#endif
#if SQLITE_DEFAULT_FILE_FORMAT<4
| SQLITE_LegacyFileFmt
#endif
@@ -129250,6 +130867,13 @@ static int openDatabase(
}
#endif
+#ifdef SQLITE_ENABLE_DBSTAT_VTAB
+ if( !db->mallocFailed && rc==SQLITE_OK){
+ int sqlite3_dbstat_register(sqlite3*);
+ rc = sqlite3_dbstat_register(db);
+ }
+#endif
+
/* -DSQLITE_DEFAULT_LOCKING_MODE=1 makes EXCLUSIVE the default locking
** mode. -DSQLITE_DEFAULT_LOCKING_MODE=0 make NORMAL the default locking
** mode. Doing nothing at all also makes NORMAL the default.
@@ -129271,7 +130895,8 @@ static int openDatabase(
opendb_out:
sqlite3_free(zOpen);
if( db ){
- assert( db->mutex!=0 || isThreadsafe==0 || sqlite3GlobalConfig.bFullMutex==0 );
+ assert( db->mutex!=0 || isThreadsafe==0
+ || sqlite3GlobalConfig.bFullMutex==0 );
sqlite3_mutex_leave(db->mutex);
}
rc = sqlite3_errcode(db);
@@ -129296,14 +130921,14 @@ opendb_out:
/*
** Open a new database handle.
*/
-SQLITE_API int sqlite3_open(
+SQLITE_API int SQLITE_STDCALL sqlite3_open(
const char *zFilename,
sqlite3 **ppDb
){
return openDatabase(zFilename, ppDb,
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0);
}
-SQLITE_API int sqlite3_open_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_open_v2(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb, /* OUT: SQLite db handle */
int flags, /* Flags */
@@ -129316,7 +130941,7 @@ SQLITE_API int sqlite3_open_v2(
/*
** Open a new database handle.
*/
-SQLITE_API int sqlite3_open16(
+SQLITE_API int SQLITE_STDCALL sqlite3_open16(
const void *zFilename,
sqlite3 **ppDb
){
@@ -129355,7 +130980,7 @@ SQLITE_API int sqlite3_open16(
/*
** Register a new collation sequence with the database handle db.
*/
-SQLITE_API int sqlite3_create_collation(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_collation(
sqlite3* db,
const char *zName,
int enc,
@@ -129368,7 +130993,7 @@ SQLITE_API int sqlite3_create_collation(
/*
** Register a new collation sequence with the database handle db.
*/
-SQLITE_API int sqlite3_create_collation_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2(
sqlite3* db,
const char *zName,
int enc,
@@ -129393,7 +131018,7 @@ SQLITE_API int sqlite3_create_collation_v2(
/*
** Register a new collation sequence with the database handle db.
*/
-SQLITE_API int sqlite3_create_collation16(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16(
sqlite3* db,
const void *zName,
int enc,
@@ -129423,7 +131048,7 @@ SQLITE_API int sqlite3_create_collation16(
** Register a collation sequence factory callback with the database handle
** db. Replace any previously installed collation sequence factory.
*/
-SQLITE_API int sqlite3_collation_needed(
+SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed(
sqlite3 *db,
void *pCollNeededArg,
void(*xCollNeeded)(void*,sqlite3*,int eTextRep,const char*)
@@ -129444,7 +131069,7 @@ SQLITE_API int sqlite3_collation_needed(
** Register a collation sequence factory callback with the database handle
** db. Replace any previously installed collation sequence factory.
*/
-SQLITE_API int sqlite3_collation_needed16(
+SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16(
sqlite3 *db,
void *pCollNeededArg,
void(*xCollNeeded16)(void*,sqlite3*,int eTextRep,const void*)
@@ -129466,7 +131091,7 @@ SQLITE_API int sqlite3_collation_needed16(
** This function is now an anachronism. It used to be used to recover from a
** malloc() failure, but SQLite now does this automatically.
*/
-SQLITE_API int sqlite3_global_recover(void){
+SQLITE_API int SQLITE_STDCALL sqlite3_global_recover(void){
return SQLITE_OK;
}
#endif
@@ -129477,7 +131102,7 @@ SQLITE_API int sqlite3_global_recover(void){
** by default. Autocommit is disabled by a BEGIN statement and reenabled
** by the next COMMIT or ROLLBACK.
*/
-SQLITE_API int sqlite3_get_autocommit(sqlite3 *db){
+SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3 *db){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
(void)SQLITE_MISUSE_BKPT;
@@ -129529,7 +131154,7 @@ SQLITE_PRIVATE int sqlite3CantopenError(int lineno){
** SQLite no longer uses thread-specific data so this routine is now a
** no-op. It is retained for historical compatibility.
*/
-SQLITE_API void sqlite3_thread_cleanup(void){
+SQLITE_API void SQLITE_STDCALL sqlite3_thread_cleanup(void){
}
#endif
@@ -129537,7 +131162,7 @@ SQLITE_API void sqlite3_thread_cleanup(void){
** Return meta information about a specific column of a database table.
** See comment in sqlite3.h (sqlite.h.in) for details.
*/
-SQLITE_API int sqlite3_table_column_metadata(
+SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata(
sqlite3 *db, /* Connection handle */
const char *zDbName, /* Database name or NULL */
const char *zTableName, /* Table name */
@@ -129553,13 +131178,19 @@ SQLITE_API int sqlite3_table_column_metadata(
Table *pTab = 0;
Column *pCol = 0;
int iCol = 0;
-
char const *zDataType = 0;
char const *zCollSeq = 0;
int notnull = 0;
int primarykey = 0;
int autoinc = 0;
+
+#ifdef SQLITE_ENABLE_API_ARMOR
+ if( !sqlite3SafetyCheckOk(db) || zTableName==0 ){
+ return SQLITE_MISUSE_BKPT;
+ }
+#endif
+
/* Ensure the database schema has been loaded */
sqlite3_mutex_enter(db->mutex);
sqlite3BtreeEnterAll(db);
@@ -129649,7 +131280,7 @@ error_out:
/*
** Sleep for a little while. Return the amount of time slept.
*/
-SQLITE_API int sqlite3_sleep(int ms){
+SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int ms){
sqlite3_vfs *pVfs;
int rc;
pVfs = sqlite3_vfs_find(0);
@@ -129665,7 +131296,7 @@ SQLITE_API int sqlite3_sleep(int ms){
/*
** Enable or disable the extended result codes.
*/
-SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff){
+SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3 *db, int onoff){
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ) return SQLITE_MISUSE_BKPT;
#endif
@@ -129678,7 +131309,7 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3 *db, int onoff){
/*
** Invoke the xFileControl method on a particular database.
*/
-SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
+SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, void *pArg){
int rc = SQLITE_ERROR;
Btree *pBtree;
@@ -129706,13 +131337,13 @@ SQLITE_API int sqlite3_file_control(sqlite3 *db, const char *zDbName, int op, vo
sqlite3BtreeLeave(pBtree);
}
sqlite3_mutex_leave(db->mutex);
- return rc;
+ return rc;
}
/*
** Interface to the testing logic.
*/
-SQLITE_API int sqlite3_test_control(int op, ...){
+SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...){
int rc = 0;
#ifndef SQLITE_OMIT_BUILTIN_TEST
va_list ap;
@@ -130009,6 +131640,35 @@ SQLITE_API int sqlite3_test_control(int op, ...){
if( sqlite3GlobalConfig.isInit==0 ) rc = SQLITE_ERROR;
break;
}
+
+ /* sqlite3_test_control(SQLITE_TESTCTRL_IMPOSTER, db, dbName, onOff, tnum);
+ **
+ ** This test control is used to create imposter tables. "db" is a pointer
+ ** to the database connection. dbName is the database name (ex: "main" or
+ ** "temp") which will receive the imposter. "onOff" turns imposter mode on
+ ** or off. "tnum" is the root page of the b-tree to which the imposter
+ ** table should connect.
+ **
+ ** Enable imposter mode only when the schema has already been parsed. Then
+ ** run a single CREATE TABLE statement to construct the imposter table in
+ ** the parsed schema. Then turn imposter mode back off again.
+ **
+ ** If onOff==0 and tnum>0 then reset the schema for all databases, causing
+ ** the schema to be reparsed the next time it is needed. This has the
+ ** effect of erasing all imposter tables.
+ */
+ case SQLITE_TESTCTRL_IMPOSTER: {
+ sqlite3 *db = va_arg(ap, sqlite3*);
+ sqlite3_mutex_enter(db->mutex);
+ db->init.iDb = sqlite3FindDbName(db, va_arg(ap,const char*));
+ db->init.busy = db->init.imposterTable = va_arg(ap,int);
+ db->init.newTnum = va_arg(ap,int);
+ if( db->init.busy==0 && db->init.newTnum>0 ){
+ sqlite3ResetAllSchemasOfConnection(db);
+ }
+ sqlite3_mutex_leave(db->mutex);
+ break;
+ }
}
va_end(ap);
#endif /* SQLITE_OMIT_BUILTIN_TEST */
@@ -130026,7 +131686,7 @@ SQLITE_API int sqlite3_test_control(int op, ...){
** parameter if it exists. If the parameter does not exist, this routine
** returns a NULL pointer.
*/
-SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam){
if( zFilename==0 || zParam==0 ) return 0;
zFilename += sqlite3Strlen30(zFilename) + 1;
while( zFilename[0] ){
@@ -130041,7 +131701,7 @@ SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *
/*
** Return a boolean value for a query parameter.
*/
-SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){
+SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFilename, const char *zParam, int bDflt){
const char *z = sqlite3_uri_parameter(zFilename, zParam);
bDflt = bDflt!=0;
return z ? sqlite3GetBoolean(z, bDflt) : bDflt;
@@ -130050,7 +131710,7 @@ SQLITE_API int sqlite3_uri_boolean(const char *zFilename, const char *zParam, in
/*
** Return a 64-bit integer value for a query parameter.
*/
-SQLITE_API sqlite3_int64 sqlite3_uri_int64(
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(
const char *zFilename, /* Filename as passed to xOpen */
const char *zParam, /* URI parameter sought */
sqlite3_int64 bDflt /* return if parameter is missing */
@@ -130082,7 +131742,7 @@ SQLITE_PRIVATE Btree *sqlite3DbNameToBtree(sqlite3 *db, const char *zDbName){
** Return the filename of the database associated with a database
** connection.
*/
-SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
+SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName){
Btree *pBt;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
@@ -130098,7 +131758,7 @@ SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName){
** Return 1 if database is read-only or 0 if read/write. Return -1 if
** no such database exists.
*/
-SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
+SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName){
Btree *pBt;
#ifdef SQLITE_ENABLE_API_ARMOR
if( !sqlite3SafetyCheckOk(db) ){
@@ -130257,7 +131917,7 @@ static void leaveMutex(void){
** on the same "db". If xNotify==0 then any prior callbacks are immediately
** cancelled.
*/
-SQLITE_API int sqlite3_unlock_notify(
+SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify(
sqlite3 *db,
void (*xNotify)(void **, int),
void *pArg
@@ -131151,6 +132811,11 @@ SQLITE_PRIVATE Fts3HashElem *sqlite3Fts3HashFindElem(const Fts3Hash *, const voi
#ifdef SQLITE_COVERAGE_TEST
# define ALWAYS(x) (1)
# define NEVER(X) (0)
+#elif defined(SQLITE_DEBUG)
+# define ALWAYS(x) sqlite3Fts3Always((x)!=0)
+# define NEVER(x) sqlite3Fts3Never((x)!=0)
+SQLITE_PRIVATE int sqlite3Fts3Always(int b);
+SQLITE_PRIVATE int sqlite3Fts3Never(int b);
#else
# define ALWAYS(x) (x)
# define NEVER(x) (x)
@@ -131551,6 +133216,7 @@ SQLITE_PRIVATE int sqlite3Fts3Incrmerge(Fts3Table*,int,int);
)
/* fts3.c */
+SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char**,const char*,...);
SQLITE_PRIVATE int sqlite3Fts3PutVarint(char *, sqlite3_int64);
SQLITE_PRIVATE int sqlite3Fts3GetVarint(const char *, sqlite_int64 *);
SQLITE_PRIVATE int sqlite3Fts3GetVarint32(const char *, int *);
@@ -131640,6 +133306,13 @@ static int fts3EvalStart(Fts3Cursor *pCsr);
static int fts3TermSegReaderCursor(
Fts3Cursor *, const char *, int, int, Fts3MultiSegReader **);
+#ifndef SQLITE_AMALGAMATION
+# if defined(SQLITE_DEBUG)
+SQLITE_PRIVATE int sqlite3Fts3Always(int b) { assert( b ); return b; }
+SQLITE_PRIVATE int sqlite3Fts3Never(int b) { assert( !b ); return b; }
+# endif
+#endif
+
/*
** Write a 64-bit variable-length integer to memory starting at p[0].
** The length of data written will be between 1 and FTS3_VARINT_MAX bytes.
@@ -131749,7 +133422,7 @@ SQLITE_PRIVATE void sqlite3Fts3Dequote(char *z){
/* If the first byte was a '[', then the close-quote character is a ']' */
if( quote=='[' ) quote = ']';
- while( ALWAYS(z[iIn]) ){
+ while( z[iIn] ){
if( z[iIn]==quote ){
if( z[iIn+1]!=quote ) break;
z[iOut++] = quote;
@@ -131829,6 +133502,17 @@ static int fts3DisconnectMethod(sqlite3_vtab *pVtab){
}
/*
+** Write an error message into *pzErr
+*/
+SQLITE_PRIVATE void sqlite3Fts3ErrMsg(char **pzErr, const char *zFormat, ...){
+ va_list ap;
+ sqlite3_free(*pzErr);
+ va_start(ap, zFormat);
+ *pzErr = sqlite3_vmprintf(zFormat, ap);
+ va_end(ap);
+}
+
+/*
** Construct one or more SQL statements from the format string given
** and then evaluate those statements. The success code is written
** into *pRc.
@@ -132237,11 +133921,16 @@ static char *fts3WriteExprList(Fts3Table *p, const char *zFunc, int *pRc){
** This function is used when parsing the "prefix=" FTS4 parameter.
*/
static int fts3GobbleInt(const char **pp, int *pnOut){
+ const int MAX_NPREFIX = 10000000;
const char *p; /* Iterator pointer */
int nInt = 0; /* Output value */
for(p=*pp; p[0]>='0' && p[0]<='9'; p++){
nInt = nInt * 10 + (p[0] - '0');
+ if( nInt>MAX_NPREFIX ){
+ nInt = 0;
+ break;
+ }
}
if( p==*pp ) return SQLITE_ERROR;
*pnOut = nInt;
@@ -132284,7 +133973,6 @@ static int fts3PrefixParameter(
aIndex = sqlite3_malloc(sizeof(struct Fts3Index) * nIndex);
*apIndex = aIndex;
- *pnIndex = nIndex;
if( !aIndex ){
return SQLITE_NOMEM;
}
@@ -132294,13 +133982,20 @@ static int fts3PrefixParameter(
const char *p = zParam;
int i;
for(i=1; i<nIndex; i++){
- int nPrefix;
+ int nPrefix = 0;
if( fts3GobbleInt(&p, &nPrefix) ) return SQLITE_ERROR;
- aIndex[i].nPrefix = nPrefix;
+ assert( nPrefix>=0 );
+ if( nPrefix==0 ){
+ nIndex--;
+ i--;
+ }else{
+ aIndex[i].nPrefix = nPrefix;
+ }
p++;
}
}
+ *pnIndex = nIndex;
return SQLITE_OK;
}
@@ -132335,7 +134030,8 @@ static int fts3ContentColumns(
const char *zTbl, /* Name of content table */
const char ***pazCol, /* OUT: Malloc'd array of column names */
int *pnCol, /* OUT: Size of array *pazCol */
- int *pnStr /* OUT: Bytes of string content */
+ int *pnStr, /* OUT: Bytes of string content */
+ char **pzErr /* OUT: error message */
){
int rc = SQLITE_OK; /* Return code */
char *zSql; /* "SELECT *" statement on zTbl */
@@ -132346,6 +134042,9 @@ static int fts3ContentColumns(
rc = SQLITE_NOMEM;
}else{
rc = sqlite3_prepare(db, zSql, -1, &pStmt, 0);
+ if( rc!=SQLITE_OK ){
+ sqlite3Fts3ErrMsg(pzErr, "%s", sqlite3_errmsg(db));
+ }
}
sqlite3_free(zSql);
@@ -132424,7 +134123,7 @@ static int fts3InitVtab(
const char **aCol; /* Array of column names */
sqlite3_tokenizer *pTokenizer = 0; /* Tokenizer for this table */
- int nIndex; /* Size of aIndex[] array */
+ int nIndex = 0; /* Size of aIndex[] array */
struct Fts3Index *aIndex = 0; /* Array of indexes for this table */
/* The results of parsing supported FTS4 key=value options: */
@@ -132512,13 +134211,13 @@ static int fts3InitVtab(
}
}
if( iOpt==SizeofArray(aFts4Opt) ){
- *pzErr = sqlite3_mprintf("unrecognized parameter: %s", z);
+ sqlite3Fts3ErrMsg(pzErr, "unrecognized parameter: %s", z);
rc = SQLITE_ERROR;
}else{
switch( iOpt ){
case 0: /* MATCHINFO */
if( strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "fts3", 4) ){
- *pzErr = sqlite3_mprintf("unrecognized matchinfo: %s", zVal);
+ sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo: %s", zVal);
rc = SQLITE_ERROR;
}
bNoDocsize = 1;
@@ -132546,7 +134245,7 @@ static int fts3InitVtab(
if( (strlen(zVal)!=3 || sqlite3_strnicmp(zVal, "asc", 3))
&& (strlen(zVal)!=4 || sqlite3_strnicmp(zVal, "desc", 4))
){
- *pzErr = sqlite3_mprintf("unrecognized order: %s", zVal);
+ sqlite3Fts3ErrMsg(pzErr, "unrecognized order: %s", zVal);
rc = SQLITE_ERROR;
}
bDescIdx = (zVal[0]=='d' || zVal[0]=='D');
@@ -132597,7 +134296,7 @@ static int fts3InitVtab(
if( nCol==0 ){
sqlite3_free((void*)aCol);
aCol = 0;
- rc = fts3ContentColumns(db, argv[1], zContent, &aCol, &nCol, &nString);
+ rc = fts3ContentColumns(db, argv[1], zContent,&aCol,&nCol,&nString,pzErr);
/* If a languageid= option was specified, remove the language id
** column from the aCol[] array. */
@@ -132632,7 +134331,7 @@ static int fts3InitVtab(
rc = fts3PrefixParameter(zPrefix, &nIndex, &aIndex);
if( rc==SQLITE_ERROR ){
assert( zPrefix );
- *pzErr = sqlite3_mprintf("error parsing prefix parameter: %s", zPrefix);
+ sqlite3Fts3ErrMsg(pzErr, "error parsing prefix parameter: %s", zPrefix);
}
if( rc!=SQLITE_OK ) goto fts3_init_out;
@@ -132714,7 +134413,7 @@ static int fts3InitVtab(
}
for(i=0; i<nNotindexed; i++){
if( azNotindexed[i] ){
- *pzErr = sqlite3_mprintf("no such column: %s", azNotindexed[i]);
+ sqlite3Fts3ErrMsg(pzErr, "no such column: %s", azNotindexed[i]);
rc = SQLITE_ERROR;
}
}
@@ -132722,7 +134421,7 @@ static int fts3InitVtab(
if( rc==SQLITE_OK && (zCompress==0)!=(zUncompress==0) ){
char const *zMiss = (zCompress==0 ? "compress" : "uncompress");
rc = SQLITE_ERROR;
- *pzErr = sqlite3_mprintf("missing %s parameter in fts4 constructor", zMiss);
+ sqlite3Fts3ErrMsg(pzErr, "missing %s parameter in fts4 constructor", zMiss);
}
p->zReadExprlist = fts3ReadExprList(p, zUncompress, &rc);
p->zWriteExprlist = fts3WriteExprList(p, zCompress, &rc);
@@ -133818,26 +135517,33 @@ static int fts3DoclistOrMerge(
**
** The right-hand input doclist is overwritten by this function.
*/
-static void fts3DoclistPhraseMerge(
+static int fts3DoclistPhraseMerge(
int bDescDoclist, /* True if arguments are desc */
int nDist, /* Distance from left to right (1=adjacent) */
char *aLeft, int nLeft, /* Left doclist */
- char *aRight, int *pnRight /* IN/OUT: Right/output doclist */
+ char **paRight, int *pnRight /* IN/OUT: Right/output doclist */
){
sqlite3_int64 i1 = 0;
sqlite3_int64 i2 = 0;
sqlite3_int64 iPrev = 0;
+ char *aRight = *paRight;
char *pEnd1 = &aLeft[nLeft];
char *pEnd2 = &aRight[*pnRight];
char *p1 = aLeft;
char *p2 = aRight;
char *p;
int bFirstOut = 0;
- char *aOut = aRight;
+ char *aOut;
assert( nDist>0 );
-
+ if( bDescDoclist ){
+ aOut = sqlite3_malloc(*pnRight + FTS3_VARINT_MAX);
+ if( aOut==0 ) return SQLITE_NOMEM;
+ }else{
+ aOut = aRight;
+ }
p = aOut;
+
fts3GetDeltaVarint3(&p1, pEnd1, 0, &i1);
fts3GetDeltaVarint3(&p2, pEnd2, 0, &i2);
@@ -133866,6 +135572,12 @@ static void fts3DoclistPhraseMerge(
}
*pnRight = (int)(p - aOut);
+ if( bDescDoclist ){
+ sqlite3_free(aRight);
+ *paRight = aOut;
+ }
+
+ return SQLITE_OK;
}
/*
@@ -133990,8 +135702,22 @@ static int fts3TermSelectMerge(
){
if( pTS->aaOutput[0]==0 ){
/* If this is the first term selected, copy the doclist to the output
- ** buffer using memcpy(). */
- pTS->aaOutput[0] = sqlite3_malloc(nDoclist);
+ ** buffer using memcpy().
+ **
+ ** Add FTS3_VARINT_MAX bytes of unused space to the end of the
+ ** allocation. This is so as to ensure that the buffer is big enough
+ ** to hold the current doclist AND'd with any other doclist. If the
+ ** doclists are stored in order=ASC order, this padding would not be
+ ** required (since the size of [doclistA AND doclistB] is always less
+ ** than or equal to the size of [doclistA] in that case). But this is
+ ** not true for order=DESC. For example, a doclist containing (1, -1)
+ ** may be smaller than (-1), as in the first example the -1 may be stored
+ ** as a single-byte delta, whereas in the second it must be stored as a
+ ** FTS3_VARINT_MAX byte varint.
+ **
+ ** Similar padding is added in the fts3DoclistOrMerge() function.
+ */
+ pTS->aaOutput[0] = sqlite3_malloc(nDoclist + FTS3_VARINT_MAX + 1);
pTS->anOutput[0] = nDoclist;
if( pTS->aaOutput[0] ){
memcpy(pTS->aaOutput[0], aDoclist, nDoclist);
@@ -134088,7 +135814,7 @@ static int fts3SegReaderCursor(
** calls out here. */
if( iLevel<0 && p->aIndex ){
Fts3SegReader *pSeg = 0;
- rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix, &pSeg);
+ rc = sqlite3Fts3SegReaderPending(p, iIndex, zTerm, nTerm, isPrefix||isScan, &pSeg);
if( rc==SQLITE_OK && pSeg ){
rc = fts3SegReaderCursorAppend(pCsr, pSeg);
}
@@ -134491,10 +136217,17 @@ static int fts3FilterMethod(
** row by docid.
*/
if( eSearch==FTS3_FULLSCAN_SEARCH ){
- zSql = sqlite3_mprintf(
- "SELECT %s ORDER BY rowid %s",
- p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
- );
+ if( pDocidGe || pDocidLe ){
+ zSql = sqlite3_mprintf(
+ "SELECT %s WHERE rowid BETWEEN %lld AND %lld ORDER BY rowid %s",
+ p->zReadExprlist, pCsr->iMinDocid, pCsr->iMaxDocid,
+ (pCsr->bDesc ? "DESC" : "ASC")
+ );
+ }else{
+ zSql = sqlite3_mprintf("SELECT %s ORDER BY rowid %s",
+ p->zReadExprlist, (pCsr->bDesc ? "DESC" : "ASC")
+ );
+ }
if( zSql ){
rc = sqlite3_prepare_v2(p->db, zSql, -1, &pCsr->pStmt, 0);
sqlite3_free(zSql);
@@ -134730,11 +136463,31 @@ static void fts3ReversePoslist(char *pStart, char **ppPoslist){
char *p = &(*ppPoslist)[-2];
char c = 0;
+ /* Skip backwards passed any trailing 0x00 bytes added by NearTrim() */
while( p>pStart && (c=*p--)==0 );
+
+ /* Search backwards for a varint with value zero (the end of the previous
+ ** poslist). This is an 0x00 byte preceded by some byte that does not
+ ** have the 0x80 bit set. */
while( p>pStart && (*p & 0x80) | c ){
c = *p--;
}
- if( p>pStart ){ p = &p[2]; }
+ assert( p==pStart || c==0 );
+
+ /* At this point p points to that preceding byte without the 0x80 bit
+ ** set. So to find the start of the poslist, skip forward 2 bytes then
+ ** over a varint.
+ **
+ ** Normally. The other case is that p==pStart and the poslist to return
+ ** is the first in the doclist. In this case do not skip forward 2 bytes.
+ ** The second part of the if condition (c==0 && *ppPoslist>&p[2])
+ ** is required for cases where the first byte of a doclist and the
+ ** doclist is empty. For example, if the first docid is 10, a doclist
+ ** that begins with:
+ **
+ ** 0x0A 0x00 <next docid delta varint>
+ */
+ if( p>pStart || (c==0 && *ppPoslist>&p[2]) ){ p = &p[2]; }
while( *p++&0x80 );
*ppPoslist = p;
}
@@ -134805,6 +136558,8 @@ static void fts3SnippetFunc(
}
if( !zEllipsis || !zEnd || !zStart ){
sqlite3_result_error_nomem(pContext);
+ }else if( nToken==0 ){
+ sqlite3_result_text(pContext, "", -1, SQLITE_STATIC);
}else if( SQLITE_OK==fts3CursorSeek(pContext, pCsr) ){
sqlite3Fts3Snippet(pContext, pCsr, zStart, zEnd, zEllipsis, iCol, nToken);
}
@@ -135240,14 +136995,17 @@ static void fts3EvalAllocateReaders(
** This function assumes that pList points to a buffer allocated using
** sqlite3_malloc(). This function takes responsibility for eventually
** freeing the buffer.
+**
+** SQLITE_OK is returned if successful, or SQLITE_NOMEM if an error occurs.
*/
-static void fts3EvalPhraseMergeToken(
+static int fts3EvalPhraseMergeToken(
Fts3Table *pTab, /* FTS Table pointer */
Fts3Phrase *p, /* Phrase to merge pList/nList into */
int iToken, /* Token pList/nList corresponds to */
char *pList, /* Pointer to doclist */
int nList /* Number of bytes in pList */
){
+ int rc = SQLITE_OK;
assert( iToken!=p->iDoclistToken );
if( pList==0 ){
@@ -135286,13 +137044,16 @@ static void fts3EvalPhraseMergeToken(
nDiff = p->iDoclistToken - iToken;
}
- fts3DoclistPhraseMerge(pTab->bDescIdx, nDiff, pLeft, nLeft, pRight,&nRight);
+ rc = fts3DoclistPhraseMerge(
+ pTab->bDescIdx, nDiff, pLeft, nLeft, &pRight, &nRight
+ );
sqlite3_free(pLeft);
p->doclist.aAll = pRight;
p->doclist.nAll = nRight;
}
if( iToken>p->iDoclistToken ) p->iDoclistToken = iToken;
+ return rc;
}
/*
@@ -135318,7 +137079,7 @@ static int fts3EvalPhraseLoad(
char *pThis = 0;
rc = fts3TermSelect(pTab, pToken, p->iColumn, &nThis, &pThis);
if( rc==SQLITE_OK ){
- fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
+ rc = fts3EvalPhraseMergeToken(pTab, p, iToken, pThis, nThis);
}
}
assert( pToken->pSegcsr==0 );
@@ -135860,12 +137621,14 @@ static void fts3EvalStartReaders(
){
if( pExpr && SQLITE_OK==*pRc ){
if( pExpr->eType==FTSQUERY_PHRASE ){
- int i;
int nToken = pExpr->pPhrase->nToken;
- for(i=0; i<nToken; i++){
- if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
+ if( nToken ){
+ int i;
+ for(i=0; i<nToken; i++){
+ if( pExpr->pPhrase->aToken[i].pDeferred==0 ) break;
+ }
+ pExpr->bDeferred = (i==nToken);
}
- pExpr->bDeferred = (i==nToken);
*pRc = fts3EvalPhraseStart(pCsr, 1, pExpr->pPhrase);
}else{
fts3EvalStartReaders(pCsr, pExpr->pLeft, pRc);
@@ -136121,8 +137884,12 @@ static int fts3EvalSelectDeferred(
rc = fts3TermSelect(pTab, pToken, pTC->iCol, &nList, &pList);
assert( rc==SQLITE_OK || pList==0 );
if( rc==SQLITE_OK ){
+ rc = fts3EvalPhraseMergeToken(
+ pTab, pTC->pPhrase, pTC->iToken,pList,nList
+ );
+ }
+ if( rc==SQLITE_OK ){
int nCount;
- fts3EvalPhraseMergeToken(pTab, pTC->pPhrase, pTC->iToken,pList,nList);
nCount = fts3DoclistCountDocids(
pTC->pPhrase->doclist.aAll, pTC->pPhrase->doclist.nAll
);
@@ -136983,7 +138750,6 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
if( iDocid!=pCsr->iPrevId || pExpr->bEof ){
int rc = SQLITE_OK;
int bDescDoclist = pTab->bDescIdx; /* For DOCID_CMP macro */
- int iMul; /* +1 if csr dir matches index dir, else -1 */
int bOr = 0;
u8 bEof = 0;
u8 bTreeEof = 0;
@@ -137025,7 +138791,8 @@ SQLITE_PRIVATE int sqlite3Fts3EvalPhrasePoslist(
pIter = pPhrase->pOrPoslist;
iDocid = pPhrase->iOrDocid;
if( pCsr->bDesc==bDescDoclist ){
- bEof = (pIter >= (pPhrase->doclist.aAll + pPhrase->doclist.nAll));
+ bEof = !pPhrase->doclist.nAll ||
+ (pIter >= (pPhrase->doclist.aAll + pPhrase->doclist.nAll));
while( (pIter==0 || DOCID_CMP(iDocid, pCsr->iPrevId)<0 ) && bEof==0 ){
sqlite3Fts3DoclistNext(
bDescDoclist, pPhrase->doclist.aAll, pPhrase->doclist.nAll,
@@ -137106,7 +138873,7 @@ SQLITE_PRIVATE int sqlite3Fts3Corrupt(){
#ifdef _WIN32
__declspec(dllexport)
#endif
-SQLITE_API int sqlite3_fts3_init(
+SQLITE_API int SQLITE_STDCALL sqlite3_fts3_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
@@ -137237,7 +139004,7 @@ static int fts3auxConnectMethod(
return SQLITE_OK;
bad_args:
- *pzErr = sqlite3_mprintf("invalid arguments to fts4aux constructor");
+ sqlite3Fts3ErrMsg(pzErr, "invalid arguments to fts4aux constructor");
return SQLITE_ERROR;
}
@@ -138695,13 +140462,13 @@ SQLITE_PRIVATE int sqlite3Fts3ExprParse(
sqlite3Fts3ExprFree(*ppExpr);
*ppExpr = 0;
if( rc==SQLITE_TOOBIG ){
- *pzErr = sqlite3_mprintf(
+ sqlite3Fts3ErrMsg(pzErr,
"FTS expression tree is too large (maximum depth %d)",
SQLITE_FTS3_MAX_EXPR_DEPTH
);
rc = SQLITE_ERROR;
}else if( rc==SQLITE_ERROR ){
- *pzErr = sqlite3_mprintf("malformed MATCH expression: [%s]", z);
+ sqlite3Fts3ErrMsg(pzErr, "malformed MATCH expression: [%s]", z);
}
}
@@ -140074,7 +141841,7 @@ static void scalarFunc(
if( argc==2 ){
void *pOld;
int n = sqlite3_value_bytes(argv[1]);
- if( n!=sizeof(pPtr) ){
+ if( zName==0 || n!=sizeof(pPtr) ){
sqlite3_result_error(context, "argument type mismatch", -1);
return;
}
@@ -140085,7 +141852,9 @@ static void scalarFunc(
return;
}
}else{
- pPtr = sqlite3Fts3HashFind(pHash, zName, nName);
+ if( zName ){
+ pPtr = sqlite3Fts3HashFind(pHash, zName, nName);
+ }
if( !pPtr ){
char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
sqlite3_result_error(context, zErr, -1);
@@ -140166,12 +141935,16 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
zEnd = &zCopy[strlen(zCopy)];
z = (char *)sqlite3Fts3NextToken(zCopy, &n);
+ if( z==0 ){
+ assert( n==0 );
+ z = zCopy;
+ }
z[n] = '\0';
sqlite3Fts3Dequote(z);
m = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash,z,(int)strlen(z)+1);
if( !m ){
- *pzErr = sqlite3_mprintf("unknown tokenizer: %s", z);
+ sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", z);
rc = SQLITE_ERROR;
}else{
char const **aArg = 0;
@@ -140194,7 +141967,7 @@ SQLITE_PRIVATE int sqlite3Fts3InitTokenizer(
rc = m->xCreate(iArg, aArg, ppTok);
assert( rc!=SQLITE_OK || *ppTok );
if( rc!=SQLITE_OK ){
- *pzErr = sqlite3_mprintf("unknown tokenizer");
+ sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer");
}else{
(*ppTok)->pModule = m;
}
@@ -140278,9 +142051,9 @@ static void testFunc(
p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
if( !p ){
- char *zErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
- sqlite3_result_error(context, zErr, -1);
- sqlite3_free(zErr);
+ char *zErr2 = sqlite3_mprintf("unknown tokenizer: %s", zName);
+ sqlite3_result_error(context, zErr2, -1);
+ sqlite3_free(zErr2);
return;
}
@@ -140815,7 +142588,7 @@ static int fts3tokQueryTokenizer(
p = (sqlite3_tokenizer_module *)sqlite3Fts3HashFind(pHash, zName, nName+1);
if( !p ){
- *pzErr = sqlite3_mprintf("unknown tokenizer: %s", zName);
+ sqlite3Fts3ErrMsg(pzErr, "unknown tokenizer: %s", zName);
return SQLITE_ERROR;
}
@@ -141512,7 +143285,7 @@ static int fts3SqlStmt(
/* 25 */ "",
/* 26 */ "DELETE FROM %Q.'%q_segdir' WHERE level BETWEEN ? AND ?",
-/* 27 */ "SELECT DISTINCT level / (1024 * ?) FROM %Q.'%q_segdir'",
+/* 27 */ "SELECT ? UNION SELECT level / (1024 * ?) FROM %Q.'%q_segdir'",
/* This statement is used to determine which level to read the input from
** when performing an incremental merge. It returns the absolute level number
@@ -142811,7 +144584,10 @@ SQLITE_PRIVATE int sqlite3Fts3SegReaderNew(
** an array of pending terms by term. This occurs as part of flushing
** the contents of the pending-terms hash table to the database.
*/
-static int fts3CompareElemByTerm(const void *lhs, const void *rhs){
+static int SQLITE_CDECL fts3CompareElemByTerm(
+ const void *lhs,
+ const void *rhs
+){
char *z1 = fts3HashKey(*(Fts3HashElem **)lhs);
char *z2 = fts3HashKey(*(Fts3HashElem **)rhs);
int n1 = fts3HashKeysize(*(Fts3HashElem **)lhs);
@@ -144627,7 +146403,8 @@ static int fts3DoOptimize(Fts3Table *p, int bReturnDone){
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
if( rc==SQLITE_OK ){
int rc2;
- sqlite3_bind_int(pAllLangid, 1, p->nIndex);
+ sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
+ sqlite3_bind_int(pAllLangid, 2, p->nIndex);
while( sqlite3_step(pAllLangid)==SQLITE_ROW ){
int i;
int iLangid = sqlite3_column_int(pAllLangid, 0);
@@ -145959,7 +147736,7 @@ static int fts3IncrmergeHintPop(Blob *pHint, i64 *piAbsLevel, int *pnInput){
pHint->n = i;
i += sqlite3Fts3GetVarint(&pHint->a[i], piAbsLevel);
i += fts3GetVarint32(&pHint->a[i], pnInput);
- if( i!=nHint ) return SQLITE_CORRUPT_VTAB;
+ if( i!=nHint ) return FTS_CORRUPT_VTAB;
return SQLITE_OK;
}
@@ -146327,7 +148104,8 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
if( rc==SQLITE_OK ){
int rc2;
- sqlite3_bind_int(pAllLangid, 1, p->nIndex);
+ sqlite3_bind_int(pAllLangid, 1, p->iPrevLangid);
+ sqlite3_bind_int(pAllLangid, 2, p->nIndex);
while( rc==SQLITE_OK && sqlite3_step(pAllLangid)==SQLITE_ROW ){
int iLangid = sqlite3_column_int(pAllLangid, 0);
int i;
@@ -146340,7 +148118,6 @@ static int fts3IntegrityCheck(Fts3Table *p, int *pbOk){
}
/* This block calculates the checksum according to the %_content table */
- rc = fts3SqlStmt(p, SQL_SELECT_ALL_LANGID, &pAllLangid, 0);
if( rc==SQLITE_OK ){
sqlite3_tokenizer_module const *pModule = p->pTokenizer->pModule;
sqlite3_stmt *pStmt = 0;
@@ -146437,7 +148214,7 @@ static int fts3DoIntegrityCheck(
int rc;
int bOk = 0;
rc = fts3IntegrityCheck(p, &bOk);
- if( rc==SQLITE_OK && bOk==0 ) rc = SQLITE_CORRUPT_VTAB;
+ if( rc==SQLITE_OK && bOk==0 ) rc = FTS_CORRUPT_VTAB;
return rc;
}
@@ -146875,6 +148652,7 @@ SQLITE_PRIVATE int sqlite3Fts3Optimize(Fts3Table *p){
#define FTS3_MATCHINFO_LENGTH 'l' /* nCol values */
#define FTS3_MATCHINFO_LCS 's' /* nCol values */
#define FTS3_MATCHINFO_HITS 'x' /* 3*nCol*nPhrase values */
+#define FTS3_MATCHINFO_LHITS 'y' /* nCol*nPhrase values */
/*
** The default value for the second argument to matchinfo().
@@ -147530,8 +149308,12 @@ static int fts3SnippetText(
** required. They are required if (a) this is not the first fragment,
** or (b) this fragment does not begin at position 0 of its column.
*/
- if( rc==SQLITE_OK && (iPos>0 || iFragment>0) ){
- rc = fts3StringAppend(pOut, zEllipsis, -1);
+ if( rc==SQLITE_OK ){
+ if( iPos>0 || iFragment>0 ){
+ rc = fts3StringAppend(pOut, zEllipsis, -1);
+ }else if( iBegin ){
+ rc = fts3StringAppend(pOut, zDoc, iBegin);
+ }
}
if( rc!=SQLITE_OK || iCurrent<iPos ) continue;
}
@@ -147653,6 +149435,51 @@ static int fts3ExprLocalHitsCb(
return rc;
}
+/*
+** fts3ExprIterate() callback used to gather information for the matchinfo
+** directive 'y'.
+*/
+static int fts3ExprLHitsCb(
+ Fts3Expr *pExpr, /* Phrase expression node */
+ int iPhrase, /* Phrase number */
+ void *pCtx /* Pointer to MatchInfo structure */
+){
+ MatchInfo *p = (MatchInfo *)pCtx;
+ Fts3Table *pTab = (Fts3Table *)p->pCursor->base.pVtab;
+ int rc = SQLITE_OK;
+ int iStart = iPhrase * p->nCol;
+ Fts3Expr *pEof; /* Ancestor node already at EOF */
+
+ /* This must be a phrase */
+ assert( pExpr->pPhrase );
+
+ /* Initialize all output integers to zero. */
+ memset(&p->aMatchinfo[iStart], 0, sizeof(u32) * p->nCol);
+
+ /* Check if this or any parent node is at EOF. If so, then all output
+ ** values are zero. */
+ for(pEof=pExpr; pEof && pEof->bEof==0; pEof=pEof->pParent);
+
+ if( pEof==0 && pExpr->iDocid==p->pCursor->iPrevId ){
+ Fts3Phrase *pPhrase = pExpr->pPhrase;
+ char *pIter = pPhrase->doclist.pList;
+ int iCol = 0;
+
+ while( 1 ){
+ int nHit = fts3ColumnlistCount(&pIter);
+ if( (pPhrase->iColumn>=pTab->nColumn || pPhrase->iColumn==iCol) ){
+ p->aMatchinfo[iStart + iCol] = (u32)nHit;
+ }
+ assert( *pIter==0x00 || *pIter==0x01 );
+ if( *pIter!=0x01 ) break;
+ pIter++;
+ pIter += fts3GetVarint32(pIter, &iCol);
+ }
+ }
+
+ return rc;
+}
+
static int fts3MatchinfoCheck(
Fts3Table *pTab,
char cArg,
@@ -147665,10 +149492,11 @@ static int fts3MatchinfoCheck(
|| (cArg==FTS3_MATCHINFO_LENGTH && pTab->bHasDocsize)
|| (cArg==FTS3_MATCHINFO_LCS)
|| (cArg==FTS3_MATCHINFO_HITS)
+ || (cArg==FTS3_MATCHINFO_LHITS)
){
return SQLITE_OK;
}
- *pzErr = sqlite3_mprintf("unrecognized matchinfo request: %c", cArg);
+ sqlite3Fts3ErrMsg(pzErr, "unrecognized matchinfo request: %c", cArg);
return SQLITE_ERROR;
}
@@ -147688,6 +149516,10 @@ static int fts3MatchinfoSize(MatchInfo *pInfo, char cArg){
nVal = pInfo->nCol;
break;
+ case FTS3_MATCHINFO_LHITS:
+ nVal = pInfo->nCol * pInfo->nPhrase;
+ break;
+
default:
assert( cArg==FTS3_MATCHINFO_HITS );
nVal = pInfo->nCol * pInfo->nPhrase * 3;
@@ -147942,6 +149774,10 @@ static int fts3MatchinfoValues(
}
break;
+ case FTS3_MATCHINFO_LHITS:
+ (void)fts3ExprIterate(pCsr->pExpr, fts3ExprLHitsCb, (void*)pInfo);
+ break;
+
default: {
Fts3Expr *pExpr;
assert( zArg[i]==FTS3_MATCHINFO_HITS );
@@ -148097,7 +149933,7 @@ SQLITE_PRIVATE void sqlite3Fts3Snippet(
*/
for(iRead=0; iRead<pTab->nColumn; iRead++){
SnippetFragment sF = {0, 0, 0, 0};
- int iS;
+ int iS = 0;
if( iCol>=0 && iRead!=iCol ) continue;
/* Find the best snippet of nFToken tokens in column iRead. */
@@ -151954,11 +153790,19 @@ static int rtreeUpdate(
if( nData>1 ){
int ii;
- /* Populate the cell.aCoord[] array. The first coordinate is azData[3]. */
- assert( nData==(pRtree->nDim*2 + 3) );
+ /* Populate the cell.aCoord[] array. The first coordinate is azData[3].
+ **
+ ** NB: nData can only be less than nDim*2+3 if the rtree is mis-declared
+ ** with "column" that are interpreted as table constraints.
+ ** Example: CREATE VIRTUAL TABLE bad USING rtree(x,y,CHECK(y>5));
+ ** This problem was discovered after years of use, so we silently ignore
+ ** these kinds of misdeclared tables to avoid breaking any legacy.
+ */
+ assert( nData<=(pRtree->nDim*2 + 3) );
+
#ifndef SQLITE_RTREE_INT_ONLY
if( pRtree->eCoordType==RTREE_COORD_REAL32 ){
- for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ for(ii=0; ii<nData-4; ii+=2){
cell.aCoord[ii].f = rtreeValueDown(azData[ii+3]);
cell.aCoord[ii+1].f = rtreeValueUp(azData[ii+4]);
if( cell.aCoord[ii].f>cell.aCoord[ii+1].f ){
@@ -151969,7 +153813,7 @@ static int rtreeUpdate(
}else
#endif
{
- for(ii=0; ii<(pRtree->nDim*2); ii+=2){
+ for(ii=0; ii<nData-4; ii+=2){
cell.aCoord[ii].i = sqlite3_value_int(azData[ii+3]);
cell.aCoord[ii+1].i = sqlite3_value_int(azData[ii+4]);
if( cell.aCoord[ii].i>cell.aCoord[ii+1].i ){
@@ -152540,7 +154384,7 @@ static void geomCallback(sqlite3_context *ctx, int nArg, sqlite3_value **aArg){
/*
** Register a new geometry function for use with the r-tree MATCH operator.
*/
-SQLITE_API int sqlite3_rtree_geometry_callback(
+SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback(
sqlite3 *db, /* Register SQL function on this connection */
const char *zGeom, /* Name of the new SQL function */
int (*xGeom)(sqlite3_rtree_geometry*,int,RtreeDValue*,int*), /* Callback */
@@ -152564,7 +154408,7 @@ SQLITE_API int sqlite3_rtree_geometry_callback(
** Register a new 2nd-generation geometry function for use with the
** r-tree MATCH operator.
*/
-SQLITE_API int sqlite3_rtree_query_callback(
+SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback(
sqlite3 *db, /* Register SQL function on this connection */
const char *zQueryFunc, /* Name of new SQL function */
int (*xQueryFunc)(sqlite3_rtree_query_info*), /* Callback */
@@ -152589,7 +154433,7 @@ SQLITE_API int sqlite3_rtree_query_callback(
#ifdef _WIN32
__declspec(dllexport)
#endif
-SQLITE_API int sqlite3_rtree_init(
+SQLITE_API int SQLITE_STDCALL sqlite3_rtree_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
@@ -153094,7 +154938,7 @@ SQLITE_PRIVATE int sqlite3IcuInit(sqlite3 *db){
#ifdef _WIN32
__declspec(dllexport)
#endif
-SQLITE_API int sqlite3_icu_init(
+SQLITE_API int SQLITE_STDCALL sqlite3_icu_init(
sqlite3 *db,
char **pzErrMsg,
const sqlite3_api_routines *pApi
@@ -153369,3 +155213,654 @@ SQLITE_PRIVATE void sqlite3Fts3IcuTokenizerModule(
#endif /* !defined(SQLITE_CORE) || defined(SQLITE_ENABLE_FTS3) */
/************** End of fts3_icu.c ********************************************/
+/************** Begin file dbstat.c ******************************************/
+/*
+** 2010 July 12
+**
+** The author disclaims copyright to this source code. In place of
+** a legal notice, here is a blessing:
+**
+** May you do good and not evil.
+** May you find forgiveness for yourself and forgive others.
+** May you share freely, never taking more than you give.
+**
+******************************************************************************
+**
+** This file contains an implementation of the "dbstat" virtual table.
+**
+** The dbstat virtual table is used to extract low-level formatting
+** information from an SQLite database in order to implement the
+** "sqlite3_analyzer" utility. See the ../tool/spaceanal.tcl script
+** for an example implementation.
+*/
+
+#if (defined(SQLITE_ENABLE_DBSTAT_VTAB) || defined(SQLITE_TEST)) \
+ && !defined(SQLITE_OMIT_VIRTUALTABLE)
+
+/*
+** Page paths:
+**
+** The value of the 'path' column describes the path taken from the
+** root-node of the b-tree structure to each page. The value of the
+** root-node path is '/'.
+**
+** The value of the path for the left-most child page of the root of
+** a b-tree is '/000/'. (Btrees store content ordered from left to right
+** so the pages to the left have smaller keys than the pages to the right.)
+** The next to left-most child of the root page is
+** '/001', and so on, each sibling page identified by a 3-digit hex
+** value. The children of the 451st left-most sibling have paths such
+** as '/1c2/000/, '/1c2/001/' etc.
+**
+** Overflow pages are specified by appending a '+' character and a
+** six-digit hexadecimal value to the path to the cell they are linked
+** from. For example, the three overflow pages in a chain linked from
+** the left-most cell of the 450th child of the root page are identified
+** by the paths:
+**
+** '/1c2/000+000000' // First page in overflow chain
+** '/1c2/000+000001' // Second page in overflow chain
+** '/1c2/000+000002' // Third page in overflow chain
+**
+** If the paths are sorted using the BINARY collation sequence, then
+** the overflow pages associated with a cell will appear earlier in the
+** sort-order than its child page:
+**
+** '/1c2/000/' // Left-most child of 451st child of root
+*/
+#define VTAB_SCHEMA \
+ "CREATE TABLE xx( " \
+ " name STRING, /* Name of table or index */" \
+ " path INTEGER, /* Path to page from root */" \
+ " pageno INTEGER, /* Page number */" \
+ " pagetype STRING, /* 'internal', 'leaf' or 'overflow' */" \
+ " ncell INTEGER, /* Cells on page (0 for overflow) */" \
+ " payload INTEGER, /* Bytes of payload on this page */" \
+ " unused INTEGER, /* Bytes of unused space on this page */" \
+ " mx_payload INTEGER, /* Largest payload size of all cells */" \
+ " pgoffset INTEGER, /* Offset of page in file */" \
+ " pgsize INTEGER /* Size of the page */" \
+ ");"
+
+
+typedef struct StatTable StatTable;
+typedef struct StatCursor StatCursor;
+typedef struct StatPage StatPage;
+typedef struct StatCell StatCell;
+
+struct StatCell {
+ int nLocal; /* Bytes of local payload */
+ u32 iChildPg; /* Child node (or 0 if this is a leaf) */
+ int nOvfl; /* Entries in aOvfl[] */
+ u32 *aOvfl; /* Array of overflow page numbers */
+ int nLastOvfl; /* Bytes of payload on final overflow page */
+ int iOvfl; /* Iterates through aOvfl[] */
+};
+
+struct StatPage {
+ u32 iPgno;
+ DbPage *pPg;
+ int iCell;
+
+ char *zPath; /* Path to this page */
+
+ /* Variables populated by statDecodePage(): */
+ u8 flags; /* Copy of flags byte */
+ int nCell; /* Number of cells on page */
+ int nUnused; /* Number of unused bytes on page */
+ StatCell *aCell; /* Array of parsed cells */
+ u32 iRightChildPg; /* Right-child page number (or 0) */
+ int nMxPayload; /* Largest payload of any cell on this page */
+};
+
+struct StatCursor {
+ sqlite3_vtab_cursor base;
+ sqlite3_stmt *pStmt; /* Iterates through set of root pages */
+ int isEof; /* After pStmt has returned SQLITE_DONE */
+
+ StatPage aPage[32];
+ int iPage; /* Current entry in aPage[] */
+
+ /* Values to return. */
+ char *zName; /* Value of 'name' column */
+ char *zPath; /* Value of 'path' column */
+ u32 iPageno; /* Value of 'pageno' column */
+ char *zPagetype; /* Value of 'pagetype' column */
+ int nCell; /* Value of 'ncell' column */
+ int nPayload; /* Value of 'payload' column */
+ int nUnused; /* Value of 'unused' column */
+ int nMxPayload; /* Value of 'mx_payload' column */
+ i64 iOffset; /* Value of 'pgOffset' column */
+ int szPage; /* Value of 'pgSize' column */
+};
+
+struct StatTable {
+ sqlite3_vtab base;
+ sqlite3 *db;
+ int iDb; /* Index of database to analyze */
+};
+
+#ifndef get2byte
+# define get2byte(x) ((x)[0]<<8 | (x)[1])
+#endif
+
+/*
+** Connect to or create a statvfs virtual table.
+*/
+static int statConnect(
+ sqlite3 *db,
+ void *pAux,
+ int argc, const char *const*argv,
+ sqlite3_vtab **ppVtab,
+ char **pzErr
+){
+ StatTable *pTab = 0;
+ int rc = SQLITE_OK;
+ int iDb;
+
+ if( argc>=4 ){
+ iDb = sqlite3FindDbName(db, argv[3]);
+ if( iDb<0 ){
+ *pzErr = sqlite3_mprintf("no such database: %s", argv[3]);
+ return SQLITE_ERROR;
+ }
+ }else{
+ iDb = 0;
+ }
+ rc = sqlite3_declare_vtab(db, VTAB_SCHEMA);
+ if( rc==SQLITE_OK ){
+ pTab = (StatTable *)sqlite3_malloc64(sizeof(StatTable));
+ if( pTab==0 ) rc = SQLITE_NOMEM;
+ }
+
+ assert( rc==SQLITE_OK || pTab==0 );
+ if( rc==SQLITE_OK ){
+ memset(pTab, 0, sizeof(StatTable));
+ pTab->db = db;
+ pTab->iDb = iDb;
+ }
+
+ *ppVtab = (sqlite3_vtab*)pTab;
+ return rc;
+}
+
+/*
+** Disconnect from or destroy a statvfs virtual table.
+*/
+static int statDisconnect(sqlite3_vtab *pVtab){
+ sqlite3_free(pVtab);
+ return SQLITE_OK;
+}
+
+/*
+** There is no "best-index". This virtual table always does a linear
+** scan of the binary VFS log file.
+*/
+static int statBestIndex(sqlite3_vtab *tab, sqlite3_index_info *pIdxInfo){
+
+ /* Records are always returned in ascending order of (name, path).
+ ** If this will satisfy the client, set the orderByConsumed flag so that
+ ** SQLite does not do an external sort.
+ */
+ if( ( pIdxInfo->nOrderBy==1
+ && pIdxInfo->aOrderBy[0].iColumn==0
+ && pIdxInfo->aOrderBy[0].desc==0
+ ) ||
+ ( pIdxInfo->nOrderBy==2
+ && pIdxInfo->aOrderBy[0].iColumn==0
+ && pIdxInfo->aOrderBy[0].desc==0
+ && pIdxInfo->aOrderBy[1].iColumn==1
+ && pIdxInfo->aOrderBy[1].desc==0
+ )
+ ){
+ pIdxInfo->orderByConsumed = 1;
+ }
+
+ pIdxInfo->estimatedCost = 10.0;
+ return SQLITE_OK;
+}
+
+/*
+** Open a new statvfs cursor.
+*/
+static int statOpen(sqlite3_vtab *pVTab, sqlite3_vtab_cursor **ppCursor){
+ StatTable *pTab = (StatTable *)pVTab;
+ StatCursor *pCsr;
+ int rc;
+
+ pCsr = (StatCursor *)sqlite3_malloc64(sizeof(StatCursor));
+ if( pCsr==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ char *zSql;
+ memset(pCsr, 0, sizeof(StatCursor));
+ pCsr->base.pVtab = pVTab;
+
+ zSql = sqlite3_mprintf(
+ "SELECT 'sqlite_master' AS name, 1 AS rootpage, 'table' AS type"
+ " UNION ALL "
+ "SELECT name, rootpage, type"
+ " FROM \"%w\".sqlite_master WHERE rootpage!=0"
+ " ORDER BY name", pTab->db->aDb[pTab->iDb].zName);
+ if( zSql==0 ){
+ rc = SQLITE_NOMEM;
+ }else{
+ rc = sqlite3_prepare_v2(pTab->db, zSql, -1, &pCsr->pStmt, 0);
+ sqlite3_free(zSql);
+ }
+ if( rc!=SQLITE_OK ){
+ sqlite3_free(pCsr);
+ pCsr = 0;
+ }
+ }
+
+ *ppCursor = (sqlite3_vtab_cursor *)pCsr;
+ return rc;
+}
+
+static void statClearPage(StatPage *p){
+ int i;
+ if( p->aCell ){
+ for(i=0; i<p->nCell; i++){
+ sqlite3_free(p->aCell[i].aOvfl);
+ }
+ sqlite3_free(p->aCell);
+ }
+ sqlite3PagerUnref(p->pPg);
+ sqlite3_free(p->zPath);
+ memset(p, 0, sizeof(StatPage));
+}
+
+static void statResetCsr(StatCursor *pCsr){
+ int i;
+ sqlite3_reset(pCsr->pStmt);
+ for(i=0; i<ArraySize(pCsr->aPage); i++){
+ statClearPage(&pCsr->aPage[i]);
+ }
+ pCsr->iPage = 0;
+ sqlite3_free(pCsr->zPath);
+ pCsr->zPath = 0;
+}
+
+/*
+** Close a statvfs cursor.
+*/
+static int statClose(sqlite3_vtab_cursor *pCursor){
+ StatCursor *pCsr = (StatCursor *)pCursor;
+ statResetCsr(pCsr);
+ sqlite3_finalize(pCsr->pStmt);
+ sqlite3_free(pCsr);
+ return SQLITE_OK;
+}
+
+static void getLocalPayload(
+ int nUsable, /* Usable bytes per page */
+ u8 flags, /* Page flags */
+ int nTotal, /* Total record (payload) size */
+ int *pnLocal /* OUT: Bytes stored locally */
+){
+ int nLocal;
+ int nMinLocal;
+ int nMaxLocal;
+
+ if( flags==0x0D ){ /* Table leaf node */
+ nMinLocal = (nUsable - 12) * 32 / 255 - 23;
+ nMaxLocal = nUsable - 35;
+ }else{ /* Index interior and leaf nodes */
+ nMinLocal = (nUsable - 12) * 32 / 255 - 23;
+ nMaxLocal = (nUsable - 12) * 64 / 255 - 23;
+ }
+
+ nLocal = nMinLocal + (nTotal - nMinLocal) % (nUsable - 4);
+ if( nLocal>nMaxLocal ) nLocal = nMinLocal;
+ *pnLocal = nLocal;
+}
+
+static int statDecodePage(Btree *pBt, StatPage *p){
+ int nUnused;
+ int iOff;
+ int nHdr;
+ int isLeaf;
+ int szPage;
+
+ u8 *aData = sqlite3PagerGetData(p->pPg);
+ u8 *aHdr = &aData[p->iPgno==1 ? 100 : 0];
+
+ p->flags = aHdr[0];
+ p->nCell = get2byte(&aHdr[3]);
+ p->nMxPayload = 0;
+
+ isLeaf = (p->flags==0x0A || p->flags==0x0D);
+ nHdr = 12 - isLeaf*4 + (p->iPgno==1)*100;
+
+ nUnused = get2byte(&aHdr[5]) - nHdr - 2*p->nCell;
+ nUnused += (int)aHdr[7];
+ iOff = get2byte(&aHdr[1]);
+ while( iOff ){
+ nUnused += get2byte(&aData[iOff+2]);
+ iOff = get2byte(&aData[iOff]);
+ }
+ p->nUnused = nUnused;
+ p->iRightChildPg = isLeaf ? 0 : sqlite3Get4byte(&aHdr[8]);
+ szPage = sqlite3BtreeGetPageSize(pBt);
+
+ if( p->nCell ){
+ int i; /* Used to iterate through cells */
+ int nUsable; /* Usable bytes per page */
+
+ sqlite3BtreeEnter(pBt);
+ nUsable = szPage - sqlite3BtreeGetReserveNoMutex(pBt);
+ sqlite3BtreeLeave(pBt);
+ p->aCell = sqlite3_malloc64((p->nCell+1) * sizeof(StatCell));
+ if( p->aCell==0 ) return SQLITE_NOMEM;
+ memset(p->aCell, 0, (p->nCell+1) * sizeof(StatCell));
+
+ for(i=0; i<p->nCell; i++){
+ StatCell *pCell = &p->aCell[i];
+
+ iOff = get2byte(&aData[nHdr+i*2]);
+ if( !isLeaf ){
+ pCell->iChildPg = sqlite3Get4byte(&aData[iOff]);
+ iOff += 4;
+ }
+ if( p->flags==0x05 ){
+ /* A table interior node. nPayload==0. */
+ }else{
+ u32 nPayload; /* Bytes of payload total (local+overflow) */
+ int nLocal; /* Bytes of payload stored locally */
+ iOff += getVarint32(&aData[iOff], nPayload);
+ if( p->flags==0x0D ){
+ u64 dummy;
+ iOff += sqlite3GetVarint(&aData[iOff], &dummy);
+ }
+ if( nPayload>(u32)p->nMxPayload ) p->nMxPayload = nPayload;
+ getLocalPayload(nUsable, p->flags, nPayload, &nLocal);
+ pCell->nLocal = nLocal;
+ assert( nLocal>=0 );
+ assert( nPayload>=(u32)nLocal );
+ assert( nLocal<=(nUsable-35) );
+ if( nPayload>(u32)nLocal ){
+ int j;
+ int nOvfl = ((nPayload - nLocal) + nUsable-4 - 1) / (nUsable - 4);
+ pCell->nLastOvfl = (nPayload-nLocal) - (nOvfl-1) * (nUsable-4);
+ pCell->nOvfl = nOvfl;
+ pCell->aOvfl = sqlite3_malloc64(sizeof(u32)*nOvfl);
+ if( pCell->aOvfl==0 ) return SQLITE_NOMEM;
+ pCell->aOvfl[0] = sqlite3Get4byte(&aData[iOff+nLocal]);
+ for(j=1; j<nOvfl; j++){
+ int rc;
+ u32 iPrev = pCell->aOvfl[j-1];
+ DbPage *pPg = 0;
+ rc = sqlite3PagerGet(sqlite3BtreePager(pBt), iPrev, &pPg);
+ if( rc!=SQLITE_OK ){
+ assert( pPg==0 );
+ return rc;
+ }
+ pCell->aOvfl[j] = sqlite3Get4byte(sqlite3PagerGetData(pPg));
+ sqlite3PagerUnref(pPg);
+ }
+ }
+ }
+ }
+ }
+
+ return SQLITE_OK;
+}
+
+/*
+** Populate the pCsr->iOffset and pCsr->szPage member variables. Based on
+** the current value of pCsr->iPageno.
+*/
+static void statSizeAndOffset(StatCursor *pCsr){
+ StatTable *pTab = (StatTable *)((sqlite3_vtab_cursor *)pCsr)->pVtab;
+ Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
+ Pager *pPager = sqlite3BtreePager(pBt);
+ sqlite3_file *fd;
+ sqlite3_int64 x[2];
+
+ /* The default page size and offset */
+ pCsr->szPage = sqlite3BtreeGetPageSize(pBt);
+ pCsr->iOffset = (i64)pCsr->szPage * (pCsr->iPageno - 1);
+
+ /* If connected to a ZIPVFS backend, override the page size and
+ ** offset with actual values obtained from ZIPVFS.
+ */
+ fd = sqlite3PagerFile(pPager);
+ x[0] = pCsr->iPageno;
+ if( fd->pMethods!=0 && sqlite3OsFileControl(fd, 230440, &x)==SQLITE_OK ){
+ pCsr->iOffset = x[0];
+ pCsr->szPage = (int)x[1];
+ }
+}
+
+/*
+** Move a statvfs cursor to the next entry in the file.
+*/
+static int statNext(sqlite3_vtab_cursor *pCursor){
+ int rc;
+ int nPayload;
+ char *z;
+ StatCursor *pCsr = (StatCursor *)pCursor;
+ StatTable *pTab = (StatTable *)pCursor->pVtab;
+ Btree *pBt = pTab->db->aDb[pTab->iDb].pBt;
+ Pager *pPager = sqlite3BtreePager(pBt);
+
+ sqlite3_free(pCsr->zPath);
+ pCsr->zPath = 0;
+
+statNextRestart:
+ if( pCsr->aPage[0].pPg==0 ){
+ rc = sqlite3_step(pCsr->pStmt);
+ if( rc==SQLITE_ROW ){
+ int nPage;
+ u32 iRoot = (u32)sqlite3_column_int64(pCsr->pStmt, 1);
+ sqlite3PagerPagecount(pPager, &nPage);
+ if( nPage==0 ){
+ pCsr->isEof = 1;
+ return sqlite3_reset(pCsr->pStmt);
+ }
+ rc = sqlite3PagerGet(pPager, iRoot, &pCsr->aPage[0].pPg);
+ pCsr->aPage[0].iPgno = iRoot;
+ pCsr->aPage[0].iCell = 0;
+ pCsr->aPage[0].zPath = z = sqlite3_mprintf("/");
+ pCsr->iPage = 0;
+ if( z==0 ) rc = SQLITE_NOMEM;
+ }else{
+ pCsr->isEof = 1;
+ return sqlite3_reset(pCsr->pStmt);
+ }
+ }else{
+
+ /* Page p itself has already been visited. */
+ StatPage *p = &pCsr->aPage[pCsr->iPage];
+
+ while( p->iCell<p->nCell ){
+ StatCell *pCell = &p->aCell[p->iCell];
+ if( pCell->iOvfl<pCell->nOvfl ){
+ int nUsable;
+ sqlite3BtreeEnter(pBt);
+ nUsable = sqlite3BtreeGetPageSize(pBt) -
+ sqlite3BtreeGetReserveNoMutex(pBt);
+ sqlite3BtreeLeave(pBt);
+ pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
+ pCsr->iPageno = pCell->aOvfl[pCell->iOvfl];
+ pCsr->zPagetype = "overflow";
+ pCsr->nCell = 0;
+ pCsr->nMxPayload = 0;
+ pCsr->zPath = z = sqlite3_mprintf(
+ "%s%.3x+%.6x", p->zPath, p->iCell, pCell->iOvfl
+ );
+ if( pCell->iOvfl<pCell->nOvfl-1 ){
+ pCsr->nUnused = 0;
+ pCsr->nPayload = nUsable - 4;
+ }else{
+ pCsr->nPayload = pCell->nLastOvfl;
+ pCsr->nUnused = nUsable - 4 - pCsr->nPayload;
+ }
+ pCell->iOvfl++;
+ statSizeAndOffset(pCsr);
+ return z==0 ? SQLITE_NOMEM : SQLITE_OK;
+ }
+ if( p->iRightChildPg ) break;
+ p->iCell++;
+ }
+
+ if( !p->iRightChildPg || p->iCell>p->nCell ){
+ statClearPage(p);
+ if( pCsr->iPage==0 ) return statNext(pCursor);
+ pCsr->iPage--;
+ goto statNextRestart; /* Tail recursion */
+ }
+ pCsr->iPage++;
+ assert( p==&pCsr->aPage[pCsr->iPage-1] );
+
+ if( p->iCell==p->nCell ){
+ p[1].iPgno = p->iRightChildPg;
+ }else{
+ p[1].iPgno = p->aCell[p->iCell].iChildPg;
+ }
+ rc = sqlite3PagerGet(pPager, p[1].iPgno, &p[1].pPg);
+ p[1].iCell = 0;
+ p[1].zPath = z = sqlite3_mprintf("%s%.3x/", p->zPath, p->iCell);
+ p->iCell++;
+ if( z==0 ) rc = SQLITE_NOMEM;
+ }
+
+
+ /* Populate the StatCursor fields with the values to be returned
+ ** by the xColumn() and xRowid() methods.
+ */
+ if( rc==SQLITE_OK ){
+ int i;
+ StatPage *p = &pCsr->aPage[pCsr->iPage];
+ pCsr->zName = (char *)sqlite3_column_text(pCsr->pStmt, 0);
+ pCsr->iPageno = p->iPgno;
+
+ rc = statDecodePage(pBt, p);
+ if( rc==SQLITE_OK ){
+ statSizeAndOffset(pCsr);
+
+ switch( p->flags ){
+ case 0x05: /* table internal */
+ case 0x02: /* index internal */
+ pCsr->zPagetype = "internal";
+ break;
+ case 0x0D: /* table leaf */
+ case 0x0A: /* index leaf */
+ pCsr->zPagetype = "leaf";
+ break;
+ default:
+ pCsr->zPagetype = "corrupted";
+ break;
+ }
+ pCsr->nCell = p->nCell;
+ pCsr->nUnused = p->nUnused;
+ pCsr->nMxPayload = p->nMxPayload;
+ pCsr->zPath = z = sqlite3_mprintf("%s", p->zPath);
+ if( z==0 ) rc = SQLITE_NOMEM;
+ nPayload = 0;
+ for(i=0; i<p->nCell; i++){
+ nPayload += p->aCell[i].nLocal;
+ }
+ pCsr->nPayload = nPayload;
+ }
+ }
+
+ return rc;
+}
+
+static int statEof(sqlite3_vtab_cursor *pCursor){
+ StatCursor *pCsr = (StatCursor *)pCursor;
+ return pCsr->isEof;
+}
+
+static int statFilter(
+ sqlite3_vtab_cursor *pCursor,
+ int idxNum, const char *idxStr,
+ int argc, sqlite3_value **argv
+){
+ StatCursor *pCsr = (StatCursor *)pCursor;
+
+ statResetCsr(pCsr);
+ return statNext(pCursor);
+}
+
+static int statColumn(
+ sqlite3_vtab_cursor *pCursor,
+ sqlite3_context *ctx,
+ int i
+){
+ StatCursor *pCsr = (StatCursor *)pCursor;
+ switch( i ){
+ case 0: /* name */
+ sqlite3_result_text(ctx, pCsr->zName, -1, SQLITE_TRANSIENT);
+ break;
+ case 1: /* path */
+ sqlite3_result_text(ctx, pCsr->zPath, -1, SQLITE_TRANSIENT);
+ break;
+ case 2: /* pageno */
+ sqlite3_result_int64(ctx, pCsr->iPageno);
+ break;
+ case 3: /* pagetype */
+ sqlite3_result_text(ctx, pCsr->zPagetype, -1, SQLITE_STATIC);
+ break;
+ case 4: /* ncell */
+ sqlite3_result_int(ctx, pCsr->nCell);
+ break;
+ case 5: /* payload */
+ sqlite3_result_int(ctx, pCsr->nPayload);
+ break;
+ case 6: /* unused */
+ sqlite3_result_int(ctx, pCsr->nUnused);
+ break;
+ case 7: /* mx_payload */
+ sqlite3_result_int(ctx, pCsr->nMxPayload);
+ break;
+ case 8: /* pgoffset */
+ sqlite3_result_int64(ctx, pCsr->iOffset);
+ break;
+ default: /* pgsize */
+ assert( i==9 );
+ sqlite3_result_int(ctx, pCsr->szPage);
+ break;
+ }
+ return SQLITE_OK;
+}
+
+static int statRowid(sqlite3_vtab_cursor *pCursor, sqlite_int64 *pRowid){
+ StatCursor *pCsr = (StatCursor *)pCursor;
+ *pRowid = pCsr->iPageno;
+ return SQLITE_OK;
+}
+
+/*
+** Invoke this routine to register the "dbstat" virtual table module
+*/
+SQLITE_API int SQLITE_STDCALL sqlite3_dbstat_register(sqlite3 *db){
+ static sqlite3_module dbstat_module = {
+ 0, /* iVersion */
+ statConnect, /* xCreate */
+ statConnect, /* xConnect */
+ statBestIndex, /* xBestIndex */
+ statDisconnect, /* xDisconnect */
+ statDisconnect, /* xDestroy */
+ statOpen, /* xOpen - open a cursor */
+ statClose, /* xClose - close a cursor */
+ statFilter, /* xFilter - configure scan constraints */
+ statNext, /* xNext - advance a cursor */
+ statEof, /* xEof - check for end of scan */
+ statColumn, /* xColumn - read data */
+ statRowid, /* xRowid - read data */
+ 0, /* xUpdate */
+ 0, /* xBegin */
+ 0, /* xSync */
+ 0, /* xCommit */
+ 0, /* xRollback */
+ 0, /* xFindMethod */
+ 0, /* xRename */
+ };
+ return sqlite3_create_module(db, "dbstat", &dbstat_module, 0);
+}
+#endif /* SQLITE_ENABLE_DBSTAT_VTAB */
+
+/************** End of dbstat.c **********************************************/
diff --git a/ext/sqlite3/libsqlite/sqlite3.h b/ext/sqlite3/libsqlite/sqlite3.h
index e13073a3c6..d43b63c107 100644
--- a/ext/sqlite3/libsqlite/sqlite3.h
+++ b/ext/sqlite3/libsqlite/sqlite3.h
@@ -43,16 +43,20 @@ extern "C" {
/*
-** Add the ability to override 'extern'
+** Provide the ability to override linkage features of the interface.
*/
#ifndef SQLITE_EXTERN
# define SQLITE_EXTERN extern
#endif
-
#ifndef SQLITE_API
# define SQLITE_API
#endif
-
+#ifndef SQLITE_CDECL
+# define SQLITE_CDECL
+#endif
+#ifndef SQLITE_STDCALL
+# define SQLITE_STDCALL
+#endif
/*
** These no-op macros are used in front of interfaces to mark those
@@ -107,9 +111,9 @@ extern "C" {
** [sqlite3_libversion_number()], [sqlite3_sourceid()],
** [sqlite_version()] and [sqlite_source_id()].
*/
-#define SQLITE_VERSION "3.8.8.3"
-#define SQLITE_VERSION_NUMBER 3008008
-#define SQLITE_SOURCE_ID "2015-02-25 13:29:11 9d6c1880fb75660bbabd693175579529785f8a6b"
+#define SQLITE_VERSION "3.8.10.2"
+#define SQLITE_VERSION_NUMBER 3008010
+#define SQLITE_SOURCE_ID "2015-05-20 18:17:19 2ef4f3a5b1d1d0c4338f8243d40a2452cc1f7fe4"
/*
** CAPI3REF: Run-Time Library Version Numbers
@@ -142,9 +146,9 @@ extern "C" {
** See also: [sqlite_version()] and [sqlite_source_id()].
*/
SQLITE_API SQLITE_EXTERN const char sqlite3_version[];
-SQLITE_API const char *sqlite3_libversion(void);
-SQLITE_API const char *sqlite3_sourceid(void);
-SQLITE_API int sqlite3_libversion_number(void);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_libversion(void);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_sourceid(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_libversion_number(void);
/*
** CAPI3REF: Run-Time Library Compilation Options Diagnostics
@@ -169,8 +173,8 @@ SQLITE_API int sqlite3_libversion_number(void);
** [sqlite_compileoption_get()] and the [compile_options pragma].
*/
#ifndef SQLITE_OMIT_COMPILEOPTION_DIAGS
-SQLITE_API int sqlite3_compileoption_used(const char *zOptName);
-SQLITE_API const char *sqlite3_compileoption_get(int N);
+SQLITE_API int SQLITE_STDCALL sqlite3_compileoption_used(const char *zOptName);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_compileoption_get(int N);
#endif
/*
@@ -209,7 +213,7 @@ SQLITE_API const char *sqlite3_compileoption_get(int N);
**
** See the [threading mode] documentation for additional information.
*/
-SQLITE_API int sqlite3_threadsafe(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_threadsafe(void);
/*
** CAPI3REF: Database Connection Handle
@@ -266,6 +270,7 @@ typedef sqlite_uint64 sqlite3_uint64;
/*
** CAPI3REF: Closing A Database Connection
+** DESTRUCTOR: sqlite3
**
** ^The sqlite3_close() and sqlite3_close_v2() routines are destructors
** for the [sqlite3] object.
@@ -305,8 +310,8 @@ typedef sqlite_uint64 sqlite3_uint64;
** ^Calling sqlite3_close() or sqlite3_close_v2() with a NULL pointer
** argument is a harmless no-op.
*/
-SQLITE_API int sqlite3_close(sqlite3*);
-SQLITE_API int sqlite3_close_v2(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_close(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_close_v2(sqlite3*);
/*
** The type for a callback function.
@@ -317,6 +322,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
/*
** CAPI3REF: One-Step Query Execution Interface
+** METHOD: sqlite3
**
** The sqlite3_exec() interface is a convenience wrapper around
** [sqlite3_prepare_v2()], [sqlite3_step()], and [sqlite3_finalize()],
@@ -376,7 +382,7 @@ typedef int (*sqlite3_callback)(void*,int,char**, char**);
** the 2nd parameter of sqlite3_exec() while sqlite3_exec() is running.
** </ul>
*/
-SQLITE_API int sqlite3_exec(
+SQLITE_API int SQLITE_STDCALL sqlite3_exec(
sqlite3*, /* An open database */
const char *sql, /* SQL to be evaluated */
int (*callback)(void*,int,char**,char**), /* Callback function */
@@ -756,14 +762,16 @@ struct sqlite3_io_methods {
** of the [sqlite3_io_methods] object and for the [sqlite3_file_control()]
** interface.
**
+** <ul>
+** <li>[[SQLITE_FCNTL_LOCKSTATE]]
** The [SQLITE_FCNTL_LOCKSTATE] opcode is used for debugging. This
** opcode causes the xFileControl method to write the current state of
** the lock (one of [SQLITE_LOCK_NONE], [SQLITE_LOCK_SHARED],
** [SQLITE_LOCK_RESERVED], [SQLITE_LOCK_PENDING], or [SQLITE_LOCK_EXCLUSIVE])
** into an integer that the pArg argument points to. This capability
-** is used during testing and only needs to be supported when SQLITE_TEST
-** is defined.
-** <ul>
+** is used during testing and is only available when the SQLITE_TEST
+** compile-time option is used.
+**
** <li>[[SQLITE_FCNTL_SIZE_HINT]]
** The [SQLITE_FCNTL_SIZE_HINT] opcode is used by SQLite to give the VFS
** layer a hint of how large the database file will grow to be during the
@@ -888,7 +896,9 @@ struct sqlite3_io_methods {
** [PRAGMA] processing continues. ^If the [SQLITE_FCNTL_PRAGMA]
** file control returns [SQLITE_OK], then the parser assumes that the
** VFS has handled the PRAGMA itself and the parser generates a no-op
-** prepared statement. ^If the [SQLITE_FCNTL_PRAGMA] file control returns
+** prepared statement if result string is NULL, or that returns a copy
+** of the result string if the string is non-NULL.
+** ^If the [SQLITE_FCNTL_PRAGMA] file control returns
** any result code other than [SQLITE_OK] or [SQLITE_NOTFOUND], that means
** that the VFS encountered an error while handling the [PRAGMA] and the
** compilation of the PRAGMA fails with an error. ^The [SQLITE_FCNTL_PRAGMA]
@@ -946,12 +956,19 @@ struct sqlite3_io_methods {
** pointed to by the pArg argument. This capability is used during testing
** and only needs to be supported when SQLITE_TEST is defined.
**
+** <li>[[SQLITE_FCNTL_WAL_BLOCK]]
+** The [SQLITE_FCNTL_WAL_BLOCK] is a signal to the VFS layer that it might
+** be advantageous to block on the next WAL lock if the lock is not immediately
+** available. The WAL subsystem issues this signal during rare
+** circumstances in order to fix a problem with priority inversion.
+** Applications should <em>not</em> use this file-control.
+**
** </ul>
*/
#define SQLITE_FCNTL_LOCKSTATE 1
-#define SQLITE_GET_LOCKPROXYFILE 2
-#define SQLITE_SET_LOCKPROXYFILE 3
-#define SQLITE_LAST_ERRNO 4
+#define SQLITE_FCNTL_GET_LOCKPROXYFILE 2
+#define SQLITE_FCNTL_SET_LOCKPROXYFILE 3
+#define SQLITE_FCNTL_LAST_ERRNO 4
#define SQLITE_FCNTL_SIZE_HINT 5
#define SQLITE_FCNTL_CHUNK_SIZE 6
#define SQLITE_FCNTL_FILE_POINTER 7
@@ -970,6 +987,13 @@ struct sqlite3_io_methods {
#define SQLITE_FCNTL_SYNC 21
#define SQLITE_FCNTL_COMMIT_PHASETWO 22
#define SQLITE_FCNTL_WIN32_SET_HANDLE 23
+#define SQLITE_FCNTL_WAL_BLOCK 24
+
+/* deprecated names */
+#define SQLITE_GET_LOCKPROXYFILE SQLITE_FCNTL_GET_LOCKPROXYFILE
+#define SQLITE_SET_LOCKPROXYFILE SQLITE_FCNTL_SET_LOCKPROXYFILE
+#define SQLITE_LAST_ERRNO SQLITE_FCNTL_LAST_ERRNO
+
/*
** CAPI3REF: Mutex Handle
@@ -1318,10 +1342,10 @@ struct sqlite3_vfs {
** must return [SQLITE_OK] on success and some other [error code] upon
** failure.
*/
-SQLITE_API int sqlite3_initialize(void);
-SQLITE_API int sqlite3_shutdown(void);
-SQLITE_API int sqlite3_os_init(void);
-SQLITE_API int sqlite3_os_end(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_initialize(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_shutdown(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_os_init(void);
+SQLITE_API int SQLITE_STDCALL sqlite3_os_end(void);
/*
** CAPI3REF: Configuring The SQLite Library
@@ -1352,10 +1376,11 @@ SQLITE_API int sqlite3_os_end(void);
** ^If the option is unknown or SQLite is unable to set the option
** then this routine returns a non-zero [error code].
*/
-SQLITE_API int sqlite3_config(int, ...);
+SQLITE_API int SQLITE_CDECL sqlite3_config(int, ...);
/*
** CAPI3REF: Configure database connections
+** METHOD: sqlite3
**
** The sqlite3_db_config() interface is used to make configuration
** changes to a [database connection]. The interface is similar to
@@ -1370,7 +1395,7 @@ SQLITE_API int sqlite3_config(int, ...);
** ^Calls to sqlite3_db_config() return SQLITE_OK if and only if
** the call is considered successful.
*/
-SQLITE_API int sqlite3_db_config(sqlite3*, int op, ...);
+SQLITE_API int SQLITE_CDECL sqlite3_db_config(sqlite3*, int op, ...);
/*
** CAPI3REF: Memory Allocation Routines
@@ -1530,7 +1555,7 @@ struct sqlite3_mem_methods {
** <li> [sqlite3_memory_used()]
** <li> [sqlite3_memory_highwater()]
** <li> [sqlite3_soft_heap_limit64()]
-** <li> [sqlite3_status()]
+** <li> [sqlite3_status64()]
** </ul>)^
** ^Memory allocation statistics are enabled by default unless SQLite is
** compiled with [SQLITE_DEFAULT_MEMSTATUS]=0 in which case memory
@@ -1741,7 +1766,6 @@ struct sqlite3_mem_methods {
** compiled for Windows with the [SQLITE_WIN32_MALLOC] pre-processor macro
** defined. ^SQLITE_CONFIG_WIN32_HEAPSIZE takes a 32-bit unsigned integer value
** that specifies the maximum size of the created heap.
-** </dl>
**
** [[SQLITE_CONFIG_PCACHE_HDRSZ]]
** <dt>SQLITE_CONFIG_PCACHE_HDRSZ
@@ -1854,15 +1878,17 @@ struct sqlite3_mem_methods {
/*
** CAPI3REF: Enable Or Disable Extended Result Codes
+** METHOD: sqlite3
**
** ^The sqlite3_extended_result_codes() routine enables or disables the
** [extended result codes] feature of SQLite. ^The extended result
** codes are disabled by default for historical compatibility.
*/
-SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
+SQLITE_API int SQLITE_STDCALL sqlite3_extended_result_codes(sqlite3*, int onoff);
/*
** CAPI3REF: Last Insert Rowid
+** METHOD: sqlite3
**
** ^Each entry in most SQLite tables (except for [WITHOUT ROWID] tables)
** has a unique 64-bit signed
@@ -1910,10 +1936,11 @@ SQLITE_API int sqlite3_extended_result_codes(sqlite3*, int onoff);
** unpredictable and might not equal either the old or the new
** last insert [rowid].
*/
-SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_last_insert_rowid(sqlite3*);
/*
** CAPI3REF: Count The Number Of Rows Modified
+** METHOD: sqlite3
**
** ^This function returns the number of rows modified, inserted or
** deleted by the most recently completed INSERT, UPDATE or DELETE
@@ -1962,10 +1989,11 @@ SQLITE_API sqlite3_int64 sqlite3_last_insert_rowid(sqlite3*);
** while [sqlite3_changes()] is running then the value returned
** is unpredictable and not meaningful.
*/
-SQLITE_API int sqlite3_changes(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_changes(sqlite3*);
/*
** CAPI3REF: Total Number Of Rows Modified
+** METHOD: sqlite3
**
** ^This function returns the total number of rows inserted, modified or
** deleted by all [INSERT], [UPDATE] or [DELETE] statements completed
@@ -1985,10 +2013,11 @@ SQLITE_API int sqlite3_changes(sqlite3*);
** while [sqlite3_total_changes()] is running then the value
** returned is unpredictable and not meaningful.
*/
-SQLITE_API int sqlite3_total_changes(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_total_changes(sqlite3*);
/*
** CAPI3REF: Interrupt A Long-Running Query
+** METHOD: sqlite3
**
** ^This function causes any pending database operation to abort and
** return at its earliest opportunity. This routine is typically
@@ -2024,7 +2053,7 @@ SQLITE_API int sqlite3_total_changes(sqlite3*);
** If the database connection closes while [sqlite3_interrupt()]
** is running then bad things will likely happen.
*/
-SQLITE_API void sqlite3_interrupt(sqlite3*);
+SQLITE_API void SQLITE_STDCALL sqlite3_interrupt(sqlite3*);
/*
** CAPI3REF: Determine If An SQL Statement Is Complete
@@ -2059,12 +2088,13 @@ SQLITE_API void sqlite3_interrupt(sqlite3*);
** The input to [sqlite3_complete16()] must be a zero-terminated
** UTF-16 string in native byte order.
*/
-SQLITE_API int sqlite3_complete(const char *sql);
-SQLITE_API int sqlite3_complete16(const void *sql);
+SQLITE_API int SQLITE_STDCALL sqlite3_complete(const char *sql);
+SQLITE_API int SQLITE_STDCALL sqlite3_complete16(const void *sql);
/*
** CAPI3REF: Register A Callback To Handle SQLITE_BUSY Errors
** KEYWORDS: {busy-handler callback} {busy handler}
+** METHOD: sqlite3
**
** ^The sqlite3_busy_handler(D,X,P) routine sets a callback function X
** that might be invoked with argument P whenever
@@ -2120,10 +2150,11 @@ SQLITE_API int sqlite3_complete16(const void *sql);
** A busy handler must not close the database connection
** or [prepared statement] that invoked the busy handler.
*/
-SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
+SQLITE_API int SQLITE_STDCALL sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
/*
** CAPI3REF: Set A Busy Timeout
+** METHOD: sqlite3
**
** ^This routine sets a [sqlite3_busy_handler | busy handler] that sleeps
** for a specified amount of time when a table is locked. ^The handler
@@ -2142,10 +2173,11 @@ SQLITE_API int sqlite3_busy_handler(sqlite3*, int(*)(void*,int), void*);
**
** See also: [PRAGMA busy_timeout]
*/
-SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
+SQLITE_API int SQLITE_STDCALL sqlite3_busy_timeout(sqlite3*, int ms);
/*
** CAPI3REF: Convenience Routines For Running Queries
+** METHOD: sqlite3
**
** This is a legacy interface that is preserved for backwards compatibility.
** Use of this interface is not recommended.
@@ -2216,7 +2248,7 @@ SQLITE_API int sqlite3_busy_timeout(sqlite3*, int ms);
** reflected in subsequent calls to [sqlite3_errcode()] or
** [sqlite3_errmsg()].
*/
-SQLITE_API int sqlite3_get_table(
+SQLITE_API int SQLITE_STDCALL sqlite3_get_table(
sqlite3 *db, /* An open database */
const char *zSql, /* SQL to be evaluated */
char ***pazResult, /* Results of the query */
@@ -2224,13 +2256,17 @@ SQLITE_API int sqlite3_get_table(
int *pnColumn, /* Number of result columns written here */
char **pzErrmsg /* Error msg written here */
);
-SQLITE_API void sqlite3_free_table(char **result);
+SQLITE_API void SQLITE_STDCALL sqlite3_free_table(char **result);
/*
** CAPI3REF: Formatted String Printing Functions
**
** These routines are work-alikes of the "printf()" family of functions
** from the standard C library.
+** These routines understand most of the common K&R formatting options,
+** plus some additional non-standard formats, detailed below.
+** Note that some of the more obscure formatting options from recent
+** C-library standards are omitted from this implementation.
**
** ^The sqlite3_mprintf() and sqlite3_vmprintf() routines write their
** results into memory obtained from [sqlite3_malloc()].
@@ -2263,7 +2299,7 @@ SQLITE_API void sqlite3_free_table(char **result);
** These routines all implement some additional formatting
** options that are useful for constructing SQL statements.
** All of the usual printf() formatting options apply. In addition, there
-** is are "%q", "%Q", and "%z" options.
+** is are "%q", "%Q", "%w" and "%z" options.
**
** ^(The %q option works like %s in that it substitutes a nul-terminated
** string from the argument list. But %q also doubles every '\'' character.
@@ -2316,14 +2352,20 @@ SQLITE_API void sqlite3_free_table(char **result);
** The code above will render a correct SQL statement in the zSQL
** variable even if the zText variable is a NULL pointer.
**
+** ^(The "%w" formatting option is like "%q" except that it expects to
+** be contained within double-quotes instead of single quotes, and it
+** escapes the double-quote character instead of the single-quote
+** character.)^ The "%w" formatting option is intended for safely inserting
+** table and column names into a constructed SQL statement.
+**
** ^(The "%z" formatting option works like "%s" but with the
** addition that after the string has been read and copied into
** the result, [sqlite3_free()] is called on the input string.)^
*/
-SQLITE_API char *sqlite3_mprintf(const char*,...);
-SQLITE_API char *sqlite3_vmprintf(const char*, va_list);
-SQLITE_API char *sqlite3_snprintf(int,char*,const char*, ...);
-SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
+SQLITE_API char *SQLITE_CDECL sqlite3_mprintf(const char*,...);
+SQLITE_API char *SQLITE_STDCALL sqlite3_vmprintf(const char*, va_list);
+SQLITE_API char *SQLITE_CDECL sqlite3_snprintf(int,char*,const char*, ...);
+SQLITE_API char *SQLITE_STDCALL sqlite3_vsnprintf(int,char*,const char*, va_list);
/*
** CAPI3REF: Memory Allocation Subsystem
@@ -2413,12 +2455,12 @@ SQLITE_API char *sqlite3_vsnprintf(int,char*,const char*, va_list);
** a block of memory after it has been released using
** [sqlite3_free()] or [sqlite3_realloc()].
*/
-SQLITE_API void *sqlite3_malloc(int);
-SQLITE_API void *sqlite3_malloc64(sqlite3_uint64);
-SQLITE_API void *sqlite3_realloc(void*, int);
-SQLITE_API void *sqlite3_realloc64(void*, sqlite3_uint64);
-SQLITE_API void sqlite3_free(void*);
-SQLITE_API sqlite3_uint64 sqlite3_msize(void*);
+SQLITE_API void *SQLITE_STDCALL sqlite3_malloc(int);
+SQLITE_API void *SQLITE_STDCALL sqlite3_malloc64(sqlite3_uint64);
+SQLITE_API void *SQLITE_STDCALL sqlite3_realloc(void*, int);
+SQLITE_API void *SQLITE_STDCALL sqlite3_realloc64(void*, sqlite3_uint64);
+SQLITE_API void SQLITE_STDCALL sqlite3_free(void*);
+SQLITE_API sqlite3_uint64 SQLITE_STDCALL sqlite3_msize(void*);
/*
** CAPI3REF: Memory Allocator Statistics
@@ -2443,8 +2485,8 @@ SQLITE_API sqlite3_uint64 sqlite3_msize(void*);
** by [sqlite3_memory_highwater(1)] is the high-water mark
** prior to the reset.
*/
-SQLITE_API sqlite3_int64 sqlite3_memory_used(void);
-SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_used(void);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_memory_highwater(int resetFlag);
/*
** CAPI3REF: Pseudo-Random Number Generator
@@ -2467,10 +2509,11 @@ SQLITE_API sqlite3_int64 sqlite3_memory_highwater(int resetFlag);
** internally and without recourse to the [sqlite3_vfs] xRandomness
** method.
*/
-SQLITE_API void sqlite3_randomness(int N, void *P);
+SQLITE_API void SQLITE_STDCALL sqlite3_randomness(int N, void *P);
/*
** CAPI3REF: Compile-Time Authorization Callbacks
+** METHOD: sqlite3
**
** ^This routine registers an authorizer callback with a particular
** [database connection], supplied in the first argument.
@@ -2549,7 +2592,7 @@ SQLITE_API void sqlite3_randomness(int N, void *P);
** as stated in the previous paragraph, sqlite3_step() invokes
** sqlite3_prepare_v2() to reprepare a statement after a schema change.
*/
-SQLITE_API int sqlite3_set_authorizer(
+SQLITE_API int SQLITE_STDCALL sqlite3_set_authorizer(
sqlite3*,
int (*xAuth)(void*,int,const char*,const char*,const char*,const char*),
void *pUserData
@@ -2627,6 +2670,7 @@ SQLITE_API int sqlite3_set_authorizer(
/*
** CAPI3REF: Tracing And Profiling Functions
+** METHOD: sqlite3
**
** These routines register callback functions that can be used for
** tracing and profiling the execution of SQL statements.
@@ -2653,12 +2697,13 @@ SQLITE_API int sqlite3_set_authorizer(
** sqlite3_profile() function is considered experimental and is
** subject to change in future versions of SQLite.
*/
-SQLITE_API void *sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
-SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
+SQLITE_API void *SQLITE_STDCALL sqlite3_trace(sqlite3*, void(*xTrace)(void*,const char*), void*);
+SQLITE_API SQLITE_EXPERIMENTAL void *SQLITE_STDCALL sqlite3_profile(sqlite3*,
void(*xProfile)(void*,const char*,sqlite3_uint64), void*);
/*
** CAPI3REF: Query Progress Callbacks
+** METHOD: sqlite3
**
** ^The sqlite3_progress_handler(D,N,X,P) interface causes the callback
** function X to be invoked periodically during long running calls to
@@ -2688,10 +2733,11 @@ SQLITE_API SQLITE_EXPERIMENTAL void *sqlite3_profile(sqlite3*,
** database connections for the meaning of "modify" in this paragraph.
**
*/
-SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
+SQLITE_API void SQLITE_STDCALL sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
/*
** CAPI3REF: Opening A New Database Connection
+** CONSTRUCTOR: sqlite3
**
** ^These routines open an SQLite database file as specified by the
** filename argument. ^The filename argument is interpreted as UTF-8 for
@@ -2916,15 +2962,15 @@ SQLITE_API void sqlite3_progress_handler(sqlite3*, int, int(*)(void*), void*);
**
** See also: [sqlite3_temp_directory]
*/
-SQLITE_API int sqlite3_open(
+SQLITE_API int SQLITE_STDCALL sqlite3_open(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
-SQLITE_API int sqlite3_open16(
+SQLITE_API int SQLITE_STDCALL sqlite3_open16(
const void *filename, /* Database filename (UTF-16) */
sqlite3 **ppDb /* OUT: SQLite db handle */
);
-SQLITE_API int sqlite3_open_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_open_v2(
const char *filename, /* Database filename (UTF-8) */
sqlite3 **ppDb, /* OUT: SQLite db handle */
int flags, /* Flags */
@@ -2970,19 +3016,22 @@ SQLITE_API int sqlite3_open_v2(
** VFS method, then the behavior of this routine is undefined and probably
** undesirable.
*/
-SQLITE_API const char *sqlite3_uri_parameter(const char *zFilename, const char *zParam);
-SQLITE_API int sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
-SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_uri_parameter(const char *zFilename, const char *zParam);
+SQLITE_API int SQLITE_STDCALL sqlite3_uri_boolean(const char *zFile, const char *zParam, int bDefault);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_uri_int64(const char*, const char*, sqlite3_int64);
/*
** CAPI3REF: Error Codes And Messages
-**
-** ^The sqlite3_errcode() interface returns the numeric [result code] or
-** [extended result code] for the most recent failed sqlite3_* API call
-** associated with a [database connection]. If a prior API call failed
-** but the most recent API call succeeded, the return value from
-** sqlite3_errcode() is undefined. ^The sqlite3_extended_errcode()
+** METHOD: sqlite3
+**
+** ^If the most recent sqlite3_* API call associated with
+** [database connection] D failed, then the sqlite3_errcode(D) interface
+** returns the numeric [result code] or [extended result code] for that
+** API call.
+** If the most recent API call was successful,
+** then the return value from sqlite3_errcode() is undefined.
+** ^The sqlite3_extended_errcode()
** interface is the same except that it always returns the
** [extended result code] even when extended result codes are
** disabled.
@@ -3013,40 +3062,41 @@ SQLITE_API sqlite3_int64 sqlite3_uri_int64(const char*, const char*, sqlite3_int
** was invoked incorrectly by the application. In that case, the
** error code and message may or may not be set.
*/
-SQLITE_API int sqlite3_errcode(sqlite3 *db);
-SQLITE_API int sqlite3_extended_errcode(sqlite3 *db);
-SQLITE_API const char *sqlite3_errmsg(sqlite3*);
-SQLITE_API const void *sqlite3_errmsg16(sqlite3*);
-SQLITE_API const char *sqlite3_errstr(int);
+SQLITE_API int SQLITE_STDCALL sqlite3_errcode(sqlite3 *db);
+SQLITE_API int SQLITE_STDCALL sqlite3_extended_errcode(sqlite3 *db);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_errmsg(sqlite3*);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_errmsg16(sqlite3*);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_errstr(int);
/*
-** CAPI3REF: SQL Statement Object
+** CAPI3REF: Prepared Statement Object
** KEYWORDS: {prepared statement} {prepared statements}
**
-** An instance of this object represents a single SQL statement.
-** This object is variously known as a "prepared statement" or a
-** "compiled SQL statement" or simply as a "statement".
+** An instance of this object represents a single SQL statement that
+** has been compiled into binary form and is ready to be evaluated.
**
-** The life of a statement object goes something like this:
+** Think of each SQL statement as a separate computer program. The
+** original SQL text is source code. A prepared statement object
+** is the compiled object code. All SQL must be converted into a
+** prepared statement before it can be run.
+**
+** The life-cycle of a prepared statement object usually goes like this:
**
** <ol>
-** <li> Create the object using [sqlite3_prepare_v2()] or a related
-** function.
-** <li> Bind values to [host parameters] using the sqlite3_bind_*()
+** <li> Create the prepared statement object using [sqlite3_prepare_v2()].
+** <li> Bind values to [parameters] using the sqlite3_bind_*()
** interfaces.
** <li> Run the SQL by calling [sqlite3_step()] one or more times.
-** <li> Reset the statement using [sqlite3_reset()] then go back
+** <li> Reset the prepared statement using [sqlite3_reset()] then go back
** to step 2. Do this zero or more times.
** <li> Destroy the object using [sqlite3_finalize()].
** </ol>
-**
-** Refer to documentation on individual methods above for additional
-** information.
*/
typedef struct sqlite3_stmt sqlite3_stmt;
/*
** CAPI3REF: Run-time Limits
+** METHOD: sqlite3
**
** ^(This interface allows the size of various constructs to be limited
** on a connection by connection basis. The first parameter is the
@@ -3084,7 +3134,7 @@ typedef struct sqlite3_stmt sqlite3_stmt;
**
** New run-time limit categories may be added in future releases.
*/
-SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
+SQLITE_API int SQLITE_STDCALL sqlite3_limit(sqlite3*, int id, int newVal);
/*
** CAPI3REF: Run-Time Limit Categories
@@ -3158,6 +3208,8 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
/*
** CAPI3REF: Compiling An SQL Statement
** KEYWORDS: {SQL statement compiler}
+** METHOD: sqlite3
+** CONSTRUCTOR: sqlite3_stmt
**
** To execute an SQL query, it must first be compiled into a byte-code
** program using one of these routines.
@@ -3171,16 +3223,14 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** interfaces use UTF-8, and sqlite3_prepare16() and sqlite3_prepare16_v2()
** use UTF-16.
**
-** ^If the nByte argument is less than zero, then zSql is read up to the
-** first zero terminator. ^If nByte is non-negative, then it is the maximum
-** number of bytes read from zSql. ^When nByte is non-negative, the
-** zSql string ends at either the first '\000' or '\u0000' character or
-** the nByte-th byte, whichever comes first. If the caller knows
-** that the supplied string is nul-terminated, then there is a small
-** performance advantage to be gained by passing an nByte parameter that
-** is equal to the number of bytes in the input string <i>including</i>
-** the nul-terminator bytes as this saves SQLite from having to
-** make a copy of the input string.
+** ^If the nByte argument is negative, then zSql is read up to the
+** first zero terminator. ^If nByte is positive, then it is the
+** number of bytes read from zSql. ^If nByte is zero, then no prepared
+** statement is generated.
+** If the caller knows that the supplied string is nul-terminated, then
+** there is a small performance advantage to passing an nByte parameter that
+** is the number of bytes in the input string <i>including</i>
+** the nul-terminator.
**
** ^If pzTail is not NULL then *pzTail is made to point to the first byte
** past the end of the first SQL statement in zSql. These routines only
@@ -3236,28 +3286,28 @@ SQLITE_API int sqlite3_limit(sqlite3*, int id, int newVal);
** </li>
** </ol>
*/
-SQLITE_API int sqlite3_prepare(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
-SQLITE_API int sqlite3_prepare_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare_v2(
sqlite3 *db, /* Database handle */
const char *zSql, /* SQL statement, UTF-8 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const char **pzTail /* OUT: Pointer to unused portion of zSql */
);
-SQLITE_API int sqlite3_prepare16(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare16(
sqlite3 *db, /* Database handle */
const void *zSql, /* SQL statement, UTF-16 encoded */
int nByte, /* Maximum length of zSql in bytes. */
sqlite3_stmt **ppStmt, /* OUT: Statement handle */
const void **pzTail /* OUT: Pointer to unused portion of zSql */
);
-SQLITE_API int sqlite3_prepare16_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_prepare16_v2(
sqlite3 *db, /* Database handle */
const void *zSql, /* SQL statement, UTF-16 encoded */
int nByte, /* Maximum length of zSql in bytes. */
@@ -3267,15 +3317,17 @@ SQLITE_API int sqlite3_prepare16_v2(
/*
** CAPI3REF: Retrieving Statement SQL
+** METHOD: sqlite3_stmt
**
** ^This interface can be used to retrieve a saved copy of the original
** SQL text used to create a [prepared statement] if that statement was
** compiled using either [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()].
*/
-SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_sql(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If An SQL Statement Writes The Database
+** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_readonly(X) interface returns true (non-zero) if
** and only if the [prepared statement] X makes no direct changes to
@@ -3303,10 +3355,11 @@ SQLITE_API const char *sqlite3_sql(sqlite3_stmt *pStmt);
** change the configuration of a database connection, they do not make
** changes to the content of the database files on disk.
*/
-SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
+SQLITE_API int SQLITE_STDCALL sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Determine If A Prepared Statement Has Been Reset
+** METHOD: sqlite3_stmt
**
** ^The sqlite3_stmt_busy(S) interface returns true (non-zero) if the
** [prepared statement] S has been stepped at least once using
@@ -3322,7 +3375,7 @@ SQLITE_API int sqlite3_stmt_readonly(sqlite3_stmt *pStmt);
** for example, in diagnostic routines to search for prepared
** statements that are holding a transaction open.
*/
-SQLITE_API int sqlite3_stmt_busy(sqlite3_stmt*);
+SQLITE_API int SQLITE_STDCALL sqlite3_stmt_busy(sqlite3_stmt*);
/*
** CAPI3REF: Dynamically Typed Value Object
@@ -3381,6 +3434,7 @@ typedef struct sqlite3_context sqlite3_context;
** CAPI3REF: Binding Values To Prepared Statements
** KEYWORDS: {host parameter} {host parameters} {host parameter name}
** KEYWORDS: {SQL parameter} {SQL parameters} {parameter binding}
+** METHOD: sqlite3_stmt
**
** ^(In the SQL statement text input to [sqlite3_prepare_v2()] and its variants,
** literals may be replaced by a [parameter] that matches one of following
@@ -3483,22 +3537,23 @@ typedef struct sqlite3_context sqlite3_context;
** See also: [sqlite3_bind_parameter_count()],
** [sqlite3_bind_parameter_name()], and [sqlite3_bind_parameter_index()].
*/
-SQLITE_API int sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
-SQLITE_API int sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob(sqlite3_stmt*, int, const void*, int n, void(*)(void*));
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_blob64(sqlite3_stmt*, int, const void*, sqlite3_uint64,
void(*)(void*));
-SQLITE_API int sqlite3_bind_double(sqlite3_stmt*, int, double);
-SQLITE_API int sqlite3_bind_int(sqlite3_stmt*, int, int);
-SQLITE_API int sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
-SQLITE_API int sqlite3_bind_null(sqlite3_stmt*, int);
-SQLITE_API int sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
-SQLITE_API int sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
-SQLITE_API int sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_double(sqlite3_stmt*, int, double);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_int(sqlite3_stmt*, int, int);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_int64(sqlite3_stmt*, int, sqlite3_int64);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_null(sqlite3_stmt*, int);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_text(sqlite3_stmt*,int,const char*,int,void(*)(void*));
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_text16(sqlite3_stmt*, int, const void*, int, void(*)(void*));
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_text64(sqlite3_stmt*, int, const char*, sqlite3_uint64,
void(*)(void*), unsigned char encoding);
-SQLITE_API int sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
-SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_value(sqlite3_stmt*, int, const sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
/*
** CAPI3REF: Number Of SQL Parameters
+** METHOD: sqlite3_stmt
**
** ^This routine can be used to find the number of [SQL parameters]
** in a [prepared statement]. SQL parameters are tokens of the
@@ -3515,10 +3570,11 @@ SQLITE_API int sqlite3_bind_zeroblob(sqlite3_stmt*, int, int n);
** [sqlite3_bind_parameter_name()], and
** [sqlite3_bind_parameter_index()].
*/
-SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_count(sqlite3_stmt*);
/*
** CAPI3REF: Name Of A Host Parameter
+** METHOD: sqlite3_stmt
**
** ^The sqlite3_bind_parameter_name(P,N) interface returns
** the name of the N-th [SQL parameter] in the [prepared statement] P.
@@ -3542,10 +3598,11 @@ SQLITE_API int sqlite3_bind_parameter_count(sqlite3_stmt*);
** [sqlite3_bind_parameter_count()], and
** [sqlite3_bind_parameter_index()].
*/
-SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_bind_parameter_name(sqlite3_stmt*, int);
/*
** CAPI3REF: Index Of A Parameter With A Given Name
+** METHOD: sqlite3_stmt
**
** ^Return the index of an SQL parameter given its name. ^The
** index value returned is suitable for use as the second
@@ -3558,19 +3615,21 @@ SQLITE_API const char *sqlite3_bind_parameter_name(sqlite3_stmt*, int);
** [sqlite3_bind_parameter_count()], and
** [sqlite3_bind_parameter_index()].
*/
-SQLITE_API int sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
+SQLITE_API int SQLITE_STDCALL sqlite3_bind_parameter_index(sqlite3_stmt*, const char *zName);
/*
** CAPI3REF: Reset All Bindings On A Prepared Statement
+** METHOD: sqlite3_stmt
**
** ^Contrary to the intuition of many, [sqlite3_reset()] does not reset
** the [sqlite3_bind_blob | bindings] on a [prepared statement].
** ^Use this routine to reset all host parameters to NULL.
*/
-SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
+SQLITE_API int SQLITE_STDCALL sqlite3_clear_bindings(sqlite3_stmt*);
/*
** CAPI3REF: Number Of Columns In A Result Set
+** METHOD: sqlite3_stmt
**
** ^Return the number of columns in the result set returned by the
** [prepared statement]. ^This routine returns 0 if pStmt is an SQL
@@ -3578,10 +3637,11 @@ SQLITE_API int sqlite3_clear_bindings(sqlite3_stmt*);
**
** See also: [sqlite3_data_count()]
*/
-SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt);
+SQLITE_API int SQLITE_STDCALL sqlite3_column_count(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Column Names In A Result Set
+** METHOD: sqlite3_stmt
**
** ^These routines return the name assigned to a particular column
** in the result set of a [SELECT] statement. ^The sqlite3_column_name()
@@ -3606,11 +3666,12 @@ SQLITE_API int sqlite3_column_count(sqlite3_stmt *pStmt);
** then the name of the column is unspecified and may change from
** one release of SQLite to the next.
*/
-SQLITE_API const char *sqlite3_column_name(sqlite3_stmt*, int N);
-SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_name(sqlite3_stmt*, int N);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_name16(sqlite3_stmt*, int N);
/*
** CAPI3REF: Source Of Data In A Query Result
+** METHOD: sqlite3_stmt
**
** ^These routines provide a means to determine the database, table, and
** table column that is the origin of a particular result column in
@@ -3654,15 +3715,16 @@ SQLITE_API const void *sqlite3_column_name16(sqlite3_stmt*, int N);
** for the same [prepared statement] and result column
** at the same time then the results are undefined.
*/
-SQLITE_API const char *sqlite3_column_database_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_database_name16(sqlite3_stmt*,int);
-SQLITE_API const char *sqlite3_column_table_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_table_name16(sqlite3_stmt*,int);
-SQLITE_API const char *sqlite3_column_origin_name(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_database_name(sqlite3_stmt*,int);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_database_name16(sqlite3_stmt*,int);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_table_name(sqlite3_stmt*,int);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_table_name16(sqlite3_stmt*,int);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_origin_name(sqlite3_stmt*,int);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_origin_name16(sqlite3_stmt*,int);
/*
** CAPI3REF: Declared Datatype Of A Query Result
+** METHOD: sqlite3_stmt
**
** ^(The first parameter is a [prepared statement].
** If this statement is a [SELECT] statement and the Nth column of the
@@ -3690,11 +3752,12 @@ SQLITE_API const void *sqlite3_column_origin_name16(sqlite3_stmt*,int);
** is associated with individual values, not with the containers
** used to hold those values.
*/
-SQLITE_API const char *sqlite3_column_decltype(sqlite3_stmt*,int);
-SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_column_decltype(sqlite3_stmt*,int);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_decltype16(sqlite3_stmt*,int);
/*
** CAPI3REF: Evaluate An SQL Statement
+** METHOD: sqlite3_stmt
**
** After a [prepared statement] has been prepared using either
** [sqlite3_prepare_v2()] or [sqlite3_prepare16_v2()] or one of the legacy
@@ -3770,10 +3833,11 @@ SQLITE_API const void *sqlite3_column_decltype16(sqlite3_stmt*,int);
** then the more specific [error codes] are returned directly
** by sqlite3_step(). The use of the "v2" interface is recommended.
*/
-SQLITE_API int sqlite3_step(sqlite3_stmt*);
+SQLITE_API int SQLITE_STDCALL sqlite3_step(sqlite3_stmt*);
/*
** CAPI3REF: Number of columns in a result set
+** METHOD: sqlite3_stmt
**
** ^The sqlite3_data_count(P) interface returns the number of columns in the
** current row of the result set of [prepared statement] P.
@@ -3790,7 +3854,7 @@ SQLITE_API int sqlite3_step(sqlite3_stmt*);
**
** See also: [sqlite3_column_count()]
*/
-SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
+SQLITE_API int SQLITE_STDCALL sqlite3_data_count(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Fundamental Datatypes
@@ -3827,6 +3891,7 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Result Values From A Query
** KEYWORDS: {column access functions}
+** METHOD: sqlite3_stmt
**
** These routines form the "result set" interface.
**
@@ -3986,19 +4051,20 @@ SQLITE_API int sqlite3_data_count(sqlite3_stmt *pStmt);
** pointer. Subsequent calls to [sqlite3_errcode()] will return
** [SQLITE_NOMEM].)^
*/
-SQLITE_API const void *sqlite3_column_blob(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
-SQLITE_API double sqlite3_column_double(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_int(sqlite3_stmt*, int iCol);
-SQLITE_API sqlite3_int64 sqlite3_column_int64(sqlite3_stmt*, int iCol);
-SQLITE_API const unsigned char *sqlite3_column_text(sqlite3_stmt*, int iCol);
-SQLITE_API const void *sqlite3_column_text16(sqlite3_stmt*, int iCol);
-SQLITE_API int sqlite3_column_type(sqlite3_stmt*, int iCol);
-SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_blob(sqlite3_stmt*, int iCol);
+SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes(sqlite3_stmt*, int iCol);
+SQLITE_API int SQLITE_STDCALL sqlite3_column_bytes16(sqlite3_stmt*, int iCol);
+SQLITE_API double SQLITE_STDCALL sqlite3_column_double(sqlite3_stmt*, int iCol);
+SQLITE_API int SQLITE_STDCALL sqlite3_column_int(sqlite3_stmt*, int iCol);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_column_int64(sqlite3_stmt*, int iCol);
+SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_column_text(sqlite3_stmt*, int iCol);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_column_text16(sqlite3_stmt*, int iCol);
+SQLITE_API int SQLITE_STDCALL sqlite3_column_type(sqlite3_stmt*, int iCol);
+SQLITE_API sqlite3_value *SQLITE_STDCALL sqlite3_column_value(sqlite3_stmt*, int iCol);
/*
** CAPI3REF: Destroy A Prepared Statement Object
+** DESTRUCTOR: sqlite3_stmt
**
** ^The sqlite3_finalize() function is called to delete a [prepared statement].
** ^If the most recent evaluation of the statement encountered no errors
@@ -4022,10 +4088,11 @@ SQLITE_API sqlite3_value *sqlite3_column_value(sqlite3_stmt*, int iCol);
** statement after it has been finalized can result in undefined and
** undesirable behavior such as segfaults and heap corruption.
*/
-SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
+SQLITE_API int SQLITE_STDCALL sqlite3_finalize(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Reset A Prepared Statement Object
+** METHOD: sqlite3_stmt
**
** The sqlite3_reset() function is called to reset a [prepared statement]
** object back to its initial state, ready to be re-executed.
@@ -4048,13 +4115,14 @@ SQLITE_API int sqlite3_finalize(sqlite3_stmt *pStmt);
** ^The [sqlite3_reset(S)] interface does not change the values
** of any [sqlite3_bind_blob|bindings] on the [prepared statement] S.
*/
-SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
+SQLITE_API int SQLITE_STDCALL sqlite3_reset(sqlite3_stmt *pStmt);
/*
** CAPI3REF: Create Or Redefine SQL Functions
** KEYWORDS: {function creation routines}
** KEYWORDS: {application-defined SQL function}
** KEYWORDS: {application-defined SQL functions}
+** METHOD: sqlite3
**
** ^These functions (collectively known as "function creation routines")
** are used to add SQL functions or aggregates or to redefine the behavior
@@ -4147,7 +4215,7 @@ SQLITE_API int sqlite3_reset(sqlite3_stmt *pStmt);
** close the database connection nor finalize or reset the prepared
** statement in which the function is running.
*/
-SQLITE_API int sqlite3_create_function(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_function(
sqlite3 *db,
const char *zFunctionName,
int nArg,
@@ -4157,7 +4225,7 @@ SQLITE_API int sqlite3_create_function(
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*)
);
-SQLITE_API int sqlite3_create_function16(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_function16(
sqlite3 *db,
const void *zFunctionName,
int nArg,
@@ -4167,7 +4235,7 @@ SQLITE_API int sqlite3_create_function16(
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*)
);
-SQLITE_API int sqlite3_create_function_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_function_v2(
sqlite3 *db,
const char *zFunctionName,
int nArg,
@@ -4209,21 +4277,22 @@ SQLITE_API int sqlite3_create_function_v2(
** These functions are [deprecated]. In order to maintain
** backwards compatibility with older code, these functions continue
** to be supported. However, new applications should avoid
-** the use of these functions. To help encourage people to avoid
-** using these functions, we are not going to tell you what they do.
+** the use of these functions. To encourage programmers to avoid
+** these functions, we will not explain what they do.
*/
#ifndef SQLITE_OMIT_DEPRECATED
-SQLITE_API SQLITE_DEPRECATED int sqlite3_aggregate_count(sqlite3_context*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_expired(sqlite3_stmt*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_global_recover(void);
-SQLITE_API SQLITE_DEPRECATED void sqlite3_thread_cleanup(void);
-SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
+SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_aggregate_count(sqlite3_context*);
+SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_expired(sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_transfer_bindings(sqlite3_stmt*, sqlite3_stmt*);
+SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_global_recover(void);
+SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_thread_cleanup(void);
+SQLITE_API SQLITE_DEPRECATED int SQLITE_STDCALL sqlite3_memory_alarm(void(*)(void*,sqlite3_int64,int),
void*,sqlite3_int64);
#endif
/*
** CAPI3REF: Obtaining SQL Function Parameter Values
+** METHOD: sqlite3_value
**
** The C-language implementation of SQL functions and aggregates uses
** this set of interface routines to access the parameter values on
@@ -4267,21 +4336,22 @@ SQLITE_API SQLITE_DEPRECATED int sqlite3_memory_alarm(void(*)(void*,sqlite3_int6
** These routines must be called from the same thread as
** the SQL function that supplied the [sqlite3_value*] parameters.
*/
-SQLITE_API const void *sqlite3_value_blob(sqlite3_value*);
-SQLITE_API int sqlite3_value_bytes(sqlite3_value*);
-SQLITE_API int sqlite3_value_bytes16(sqlite3_value*);
-SQLITE_API double sqlite3_value_double(sqlite3_value*);
-SQLITE_API int sqlite3_value_int(sqlite3_value*);
-SQLITE_API sqlite3_int64 sqlite3_value_int64(sqlite3_value*);
-SQLITE_API const unsigned char *sqlite3_value_text(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16le(sqlite3_value*);
-SQLITE_API const void *sqlite3_value_text16be(sqlite3_value*);
-SQLITE_API int sqlite3_value_type(sqlite3_value*);
-SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_blob(sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes(sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_value_bytes16(sqlite3_value*);
+SQLITE_API double SQLITE_STDCALL sqlite3_value_double(sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_value_int(sqlite3_value*);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_value_int64(sqlite3_value*);
+SQLITE_API const unsigned char *SQLITE_STDCALL sqlite3_value_text(sqlite3_value*);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16(sqlite3_value*);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16le(sqlite3_value*);
+SQLITE_API const void *SQLITE_STDCALL sqlite3_value_text16be(sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_value_type(sqlite3_value*);
+SQLITE_API int SQLITE_STDCALL sqlite3_value_numeric_type(sqlite3_value*);
/*
** CAPI3REF: Obtain Aggregate Function Context
+** METHOD: sqlite3_context
**
** Implementations of aggregate SQL functions use this
** routine to allocate memory for storing their state.
@@ -4322,10 +4392,11 @@ SQLITE_API int sqlite3_value_numeric_type(sqlite3_value*);
** This routine must be called from the same thread in which
** the aggregate SQL function is running.
*/
-SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
+SQLITE_API void *SQLITE_STDCALL sqlite3_aggregate_context(sqlite3_context*, int nBytes);
/*
** CAPI3REF: User Data For Functions
+** METHOD: sqlite3_context
**
** ^The sqlite3_user_data() interface returns a copy of
** the pointer that was the pUserData parameter (the 5th parameter)
@@ -4336,10 +4407,11 @@ SQLITE_API void *sqlite3_aggregate_context(sqlite3_context*, int nBytes);
** This routine must be called from the same thread in which
** the application-defined function is running.
*/
-SQLITE_API void *sqlite3_user_data(sqlite3_context*);
+SQLITE_API void *SQLITE_STDCALL sqlite3_user_data(sqlite3_context*);
/*
** CAPI3REF: Database Connection For Functions
+** METHOD: sqlite3_context
**
** ^The sqlite3_context_db_handle() interface returns a copy of
** the pointer to the [database connection] (the 1st parameter)
@@ -4347,10 +4419,11 @@ SQLITE_API void *sqlite3_user_data(sqlite3_context*);
** and [sqlite3_create_function16()] routines that originally
** registered the application defined function.
*/
-SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
+SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_context_db_handle(sqlite3_context*);
/*
** CAPI3REF: Function Auxiliary Data
+** METHOD: sqlite3_context
**
** These functions may be used by (non-aggregate) SQL functions to
** associate metadata with argument values. If the same value is passed to
@@ -4399,8 +4472,8 @@ SQLITE_API sqlite3 *sqlite3_context_db_handle(sqlite3_context*);
** These routines must be called from the same thread in which
** the SQL function is running.
*/
-SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
-SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
+SQLITE_API void *SQLITE_STDCALL sqlite3_get_auxdata(sqlite3_context*, int N);
+SQLITE_API void SQLITE_STDCALL sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
/*
@@ -4423,6 +4496,7 @@ typedef void (*sqlite3_destructor_type)(void*);
/*
** CAPI3REF: Setting The Result Of An SQL Function
+** METHOD: sqlite3_context
**
** These routines are used by the xFunc or xFinal callbacks that
** implement SQL functions and aggregates. See
@@ -4535,29 +4609,30 @@ typedef void (*sqlite3_destructor_type)(void*);
** than the one containing the application-defined function that received
** the [sqlite3_context] pointer, the results are undefined.
*/
-SQLITE_API void sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_blob64(sqlite3_context*,const void*,
+SQLITE_API void SQLITE_STDCALL sqlite3_result_blob(sqlite3_context*, const void*, int, void(*)(void*));
+SQLITE_API void SQLITE_STDCALL sqlite3_result_blob64(sqlite3_context*,const void*,
sqlite3_uint64,void(*)(void*));
-SQLITE_API void sqlite3_result_double(sqlite3_context*, double);
-SQLITE_API void sqlite3_result_error(sqlite3_context*, const char*, int);
-SQLITE_API void sqlite3_result_error16(sqlite3_context*, const void*, int);
-SQLITE_API void sqlite3_result_error_toobig(sqlite3_context*);
-SQLITE_API void sqlite3_result_error_nomem(sqlite3_context*);
-SQLITE_API void sqlite3_result_error_code(sqlite3_context*, int);
-SQLITE_API void sqlite3_result_int(sqlite3_context*, int);
-SQLITE_API void sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
-SQLITE_API void sqlite3_result_null(sqlite3_context*);
-SQLITE_API void sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
+SQLITE_API void SQLITE_STDCALL sqlite3_result_double(sqlite3_context*, double);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error(sqlite3_context*, const char*, int);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error16(sqlite3_context*, const void*, int);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error_toobig(sqlite3_context*);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error_nomem(sqlite3_context*);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_error_code(sqlite3_context*, int);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_int(sqlite3_context*, int);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_int64(sqlite3_context*, sqlite3_int64);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_null(sqlite3_context*);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text(sqlite3_context*, const char*, int, void(*)(void*));
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text64(sqlite3_context*, const char*,sqlite3_uint64,
void(*)(void*), unsigned char encoding);
-SQLITE_API void sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
-SQLITE_API void sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
-SQLITE_API void sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
-SQLITE_API void sqlite3_result_value(sqlite3_context*, sqlite3_value*);
-SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text16(sqlite3_context*, const void*, int, void(*)(void*));
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text16le(sqlite3_context*, const void*, int,void(*)(void*));
+SQLITE_API void SQLITE_STDCALL sqlite3_result_text16be(sqlite3_context*, const void*, int,void(*)(void*));
+SQLITE_API void SQLITE_STDCALL sqlite3_result_value(sqlite3_context*, sqlite3_value*);
+SQLITE_API void SQLITE_STDCALL sqlite3_result_zeroblob(sqlite3_context*, int n);
/*
** CAPI3REF: Define New Collating Sequences
+** METHOD: sqlite3
**
** ^These functions add, remove, or modify a [collation] associated
** with the [database connection] specified as the first argument.
@@ -4635,14 +4710,14 @@ SQLITE_API void sqlite3_result_zeroblob(sqlite3_context*, int n);
**
** See also: [sqlite3_collation_needed()] and [sqlite3_collation_needed16()].
*/
-SQLITE_API int sqlite3_create_collation(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_collation(
sqlite3*,
const char *zName,
int eTextRep,
void *pArg,
int(*xCompare)(void*,int,const void*,int,const void*)
);
-SQLITE_API int sqlite3_create_collation_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_collation_v2(
sqlite3*,
const char *zName,
int eTextRep,
@@ -4650,7 +4725,7 @@ SQLITE_API int sqlite3_create_collation_v2(
int(*xCompare)(void*,int,const void*,int,const void*),
void(*xDestroy)(void*)
);
-SQLITE_API int sqlite3_create_collation16(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_collation16(
sqlite3*,
const void *zName,
int eTextRep,
@@ -4660,6 +4735,7 @@ SQLITE_API int sqlite3_create_collation16(
/*
** CAPI3REF: Collation Needed Callbacks
+** METHOD: sqlite3
**
** ^To avoid having to register all collation sequences before a database
** can be used, a single callback function may be registered with the
@@ -4684,12 +4760,12 @@ SQLITE_API int sqlite3_create_collation16(
** [sqlite3_create_collation()], [sqlite3_create_collation16()], or
** [sqlite3_create_collation_v2()].
*/
-SQLITE_API int sqlite3_collation_needed(
+SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed(
sqlite3*,
void*,
void(*)(void*,sqlite3*,int eTextRep,const char*)
);
-SQLITE_API int sqlite3_collation_needed16(
+SQLITE_API int SQLITE_STDCALL sqlite3_collation_needed16(
sqlite3*,
void*,
void(*)(void*,sqlite3*,int eTextRep,const void*)
@@ -4703,11 +4779,11 @@ SQLITE_API int sqlite3_collation_needed16(
** The code to implement this API is not available in the public release
** of SQLite.
*/
-SQLITE_API int sqlite3_key(
+SQLITE_API int SQLITE_STDCALL sqlite3_key(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The key */
);
-SQLITE_API int sqlite3_key_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_key_v2(
sqlite3 *db, /* Database to be rekeyed */
const char *zDbName, /* Name of the database */
const void *pKey, int nKey /* The key */
@@ -4721,11 +4797,11 @@ SQLITE_API int sqlite3_key_v2(
** The code to implement this API is not available in the public release
** of SQLite.
*/
-SQLITE_API int sqlite3_rekey(
+SQLITE_API int SQLITE_STDCALL sqlite3_rekey(
sqlite3 *db, /* Database to be rekeyed */
const void *pKey, int nKey /* The new key */
);
-SQLITE_API int sqlite3_rekey_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_rekey_v2(
sqlite3 *db, /* Database to be rekeyed */
const char *zDbName, /* Name of the database */
const void *pKey, int nKey /* The new key */
@@ -4735,7 +4811,7 @@ SQLITE_API int sqlite3_rekey_v2(
** Specify the activation key for a SEE database. Unless
** activated, none of the SEE routines will work.
*/
-SQLITE_API void sqlite3_activate_see(
+SQLITE_API void SQLITE_STDCALL sqlite3_activate_see(
const char *zPassPhrase /* Activation phrase */
);
#endif
@@ -4745,7 +4821,7 @@ SQLITE_API void sqlite3_activate_see(
** Specify the activation key for a CEROD database. Unless
** activated, none of the CEROD routines will work.
*/
-SQLITE_API void sqlite3_activate_cerod(
+SQLITE_API void SQLITE_STDCALL sqlite3_activate_cerod(
const char *zPassPhrase /* Activation phrase */
);
#endif
@@ -4767,7 +4843,7 @@ SQLITE_API void sqlite3_activate_cerod(
** all, then the behavior of sqlite3_sleep() may deviate from the description
** in the previous paragraphs.
*/
-SQLITE_API int sqlite3_sleep(int);
+SQLITE_API int SQLITE_STDCALL sqlite3_sleep(int);
/*
** CAPI3REF: Name Of The Folder Holding Temporary Files
@@ -4867,6 +4943,7 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory;
/*
** CAPI3REF: Test For Auto-Commit Mode
** KEYWORDS: {autocommit mode}
+** METHOD: sqlite3
**
** ^The sqlite3_get_autocommit() interface returns non-zero or
** zero if the given database connection is or is not in autocommit mode,
@@ -4885,10 +4962,11 @@ SQLITE_API SQLITE_EXTERN char *sqlite3_data_directory;
** connection while this routine is running, then the return value
** is undefined.
*/
-SQLITE_API int sqlite3_get_autocommit(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_get_autocommit(sqlite3*);
/*
** CAPI3REF: Find The Database Handle Of A Prepared Statement
+** METHOD: sqlite3_stmt
**
** ^The sqlite3_db_handle interface returns the [database connection] handle
** to which a [prepared statement] belongs. ^The [database connection]
@@ -4897,10 +4975,11 @@ SQLITE_API int sqlite3_get_autocommit(sqlite3*);
** to the [sqlite3_prepare_v2()] call (or its variants) that was used to
** create the statement in the first place.
*/
-SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
+SQLITE_API sqlite3 *SQLITE_STDCALL sqlite3_db_handle(sqlite3_stmt*);
/*
** CAPI3REF: Return The Filename For A Database Connection
+** METHOD: sqlite3
**
** ^The sqlite3_db_filename(D,N) interface returns a pointer to a filename
** associated with database N of connection D. ^The main database file
@@ -4913,19 +4992,21 @@ SQLITE_API sqlite3 *sqlite3_db_handle(sqlite3_stmt*);
** will be an absolute pathname, even if the filename used
** to open the database originally was a URI or relative pathname.
*/
-SQLITE_API const char *sqlite3_db_filename(sqlite3 *db, const char *zDbName);
+SQLITE_API const char *SQLITE_STDCALL sqlite3_db_filename(sqlite3 *db, const char *zDbName);
/*
** CAPI3REF: Determine if a database is read-only
+** METHOD: sqlite3
**
** ^The sqlite3_db_readonly(D,N) interface returns 1 if the database N
** of connection D is read-only, 0 if it is read/write, or -1 if N is not
** the name of a database on connection D.
*/
-SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
+SQLITE_API int SQLITE_STDCALL sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
/*
** CAPI3REF: Find the next prepared statement
+** METHOD: sqlite3
**
** ^This interface returns a pointer to the next [prepared statement] after
** pStmt associated with the [database connection] pDb. ^If pStmt is NULL
@@ -4937,10 +5018,11 @@ SQLITE_API int sqlite3_db_readonly(sqlite3 *db, const char *zDbName);
** [sqlite3_next_stmt(D,S)] must refer to an open database
** connection and in particular must not be a NULL pointer.
*/
-SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
+SQLITE_API sqlite3_stmt *SQLITE_STDCALL sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
/*
** CAPI3REF: Commit And Rollback Notification Callbacks
+** METHOD: sqlite3
**
** ^The sqlite3_commit_hook() interface registers a callback
** function to be invoked whenever a transaction is [COMMIT | committed].
@@ -4985,11 +5067,12 @@ SQLITE_API sqlite3_stmt *sqlite3_next_stmt(sqlite3 *pDb, sqlite3_stmt *pStmt);
**
** See also the [sqlite3_update_hook()] interface.
*/
-SQLITE_API void *sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
-SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
+SQLITE_API void *SQLITE_STDCALL sqlite3_commit_hook(sqlite3*, int(*)(void*), void*);
+SQLITE_API void *SQLITE_STDCALL sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
/*
** CAPI3REF: Data Change Notification Callbacks
+** METHOD: sqlite3
**
** ^The sqlite3_update_hook() interface registers a callback function
** with the [database connection] identified by the first argument
@@ -5036,7 +5119,7 @@ SQLITE_API void *sqlite3_rollback_hook(sqlite3*, void(*)(void *), void*);
** See also the [sqlite3_commit_hook()] and [sqlite3_rollback_hook()]
** interfaces.
*/
-SQLITE_API void *sqlite3_update_hook(
+SQLITE_API void *SQLITE_STDCALL sqlite3_update_hook(
sqlite3*,
void(*)(void *,int ,char const *,char const *,sqlite3_int64),
void*
@@ -5066,12 +5149,17 @@ SQLITE_API void *sqlite3_update_hook(
** future releases of SQLite. Applications that care about shared
** cache setting should set it explicitly.
**
+** Note: This method is disabled on MacOS X 10.7 and iOS version 5.0
+** and will always return SQLITE_MISUSE. On those systems,
+** shared cache mode should be enabled per-database connection via
+** [sqlite3_open_v2()] with [SQLITE_OPEN_SHAREDCACHE].
+**
** This interface is threadsafe on processors where writing a
** 32-bit integer is atomic.
**
** See Also: [SQLite Shared-Cache Mode]
*/
-SQLITE_API int sqlite3_enable_shared_cache(int);
+SQLITE_API int SQLITE_STDCALL sqlite3_enable_shared_cache(int);
/*
** CAPI3REF: Attempt To Free Heap Memory
@@ -5087,10 +5175,11 @@ SQLITE_API int sqlite3_enable_shared_cache(int);
**
** See also: [sqlite3_db_release_memory()]
*/
-SQLITE_API int sqlite3_release_memory(int);
+SQLITE_API int SQLITE_STDCALL sqlite3_release_memory(int);
/*
** CAPI3REF: Free Memory Used By A Database Connection
+** METHOD: sqlite3
**
** ^The sqlite3_db_release_memory(D) interface attempts to free as much heap
** memory as possible from database connection D. Unlike the
@@ -5100,7 +5189,7 @@ SQLITE_API int sqlite3_release_memory(int);
**
** See also: [sqlite3_release_memory()]
*/
-SQLITE_API int sqlite3_db_release_memory(sqlite3*);
+SQLITE_API int SQLITE_STDCALL sqlite3_db_release_memory(sqlite3*);
/*
** CAPI3REF: Impose A Limit On Heap Size
@@ -5152,7 +5241,7 @@ SQLITE_API int sqlite3_db_release_memory(sqlite3*);
** The circumstances under which SQLite will enforce the soft heap limit may
** changes in future releases of SQLite.
*/
-SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
+SQLITE_API sqlite3_int64 SQLITE_STDCALL sqlite3_soft_heap_limit64(sqlite3_int64 N);
/*
** CAPI3REF: Deprecated Soft Heap Limit Interface
@@ -5163,11 +5252,12 @@ SQLITE_API sqlite3_int64 sqlite3_soft_heap_limit64(sqlite3_int64 N);
** only. All new applications should use the
** [sqlite3_soft_heap_limit64()] interface rather than this one.
*/
-SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
+SQLITE_API SQLITE_DEPRECATED void SQLITE_STDCALL sqlite3_soft_heap_limit(int N);
/*
** CAPI3REF: Extract Metadata About A Column Of A Table
+** METHOD: sqlite3
**
** ^(The sqlite3_table_column_metadata(X,D,T,C,....) routine returns
** information about column C of table T in database D
@@ -5232,7 +5322,7 @@ SQLITE_API SQLITE_DEPRECATED void sqlite3_soft_heap_limit(int N);
** parsed, if that has not already been done, and returns an error if
** any errors are encountered while loading the schema.
*/
-SQLITE_API int sqlite3_table_column_metadata(
+SQLITE_API int SQLITE_STDCALL sqlite3_table_column_metadata(
sqlite3 *db, /* Connection handle */
const char *zDbName, /* Database name or NULL */
const char *zTableName, /* Table name */
@@ -5246,6 +5336,7 @@ SQLITE_API int sqlite3_table_column_metadata(
/*
** CAPI3REF: Load An Extension
+** METHOD: sqlite3
**
** ^This interface loads an SQLite extension library from the named file.
**
@@ -5278,7 +5369,7 @@ SQLITE_API int sqlite3_table_column_metadata(
**
** See also the [load_extension() SQL function].
*/
-SQLITE_API int sqlite3_load_extension(
+SQLITE_API int SQLITE_STDCALL sqlite3_load_extension(
sqlite3 *db, /* Load the extension into this database connection */
const char *zFile, /* Name of the shared library containing extension */
const char *zProc, /* Entry point. Derived from zFile if 0 */
@@ -5287,6 +5378,7 @@ SQLITE_API int sqlite3_load_extension(
/*
** CAPI3REF: Enable Or Disable Extension Loading
+** METHOD: sqlite3
**
** ^So as not to open security holes in older applications that are
** unprepared to deal with [extension loading], and as a means of disabling
@@ -5298,7 +5390,7 @@ SQLITE_API int sqlite3_load_extension(
** to turn extension loading on and call it with onoff==0 to turn
** it back off again.
*/
-SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
+SQLITE_API int SQLITE_STDCALL sqlite3_enable_load_extension(sqlite3 *db, int onoff);
/*
** CAPI3REF: Automatically Load Statically Linked Extensions
@@ -5336,7 +5428,7 @@ SQLITE_API int sqlite3_enable_load_extension(sqlite3 *db, int onoff);
** See also: [sqlite3_reset_auto_extension()]
** and [sqlite3_cancel_auto_extension()]
*/
-SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
+SQLITE_API int SQLITE_STDCALL sqlite3_auto_extension(void (*xEntryPoint)(void));
/*
** CAPI3REF: Cancel Automatic Extension Loading
@@ -5348,7 +5440,7 @@ SQLITE_API int sqlite3_auto_extension(void (*xEntryPoint)(void));
** unregistered and it returns 0 if X was not on the list of initialization
** routines.
*/
-SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
+SQLITE_API int SQLITE_STDCALL sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
/*
** CAPI3REF: Reset Automatic Extension Loading
@@ -5356,7 +5448,7 @@ SQLITE_API int sqlite3_cancel_auto_extension(void (*xEntryPoint)(void));
** ^This interface disables all automatic extensions previously
** registered using [sqlite3_auto_extension()].
*/
-SQLITE_API void sqlite3_reset_auto_extension(void);
+SQLITE_API void SQLITE_STDCALL sqlite3_reset_auto_extension(void);
/*
** The interface to the virtual-table mechanism is currently considered
@@ -5536,6 +5628,7 @@ struct sqlite3_index_info {
/*
** CAPI3REF: Register A Virtual Table Implementation
+** METHOD: sqlite3
**
** ^These routines are used to register a new [virtual table module] name.
** ^Module names must be registered before
@@ -5559,13 +5652,13 @@ struct sqlite3_index_info {
** interface is equivalent to sqlite3_create_module_v2() with a NULL
** destructor.
*/
-SQLITE_API int sqlite3_create_module(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_module(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *p, /* Methods for the module */
void *pClientData /* Client data for xCreate/xConnect */
);
-SQLITE_API int sqlite3_create_module_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_create_module_v2(
sqlite3 *db, /* SQLite connection to register module with */
const char *zName, /* Name of the module */
const sqlite3_module *p, /* Methods for the module */
@@ -5593,7 +5686,7 @@ SQLITE_API int sqlite3_create_module_v2(
*/
struct sqlite3_vtab {
const sqlite3_module *pModule; /* The module for this virtual table */
- int nRef; /* NO LONGER USED */
+ int nRef; /* Number of open cursors */
char *zErrMsg; /* Error message from sqlite3_mprintf() */
/* Virtual table implementations will typically add additional fields */
};
@@ -5628,10 +5721,11 @@ struct sqlite3_vtab_cursor {
** to declare the format (the names and datatypes of the columns) of
** the virtual tables they implement.
*/
-SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
+SQLITE_API int SQLITE_STDCALL sqlite3_declare_vtab(sqlite3*, const char *zSQL);
/*
** CAPI3REF: Overload A Function For A Virtual Table
+** METHOD: sqlite3
**
** ^(Virtual tables can provide alternative implementations of functions
** using the [xFindFunction] method of the [virtual table module].
@@ -5646,7 +5740,7 @@ SQLITE_API int sqlite3_declare_vtab(sqlite3*, const char *zSQL);
** purpose is to be a placeholder function that can be overloaded
** by a [virtual table].
*/
-SQLITE_API int sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
+SQLITE_API int SQLITE_STDCALL sqlite3_overload_function(sqlite3*, const char *zFuncName, int nArg);
/*
** The interface to the virtual-table mechanism defined above (back up
@@ -5674,6 +5768,8 @@ typedef struct sqlite3_blob sqlite3_blob;
/*
** CAPI3REF: Open A BLOB For Incremental I/O
+** METHOD: sqlite3
+** CONSTRUCTOR: sqlite3_blob
**
** ^(This interfaces opens a [BLOB handle | handle] to the BLOB located
** in row iRow, column zColumn, table zTable in database zDb;
@@ -5743,7 +5839,7 @@ typedef struct sqlite3_blob sqlite3_blob;
** To avoid a resource leak, every open [BLOB handle] should eventually
** be released by a call to [sqlite3_blob_close()].
*/
-SQLITE_API int sqlite3_blob_open(
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_open(
sqlite3*,
const char *zDb,
const char *zTable,
@@ -5755,6 +5851,7 @@ SQLITE_API int sqlite3_blob_open(
/*
** CAPI3REF: Move a BLOB Handle to a New Row
+** METHOD: sqlite3_blob
**
** ^This function is used to move an existing blob handle so that it points
** to a different row of the same database table. ^The new row is identified
@@ -5775,10 +5872,11 @@ SQLITE_API int sqlite3_blob_open(
**
** ^This function sets the database handle error code and message.
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
+SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_blob_reopen(sqlite3_blob *, sqlite3_int64);
/*
** CAPI3REF: Close A BLOB Handle
+** DESTRUCTOR: sqlite3_blob
**
** ^This function closes an open [BLOB handle]. ^(The BLOB handle is closed
** unconditionally. Even if this routine returns an error code, the
@@ -5797,10 +5895,11 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_blob_reopen(sqlite3_blob *, sqlite3_i
** is passed a valid open blob handle, the values returned by the
** sqlite3_errcode() and sqlite3_errmsg() functions are set before returning.
*/
-SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_close(sqlite3_blob *);
/*
** CAPI3REF: Return The Size Of An Open BLOB
+** METHOD: sqlite3_blob
**
** ^Returns the size in bytes of the BLOB accessible via the
** successfully opened [BLOB handle] in its only argument. ^The
@@ -5812,10 +5911,11 @@ SQLITE_API int sqlite3_blob_close(sqlite3_blob *);
** been closed by [sqlite3_blob_close()]. Passing any other pointer in
** to this routine results in undefined and probably undesirable behavior.
*/
-SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_bytes(sqlite3_blob *);
/*
** CAPI3REF: Read Data From A BLOB Incrementally
+** METHOD: sqlite3_blob
**
** ^(This function is used to read data from an open [BLOB handle] into a
** caller-supplied buffer. N bytes of data are copied into buffer Z
@@ -5840,10 +5940,11 @@ SQLITE_API int sqlite3_blob_bytes(sqlite3_blob *);
**
** See also: [sqlite3_blob_write()].
*/
-SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
/*
** CAPI3REF: Write Data Into A BLOB Incrementally
+** METHOD: sqlite3_blob
**
** ^(This function is used to write data into an open [BLOB handle] from a
** caller-supplied buffer. N bytes of data are copied from the buffer Z
@@ -5881,7 +5982,7 @@ SQLITE_API int sqlite3_blob_read(sqlite3_blob *, void *Z, int N, int iOffset);
**
** See also: [sqlite3_blob_read()].
*/
-SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
+SQLITE_API int SQLITE_STDCALL sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOffset);
/*
** CAPI3REF: Virtual File System Objects
@@ -5912,9 +6013,9 @@ SQLITE_API int sqlite3_blob_write(sqlite3_blob *, const void *z, int n, int iOff
** ^(If the default VFS is unregistered, another VFS is chosen as
** the default. The choice for the new VFS is arbitrary.)^
*/
-SQLITE_API sqlite3_vfs *sqlite3_vfs_find(const char *zVfsName);
-SQLITE_API int sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
-SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
+SQLITE_API sqlite3_vfs *SQLITE_STDCALL sqlite3_vfs_find(const char *zVfsName);
+SQLITE_API int SQLITE_STDCALL sqlite3_vfs_register(sqlite3_vfs*, int makeDflt);
+SQLITE_API int SQLITE_STDCALL sqlite3_vfs_unregister(sqlite3_vfs*);
/*
** CAPI3REF: Mutexes
@@ -6027,11 +6128,11 @@ SQLITE_API int sqlite3_vfs_unregister(sqlite3_vfs*);
**
** See also: [sqlite3_mutex_held()] and [sqlite3_mutex_notheld()].
*/
-SQLITE_API sqlite3_mutex *sqlite3_mutex_alloc(int);
-SQLITE_API void sqlite3_mutex_free(sqlite3_mutex*);
-SQLITE_API void sqlite3_mutex_enter(sqlite3_mutex*);
-SQLITE_API int sqlite3_mutex_try(sqlite3_mutex*);
-SQLITE_API void sqlite3_mutex_leave(sqlite3_mutex*);
+SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_mutex_alloc(int);
+SQLITE_API void SQLITE_STDCALL sqlite3_mutex_free(sqlite3_mutex*);
+SQLITE_API void SQLITE_STDCALL sqlite3_mutex_enter(sqlite3_mutex*);
+SQLITE_API int SQLITE_STDCALL sqlite3_mutex_try(sqlite3_mutex*);
+SQLITE_API void SQLITE_STDCALL sqlite3_mutex_leave(sqlite3_mutex*);
/*
** CAPI3REF: Mutex Methods Object
@@ -6141,8 +6242,8 @@ struct sqlite3_mutex_methods {
** interface should also return 1 when given a NULL pointer.
*/
#ifndef NDEBUG
-SQLITE_API int sqlite3_mutex_held(sqlite3_mutex*);
-SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
+SQLITE_API int SQLITE_STDCALL sqlite3_mutex_held(sqlite3_mutex*);
+SQLITE_API int SQLITE_STDCALL sqlite3_mutex_notheld(sqlite3_mutex*);
#endif
/*
@@ -6171,6 +6272,7 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
/*
** CAPI3REF: Retrieve the mutex for a database connection
+** METHOD: sqlite3
**
** ^This interface returns a pointer the [sqlite3_mutex] object that
** serializes access to the [database connection] given in the argument
@@ -6178,10 +6280,11 @@ SQLITE_API int sqlite3_mutex_notheld(sqlite3_mutex*);
** ^If the [threading mode] is Single-thread or Multi-thread then this
** routine returns a NULL pointer.
*/
-SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
+SQLITE_API sqlite3_mutex *SQLITE_STDCALL sqlite3_db_mutex(sqlite3*);
/*
** CAPI3REF: Low-Level Control Of Database Files
+** METHOD: sqlite3
**
** ^The [sqlite3_file_control()] interface makes a direct call to the
** xFileControl method for the [sqlite3_io_methods] object associated
@@ -6212,7 +6315,7 @@ SQLITE_API sqlite3_mutex *sqlite3_db_mutex(sqlite3*);
**
** See also: [SQLITE_FCNTL_LOCKSTATE]
*/
-SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
+SQLITE_API int SQLITE_STDCALL sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*);
/*
** CAPI3REF: Testing Interface
@@ -6231,7 +6334,7 @@ SQLITE_API int sqlite3_file_control(sqlite3*, const char *zDbName, int op, void*
** Unlike most of the SQLite API, this function is not guaranteed to
** operate consistently from one release to the next.
*/
-SQLITE_API int sqlite3_test_control(int op, ...);
+SQLITE_API int SQLITE_CDECL sqlite3_test_control(int op, ...);
/*
** CAPI3REF: Testing Interface Operation Codes
@@ -6265,12 +6368,13 @@ SQLITE_API int sqlite3_test_control(int op, ...);
#define SQLITE_TESTCTRL_BYTEORDER 22
#define SQLITE_TESTCTRL_ISINIT 23
#define SQLITE_TESTCTRL_SORTER_MMAP 24
-#define SQLITE_TESTCTRL_LAST 24
+#define SQLITE_TESTCTRL_IMPOSTER 25
+#define SQLITE_TESTCTRL_LAST 25
/*
** CAPI3REF: SQLite Runtime Status
**
-** ^This interface is used to retrieve runtime status information
+** ^These interfaces are used to retrieve runtime status information
** about the performance of SQLite, and optionally to reset various
** highwater marks. ^The first argument is an integer code for
** the specific parameter to measure. ^(Recognized integer codes
@@ -6284,19 +6388,22 @@ SQLITE_API int sqlite3_test_control(int op, ...);
** ^(Other parameters record only the highwater mark and not the current
** value. For these latter parameters nothing is written into *pCurrent.)^
**
-** ^The sqlite3_status() routine returns SQLITE_OK on success and a
-** non-zero [error code] on failure.
+** ^The sqlite3_status() and sqlite3_status64() routines return
+** SQLITE_OK on success and a non-zero [error code] on failure.
**
-** This routine is threadsafe but is not atomic. This routine can be
-** called while other threads are running the same or different SQLite
-** interfaces. However the values returned in *pCurrent and
-** *pHighwater reflect the status of SQLite at different points in time
-** and it is possible that another thread might change the parameter
-** in between the times when *pCurrent and *pHighwater are written.
+** If either the current value or the highwater mark is too large to
+** be represented by a 32-bit integer, then the values returned by
+** sqlite3_status() are undefined.
**
** See also: [sqlite3_db_status()]
*/
-SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+SQLITE_API int SQLITE_STDCALL sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetFlag);
+SQLITE_API int SQLITE_STDCALL sqlite3_status64(
+ int op,
+ sqlite3_int64 *pCurrent,
+ sqlite3_int64 *pHighwater,
+ int resetFlag
+);
/*
@@ -6394,6 +6501,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
/*
** CAPI3REF: Database Connection Status
+** METHOD: sqlite3
**
** ^This interface is used to retrieve runtime status information
** about a single [database connection]. ^The first argument is the
@@ -6414,7 +6522,7 @@ SQLITE_API int sqlite3_status(int op, int *pCurrent, int *pHighwater, int resetF
**
** See also: [sqlite3_status()] and [sqlite3_stmt_status()].
*/
-SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
+SQLITE_API int SQLITE_STDCALL sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int resetFlg);
/*
** CAPI3REF: Status Parameters for database connections
@@ -6522,6 +6630,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
/*
** CAPI3REF: Prepared Statement Status
+** METHOD: sqlite3_stmt
**
** ^(Each prepared statement maintains various
** [SQLITE_STMTSTATUS counters] that measure the number
@@ -6543,7 +6652,7 @@ SQLITE_API int sqlite3_db_status(sqlite3*, int op, int *pCur, int *pHiwtr, int r
**
** See also: [sqlite3_status()] and [sqlite3_db_status()].
*/
-SQLITE_API int sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
+SQLITE_API int SQLITE_STDCALL sqlite3_stmt_status(sqlite3_stmt*, int op,int resetFlg);
/*
** CAPI3REF: Status Parameters for prepared statements
@@ -6966,20 +7075,20 @@ typedef struct sqlite3_backup sqlite3_backup;
** is not a permanent error and does not affect the return value of
** sqlite3_backup_finish().
**
-** [[sqlite3_backup__remaining()]] [[sqlite3_backup_pagecount()]]
+** [[sqlite3_backup_remaining()]] [[sqlite3_backup_pagecount()]]
** <b>sqlite3_backup_remaining() and sqlite3_backup_pagecount()</b>
**
-** ^Each call to sqlite3_backup_step() sets two values inside
-** the [sqlite3_backup] object: the number of pages still to be backed
-** up and the total number of pages in the source database file.
-** The sqlite3_backup_remaining() and sqlite3_backup_pagecount() interfaces
-** retrieve these two values, respectively.
-**
-** ^The values returned by these functions are only updated by
-** sqlite3_backup_step(). ^If the source database is modified during a backup
-** operation, then the values are not updated to account for any extra
-** pages that need to be updated or the size of the source database file
-** changing.
+** ^The sqlite3_backup_remaining() routine returns the number of pages still
+** to be backed up at the conclusion of the most recent sqlite3_backup_step().
+** ^The sqlite3_backup_pagecount() routine returns the total number of pages
+** in the source database at the conclusion of the most recent
+** sqlite3_backup_step().
+** ^(The values returned by these functions are only updated by
+** sqlite3_backup_step(). If the source database is modified in a way that
+** changes the size of the source database or the number of pages remaining,
+** those changes are not reflected in the output of sqlite3_backup_pagecount()
+** and sqlite3_backup_remaining() until after the next
+** sqlite3_backup_step().)^
**
** <b>Concurrent Usage of Database Handles</b>
**
@@ -7012,19 +7121,20 @@ typedef struct sqlite3_backup sqlite3_backup;
** same time as another thread is invoking sqlite3_backup_step() it is
** possible that they return invalid values.
*/
-SQLITE_API sqlite3_backup *sqlite3_backup_init(
+SQLITE_API sqlite3_backup *SQLITE_STDCALL sqlite3_backup_init(
sqlite3 *pDest, /* Destination database handle */
const char *zDestName, /* Destination database name */
sqlite3 *pSource, /* Source database handle */
const char *zSourceName /* Source database name */
);
-SQLITE_API int sqlite3_backup_step(sqlite3_backup *p, int nPage);
-SQLITE_API int sqlite3_backup_finish(sqlite3_backup *p);
-SQLITE_API int sqlite3_backup_remaining(sqlite3_backup *p);
-SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_step(sqlite3_backup *p, int nPage);
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_finish(sqlite3_backup *p);
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_remaining(sqlite3_backup *p);
+SQLITE_API int SQLITE_STDCALL sqlite3_backup_pagecount(sqlite3_backup *p);
/*
** CAPI3REF: Unlock Notification
+** METHOD: sqlite3
**
** ^When running in shared-cache mode, a database operation may fail with
** an [SQLITE_LOCKED] error if the required locks on the shared-cache or
@@ -7137,7 +7247,7 @@ SQLITE_API int sqlite3_backup_pagecount(sqlite3_backup *p);
** the special "DROP TABLE/INDEX" case, the extended error code is just
** SQLITE_LOCKED.)^
*/
-SQLITE_API int sqlite3_unlock_notify(
+SQLITE_API int SQLITE_STDCALL sqlite3_unlock_notify(
sqlite3 *pBlocked, /* Waiting connection */
void (*xNotify)(void **apArg, int nArg), /* Callback function to invoke */
void *pNotifyArg /* Argument to pass to xNotify */
@@ -7152,8 +7262,8 @@ SQLITE_API int sqlite3_unlock_notify(
** strings in a case-independent fashion, using the same definition of "case
** independence" that SQLite uses internally when comparing identifiers.
*/
-SQLITE_API int sqlite3_stricmp(const char *, const char *);
-SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
+SQLITE_API int SQLITE_STDCALL sqlite3_stricmp(const char *, const char *);
+SQLITE_API int SQLITE_STDCALL sqlite3_strnicmp(const char *, const char *, int);
/*
** CAPI3REF: String Globbing
@@ -7168,7 +7278,7 @@ SQLITE_API int sqlite3_strnicmp(const char *, const char *, int);
** Note that this routine returns zero on a match and non-zero if the strings
** do not match, the same as [sqlite3_stricmp()] and [sqlite3_strnicmp()].
*/
-SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr);
+SQLITE_API int SQLITE_STDCALL sqlite3_strglob(const char *zGlob, const char *zStr);
/*
** CAPI3REF: Error Logging Interface
@@ -7191,10 +7301,11 @@ SQLITE_API int sqlite3_strglob(const char *zGlob, const char *zStr);
** a few hundred characters, it will be truncated to the length of the
** buffer.
*/
-SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
+SQLITE_API void SQLITE_CDECL sqlite3_log(int iErrCode, const char *zFormat, ...);
/*
** CAPI3REF: Write-Ahead Log Commit Hook
+** METHOD: sqlite3
**
** ^The [sqlite3_wal_hook()] function is used to register a callback that
** is invoked each time data is committed to a database in wal mode.
@@ -7226,7 +7337,7 @@ SQLITE_API void sqlite3_log(int iErrCode, const char *zFormat, ...);
** [wal_autocheckpoint pragma] both invoke [sqlite3_wal_hook()] and will
** those overwrite any prior [sqlite3_wal_hook()] settings.
*/
-SQLITE_API void *sqlite3_wal_hook(
+SQLITE_API void *SQLITE_STDCALL sqlite3_wal_hook(
sqlite3*,
int(*)(void *,sqlite3*,const char*,int),
void*
@@ -7234,6 +7345,7 @@ SQLITE_API void *sqlite3_wal_hook(
/*
** CAPI3REF: Configure an auto-checkpoint
+** METHOD: sqlite3
**
** ^The [sqlite3_wal_autocheckpoint(D,N)] is a wrapper around
** [sqlite3_wal_hook()] that causes any database on [database connection] D
@@ -7260,10 +7372,11 @@ SQLITE_API void *sqlite3_wal_hook(
** is only necessary if the default setting is found to be suboptimal
** for a particular application.
*/
-SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
+SQLITE_API int SQLITE_STDCALL sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
/*
** CAPI3REF: Checkpoint a database
+** METHOD: sqlite3
**
** ^(The sqlite3_wal_checkpoint(D,X) is equivalent to
** [sqlite3_wal_checkpoint_v2](D,X,[SQLITE_CHECKPOINT_PASSIVE],0,0).)^
@@ -7281,10 +7394,11 @@ SQLITE_API int sqlite3_wal_autocheckpoint(sqlite3 *db, int N);
** start a callback but which do not need the full power (and corresponding
** complication) of [sqlite3_wal_checkpoint_v2()].
*/
-SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
+SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
/*
** CAPI3REF: Checkpoint a database
+** METHOD: sqlite3
**
** ^(The sqlite3_wal_checkpoint_v2(D,X,M,L,C) interface runs a checkpoint
** operation on database X of [database connection] D in mode M. Status
@@ -7374,7 +7488,7 @@ SQLITE_API int sqlite3_wal_checkpoint(sqlite3 *db, const char *zDb);
** ^The [PRAGMA wal_checkpoint] command can be used to invoke this interface
** from SQL.
*/
-SQLITE_API int sqlite3_wal_checkpoint_v2(
+SQLITE_API int SQLITE_STDCALL sqlite3_wal_checkpoint_v2(
sqlite3 *db, /* Database handle */
const char *zDb, /* Name of attached database (or NULL) */
int eMode, /* SQLITE_CHECKPOINT_* value */
@@ -7410,7 +7524,7 @@ SQLITE_API int sqlite3_wal_checkpoint_v2(
** this function. (See [SQLITE_VTAB_CONSTRAINT_SUPPORT].) Further options
** may be added in the future.
*/
-SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
+SQLITE_API int SQLITE_CDECL sqlite3_vtab_config(sqlite3*, int op, ...);
/*
** CAPI3REF: Virtual Table Configuration Options
@@ -7463,7 +7577,7 @@ SQLITE_API int sqlite3_vtab_config(sqlite3*, int op, ...);
** of the SQL statement that triggered the call to the [xUpdate] method of the
** [virtual table].
*/
-SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
+SQLITE_API int SQLITE_STDCALL sqlite3_vtab_on_conflict(sqlite3 *);
/*
** CAPI3REF: Conflict resolution modes
@@ -7539,6 +7653,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
/*
** CAPI3REF: Prepared Statement Scan Status
+** METHOD: sqlite3_stmt
**
** This interface returns information about the predicted and measured
** performance for pStmt. Advanced applications can use this
@@ -7567,7 +7682,7 @@ SQLITE_API int sqlite3_vtab_on_conflict(sqlite3 *);
**
** See also: [sqlite3_stmt_scanstatus_reset()]
*/
-SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus(
+SQLITE_API SQLITE_EXPERIMENTAL int SQLITE_STDCALL sqlite3_stmt_scanstatus(
sqlite3_stmt *pStmt, /* Prepared statement for which info desired */
int idx, /* Index of loop to report on */
int iScanStatusOp, /* Information desired. SQLITE_SCANSTAT_* */
@@ -7576,13 +7691,14 @@ SQLITE_API SQLITE_EXPERIMENTAL int sqlite3_stmt_scanstatus(
/*
** CAPI3REF: Zero Scan-Status Counters
+** METHOD: sqlite3_stmt
**
** ^Zero all [sqlite3_stmt_scanstatus()] related event counters.
**
** This API is only available if the library is built with pre-processor
** symbol [SQLITE_ENABLE_STMT_SCANSTATUS] defined.
*/
-SQLITE_API SQLITE_EXPERIMENTAL void sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
+SQLITE_API SQLITE_EXPERIMENTAL void SQLITE_STDCALL sqlite3_stmt_scanstatus_reset(sqlite3_stmt*);
/*
@@ -7637,7 +7753,7 @@ typedef struct sqlite3_rtree_query_info sqlite3_rtree_query_info;
**
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zGeom(... params ...)
*/
-SQLITE_API int sqlite3_rtree_geometry_callback(
+SQLITE_API int SQLITE_STDCALL sqlite3_rtree_geometry_callback(
sqlite3 *db,
const char *zGeom,
int (*xGeom)(sqlite3_rtree_geometry*, int, sqlite3_rtree_dbl*,int*),
@@ -7663,7 +7779,7 @@ struct sqlite3_rtree_geometry {
**
** SELECT ... FROM <rtree> WHERE <rtree col> MATCH $zQueryFunc(... params ...)
*/
-SQLITE_API int sqlite3_rtree_query_callback(
+SQLITE_API int SQLITE_STDCALL sqlite3_rtree_query_callback(
sqlite3 *db,
const char *zQueryFunc,
int (*xQueryFunc)(sqlite3_rtree_query_info*),
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 3397de923b..b05900656d 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -821,7 +821,8 @@ PHP_FUNCTION(end)
entry = Z_INDIRECT_P(entry);
}
- RETURN_ZVAL_FAST(entry);
+ ZVAL_DEREF(entry);
+ ZVAL_COPY(return_value, entry);
}
}
/* }}} */
@@ -854,7 +855,8 @@ PHP_FUNCTION(prev)
entry = Z_INDIRECT_P(entry);
}
- RETURN_ZVAL_FAST(entry);
+ ZVAL_DEREF(entry);
+ ZVAL_COPY(return_value, entry);
}
}
/* }}} */
@@ -887,7 +889,8 @@ PHP_FUNCTION(next)
entry = Z_INDIRECT_P(entry);
}
- RETURN_ZVAL_FAST(entry);
+ ZVAL_DEREF(entry);
+ ZVAL_COPY(return_value, entry);
}
}
/* }}} */
@@ -920,7 +923,8 @@ PHP_FUNCTION(reset)
entry = Z_INDIRECT_P(entry);
}
- RETURN_ZVAL_FAST(entry);
+ ZVAL_DEREF(entry);
+ ZVAL_COPY(return_value, entry);
}
}
/* }}} */
@@ -950,7 +954,8 @@ PHP_FUNCTION(current)
entry = Z_INDIRECT_P(entry);
}
- RETURN_ZVAL_FAST(entry);
+ ZVAL_DEREF(entry);
+ ZVAL_COPY(return_value, entry);
}
/* }}} */
@@ -996,7 +1001,8 @@ PHP_FUNCTION(min)
RETVAL_NULL();
} else {
if ((result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare, 0)) != NULL) {
- RETVAL_ZVAL_FAST(result);
+ ZVAL_DEREF(result);
+ ZVAL_COPY(return_value, result);
} else {
php_error_docref(NULL, E_WARNING, "Array must contain at least one element");
RETVAL_FALSE;
@@ -1016,7 +1022,8 @@ PHP_FUNCTION(min)
}
}
- RETVAL_ZVAL_FAST(min);
+ ZVAL_DEREF(min);
+ ZVAL_COPY(return_value, min);
}
}
/* }}} */
@@ -1043,7 +1050,8 @@ PHP_FUNCTION(max)
RETVAL_NULL();
} else {
if ((result = zend_hash_minmax(Z_ARRVAL(args[0]), php_array_data_compare, 1)) != NULL) {
- RETVAL_ZVAL_FAST(result);
+ ZVAL_DEREF(result);
+ ZVAL_COPY(return_value, result);
} else {
php_error_docref(NULL, E_WARNING, "Array must contain at least one element");
RETVAL_FALSE;
@@ -1063,7 +1071,8 @@ PHP_FUNCTION(max)
}
}
- RETVAL_ZVAL_FAST(max);
+ ZVAL_DEREF(max);
+ ZVAL_COPY(return_value, max);
}
}
/* }}} */
@@ -2588,7 +2597,7 @@ PHPAPI int php_array_merge_recursive(HashTable *dest, HashTable *src) /* {{{ */
}
ZVAL_UNDEF(&tmp);
if (Z_TYPE_P(src_zval) == IS_OBJECT) {
- ZVAL_DUP(&tmp, src_zval);
+ ZVAL_COPY(&tmp, src_zval);
convert_to_array(&tmp);
src_zval = &tmp;
}
@@ -3061,6 +3070,7 @@ PHP_FUNCTION(array_column)
array_init(return_value);
ZEND_HASH_FOREACH_VAL(arr_hash, data) {
+ ZVAL_DEREF(data);
if (Z_TYPE_P(data) != IS_ARRAY) {
/* Skip elemens which are not sub-arrays */
continue;
@@ -4623,7 +4633,7 @@ PHP_FUNCTION(array_sum)
if (Z_TYPE_P(entry) == IS_ARRAY || Z_TYPE_P(entry) == IS_OBJECT) {
continue;
}
- ZVAL_DUP(&entry_n, entry);
+ ZVAL_COPY(&entry_n, entry);
convert_scalar_to_number(&entry_n);
fast_add_function(return_value, return_value, &entry_n);
} ZEND_HASH_FOREACH_END();
@@ -4652,7 +4662,7 @@ PHP_FUNCTION(array_product)
if (Z_TYPE_P(entry) == IS_ARRAY || Z_TYPE_P(entry) == IS_OBJECT) {
continue;
}
- ZVAL_DUP(&entry_n, entry);
+ ZVAL_COPY(&entry_n, entry);
convert_scalar_to_number(&entry_n);
if (Z_TYPE(entry_n) == IS_LONG && Z_TYPE_P(return_value) == IS_LONG) {
@@ -4700,7 +4710,8 @@ PHP_FUNCTION(array_reduce)
htbl = Z_ARRVAL_P(input);
if (zend_hash_num_elements(htbl) == 0) {
- RETURN_ZVAL(&result, 1, 1);
+ ZVAL_COPY_VALUE(return_value, &result);
+ return;
}
fci.retval = &retval;
@@ -4855,7 +4866,7 @@ PHP_FUNCTION(array_map)
/* Short-circuit: if no callback and only one array, just return it. */
if (!ZEND_FCI_INITIALIZED(fci)) {
- RETVAL_ZVAL(&arrays[0], 1, 0);
+ ZVAL_COPY(return_value, &arrays[0]);
return;
}
diff --git a/ext/standard/assert.c b/ext/standard/assert.c
index 59db4068bd..236c2c18e9 100644
--- a/ext/standard/assert.c
+++ b/ext/standard/assert.c
@@ -343,7 +343,7 @@ PHP_FUNCTION(assert_options)
case ASSERT_CALLBACK:
if (Z_TYPE(ASSERTG(callback)) != IS_UNDEF) {
- RETVAL_ZVAL(&ASSERTG(callback), 1, 0);
+ ZVAL_COPY(return_value, &ASSERTG(callback));
} else if (ASSERTG(cb)) {
RETVAL_STRING(ASSERTG(cb));
} else {
diff --git a/ext/standard/basic_functions.c b/ext/standard/basic_functions.c
index 462a234205..c4e0cee9f1 100644
--- a/ext/standard/basic_functions.c
+++ b/ext/standard/basic_functions.c
@@ -4144,7 +4144,7 @@ PHP_FUNCTION(putenv)
Obviously the CRT version will be useful more often. But
generally, doing both brings us on the safe track at least
in NTS build. */
- && _putenv(pe.putenv_string) == 0
+ && _putenv_s(pe.key, value ? value : "") == 0
# endif
) { /* success */
# endif
diff --git a/ext/standard/credits.c b/ext/standard/credits.c
index 7edec5c51d..dc40c637b7 100644
--- a/ext/standard/credits.c
+++ b/ext/standard/credits.c
@@ -96,8 +96,8 @@ PHPAPI void php_print_credits(int flag) /* {{{ */
if (flag & PHP_CREDITS_DOCS) {
php_info_print_table_start();
php_info_print_table_colspan_header(2, "PHP Documentation");
- CREDIT_LINE("Authors", "Mehdi Achour, Friedhelm Betz, Antony Dovgal, Nuno Lopes, Hannes Magnusson, Georg Richter, Damien Seguy, Jakub Vrana, Adam Harvey, Peter Cowburn");
- CREDIT_LINE("Editor", "Philip Olson");
+ CREDIT_LINE("Authors", "Mehdi Achour, Friedhelm Betz, Antony Dovgal, Nuno Lopes, Hannes Magnusson, Philip Olson, Georg Richter, Damien Seguy, Jakub Vrana, Adam Harvey");
+ CREDIT_LINE("Editor", "Peter Cowburn");
CREDIT_LINE("User Note Maintainers", "Daniel P. Brown, Thiago Henrique Pojda");
CREDIT_LINE("Other Contributors", "Previously active authors, editors and other contributors are listed in the manual.");
php_info_print_table_end();
diff --git a/ext/standard/credits_sapi.h b/ext/standard/credits_sapi.h
index a98add49de..f677344a54 100644
--- a/ext/standard/credits_sapi.h
+++ b/ext/standard/credits_sapi.h
@@ -16,5 +16,4 @@ CREDIT_LINE("CLI", "Edin Kadribasic, Marcus Boerger, Johannes Schlueter, Moriyos
CREDIT_LINE("Embed", "Edin Kadribasic");
CREDIT_LINE("FastCGI Process Manager", "Andrei Nigmatulin, dreamcat4, Antony Dovgal, Jerome Loyet");
CREDIT_LINE("litespeed", "George Wang");
-CREDIT_LINE("NSAPI", "Jayakumar Muthukumarasamy, Uwe Schindler");
CREDIT_LINE("phpdbg", "Felipe Pena, Joe Watkins, Bob Weinand");
diff --git a/ext/standard/crypt.c b/ext/standard/crypt.c
index da51ee9885..74ab291f62 100644
--- a/ext/standard/crypt.c
+++ b/ext/standard/crypt.c
@@ -151,7 +151,7 @@ static void php_to64(char *s, zend_long v, int n) /* {{{ */
}
/* }}} */
-PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const char *salt, int salt_len)
+PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const char *salt, int salt_len, zend_bool quiet)
{
char *crypt_res;
zend_string *result;
@@ -225,7 +225,10 @@ PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const ch
if (salt[0] != '_') {
/* DES style hashes */
if (!IS_VALID_SALT_CHARACTER(salt[0]) || !IS_VALID_SALT_CHARACTER(salt[1])) {
- php_error_docref(NULL, E_DEPRECATED, DES_INVALID_SALT_ERROR);
+ if (!quiet) {
+ /* error consistently about invalid DES fallbacks */
+ php_error_docref(NULL, E_DEPRECATED, DES_INVALID_SALT_ERROR);
+ }
}
}
@@ -254,8 +257,10 @@ PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const ch
# error Data struct used by crypt_r() is unknown. Please report.
# endif
if (salt[0] != '$' && salt[0] != '_' && (!IS_VALID_SALT_CHARACTER(salt[0]) || !IS_VALID_SALT_CHARACTER(salt[1]))) {
- /* error consistently about invalid DES fallbacks */
- php_error_docref(NULL, E_DEPRECATED, DES_INVALID_SALT_ERROR);
+ if (!quiet) {
+ /* error consistently about invalid DES fallbacks */
+ php_error_docref(NULL, E_DEPRECATED, DES_INVALID_SALT_ERROR);
+ }
}
crypt_res = crypt_r(password, salt, &buffer);
if (!crypt_res || (salt[0] == '*' && salt[1] == '0')) {
@@ -313,7 +318,7 @@ PHP_FUNCTION(crypt)
}
salt[salt_in_len] = '\0';
- if ((result = php_crypt(str, (int)str_len, salt, (int)salt_in_len)) == NULL) {
+ if ((result = php_crypt(str, (int)str_len, salt, (int)salt_in_len, 0)) == NULL) {
if (salt[0] == '*' && salt[1] == '0') {
RETURN_STRING("*1");
} else {
diff --git a/ext/standard/exec.c b/ext/standard/exec.c
index 71dfc7c361..60fd7ba1aa 100644
--- a/ext/standard/exec.c
+++ b/ext/standard/exec.c
@@ -383,6 +383,14 @@ PHPAPI zend_string *php_escape_shell_arg(char *str)
}
}
#ifdef PHP_WIN32
+ if (y > 0 && '\\' == cmd->val[y - 1]) {
+ int k = 0, n = y - 1;
+ for (; n >= 0 && '\\' == cmd->val[n]; n--, k++);
+ if (k % 2) {
+ cmd->val[y++] = '\\';
+ }
+ }
+
cmd->val[y++] = '"';
#else
cmd->val[y++] = '\'';
diff --git a/ext/standard/file.c b/ext/standard/file.c
index 7aa1ce7a85..1755dab81b 100644
--- a/ext/standard/file.c
+++ b/ext/standard/file.c
@@ -122,9 +122,6 @@ php_file_globals file_globals;
# include <wchar.h>
#endif
-#ifndef S_ISDIR
-# define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
-#endif
/* }}} */
#define PHP_STREAM_TO_ZVAL(stream, arg) \
@@ -522,7 +519,7 @@ PHP_FUNCTION(file_get_contents)
zend_bool use_include_path = 0;
php_stream *stream;
zend_long offset = -1;
- zend_long maxlen = PHP_STREAM_COPY_ALL;
+ zend_long maxlen = (ssize_t) PHP_STREAM_COPY_ALL;
zval *zcontext = NULL;
php_stream_context *context = NULL;
zend_string *contents;
diff --git a/ext/standard/filestat.c b/ext/standard/filestat.c
index ffcba3598d..764b490b9a 100644
--- a/ext/standard/filestat.c
+++ b/ext/standard/filestat.c
@@ -85,18 +85,6 @@
#include "basic_functions.h"
#include "php_filestat.h"
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
-#endif
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
-#endif
-#ifndef S_ISLNK
-#define S_ISLNK(mode) (((mode)&S_IFMT) == S_IFLNK)
-#endif
-
-#define S_IXROOT ( S_IXUSR | S_IXGRP | S_IXOTH )
-
PHP_RINIT_FUNCTION(filestat) /* {{{ */
{
BG(CurrentStatFile)=NULL;
diff --git a/ext/standard/http.c b/ext/standard/http.c
index 25b77280de..7fe094009e 100644
--- a/ext/standard/http.c
+++ b/ext/standard/http.c
@@ -36,7 +36,7 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
const char *prop_name;
size_t arg_sep_len, newprefix_len, prop_len;
zend_ulong idx;
- zval *zdata = NULL, copyzval;
+ zval *zdata = NULL;
if (!ht) {
return FAILURE;
@@ -204,16 +204,14 @@ PHPAPI int php_url_encode_hash_ex(HashTable *ht, smart_str *formstr,
default:
{
zend_string *ekey;
- /* fall back on convert to string */
- ZVAL_DUP(&copyzval, zdata);
- convert_to_string_ex(&copyzval);
+ zend_string *tmp = zval_get_string(zdata);
if (enc_type == PHP_QUERY_RFC3986) {
- ekey = php_raw_url_encode(Z_STRVAL(copyzval), Z_STRLEN(copyzval));
+ ekey = php_raw_url_encode(tmp->val, tmp->len);
} else {
- ekey = php_url_encode(Z_STRVAL(copyzval), Z_STRLEN(copyzval));
+ ekey = php_url_encode(tmp->val, tmp->len);
}
smart_str_append(formstr, ekey);
- zval_ptr_dtor(&copyzval);
+ zend_string_release(tmp);
zend_string_free(ekey);
}
}
diff --git a/ext/standard/info.c b/ext/standard/info.c
index 9490aae7d6..d8794c4ad6 100644
--- a/ext/standard/info.c
+++ b/ext/standard/info.c
@@ -307,7 +307,17 @@ char* php_get_windows_name()
GetSystemInfo(&si);
}
- if (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion >= 6 ) {
+ if (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion >= 10) {
+ if (osvi.dwMajorVersion == 10) {
+ if( osvi.dwMinorVersion == 0 ) {
+ if( osvi.wProductType == VER_NT_WORKSTATION ) {
+ major = "Windows 10";
+ } else {
+ major = "Windows Server 2016";
+ }
+ }
+ }
+ } else if (VER_PLATFORM_WIN32_NT==osvi.dwPlatformId && osvi.dwMajorVersion >= 6) {
if (osvi.dwMajorVersion == 6) {
if( osvi.dwMinorVersion == 0 ) {
if( osvi.wProductType == VER_NT_WORKSTATION ) {
@@ -323,6 +333,11 @@ char* php_get_windows_name()
}
} else if ( osvi.dwMinorVersion == 2 ) {
/* could be Windows 8/Windows Server 2012, could be Windows 8.1/Windows Server 2012 R2 */
+ /* XXX and one more X - the above comment is true if no manifest is used for two cases:
+ - if the PHP build doesn't use the correct manifest
+ - if PHP DLL loaded under some binary that doesn't use the correct manifest
+
+ So keep the handling here as is for now, even if we know 6.2 is win8 and nothing else, and think about an improvement. */
OSVERSIONINFOEX osvi81;
DWORDLONG dwlConditionMask = 0;
int op = VER_GREATER_EQUAL;
@@ -353,6 +368,12 @@ char* php_get_windows_name()
major = "Windows Server 2012";
}
}
+ } else if (osvi.dwMinorVersion == 3) {
+ if( osvi.wProductType == VER_NT_WORKSTATION ) {
+ major = "Windows 8.1";
+ } else {
+ major = "Windows Server 2012 R2";
+ }
} else {
major = "Unknown Windows version";
}
@@ -374,10 +395,25 @@ char* php_get_windows_name()
sub = "Enterprise Edition";
break;
case PRODUCT_BUSINESS:
- sub = "Business Edition";
+ if ((osvi.dwMajorVersion > 6) || (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion > 0)) {
+ sub = "Professional Edition";
+ } else {
+ sub = "Business Edition";
+ }
+ break;
+ case PRODUCT_BUSINESS_N:
+ if ((osvi.dwMajorVersion > 6) || (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion > 0)) {
+ sub = "Professional N Edition";
+ } else {
+ sub = "Business N Edition";
+ }
break;
case PRODUCT_STARTER:
- sub = "Starter Edition";
+ if ((osvi.dwMajorVersion > 6) || (osvi.dwMajorVersion == 6 && osvi.dwMinorVersion > 0)) {
+ sub = "Starter N Edition";
+ } else {
+ sub = "Starter Edition";
+ }
break;
case PRODUCT_CLUSTER_SERVER:
sub = "Cluster Server Edition";
diff --git a/ext/standard/mail.c b/ext/standard/mail.c
index 5633372022..a9046cea69 100644
--- a/ext/standard/mail.c
+++ b/ext/standard/mail.c
@@ -224,6 +224,44 @@ void php_mail_log_to_file(char *filename, char *message, size_t message_size) {
}
+static int php_mail_detect_multiple_crlf(char *hdr) {
+ /* This function detects multiple/malformed multiple newlines. */
+ size_t len;
+
+ if (!hdr) {
+ return 0;
+ }
+
+ /* Should not have any newlines at the beginning. */
+ /* RFC 2822 2.2. Header Fields */
+ if (*hdr < 33 || *hdr > 126 || *hdr == ':') {
+ return 1;
+ }
+
+ while(*hdr) {
+ if (*hdr == '\r') {
+ if (*(hdr+1) == '\0' || *(hdr+1) == '\r' || (*(hdr+1) == '\n' && (*(hdr+2) == '\0' || *(hdr+2) == '\n' || *(hdr+2) == '\r'))) {
+ /* Malformed or multiple newlines. */
+ return 1;
+ } else {
+ hdr += 2;
+ }
+ } else if (*hdr == '\n') {
+ if (*(hdr+1) == '\0' || *(hdr+1) == '\r' || *(hdr+1) == '\n') {
+ /* Malformed or multiple newlines. */
+ return 1;
+ } else {
+ hdr += 2;
+ }
+ } else {
+ hdr++;
+ }
+ }
+
+ return 0;
+}
+
+
/* {{{ php_mail
*/
PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char *extra_cmd)
@@ -278,6 +316,7 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
efree(tmp);
}
+
if (PG(mail_x_header)) {
const char *tmp = zend_get_executed_filename();
zend_string *f;
@@ -292,6 +331,11 @@ PHPAPI int php_mail(char *to, char *subject, char *message, char *headers, char
zend_string_release(f);
}
+ if (hdr && php_mail_detect_multiple_crlf(hdr)) {
+ php_error_docref(NULL TSRMLS_CC, E_WARNING, "Multiple or malformed newlines found in additional_header");
+ MAIL_RET(0);
+ }
+
if (!sendmail_path) {
#if (defined PHP_WIN32 || defined NETWARE)
/* handle old style win smtp sending */
diff --git a/ext/standard/math.c b/ext/standard/math.c
index a3685c00b9..1ae74f8049 100644
--- a/ext/standard/math.c
+++ b/ext/standard/math.c
@@ -327,9 +327,16 @@ PHP_FUNCTION(ceil)
{
zval *value;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &value) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ZVAL(value)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
+
convert_scalar_to_number_ex(value);
if (Z_TYPE_P(value) == IS_DOUBLE) {
@@ -347,9 +354,16 @@ PHP_FUNCTION(floor)
{
zval *value;
+#ifndef FAST_ZPP
if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &value) == FAILURE) {
return;
}
+#else
+ ZEND_PARSE_PARAMETERS_START(1, 1)
+ Z_PARAM_ZVAL(value)
+ ZEND_PARSE_PARAMETERS_END();
+#endif
+
convert_scalar_to_number_ex(value);
if (Z_TYPE_P(value) == IS_DOUBLE) {
diff --git a/ext/standard/microtime.c b/ext/standard/microtime.c
index 6d5b8cc695..4b391bbb7d 100644
--- a/ext/standard/microtime.c
+++ b/ext/standard/microtime.c
@@ -25,6 +25,7 @@
#endif
#ifdef PHP_WIN32
#include "win32/time.h"
+#include "win32/getrusage.h"
#elif defined(NETWARE)
#include <sys/timeval.h>
#include <sys/time.h>
@@ -129,9 +130,14 @@ PHP_FUNCTION(getrusage)
}
array_init(return_value);
+
#define PHP_RUSAGE_PARA(a) \
add_assoc_long(return_value, #a, usg.a)
-#if !defined( _OSD_POSIX) && !defined(__BEOS__) /* BS2000 has only a few fields in the rusage struct */
+
+#ifdef PHP_WIN32 /* Windows only implements a limited amount of fields from the rusage struct */
+ PHP_RUSAGE_PARA(ru_majflt);
+ PHP_RUSAGE_PARA(ru_maxrss);
+#elif !defined( _OSD_POSIX) && !defined(__BEOS__) /* BS2000 has only a few fields in the rusage struct*/
PHP_RUSAGE_PARA(ru_oublock);
PHP_RUSAGE_PARA(ru_inblock);
PHP_RUSAGE_PARA(ru_msgsnd);
@@ -150,6 +156,7 @@ PHP_FUNCTION(getrusage)
PHP_RUSAGE_PARA(ru_utime.tv_sec);
PHP_RUSAGE_PARA(ru_stime.tv_usec);
PHP_RUSAGE_PARA(ru_stime.tv_sec);
+
#undef PHP_RUSAGE_PARA
}
#endif /* HAVE_GETRUSAGE */
diff --git a/ext/standard/password.c b/ext/standard/password.c
index 209e2533f8..592f41838d 100644
--- a/ext/standard/password.c
+++ b/ext/standard/password.c
@@ -260,7 +260,7 @@ PHP_FUNCTION(password_verify)
if (zend_parse_parameters(ZEND_NUM_ARGS(), "ss", &password, &password_len, &hash, &hash_len) == FAILURE) {
RETURN_FALSE;
}
- if ((ret = php_crypt(password, (int)password_len, hash, (int)hash_len)) == NULL) {
+ if ((ret = php_crypt(password, (int)password_len, hash, (int)hash_len, 1)) == NULL) {
RETURN_FALSE;
}
@@ -340,18 +340,13 @@ PHP_FUNCTION(password_hash)
break;
case IS_LONG:
case IS_DOUBLE:
- case IS_OBJECT: {
- zval cast_option_buffer;
-
- ZVAL_DUP(&cast_option_buffer, option_buffer);
- convert_to_string(&cast_option_buffer);
- if (Z_TYPE(cast_option_buffer) == IS_STRING) {
- buffer = estrndup(Z_STRVAL(cast_option_buffer), Z_STRLEN(cast_option_buffer));
- buffer_len = Z_STRLEN(cast_option_buffer);
- zval_dtor(&cast_option_buffer);
- break;
- }
- zval_dtor(&cast_option_buffer);
+ case IS_OBJECT:
+ {
+ zend_string *tmp = zval_get_string(option_buffer);
+ buffer = estrndup(tmp->val, tmp->len);
+ buffer_len = tmp->len;
+ zend_string_release(tmp);
+ break;
}
case IS_FALSE:
case IS_TRUE:
@@ -415,7 +410,7 @@ PHP_FUNCTION(password_hash)
/* This cast is safe, since both values are defined here in code and cannot overflow */
hash_len = (int) (hash_format_len + salt_len);
- if ((result = php_crypt(password, (int)password_len, hash, hash_len)) == NULL) {
+ if ((result = php_crypt(password, (int)password_len, hash, hash_len, 1)) == NULL) {
efree(hash);
RETURN_FALSE;
}
diff --git a/ext/standard/php_crypt.h b/ext/standard/php_crypt.h
index d77180bd0b..88368c966f 100644
--- a/ext/standard/php_crypt.h
+++ b/ext/standard/php_crypt.h
@@ -23,7 +23,7 @@
#ifndef PHP_CRYPT_H
#define PHP_CRYPT_H
-PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const char *salt, int salt_len);
+PHPAPI zend_string *php_crypt(const char *password, const int pass_len, const char *salt, int salt_len, zend_bool quiet);
PHP_FUNCTION(crypt);
#if HAVE_CRYPT
PHP_MINIT_FUNCTION(crypt);
diff --git a/ext/standard/php_string.h b/ext/standard/php_string.h
index a02658dc63..b5cf8f3051 100644
--- a/ext/standard/php_string.h
+++ b/ext/standard/php_string.h
@@ -154,6 +154,9 @@ PHPAPI char *php_strerror(int errnum);
# define php_mblen(ptr, len) 1
# define php_mb_reset()
#elif defined(_REENTRANT) && defined(HAVE_MBRLEN) && defined(HAVE_MBSTATE_T)
+# ifdef PHP_WIN32
+# include <wchar.h>
+# endif
# define php_mblen(ptr, len) ((int) mbrlen(ptr, len, &BG(mblen_state)))
# define php_mb_reset() memset(&BG(mblen_state), 0, sizeof(BG(mblen_state)))
#else
diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c
index d774808a7b..bbcdd1073a 100644
--- a/ext/standard/proc_open.c
+++ b/ext/standard/proc_open.c
@@ -240,6 +240,7 @@ static void proc_open_rsrc_dtor(zend_resource *rsrc)
FG(pclose_ret) = -1;
#endif
_php_free_envp(proc->env, proc->is_persistent);
+ pefree(proc->pipes, proc->is_persistent);
pefree(proc->command, proc->is_persistent);
pefree(proc, proc->is_persistent);
@@ -434,7 +435,8 @@ PHP_FUNCTION(proc_open)
zval *descitem = NULL;
zend_string *str_index;
zend_ulong nindex;
- struct php_proc_open_descriptor_item descriptors[PHP_PROC_OPEN_MAX_DESCRIPTORS];
+ struct php_proc_open_descriptor_item *descriptors = NULL;
+ int ndescriptors_array;
#ifdef PHP_WIN32
PROCESS_INFORMATION pi;
HANDLE childHandle;
@@ -499,7 +501,11 @@ PHP_FUNCTION(proc_open)
memset(&env, 0, sizeof(env));
}
- memset(descriptors, 0, sizeof(descriptors));
+ ndescriptors_array = zend_hash_num_elements(Z_ARRVAL_P(descriptorspec));
+
+ descriptors = safe_emalloc(sizeof(struct php_proc_open_descriptor_item), ndescriptors_array, 0);
+
+ memset(descriptors, 0, sizeof(struct php_proc_open_descriptor_item) * ndescriptors_array);
#ifdef PHP_WIN32
/* we use this to allow the child to inherit handles */
@@ -669,9 +675,7 @@ PHP_FUNCTION(proc_open)
goto exit_fail;
}
}
-
- if (++ndesc == PHP_PROC_OPEN_MAX_DESCRIPTORS)
- break;
+ ndesc++;
} ZEND_HASH_FOREACH_END();
#ifdef PHP_WIN32
@@ -875,6 +879,7 @@ PHP_FUNCTION(proc_open)
proc = (struct php_process_handle*)pemalloc(sizeof(struct php_process_handle), is_persistent);
proc->is_persistent = is_persistent;
proc->command = command;
+ proc->pipes = pemalloc(sizeof(zend_resource *) * ndesc, is_persistent);
proc->npipes = ndesc;
proc->child = child;
#ifdef PHP_WIN32
@@ -952,10 +957,12 @@ PHP_FUNCTION(proc_open)
}
}
+ efree(descriptors);
ZVAL_RES(return_value, zend_register_resource(proc, le_proc_open));
return;
exit_fail:
+ efree(descriptors);
_php_free_envp(env, is_persistent);
pefree(command, is_persistent);
#if PHP_CAN_DO_PTS
diff --git a/ext/standard/proc_open.h b/ext/standard/proc_open.h
index 13177ce2b0..52e5c1ed87 100644
--- a/ext/standard/proc_open.h
+++ b/ext/standard/proc_open.h
@@ -25,8 +25,6 @@ typedef int php_file_descriptor_t;
typedef pid_t php_process_id_t;
#endif
-#define PHP_PROC_OPEN_MAX_DESCRIPTORS 16
-
/* Environment block under win32 is a NUL terminated sequence of NUL terminated
* name=value strings.
* Under unix, it is an argv style array.
@@ -44,7 +42,7 @@ struct php_process_handle {
HANDLE childHandle;
#endif
int npipes;
- zend_resource *pipes[PHP_PROC_OPEN_MAX_DESCRIPTORS];
+ zend_resource **pipes;
char *command;
int is_persistent;
php_process_env_t env;
diff --git a/ext/standard/streamsfuncs.c b/ext/standard/streamsfuncs.c
index fa9758b06c..be0cbefac1 100644
--- a/ext/standard/streamsfuncs.c
+++ b/ext/standard/streamsfuncs.c
@@ -397,7 +397,7 @@ PHP_FUNCTION(stream_get_contents)
{
php_stream *stream;
zval *zsrc;
- zend_long maxlen = PHP_STREAM_COPY_ALL,
+ zend_long maxlen = (ssize_t) PHP_STREAM_COPY_ALL,
desiredpos = -1L;
zend_string *contents;
@@ -955,7 +955,7 @@ PHP_FUNCTION(stream_context_get_options)
RETURN_FALSE;
}
- RETURN_ZVAL(&context->options, 1, 0);
+ ZVAL_COPY(return_value, &context->options);
}
/* }}} */
@@ -1038,8 +1038,8 @@ PHP_FUNCTION(stream_context_get_params)
add_assoc_zval_ex(return_value, "notification", sizeof("notification")-1, &context->notifier->ptr);
if (Z_REFCOUNTED(context->notifier->ptr)) Z_ADDREF(context->notifier->ptr);
}
- ZVAL_ZVAL(&options, &context->options, 1, 0);
- add_assoc_zval_ex(return_value, "options", sizeof("options")-1, &options);
+ if (Z_REFCOUNTED(context->options)) Z_ADDREF(context->options);
+ add_assoc_zval_ex(return_value, "options", sizeof("options")-1, &context->options);
}
/* }}} */
diff --git a/ext/standard/string.c b/ext/standard/string.c
index 3162533186..9bf3b4c61f 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -1200,69 +1200,79 @@ PHP_FUNCTION(explode)
*/
PHPAPI void php_implode(const zend_string *delim, zval *arr, zval *return_value)
{
- zval *tmp;
- smart_str implstr = {0};
- int numelems, i = 0;
- zend_string *str;
+ zval *tmp;
+ int numelems;
+ zend_string *str;
+ char *cptr;
+ size_t len = 0;
+ zend_string **strings, **strptr;
numelems = zend_hash_num_elements(Z_ARRVAL_P(arr));
if (numelems == 0) {
RETURN_EMPTY_STRING();
+ } else if (numelems == 1) {
+ /* loop to search the first not undefined element... */
+ ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), tmp) {
+ RETURN_STR(zval_get_string(tmp));
+ } ZEND_HASH_FOREACH_END();
}
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), tmp) {
-again:
- switch (Z_TYPE_P(tmp)) {
- case IS_STRING:
- smart_str_append(&implstr, Z_STR_P(tmp));
- break;
-
- case IS_LONG:
- smart_str_append_long(&implstr, Z_LVAL_P(tmp));
- break;
+ strings = emalloc((sizeof(zend_long) + sizeof(zend_string *)) * numelems);
+ strptr = strings - 1;
- case IS_TRUE:
- smart_str_appendl(&implstr, "1", sizeof("1")-1);
- break;
-
- case IS_NULL:
- case IS_FALSE:
- break;
-
- case IS_DOUBLE: {
- char *stmp;
- size_t str_len = spprintf(&stmp, 0, "%.*G", (int) EG(precision), Z_DVAL_P(tmp));
- smart_str_appendl(&implstr, stmp, str_len);
- efree(stmp);
- break;
+ ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(arr), tmp) {
+ if (Z_TYPE_P(tmp) == IS_LONG) {
+ double val = Z_LVAL_P(tmp);
+ *++strptr = NULL;
+ ((zend_long *) (strings + numelems))[strptr - strings] = Z_LVAL_P(tmp);
+ if (val < 0) {
+ val = -10 * val;
}
-
- case IS_REFERENCE:
- tmp = Z_REFVAL_P(tmp);
- goto again;
-
- default:
- str = zval_get_string(tmp);
- smart_str_append(&implstr, str);
- zend_string_release(str);
- break;
-
+ if (val < 10) {
+ len++;
+ } else {
+ len += (int) log10(10 * (double) val);
+ }
+ } else {
+ *++strptr = zval_get_string(tmp);
+ len += (*strptr)->len;
}
+ } ZEND_HASH_FOREACH_END();
- if (++i != numelems) {
- smart_str_append(&implstr, delim);
+ str = zend_string_alloc(len + (numelems - 1) * delim->len, 0);
+ cptr = str->val + str->len;
+ *cptr = 0;
+
+ do {
+ if (*strptr) {
+ cptr -= (*strptr)->len;
+ memcpy(cptr, (*strptr)->val, (*strptr)->len);
+ zend_string_release(*strptr);
+ } else {
+ char *oldPtr = cptr;
+ char oldVal = *cptr;
+ zend_long val = ((zend_long *) (strings + numelems))[strptr - strings];
+ cptr = zend_print_long_to_buf(cptr, val);
+ *oldPtr = oldVal;
}
- } ZEND_HASH_FOREACH_END();
- smart_str_0(&implstr);
+ cptr -= delim->len;
+ memcpy(cptr, delim->val, delim->len);
+ } while (--strptr > strings);
- if (implstr.s) {
- RETURN_NEW_STR(implstr.s);
+ if (*strptr) {
+ memcpy(str->val, (*strptr)->val, (*strptr)->len);
+ zend_string_release(*strptr);
} else {
- smart_str_free(&implstr);
- RETURN_EMPTY_STRING();
+ char *oldPtr = cptr;
+ char oldVal = *cptr;
+ zend_print_long_to_buf(cptr, ((zend_long *) (strings + numelems))[strptr - strings]);
+ *oldPtr = oldVal;
}
+
+ efree(strings);
+ RETURN_NEW_STR(str);
}
/* }}} */
@@ -1725,17 +1735,17 @@ PHP_FUNCTION(pathinfo)
}
if (opt == PHP_PATHINFO_ALL) {
- RETURN_ZVAL(&tmp, 0, 1);
+ ZVAL_COPY_VALUE(return_value, &tmp);
} else {
zval *element;
if ((element = zend_hash_get_current_data(Z_ARRVAL(tmp))) != NULL) {
- RETVAL_ZVAL(element, 1, 0);
+ ZVAL_DEREF(element);
+ ZVAL_COPY(return_value, element);
} else {
ZVAL_EMPTY_STRING(return_value);
}
+ zval_ptr_dtor(&tmp);
}
-
- zval_ptr_dtor(&tmp);
}
/* }}} */
diff --git a/ext/standard/tests/array/bug69723.phpt b/ext/standard/tests/array/bug69723.phpt
new file mode 100644
index 0000000000..23b3576a51
--- /dev/null
+++ b/ext/standard/tests/array/bug69723.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Bug #69723 (Passing parameters by reference and array_column)
+--FILE--
+<?php
+function byReference( & $array){
+ foreach($array as &$item){
+ $item['nanana'] = 'batman';
+ $item['superhero'] = 'robin';
+ }
+}
+
+$array = [
+ [
+ 'superhero'=> 'superman',
+ 'nanana' => 'no nana'
+ ],
+ [
+ 'superhero'=> 'acuaman',
+ 'nanana' => 'no nana'
+ ],
+
+ ];
+
+var_dump(array_column($array, 'superhero'));
+byReference($array);
+var_dump(array_column($array, 'superhero'));
+?>
+--EXPECT--
+array(2) {
+ [0]=>
+ string(8) "superman"
+ [1]=>
+ string(7) "acuaman"
+}
+array(2) {
+ [0]=>
+ string(5) "robin"
+ [1]=>
+ string(5) "robin"
+}
diff --git a/ext/standard/tests/file/bug69628.phpt b/ext/standard/tests/file/bug69628.phpt
new file mode 100644
index 0000000000..7e18619a3e
--- /dev/null
+++ b/ext/standard/tests/file/bug69628.phpt
@@ -0,0 +1,49 @@
+--TEST--
+Bug #69628: GLOB_BRACE with multiple brackets within the braces fails
+--SKIPIF--
+<?php
+if (!defined('GLOB_BRACE')) {
+ die('skip this test requires GLOB_BRACE support');
+}
+?>
+--FILE--
+<?php
+
+$file_path = dirname(__FILE__);
+
+// temp dirname used here
+$dirname = "$file_path/bug69628";
+
+// temp dir created
+mkdir($dirname);
+
+// temp files created
+file_put_contents("$dirname/image.jPg", '');
+file_put_contents("$dirname/image.gIf", '');
+file_put_contents("$dirname/image.png", '');
+
+sort_var_dump(glob("$dirname/*.{[jJ][pP][gG],[gG][iI][fF]}", GLOB_BRACE));
+
+function sort_var_dump($results) {
+ sort($results);
+ var_dump($results);
+}
+
+?>
+--CLEAN--
+<?php
+
+$file_path = dirname(__FILE__);
+unlink("$file_path/bug69628/image.jPg");
+unlink("$file_path/bug69628/image.gIf");
+unlink("$file_path/bug69628/image.png");
+rmdir("$file_path/bug69628/");
+
+?>
+--EXPECTF--
+array(2) {
+ [0]=>
+ string(%d) "%s/bug69628/image.gIf"
+ [1]=>
+ string(%d) "%s/bug69628/image.jPg"
+}
diff --git a/ext/standard/tests/file/glob_variation.phpt b/ext/standard/tests/file/glob_variation.phpt
index 00fd6ff3ed..9d3b879379 100644
--- a/ext/standard/tests/file/glob_variation.phpt
+++ b/ext/standard/tests/file/glob_variation.phpt
@@ -5,6 +5,9 @@ Test glob() function: usage variations
if (substr(PHP_OS, 0, 3) == 'WIN') {
die('skip.. Not valid for Windows');
}
+if (!defined('GLOB_BRACE')) {
+ die('skip this test requires GLOB_BRACE support');
+}
?>
--FILE--
<?php
diff --git a/ext/standard/tests/file/tempnam_variation3-win32.phpt b/ext/standard/tests/file/tempnam_variation3-win32.phpt
index cc8194afa3..df0d88feda 100644
--- a/ext/standard/tests/file/tempnam_variation3-win32.phpt
+++ b/ext/standard/tests/file/tempnam_variation3-win32.phpt
@@ -102,7 +102,10 @@ OK
Failed, not created in the correct directory %s vs %s
0
-- Iteration 6 --
-OK
+
+Warning: tempnam() expects parameter 2 to be a valid path, string given in %stempnam_variation3-win32.php on line 54
+Failed, not created in the correct directory %s vs %sext\standard\tests\file\tempnamVar3
+0
-- Iteration 7 --
Warning: tempnam() expects parameter 2 to be a valid path, array given in %s\ext\standard\tests\file\tempnam_variation3-win32.php on line %d
diff --git a/ext/standard/tests/general_functions/bug69646.phpt b/ext/standard/tests/general_functions/bug69646.phpt
new file mode 100644
index 0000000000..b077c67319
--- /dev/null
+++ b/ext/standard/tests/general_functions/bug69646.phpt
@@ -0,0 +1,47 @@
+--TEST--
+Bug #69646 OS command injection vulnerability in escapeshellarg()
+--SKIPIF--
+<?php
+if( substr(PHP_OS, 0, 3) != "WIN" )
+ die("skip.. Windows only");
+?>
+--FILE--
+<?php
+
+$a = 'a\\';
+$b = 'b -c d\\';
+var_dump( $a, escapeshellarg($a) );
+var_dump( $b, escapeshellarg($b) );
+
+$helper_script = <<<SCRIPT
+<?php
+
+print( "--- ARG INFO ---\n" );
+var_dump( \$argv );
+
+SCRIPT;
+
+$script = dirname(__FILE__) . DIRECTORY_SEPARATOR . "arginfo.php";
+file_put_contents($script, $helper_script);
+
+$cmd = PHP_BINARY . " " . $script . " " . escapeshellarg($a) . " " . escapeshellarg($b);
+
+system($cmd);
+
+unlink($script);
+?>
+--EXPECTF--
+string(2) "a\"
+string(5) ""a\\""
+string(7) "b -c d\"
+string(10) ""b -c d\\""
+--- ARG INFO ---
+array(3) {
+ [0]=>
+ string(%d) "%sarginfo.php"
+ [1]=>
+ string(2) "a\"
+ [2]=>
+ string(7) "b -c d\"
+}
+
diff --git a/ext/standard/tests/general_functions/getrusage_basic.phpt b/ext/standard/tests/general_functions/getrusage_basic.phpt
index 0e5b42c420..b2379a7663 100644
--- a/ext/standard/tests/general_functions/getrusage_basic.phpt
+++ b/ext/standard/tests/general_functions/getrusage_basic.phpt
@@ -1,10 +1,7 @@
--TEST--
Test getrusage() function: basic test
--SKIPIF--
-<?php
-if( substr(PHP_OS, 0, 3) == "WIN" )
- die("skip.. Do not run on Windows");
-?>
+<?php if (!function_exists("getrusage")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array getrusage ([ int $who ] )
diff --git a/ext/standard/tests/general_functions/getrusage_error.phpt b/ext/standard/tests/general_functions/getrusage_error.phpt
index f00627a766..7ac99655b8 100644
--- a/ext/standard/tests/general_functions/getrusage_error.phpt
+++ b/ext/standard/tests/general_functions/getrusage_error.phpt
@@ -1,10 +1,7 @@
--TEST--
Test getrusage() function : error conditions - incorrect number of args
--SKIPIF--
-<?php
-if( substr(PHP_OS, 0, 3) == "WIN" )
- die("skip.. Do not run on Windows");
-?>
+<?php if (!function_exists("getrusage")) print "skip"; ?>
--FILE--
<?php
/* Prototype : array getrusage ([ int $who ] )
diff --git a/ext/standard/tests/general_functions/getrusage_variation1.phpt b/ext/standard/tests/general_functions/getrusage_variation1.phpt
index ae2b150548..568c9c7383 100644
--- a/ext/standard/tests/general_functions/getrusage_variation1.phpt
+++ b/ext/standard/tests/general_functions/getrusage_variation1.phpt
@@ -3,8 +3,7 @@ Test getrusage() function : usage variation - diff data types as $who arg
--SKIPIF--
<?php
if (PHP_INT_SIZE != 8) die("skip this test is for 64-bit only");
-if( substr(PHP_OS, 0, 3) == "WIN" )
- die("skip.. Do not run on Windows");
+if (!function_exists("getrusage")) die("skip");
?>
--FILE--
<?php
diff --git a/ext/standard/tests/general_functions/proc_open_pipes.inc b/ext/standard/tests/general_functions/proc_open_pipes.inc
new file mode 100644
index 0000000000..0d9894683a
--- /dev/null
+++ b/ext/standard/tests/general_functions/proc_open_pipes.inc
@@ -0,0 +1,22 @@
+<?php
+
+function create_sleep_script()
+{
+ $fname = dirname(__FILE__) . DIRECTORY_SEPARATOR . "proc_open_pipes_sleep.php";
+
+ if (!file_exists($fname)) {
+ file_put_contents($fname, "<?php\nsleep(1);\n");
+ }
+
+ return $fname;
+}
+
+function unlink_sleep_script()
+{
+ $fname = dirname(__FILE__) . DIRECTORY_SEPARATOR . "proc_open_pipes_sleep.php";
+
+ if (file_exists($fname)) {
+ unlink($fname);
+ }
+}
+
diff --git a/ext/standard/tests/general_functions/proc_open_pipes1.phpt b/ext/standard/tests/general_functions/proc_open_pipes1.phpt
new file mode 100644
index 0000000000..f6472e2f99
--- /dev/null
+++ b/ext/standard/tests/general_functions/proc_open_pipes1.phpt
@@ -0,0 +1,86 @@
+--TEST--
+proc_open() with > 16 pipes
+--FILE--
+<?php
+
+include dirname(__FILE__) . "/proc_open_pipes.inc";
+
+for ($i = 3; $i<= 30; $i++) {
+ $spec[$i] = array('pipe', 'w');
+}
+
+$php = getenv("TEST_PHP_EXECUTABLE");
+$callee = create_sleep_script();
+proc_open("$php $callee", $spec, $pipes);
+
+var_dump(count($spec));
+var_dump($pipes);
+
+?>
+--CLEAN--
+<?php
+include dirname(__FILE__) . "/proc_open_pipes.inc";
+
+unlink_sleep_script();
+
+?>
+--EXPECTF--
+int(28)
+array(28) {
+ [3]=>
+ resource(%d) of type (Unknown)
+ [4]=>
+ resource(%d) of type (Unknown)
+ [5]=>
+ resource(%d) of type (Unknown)
+ [6]=>
+ resource(%d) of type (Unknown)
+ [7]=>
+ resource(%d) of type (Unknown)
+ [8]=>
+ resource(%d) of type (Unknown)
+ [9]=>
+ resource(%d) of type (Unknown)
+ [10]=>
+ resource(%d) of type (Unknown)
+ [11]=>
+ resource(%d) of type (Unknown)
+ [12]=>
+ resource(%d) of type (Unknown)
+ [13]=>
+ resource(%d) of type (Unknown)
+ [14]=>
+ resource(%d) of type (Unknown)
+ [15]=>
+ resource(%d) of type (Unknown)
+ [16]=>
+ resource(%d) of type (Unknown)
+ [17]=>
+ resource(%d) of type (Unknown)
+ [18]=>
+ resource(%d) of type (Unknown)
+ [19]=>
+ resource(%d) of type (Unknown)
+ [20]=>
+ resource(%d) of type (Unknown)
+ [21]=>
+ resource(%d) of type (Unknown)
+ [22]=>
+ resource(%d) of type (Unknown)
+ [23]=>
+ resource(%d) of type (Unknown)
+ [24]=>
+ resource(%d) of type (Unknown)
+ [25]=>
+ resource(%d) of type (Unknown)
+ [26]=>
+ resource(%d) of type (Unknown)
+ [27]=>
+ resource(%d) of type (Unknown)
+ [28]=>
+ resource(%d) of type (Unknown)
+ [29]=>
+ resource(%d) of type (Unknown)
+ [30]=>
+ resource(%d) of type (Unknown)
+}
diff --git a/ext/standard/tests/general_functions/proc_open_pipes2.phpt b/ext/standard/tests/general_functions/proc_open_pipes2.phpt
new file mode 100644
index 0000000000..b07a19e143
--- /dev/null
+++ b/ext/standard/tests/general_functions/proc_open_pipes2.phpt
@@ -0,0 +1,28 @@
+--TEST--
+proc_open() with no pipes
+--FILE--
+<?php
+
+include dirname(__FILE__) . "/proc_open_pipes.inc";
+
+$spec = array();
+
+$php = getenv("TEST_PHP_EXECUTABLE");
+$callee = create_sleep_script();
+proc_open("$php $callee", $spec, $pipes);
+
+var_dump(count($spec));
+var_dump($pipes);
+
+?>
+--CLEAN--
+<?php
+include dirname(__FILE__) . "/proc_open_pipes.inc";
+
+unlink_sleep_script();
+
+?>
+--EXPECTF--
+int(0)
+array(0) {
+}
diff --git a/ext/standard/tests/general_functions/proc_open_pipes3.phpt b/ext/standard/tests/general_functions/proc_open_pipes3.phpt
new file mode 100644
index 0000000000..2ddcd276d7
--- /dev/null
+++ b/ext/standard/tests/general_functions/proc_open_pipes3.phpt
@@ -0,0 +1,64 @@
+--TEST--
+proc_open() with invalid pipes
+--FILE--
+<?php
+
+include dirname(__FILE__) . "/proc_open_pipes.inc";
+
+for ($i = 3; $i<= 5; $i++) {
+ $spec[$i] = array('pipe', 'w');
+}
+
+$php = getenv("TEST_PHP_EXECUTABLE");
+$callee = create_sleep_script();
+
+$spec[$i] = array('pi');
+proc_open("$php $callee", $spec, $pipes);
+
+$spec[$i] = 1;
+proc_open("$php $callee", $spec, $pipes);
+
+$spec[$i] = array('pipe', "test");
+proc_open("$php $callee", $spec, $pipes);
+var_dump($pipes);
+
+$spec[$i] = array('file', "test", "z");
+proc_open("$php $callee", $spec, $pipes);
+var_dump($pipes);
+
+echo "END\n";
+?>
+--CLEAN--
+<?php
+include dirname(__FILE__) . "/proc_open_pipes.inc";
+
+unlink_sleep_script();
+
+?>
+--EXPECTF--
+Warning: proc_open(): pi is not a valid descriptor spec/mode in %s on line %d
+
+Warning: proc_open(): Descriptor item must be either an array or a File-Handle in %s on line %d
+array(4) {
+ [3]=>
+ resource(%d) of type (Unknown)
+ [4]=>
+ resource(%d) of type (Unknown)
+ [5]=>
+ resource(%d) of type (Unknown)
+ [6]=>
+ resource(%d) of type (Unknown)
+}
+
+Warning: proc_open(test): failed to open stream: %s in %s on line %d
+array(4) {
+ [3]=>
+ resource(%d) of type (Unknown)
+ [4]=>
+ resource(%d) of type (Unknown)
+ [5]=>
+ resource(%d) of type (Unknown)
+ [6]=>
+ resource(%d) of type (Unknown)
+}
+END
diff --git a/ext/standard/tests/mail/mail_basic6.phpt b/ext/standard/tests/mail/mail_basic6.phpt
new file mode 100644
index 0000000000..d0d45b78f3
--- /dev/null
+++ b/ext/standard/tests/mail/mail_basic6.phpt
@@ -0,0 +1,329 @@
+--TEST--
+Test mail() function : basic functionality
+--INI--
+sendmail_path=tee mailBasic.out >/dev/null
+mail.add_x_header = Off
+--SKIPIF--
+<?php
+if(substr(PHP_OS, 0, 3) == "WIN")
+ die("skip Won't run on Windows");
+?>
+--FILE--
+<?php
+/* Prototype : int mail(string to, string subject, string message [, string additional_headers [, string additional_parameters]])
+ * Description: Send an email message with invalid addtional_headers
+ * Source code: ext/standard/mail.c
+ * Alias to functions:
+ */
+
+echo "*** Testing mail() : basic functionality ***\n";
+
+
+// Valid header
+$to = 'user@example.com';
+$subject = 'Test Subject';
+$message = 'A Message';
+$additional_headers = "HEAD1: a\r\nHEAD2: b\r\n";
+$outFile = "mailBasic.out";
+@unlink($outFile);
+
+echo "-- Valid Header --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo file_get_contents($outFile);
+unlink($outFile);
+
+// Valid header
+$additional_headers = "HEAD1: a\nHEAD2: b\n";
+@unlink($outFile);
+
+echo "-- Valid Header --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Valid header
+// \r is accepted as valid. This may be changed to invalid.
+$additional_headers = "HEAD1: a\rHEAD2: b\r";
+@unlink($outFile);
+
+echo "-- Valid Header --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+//===============================================================================
+// Invalid header
+$additional_headers = "\nHEAD1: a\nHEAD2: b\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - preceeding newline--\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+$additional_headers = "\rHEAD1: a\nHEAD2: b\r";
+@unlink($outFile);
+
+echo "-- Invalid Header - preceeding newline--\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+$additional_headers = "\r\nHEAD1: a\r\nHEAD2: b\r\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - preceeding newline--\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+$additional_headers = "\r\n\r\nHEAD1: a\r\nHEAD2: b\r\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - preceeding newline--\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+$additional_headers = "\n\nHEAD1: a\r\nHEAD2: b\r\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - preceeding newline--\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+$additional_headers = "\r\rHEAD1: a\r\nHEAD2: b\r\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - preceeding newline--\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+$additional_headers = "HEAD1: a\r\n\r\nHEAD2: b\r\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - multiple newlines in the middle --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+$additional_headers = "HEAD1: a\r\n\nHEAD2: b\r\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - multiple newlines in the middle --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+$additional_headers = "HEAD1: a\n\nHEAD2: b\r\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - multiple newlines in the middle --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+$additional_headers = "HEAD1: a\r\rHEAD2: b\r\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - multiple newlines in the middle --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+$additional_headers = "HEAD1: a\n\rHEAD2: b\r\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - multiple newlines in the middle --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+$additional_headers = "HEAD1: a\n\r\nHEAD2: b\r\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - multiple newlines in the middle --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+// Invalid, but PHP_FUNCTION(mail) trims newlines
+$additional_headers = "HEAD1: a\r\nHEAD2: b\r\n\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - trailing newlines --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+// Invalid, but PHP_FUNCTION(mail) trims newlines
+$additional_headers = "HEAD1: a\r\nHEAD2: b\n\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - trailing newlines --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+// Invalid, but PHP_FUNCTION(mail) trims newlines
+$additional_headers = "HEAD1: a\r\nHEAD2: b\n";
+@unlink($outFile);
+
+echo "-- Invalid Header - trailing newlines --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+// Invalid header
+// Invalid, but PHP_FUNCTION(mail) trims newlines
+$additional_headers = "HEAD1: a\r\nHEAD2: b\r";
+@unlink($outFile);
+
+echo "-- Invalid Header - trailing newlines --\n";
+// Calling mail() with all additional headers
+var_dump( mail($to, $subject, $message, $additional_headers) );
+echo @file_get_contents($outFile);
+@unlink($outFile);
+
+?>
+===DONE===
+--EXPECTF--
+*** Testing mail() : basic functionality ***
+-- Valid Header --
+bool(true)
+To: user@example.com
+Subject: Test Subject
+HEAD1: a
+HEAD2: b
+
+A Message
+-- Valid Header --
+bool(true)
+To: user@example.com
+Subject: Test Subject
+HEAD1: a
+HEAD2: b
+
+A Message
+-- Valid Header --
+bool(true)
+To: user@example.com
+Subject: Test Subject
+HEAD1: a HEAD2: b
+
+A Message
+-- Invalid Header - preceeding newline--
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - preceeding newline--
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - preceeding newline--
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - preceeding newline--
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - preceeding newline--
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - preceeding newline--
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - multiple newlines in the middle --
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - multiple newlines in the middle --
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - multiple newlines in the middle --
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - multiple newlines in the middle --
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - multiple newlines in the middle --
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - multiple newlines in the middle --
+
+Warning: mail(): Multiple or malformed newlines found in additional_header in %s/mail_basic6.php on line %d
+bool(false)
+-- Invalid Header - trailing newlines --
+bool(true)
+To: user@example.com
+Subject: Test Subject
+HEAD1: a
+HEAD2: b
+
+A Message
+-- Invalid Header - trailing newlines --
+bool(true)
+To: user@example.com
+Subject: Test Subject
+HEAD1: a
+HEAD2: b
+
+A Message
+-- Invalid Header - trailing newlines --
+bool(true)
+To: user@example.com
+Subject: Test Subject
+HEAD1: a
+HEAD2: b
+
+A Message
+-- Invalid Header - trailing newlines --
+bool(true)
+To: user@example.com
+Subject: Test Subject
+HEAD1: a
+HEAD2: b
+
+A Message
+===DONE===
diff --git a/ext/standard/tests/password/password_verify.phpt b/ext/standard/tests/password/password_verify.phpt
index e7ecc7edd3..a196763c13 100644
--- a/ext/standard/tests/password/password_verify.phpt
+++ b/ext/standard/tests/password/password_verify.phpt
@@ -11,6 +11,13 @@ var_dump(password_verify("foo", '$2a$07$usesomesillystringforsalt$'));
var_dump(password_verify('rasmusler', '$2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi'));
var_dump(password_verify('rasmuslerdorf', '$2a$07$usesomesillystringfore2uDLvp1Ii2e./U9C8sBjqp8I90dH6hi'));
+
+var_dump(password_verify("foo", null));
+
+var_dump(password_verify("rasmuslerdorf", "rl.3StKT.4T8M"));
+
+var_dump(password_verify("foo", "$1"));
+
echo "OK!";
?>
--EXPECT--
@@ -18,4 +25,7 @@ bool(false)
bool(false)
bool(false)
bool(true)
+bool(false)
+bool(true)
+bool(false)
OK!
diff --git a/ext/standard/tests/php_version_win_const.phpt b/ext/standard/tests/php_version_win_const.phpt
new file mode 100644
index 0000000000..12de79b1ae
--- /dev/null
+++ b/ext/standard/tests/php_version_win_const.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Check that windows version constants are initialized
+--SKIPIF--
+<?php
+if (substr(PHP_OS, 0, 3) != 'WIN') {
+ die('skip.. Windows only');
+}
+?>
+--FILE--
+<?php
+var_dump(PHP_WINDOWS_VERSION_MAJOR > 0, PHP_WINDOWS_VERSION_MAJOR, PHP_WINDOWS_VERSION_MINOR);
+?>
+==DONE==
+--EXPECTF--
+bool(true)
+int(%d)
+int(%d)
+==DONE==
diff --git a/ext/standard/tests/strings/004.phpt b/ext/standard/tests/strings/004.phpt
index b9904c614a..e1414db46c 100644
--- a/ext/standard/tests/strings/004.phpt
+++ b/ext/standard/tests/strings/004.phpt
@@ -33,52 +33,52 @@ stats('str_shuffle', $a);
?>
--EXPECTREGEX--
shuffle
-1234: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-1243: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-1324: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-1342: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-1423: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-1432: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2134: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2143: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2314: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2341: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2413: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2431: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3124: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3142: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3214: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3241: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3412: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3421: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4123: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4132: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4213: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4231: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4312: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4321: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
+1234: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+1243: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+1324: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+1342: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+1423: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+1432: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2134: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2143: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2314: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2341: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2413: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2431: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3124: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3142: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3214: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3241: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3412: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3421: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4123: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4132: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4213: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4231: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4312: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4321: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
str_shuffle
-1234: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-1243: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-1324: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-1342: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-1423: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-1432: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2134: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2143: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2314: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2341: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2413: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-2431: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3124: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3142: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3214: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3241: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3412: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-3421: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4123: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4132: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4213: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4231: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4312: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
-4321: 3[0-9][0-9][0-9]: 0.0[3-4][0-9]
+1234: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+1243: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+1324: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+1342: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+1423: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+1432: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2134: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2143: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2314: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2341: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2413: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+2431: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3124: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3142: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3214: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3241: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3412: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+3421: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4123: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4132: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4213: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4231: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4312: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
+4321: [34][0-9][0-9][0-9]: 0.0[3-4][0-9]
diff --git a/ext/standard/type.c b/ext/standard/type.c
index f884017f6f..8251a3f155 100644
--- a/ext/standard/type.c
+++ b/ext/standard/type.c
@@ -101,7 +101,6 @@ PHP_FUNCTION(settype)
}
ZVAL_DEREF(var);
- SEPARATE_ZVAL_NOREF(var);
if (!strcasecmp(type, "integer")) {
convert_to_long(var);
} else if (!strcasecmp(type, "int")) {
@@ -155,7 +154,7 @@ PHP_FUNCTION(intval)
ZEND_PARSE_PARAMETERS_END();
#endif
- RETVAL_ZVAL(num, 1, 0);
+ ZVAL_DUP(return_value, num);
convert_to_long_base(return_value, (int)base);
}
/* }}} */
@@ -170,8 +169,7 @@ PHP_FUNCTION(floatval)
return;
}
- RETVAL_ZVAL(num, 1, 0);
- convert_to_double(return_value);
+ RETURN_DOUBLE(zval_get_double(num));
}
/* }}} */
diff --git a/ext/sysvmsg/sysvmsg.c b/ext/sysvmsg/sysvmsg.c
index 80fd7e940f..d0a079c280 100644
--- a/ext/sysvmsg/sysvmsg.c
+++ b/ext/sysvmsg/sysvmsg.c
@@ -273,7 +273,7 @@ PHP_FUNCTION(msg_get_queue)
RETURN_FALSE;
}
}
- RETVAL_ZVAL(zend_list_insert(mq, le_sysvmsg), 0, 0);
+ ZVAL_COPY_VALUE(return_value, zend_list_insert(mq, le_sysvmsg));
}
/* }}} */
diff --git a/ext/tokenizer/tests/bug67395.phpt b/ext/tokenizer/tests/bug67395.phpt
index c9b7f3012f..8101c81edb 100644
--- a/ext/tokenizer/tests/bug67395.phpt
+++ b/ext/tokenizer/tests/bug67395.phpt
@@ -1,5 +1,7 @@
--TEST--
Bug 67395: token_name() does not return name for T_POW and T_POW_EQUAL token
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
--FILE--
<?php
diff --git a/ext/tokenizer/tests/token_get_all_TOKEN_PARSE_000.phpt b/ext/tokenizer/tests/token_get_all_TOKEN_PARSE_000.phpt
new file mode 100644
index 0000000000..b9da91502a
--- /dev/null
+++ b/ext/tokenizer/tests/token_get_all_TOKEN_PARSE_000.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Parse errors during token_get_all() with TOKEN_PARSE flag
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
+--FILE--
+<?php
+
+try {
+ token_get_all('<?php invalid code;', TOKEN_PARSE);
+} catch (ParseError $e) {
+ echo $e->getMessage(), PHP_EOL;
+}
+
+echo "Done";
+
+?>
+--EXPECT--
+syntax error, unexpected 'code' (T_STRING)
+Done
diff --git a/ext/tokenizer/tests/token_get_all_TOKEN_PARSE_001.phpt b/ext/tokenizer/tests/token_get_all_TOKEN_PARSE_001.phpt
new file mode 100644
index 0000000000..eb0e300964
--- /dev/null
+++ b/ext/tokenizer/tests/token_get_all_TOKEN_PARSE_001.phpt
@@ -0,0 +1,81 @@
+--TEST--
+Semi reserved words support: member access
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
+--FILE--
+<?php
+$tokens = token_get_all('<?php
+X::continue;
+X::$continue;
+$x->$continue;
+X::continue();
+$x->continue();
+X::class;
+
+class X {
+ const CONTINUE = 1;
+ public $x = self::CONTINUE + 1;
+}
+', TOKEN_PARSE);
+
+array_walk($tokens, function($tk) {
+ if(is_array($tk)) {
+ if(($t = token_name($tk[0])) == 'T_WHITESPACE') return;
+ echo "L{$tk[2]}: ".$t." {$tk[1]}", PHP_EOL;
+ }
+ else echo $tk, PHP_EOL;
+});
+
+echo "Done";
+
+?>
+--EXPECTF--
+L1: T_OPEN_TAG <?php
+
+L2: T_STRING X
+L2: T_DOUBLE_COLON ::
+L2: T_STRING continue
+;
+L3: T_STRING X
+L3: T_DOUBLE_COLON ::
+L3: T_VARIABLE $continue
+;
+L4: T_VARIABLE $x
+L4: T_OBJECT_OPERATOR ->
+L4: T_VARIABLE $continue
+;
+L5: T_STRING X
+L5: T_DOUBLE_COLON ::
+L5: T_STRING continue
+(
+)
+;
+L6: T_VARIABLE $x
+L6: T_OBJECT_OPERATOR ->
+L6: T_STRING continue
+(
+)
+;
+L7: T_STRING X
+L7: T_DOUBLE_COLON ::
+L7: T_STRING class
+;
+L9: T_CLASS class
+L9: T_STRING X
+{
+L10: T_CONST const
+L10: T_STRING CONTINUE
+=
+L10: T_LNUMBER 1
+;
+L11: T_PUBLIC public
+L11: T_VARIABLE $x
+=
+L11: T_STRING self
+L11: T_DOUBLE_COLON ::
+L11: T_STRING CONTINUE
++
+L11: T_LNUMBER 1
+;
+}
+Done
diff --git a/ext/tokenizer/tests/token_get_all_TOKEN_PARSE_002.phpt b/ext/tokenizer/tests/token_get_all_TOKEN_PARSE_002.phpt
new file mode 100644
index 0000000000..3dd8e14d84
--- /dev/null
+++ b/ext/tokenizer/tests/token_get_all_TOKEN_PARSE_002.phpt
@@ -0,0 +1,68 @@
+--TEST--
+Semi reserved words support: class const
+--SKIPIF--
+<?php if (!extension_loaded("tokenizer")) print "skip"; ?>
+--FILE--
+<?php
+$tokens = token_get_all('<?php
+ class SomeClass {
+ const CONST = 1;
+ const CONTINUE = (self::CONST + 1);
+ const ARRAY = [1, self::CONTINUE => [3, 4], 5];
+ }
+', TOKEN_PARSE);
+
+array_walk($tokens, function($tk) {
+ if(is_array($tk)) {
+ if(($t = token_name($tk[0])) == 'T_WHITESPACE') return;
+ echo "L{$tk[2]}: ".$t." {$tk[1]}", PHP_EOL;
+ }
+ else echo $tk, PHP_EOL;
+});
+
+echo "Done";
+
+?>
+--EXPECTF--
+L1: T_OPEN_TAG <?php
+
+L2: T_CLASS class
+L2: T_STRING SomeClass
+{
+L3: T_CONST const
+L3: T_STRING CONST
+=
+L3: T_LNUMBER 1
+;
+L4: T_CONST const
+L4: T_STRING CONTINUE
+=
+(
+L4: T_STRING self
+L4: T_DOUBLE_COLON ::
+L4: T_STRING CONST
++
+L4: T_LNUMBER 1
+)
+;
+L5: T_CONST const
+L5: T_STRING ARRAY
+=
+[
+L5: T_LNUMBER 1
+,
+L5: T_STRING self
+L5: T_DOUBLE_COLON ::
+L5: T_STRING CONTINUE
+L5: T_DOUBLE_ARROW =>
+[
+L5: T_LNUMBER 3
+,
+L5: T_LNUMBER 4
+]
+,
+L5: T_LNUMBER 5
+]
+;
+}
+Done
diff --git a/ext/tokenizer/tests/token_get_all_error.phpt b/ext/tokenizer/tests/token_get_all_error.phpt
index 29e97c38c4..9ded0a1774 100644
--- a/ext/tokenizer/tests/token_get_all_error.phpt
+++ b/ext/tokenizer/tests/token_get_all_error.phpt
@@ -19,7 +19,7 @@ var_dump( token_get_all());
echo "-- Testing token_get_all() function with more than expected no. of arguments --\n";
$source = '<?php ?>';
$extra_arg = 10;
-var_dump( token_get_all($source, $extra_arg));
+var_dump( token_get_all($source, true, $extra_arg));
echo "Done"
?>
@@ -28,10 +28,10 @@ echo "Done"
-- Testing token_get_all() function with zero arguments --
-Warning: token_get_all() expects exactly 1 parameter, 0 given in %s on line %d
+Warning: token_get_all() expects at least 1 parameter, 0 given in %s on line 11
NULL
-- Testing token_get_all() function with more than expected no. of arguments --
-Warning: token_get_all() expects exactly 1 parameter, 2 given in %s on line %d
+Warning: token_get_all() expects at most 2 parameters, 3 given in %s on line 17
NULL
-Done
+Done \ No newline at end of file
diff --git a/ext/tokenizer/tokenizer.c b/ext/tokenizer/tokenizer.c
index c011894441..63405ea6cd 100644
--- a/ext/tokenizer/tokenizer.c
+++ b/ext/tokenizer/tokenizer.c
@@ -37,6 +37,12 @@
#define zendcursor LANG_SCNG(yy_cursor)
#define zendlimit LANG_SCNG(yy_limit)
+#define TOKEN_PARSE 1
+
+void tokenizer_token_get_all_register_constants(INIT_FUNC_ARGS) {
+ REGISTER_LONG_CONSTANT("TOKEN_PARSE", TOKEN_PARSE, CONST_CS|CONST_PERSISTENT);
+}
+
/* {{{ arginfo */
ZEND_BEGIN_ARG_INFO_EX(arginfo_token_get_all, 0, 0, 1)
ZEND_ARG_INFO(0, source)
@@ -83,6 +89,7 @@ ZEND_GET_MODULE(tokenizer)
PHP_MINIT_FUNCTION(tokenizer)
{
tokenizer_register_constants(INIT_FUNC_ARGS_PASSTHRU);
+ tokenizer_token_get_all_register_constants(INIT_FUNC_ARGS_PASSTHRU);
return SUCCESS;
}
/* }}} */
@@ -97,19 +104,33 @@ PHP_MINFO_FUNCTION(tokenizer)
}
/* }}} */
-static void tokenize(zval *return_value)
+static zend_bool tokenize(zval *return_value, zend_string *source)
{
+ zval source_zval;
+ zend_lex_state original_lex_state;
zval token;
zval keyword;
int token_type;
zend_bool destroy;
int token_line = 1;
- int need_tokens = -1; // for __halt_compiler lexing. -1 = disabled
+ int need_tokens = -1; /* for __halt_compiler lexing. -1 = disabled */
+
+ ZVAL_STR_COPY(&source_zval, source);
+ zend_save_lexical_state(&original_lex_state);
+ if (zend_prepare_string_for_scanning(&source_zval, "") == FAILURE) {
+ zend_restore_lexical_state(&original_lex_state);
+ return 0;
+ }
+
+ LANG_SCNG(yy_state) = yycINITIAL;
array_init(return_value);
ZVAL_NULL(&token);
while ((token_type = lex_scan(&token))) {
+
+ if(token_type == T_ERROR) break;
+
destroy = 1;
switch (token_type) {
case T_CLOSE_TAG:
@@ -123,8 +144,6 @@ static void tokenize(zval *return_value)
case T_DOC_COMMENT:
destroy = 0;
break;
- case T_ERROR:
- return;
}
if (token_type >= 256) {
@@ -147,13 +166,13 @@ static void tokenize(zval *return_value)
}
ZVAL_NULL(&token);
- // after T_HALT_COMPILER collect the next three non-dropped tokens
+ /* after T_HALT_COMPILER collect the next three non-dropped tokens */
if (need_tokens != -1) {
if (token_type != T_WHITESPACE && token_type != T_OPEN_TAG
- && token_type != T_COMMENT && token_type != T_DOC_COMMENT
- && --need_tokens == 0
+ && token_type != T_COMMENT && token_type != T_DOC_COMMENT
+ && --need_tokens == 0
) {
- // fetch the rest into a T_INLINE_HTML
+ /* fetch the rest into a T_INLINE_HTML */
if (zendcursor != zendlimit) {
array_init(&keyword);
add_next_index_long(&keyword, T_INLINE_HTML);
@@ -169,34 +188,114 @@ static void tokenize(zval *return_value)
token_line = CG(zend_lineno);
}
+
+ zval_dtor(&source_zval);
+ zend_restore_lexical_state(&original_lex_state);
+
+ return 1;
}
-/* {{{ proto array token_get_all(string source)
- */
-PHP_FUNCTION(token_get_all)
+zval token_stream;
+
+void on_event(zend_php_scanner_event event, int token, int line)
{
- zend_string *source;
- zval source_zval;
- zend_lex_state original_lex_state;
+ zval keyword;
+ HashTable *tokens_ht;
+ zval *token_zv;
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "S", &source) == FAILURE) {
- return;
+ switch(event) {
+ case ON_TOKEN:
+ if (token == T_ERROR || token == END) break;
+ if (token >= 256) {
+ array_init(&keyword);
+ add_next_index_long(&keyword, token);
+ add_next_index_stringl(&keyword, (char *)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
+ add_next_index_long(&keyword, line);
+ add_next_index_zval(&token_stream, &keyword);
+ } else {
+ add_next_index_stringl(&token_stream, (char *)LANG_SCNG(yy_text), LANG_SCNG(yy_leng));
+ }
+ break;
+ case ON_FEEDBACK:
+ tokens_ht = Z_ARRVAL(token_stream);
+ token_zv = zend_hash_index_find(tokens_ht, zend_hash_num_elements(tokens_ht) - 1);
+ if (token_zv && Z_TYPE_P(token_zv) == IS_ARRAY) {
+ ZVAL_LONG(zend_hash_index_find(Z_ARRVAL_P(token_zv), 0), token);
+ }
+ break;
+ case ON_STOP:
+ if (LANG_SCNG(yy_cursor) != LANG_SCNG(yy_limit)) {
+ array_init(&keyword);
+ add_next_index_long(&keyword, T_INLINE_HTML);
+ add_next_index_stringl(&keyword,
+ (char *)LANG_SCNG(yy_cursor), LANG_SCNG(yy_limit) - LANG_SCNG(yy_cursor));
+ add_next_index_long(&keyword, CG(zend_lineno));
+ add_next_index_zval(&token_stream, &keyword);
+ }
+ break;
}
+}
+
+static zend_bool tokenize_parse(zval *return_value, zend_string *source)
+{
+ zval source_zval;
+ zend_lex_state original_lex_state;
+ zend_bool original_in_compilation;
+ zend_bool success;
ZVAL_STR_COPY(&source_zval, source);
+
+ original_in_compilation = CG(in_compilation);
+ CG(in_compilation) = 1;
zend_save_lexical_state(&original_lex_state);
- if (zend_prepare_string_for_scanning(&source_zval, "") == FAILURE) {
- zend_restore_lexical_state(&original_lex_state);
- RETURN_FALSE;
- }
+ if ((success = (zend_prepare_string_for_scanning(&source_zval, "") == SUCCESS))) {
+ CG(ast) = NULL;
+ CG(ast_arena) = zend_arena_create(1024 * 32);
+ LANG_SCNG(yy_state) = yycINITIAL;
+ LANG_SCNG(on_event) = on_event;
- LANG_SCNG(yy_state) = yycINITIAL;
+ array_init(&token_stream);
+ if((success = (zendparse() == SUCCESS))) {
+ ZVAL_COPY_VALUE(return_value, &token_stream);
+ } else {
+ zval_ptr_dtor(&token_stream);
+ }
- tokenize(return_value);
+ zend_ast_destroy(CG(ast));
+ zend_arena_destroy(CG(ast_arena));
+ }
+ /* restore compiler and scanner global states */
zend_restore_lexical_state(&original_lex_state);
+ CG(in_compilation) = original_in_compilation;
+
zval_dtor(&source_zval);
+
+ return success;
+}
+
+/* }}} */
+
+/* {{{ proto array token_get_all(string source)
+ */
+PHP_FUNCTION(token_get_all)
+{
+ zend_string *source;
+ zend_long flags = 0;
+ zend_bool success;
+
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "S|l", &source, &flags) == FAILURE) {
+ return;
+ }
+
+ if (flags & TOKEN_PARSE) {
+ success = tokenize_parse(return_value, source);
+ } else {
+ success = tokenize(return_value, source);
+ }
+
+ if (!success) RETURN_FALSE;
}
/* }}} */
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index 1dd76fcba8..7c17fb983a 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -847,7 +847,7 @@ static zval *php_zip_get_property_ptr_ptr(zval *object, zval *member, int type,
zend_object_handlers *std_hnd;
if (Z_TYPE_P(member) != IS_STRING) {
- ZVAL_DUP(&tmp_member, member);
+ ZVAL_COPY(&tmp_member, member);
convert_to_string(&tmp_member);
member = &tmp_member;
cache_slot = NULL;
@@ -881,7 +881,7 @@ static zval *php_zip_read_property(zval *object, zval *member, int type, void **
zend_object_handlers *std_hnd;
if (Z_TYPE_P(member) != IS_STRING) {
- ZVAL_DUP(&tmp_member, member);
+ ZVAL_COPY(&tmp_member, member);
convert_to_string(&tmp_member);
member = &tmp_member;
cache_slot = NULL;
@@ -920,7 +920,7 @@ static int php_zip_has_property(zval *object, zval *member, int type, void **cac
int retval = 0;
if (Z_TYPE_P(member) != IS_STRING) {
- ZVAL_DUP(&tmp_member, member);
+ ZVAL_COPY(&tmp_member, member);
convert_to_string(&tmp_member);
member = &tmp_member;
cache_slot = NULL;
diff --git a/ext/zlib/tests/dictionary_usage.phpt b/ext/zlib/tests/dictionary_usage.phpt
index 8ffa9e8bcd..f7ef3b3a9c 100644
--- a/ext/zlib/tests/dictionary_usage.phpt
+++ b/ext/zlib/tests/dictionary_usage.phpt
@@ -9,6 +9,10 @@ $r = deflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => $dict]);
$a = deflate_add($r, "abdcde", ZLIB_FINISH);
var_dump($a);
+$r = deflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => implode("\0", $dict)."\0"]);
+$dictStr_a = deflate_add($r, "abdcde", ZLIB_FINISH);
+var_dump($dictStr_a === $a);
+
$r = inflate_init(ZLIB_ENCODING_DEFLATE, ["dictionary" => $dict]);
var_dump(inflate_add($r, $a, ZLIB_FINISH));
@@ -19,6 +23,7 @@ var_dump(inflate_add($r, $a, ZLIB_FINISH));
?>
--EXPECTF--
string(%d) "%s"
+bool(true)
string(6) "abdcde"
Warning: inflate_add(): dictionary does not match expected dictionary (incorrect adler32 hash) in %s on line %d
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index 8169424362..b4b95e85a5 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -759,60 +759,87 @@ static zend_bool zlib_create_dictionary_string(HashTable *options, char **dict,
zval *option_buffer;
if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("dictionary"))) != NULL) {
- HashTable *dictionary;
-
ZVAL_DEREF(option_buffer);
- if (Z_TYPE_P(option_buffer) != IS_ARRAY) {
- php_error_docref(NULL, E_WARNING, "dictionary must be of type array, got %s", zend_get_type_by_const(Z_TYPE_P(option_buffer)));
- return 0;
- }
- dictionary = Z_ARR_P(option_buffer);
-
- if (zend_hash_num_elements(dictionary) > 0) {
- char *dictptr;
- zval *cur;
- zend_string **strings = emalloc(sizeof(zend_string *) * zend_hash_num_elements(dictionary));
- zend_string **end, **ptr = strings - 1;
-
- ZEND_HASH_FOREACH_VAL(dictionary, cur) {
+ switch (Z_TYPE_P(option_buffer)) {
+ case IS_STRING: {
+ zend_string *str = Z_STR_P(option_buffer);
int i;
-
- *++ptr = zval_get_string(cur);
- if (!*ptr || (*ptr)->len == 0) {
- if (*ptr) {
- efree(*ptr);
- }
- while (--ptr >= strings) {
- efree(ptr);
+ zend_bool last_null = 1;
+
+ for (i = 0; i < str->len; i++) {
+ if (str->val[i]) {
+ last_null = 0;
+ } else {
+ if (last_null) {
+ php_error_docref(NULL, E_WARNING, "dictionary string must not contain empty entries (two consecutive NULL-bytes or one at the very beginning)");
+ return 0;
+ }
+ last_null = 1;
}
- efree(strings);
- php_error_docref(NULL, E_WARNING, "dictionary entries must be non-empty strings");
- return 0;
}
- for (i = 0; i < (*ptr)->len; i++) {
- if ((*ptr)->val[i] == 0) {
- do {
- efree(ptr);
- } while (--ptr >= strings);
- efree(strings);
- php_error_docref(NULL, E_WARNING, "dictionary entries must not contain a NULL-byte");
- return 0;
- }
+ if (!last_null) {
+ php_error_docref(NULL, E_WARNING, "dictionary string must be NULL-byte terminated (each dictionary entry has to be NULL-terminated)");
+ }
+
+ *dict = emalloc(str->len);
+ memcpy(*dict, str->val, str->len);
+ *dictlen = str->len;
+ } break;
+
+ case IS_ARRAY: {
+ HashTable *dictionary = Z_ARR_P(option_buffer);
+
+ if (zend_hash_num_elements(dictionary) > 0) {
+ char *dictptr;
+ zval *cur;
+ zend_string **strings = emalloc(sizeof(zend_string *) * zend_hash_num_elements(dictionary));
+ zend_string **end, **ptr = strings - 1;
+
+ ZEND_HASH_FOREACH_VAL(dictionary, cur) {
+ int i;
+
+ *++ptr = zval_get_string(cur);
+ if (!*ptr || (*ptr)->len == 0) {
+ if (*ptr) {
+ efree(*ptr);
+ }
+ while (--ptr >= strings) {
+ efree(ptr);
+ }
+ efree(strings);
+ php_error_docref(NULL, E_WARNING, "dictionary entries must be non-empty strings");
+ return 0;
+ }
+ for (i = 0; i < (*ptr)->len; i++) {
+ if ((*ptr)->val[i] == 0) {
+ do {
+ efree(ptr);
+ } while (--ptr >= strings);
+ efree(strings);
+ php_error_docref(NULL, E_WARNING, "dictionary entries must not contain a NULL-byte");
+ return 0;
+ }
+ }
+
+ *dictlen += (*ptr)->len + 1;
+ } ZEND_HASH_FOREACH_END();
+
+ dictptr = *dict = emalloc(*dictlen);
+ ptr = strings;
+ end = strings + zend_hash_num_elements(dictionary);
+ do {
+ memcpy(dictptr, (*ptr)->val, (*ptr)->len);
+ dictptr += (*ptr)->len;
+ *dictptr++ = 0;
+ zend_string_release(*ptr);
+ } while (++ptr != end);
+ efree(strings);
}
+ } break;
- *dictlen += (*ptr)->len + 1;
- } ZEND_HASH_FOREACH_END();
-
- dictptr = *dict = emalloc(*dictlen);
- ptr = strings;
- end = strings + zend_hash_num_elements(dictionary);
- do {
- memcpy(dictptr, *ptr, (*ptr)->len);
- dictptr += (*ptr)->len;
- *dictptr++ = 0;
- zend_string_release(*ptr);
- } while (++ptr != end);
- efree(strings);
+ default:
+ php_error_docref(NULL, E_WARNING, "dictionary must be of type zero-terminated string or array, got %s", zend_get_type_by_const(Z_TYPE_P(option_buffer)));
+ return 0;
}
}
diff --git a/genfiles b/genfiles
index 8a362c1e31..516b3316fb 100755
--- a/genfiles
+++ b/genfiles
@@ -1,6 +1,15 @@
#! /bin/sh
-STD='make -f Makefile.frag RE2C="re2c" RE2C_FLAGS="-i" YACC="bison -y -l" srcdir=Zend builddir=Zend top_srcdir=.'
+if [ -z $YACC ]; then
+ YACC="bison"
+fi
+YACC="$YACC -y -l"
+
+if [ -z $RE2C ]; then
+ RE2C="re2c"
+fi
+
+STD="make -f Makefile.frag RE2C='$RE2C' RE2C_FLAGS='-i' YACC='$YACC' srcdir=Zend builddir=Zend top_srcdir=."
(eval "$STD Zend/zend_language_parser.c Zend/zend_language_scanner.c Zend/zend_ini_parser.c Zend/zend_ini_scanner.c")
diff --git a/sapi/cgi/fastcgi.c b/main/fastcgi.c
index 7d6fd649ea..03dcc57b3c 100644
--- a/sapi/cgi/fastcgi.c
+++ b/main/fastcgi.c
@@ -20,7 +20,6 @@
#include "php.h"
#include "php_network.h"
-#include "fastcgi.h"
#include <string.h>
#include <stdlib.h>
@@ -36,15 +35,15 @@
#include <windows.h>
- typedef unsigned int in_addr_t;
+typedef unsigned int in_addr_t;
- struct sockaddr_un {
- short sun_family;
- char sun_path[MAXPATHLEN];
- };
+struct sockaddr_un {
+ short sun_family;
+ char sun_path[MAXPATHLEN];
+};
- static HANDLE fcgi_accept_mutex = INVALID_HANDLE_VALUE;
- static int is_impersonate = 0;
+static HANDLE fcgi_accept_mutex = INVALID_HANDLE_VALUE;
+static int is_impersonate = 0;
#define FCGI_LOCK(fd) \
if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \
@@ -131,10 +130,18 @@
#endif
+#include "fastcgi.h"
+
+/* maybe it's better to use weak name instead */
+#ifndef HAVE_ATTRIBUTE_WEAK
+static fcgi_logger fcgi_log;
+#endif
+
typedef union _sa_t {
struct sockaddr sa;
struct sockaddr_un sa_unix;
struct sockaddr_in sa_inet;
+ struct sockaddr_in6 sa_inet6;
} sa_t;
static HashTable fcgi_mgmt_vars;
@@ -142,44 +149,10 @@ static HashTable fcgi_mgmt_vars;
static int is_initialized = 0;
static int is_fastcgi = 0;
static int in_shutdown = 0;
-static in_addr_t *allowed_clients = NULL;
+static sa_t *allowed_clients = NULL;
+static sa_t client_sa;
/* hash table */
-
-#define FCGI_HASH_TABLE_SIZE 128
-#define FCGI_HASH_TABLE_MASK (FCGI_HASH_TABLE_SIZE - 1)
-#define FCGI_HASH_SEG_SIZE 4096
-
-typedef struct _fcgi_hash_bucket {
- unsigned int hash_value;
- unsigned int var_len;
- char *var;
- unsigned int val_len;
- char *val;
- struct _fcgi_hash_bucket *next;
- struct _fcgi_hash_bucket *list_next;
-} fcgi_hash_bucket;
-
-typedef struct _fcgi_hash_buckets {
- unsigned int idx;
- struct _fcgi_hash_buckets *next;
- struct _fcgi_hash_bucket data[FCGI_HASH_TABLE_SIZE];
-} fcgi_hash_buckets;
-
-typedef struct _fcgi_data_seg {
- char *pos;
- char *end;
- struct _fcgi_data_seg *next;
- char data[1];
-} fcgi_data_seg;
-
-typedef struct _fcgi_hash {
- fcgi_hash_bucket *hash_table[FCGI_HASH_TABLE_SIZE];
- fcgi_hash_bucket *list;
- fcgi_hash_buckets *buckets;
- fcgi_data_seg *data;
-} fcgi_hash;
-
static void fcgi_hash_init(fcgi_hash *h)
{
memset(h->hash_table, 0, sizeof(h->hash_table));
@@ -339,29 +312,6 @@ static void fcgi_hash_apply(fcgi_hash *h, fcgi_apply_func func, void *arg)
}
}
-struct _fcgi_request {
- int listen_socket;
- int tcp;
- int fd;
- int id;
- int keep;
-#ifdef TCP_NODELAY
- int nodelay;
-#endif
- int closed;
-
- int in_len;
- int in_pad;
-
- fcgi_header *out_hdr;
- unsigned char *out_pos;
- unsigned char out_buf[1024*8];
- unsigned char reserved[sizeof(fcgi_end_request_rec)];
-
- int has_env;
- fcgi_hash env;
-};
-
#ifdef _WIN32
static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg)
@@ -397,6 +347,11 @@ static void fcgi_setup_signals(void)
}
#endif
+void fcgi_set_in_shutdown(int new_value)
+{
+ in_shutdown = new_value;
+}
+
int fcgi_in_shutdown(void)
{
return in_shutdown;
@@ -407,6 +362,20 @@ void fcgi_terminate(void)
in_shutdown = 1;
}
+#ifndef HAVE_ATTRIBUTE_WEAK
+void fcgi_set_logger(fcgi_logger lg) {
+ fcgi_log = lg;
+}
+#else
+void __attribute__((weak)) fcgi_log(int type, const char *format, ...) {
+ va_list ap;
+
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+}
+#endif
+
int fcgi_init(void)
{
if (!is_initialized) {
@@ -626,10 +595,10 @@ int fcgi_listen(const char *path, int backlog)
hep = gethostbyname(host);
}
if (!hep || hep->h_addrtype != AF_INET || !hep->h_addr_list[0]) {
- fprintf(stderr, "Cannot resolve host name '%s'!\n", host);
+ fcgi_log(FCGI_ERROR, "Cannot resolve host name '%s'!\n", host);
return -1;
} else if (hep->h_addr_list[1]) {
- fprintf(stderr, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host);
+ fcgi_log(FCGI_ERROR, "Host '%s' has multiple addresses. You must choose one explicitly!\n", host);
return -1;
}
sa.sa_inet.sin_addr.s_addr = ((struct in_addr*)hep->h_addr_list[0])->s_addr;
@@ -666,7 +635,7 @@ int fcgi_listen(const char *path, int backlog)
int path_len = strlen(path);
if (path_len >= sizeof(sa.sa_unix.sun_path)) {
- fprintf(stderr, "Listening socket's path name is too long.\n");
+ fcgi_log(FCGI_ERROR, "Listening socket's path name is too long.\n");
return -1;
}
@@ -689,7 +658,7 @@ int fcgi_listen(const char *path, int backlog)
bind(listen_socket, (struct sockaddr *) &sa, sock_len) < 0 ||
listen(listen_socket, backlog) < 0) {
- fprintf(stderr, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno));
+ fcgi_log(FCGI_ERROR, "Cannot bind/listen socket - [%d] %s.\n",errno, strerror(errno));
return -1;
}
@@ -708,7 +677,7 @@ int fcgi_listen(const char *path, int backlog)
if (*cur == ',') n++;
cur++;
}
- allowed_clients = malloc(sizeof(in_addr_t) * (n+2));
+ allowed_clients = malloc(sizeof(sa_t) * (n+2));
n = 0;
cur = ip;
while (cur) {
@@ -717,15 +686,25 @@ int fcgi_listen(const char *path, int backlog)
*end = 0;
end++;
}
- allowed_clients[n] = inet_addr(cur);
- if (allowed_clients[n] == INADDR_NONE) {
- fprintf(stderr, "Wrong IP address '%s' in FCGI_WEB_SERVER_ADDRS\n", cur);
+ if (inet_pton(AF_INET, cur, &allowed_clients[n].sa_inet.sin_addr)>0) {
+ allowed_clients[n].sa.sa_family = AF_INET;
+ n++;
+#ifdef HAVE_IPV6
+ } else if (inet_pton(AF_INET6, cur, &allowed_clients[n].sa_inet6.sin6_addr)>0) {
+ allowed_clients[n].sa.sa_family = AF_INET6;
+ n++;
+#endif
+ } else {
+ fcgi_log(FCGI_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur);
}
- n++;
cur = end;
}
- allowed_clients[n] = INADDR_NONE;
+ allowed_clients[n].sa.sa_family = 0;
free(ip);
+ if (!n) {
+ fcgi_log(FCGI_ERROR, "There are no allowed addresses");
+ /* don't clear allowed_clients as it will create an "open for all" security issue */
+ }
}
}
@@ -744,36 +723,92 @@ int fcgi_listen(const char *path, int backlog)
return listen_socket;
}
-fcgi_request *fcgi_init_request(int listen_socket)
+void fcgi_set_allowed_clients(char *ip)
+{
+ char *cur, *end;
+ int n;
+
+ if (ip) {
+ ip = strdup(ip);
+ cur = ip;
+ n = 0;
+ while (*cur) {
+ if (*cur == ',') n++;
+ cur++;
+ }
+ if (allowed_clients) free(allowed_clients);
+ allowed_clients = malloc(sizeof(sa_t) * (n+2));
+ n = 0;
+ cur = ip;
+ while (cur) {
+ end = strchr(cur, ',');
+ if (end) {
+ *end = 0;
+ end++;
+ }
+ if (inet_pton(AF_INET, cur, &allowed_clients[n].sa_inet.sin_addr)>0) {
+ allowed_clients[n].sa.sa_family = AF_INET;
+ n++;
+#ifdef HAVE_IPV6
+ } else if (inet_pton(AF_INET6, cur, &allowed_clients[n].sa_inet6.sin6_addr)>0) {
+ allowed_clients[n].sa.sa_family = AF_INET6;
+ n++;
+#endif
+ } else {
+ fcgi_log(FCGI_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur);
+ }
+ cur = end;
+ }
+ allowed_clients[n].sa.sa_family = 0;
+ free(ip);
+ if (!n) {
+ fcgi_log(FCGI_ERROR, "There are no allowed addresses");
+ /* don't clear allowed_clients as it will create an "open for all" security issue */
+ }
+ }
+}
+
+static void fcgi_hook_dummy() {
+ return;
+}
+
+fcgi_request *fcgi_init_request(fcgi_request *req, int listen_socket)
{
- fcgi_request *req = (fcgi_request*)calloc(1, sizeof(fcgi_request));
+ memset(req, 0, sizeof(fcgi_request));
req->listen_socket = listen_socket;
req->fd = -1;
req->id = -1;
+ /*
req->in_len = 0;
req->in_pad = 0;
req->out_hdr = NULL;
+
+#ifdef TCP_NODELAY
+ req->nodelay = 0;
+#endif
+
+ req->env = NULL;
+ req->has_env = 0;
+
+ */
req->out_pos = req->out_buf;
+ req->hook.on_accept = fcgi_hook_dummy;
+ req->hook.on_read = fcgi_hook_dummy;
+ req->hook.on_close = fcgi_hook_dummy;
#ifdef _WIN32
req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
#endif
-#ifdef TCP_NODELAY
- req->nodelay = 0;
-#endif
-
fcgi_hash_init(&req->env);
return req;
}
-void fcgi_destroy_request(fcgi_request *req)
-{
+void fcgi_destroy_request(fcgi_request *req) {
fcgi_hash_destroy(&req->env);
- free(req);
}
static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count)
@@ -1052,7 +1087,7 @@ static int fcgi_read_request(fcgi_request *req)
}
len = (int)(p - buf - sizeof(fcgi_header));
len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len);
- if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) {
+ if (safe_write(req, buf, sizeof(fcgi_header) + len) != (ssize_t)sizeof(fcgi_header)+len) {
req->keep = 0;
return 0;
}
@@ -1117,7 +1152,7 @@ int fcgi_read(fcgi_request *req, char *str, int len)
return n;
}
-static inline void fcgi_close(fcgi_request *req, int force, int destroy)
+void fcgi_close(fcgi_request *req, int force, int destroy)
{
if (destroy && req->has_env) {
fcgi_hash_clean(&req->env);
@@ -1163,7 +1198,52 @@ static inline void fcgi_close(fcgi_request *req, int force, int destroy)
req->nodelay = 0;
#endif
req->fd = -1;
+
+ req->hook.on_close();
+ }
+}
+
+int fcgi_is_closed(fcgi_request *req)
+{
+ return (req->fd < 0);
+}
+
+static int fcgi_is_allowed() {
+ int i;
+
+ if (client_sa.sa.sa_family == AF_UNIX) {
+ return 1;
+ }
+ if (!allowed_clients) {
+ return 1;
+ }
+ if (client_sa.sa.sa_family == AF_INET) {
+ for (i = 0; allowed_clients[i].sa.sa_family ; i++) {
+ if (allowed_clients[i].sa.sa_family == AF_INET
+ && !memcmp(&client_sa.sa_inet.sin_addr, &allowed_clients[i].sa_inet.sin_addr, 4)) {
+ return 1;
+ }
+ }
}
+#ifdef HAVE_IPV6
+ if (client_sa.sa.sa_family == AF_INET6) {
+ for (i = 0; allowed_clients[i].sa.sa_family ; i++) {
+ if (allowed_clients[i].sa.sa_family == AF_INET6
+ && !memcmp(&client_sa.sa_inet6.sin6_addr, &allowed_clients[i].sa_inet6.sin6_addr, 12)) {
+ return 1;
+ }
+#ifdef IN6_IS_ADDR_V4MAPPED
+ if (allowed_clients[i].sa.sa_family == AF_INET
+ && IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr)
+ && !memcmp(((char *)&client_sa.sa_inet6.sin6_addr)+12, &allowed_clients[i].sa_inet.sin_addr, 4)) {
+ return 1;
+ }
+#endif
+ }
+ }
+#endif
+
+ return 0;
}
int fcgi_accept_request(fcgi_request *req)
@@ -1209,37 +1289,18 @@ int fcgi_accept_request(fcgi_request *req)
sa_t sa;
socklen_t len = sizeof(sa);
+ req->hook.on_accept();
+
FCGI_LOCK(req->listen_socket);
req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
FCGI_UNLOCK(req->listen_socket);
- if (req->fd >= 0) {
- if (((struct sockaddr *)&sa)->sa_family == AF_INET) {
-#ifndef _WIN32
- req->tcp = 1;
-#endif
- if (allowed_clients) {
- int n = 0;
- int allowed = 0;
-
- while (allowed_clients[n] != INADDR_NONE) {
- if (allowed_clients[n] == sa.sa_inet.sin_addr.s_addr) {
- allowed = 1;
- break;
- }
- n++;
- }
- if (!allowed) {
- fprintf(stderr, "Connection from disallowed IP address '%s' is dropped.\n", inet_ntoa(sa.sa_inet.sin_addr));
- closesocket(req->fd);
- req->fd = -1;
- continue;
- }
- }
-#ifndef _WIN32
- } else {
- req->tcp = 0;
-#endif
- }
+
+ client_sa = sa;
+ if (req->fd >= 0 && !fcgi_is_allowed()) {
+ fcgi_log(FCGI_ERROR, "Connection disallowed: IP address '%s' has been dropped.", fcgi_get_last_client_ip());
+ closesocket(req->fd);
+ req->fd = -1;
+ continue;
}
}
@@ -1259,6 +1320,8 @@ int fcgi_accept_request(fcgi_request *req)
struct pollfd fds;
int ret;
+ req->hook.on_read();
+
fds.fd = req->fd;
fds.events = POLLIN;
fds.revents = 0;
@@ -1271,6 +1334,8 @@ int fcgi_accept_request(fcgi_request *req)
}
fcgi_close(req, 1, 0);
#else
+ req->hook.on_read();
+
if (req->fd < FD_SETSIZE) {
struct timeval tv = {5,0};
fd_set set;
@@ -1287,7 +1352,7 @@ int fcgi_accept_request(fcgi_request *req)
}
fcgi_close(req, 1, 0);
} else {
- fprintf(stderr, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
+ fcgi_log(FCGI_ERROR, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
fcgi_close(req, 1, 0);
}
#endif
@@ -1554,6 +1619,31 @@ void fcgi_free_mgmt_var_cb(zval *zv)
pefree(Z_STR_P(zv), 1);
}
+const char *fcgi_get_last_client_ip()
+{
+ static char str[INET6_ADDRSTRLEN];
+
+ /* Ipv4 */
+ if (client_sa.sa.sa_family == AF_INET) {
+ return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet.sin_addr, str, INET6_ADDRSTRLEN);
+ }
+#ifdef HAVE_IPV6
+#ifdef IN6_IS_ADDR_V4MAPPED
+ /* Ipv4-Mapped-Ipv6 */
+ if (client_sa.sa.sa_family == AF_INET6
+ && IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr)) {
+ return inet_ntop(AF_INET, ((char *)&client_sa.sa_inet6.sin6_addr)+12, str, INET6_ADDRSTRLEN);
+ }
+#endif
+ /* Ipv6 */
+ if (client_sa.sa.sa_family == AF_INET6) {
+ return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet6.sin6_addr, str, INET6_ADDRSTRLEN);
+ }
+#endif
+ /* Unix socket */
+ return NULL;
+}
+
/*
* Local variables:
* tab-width: 4
diff --git a/sapi/cgi/fastcgi.h b/main/fastcgi.h
index fa98730220..7e56f0ef89 100644
--- a/sapi/cgi/fastcgi.h
+++ b/main/fastcgi.h
@@ -49,6 +49,14 @@ typedef enum _fcgi_role {
FCGI_FILTER = 3
} fcgi_role;
+enum {
+ FCGI_DEBUG = 1,
+ FCGI_NOTICE = 2,
+ FCGI_WARNING = 3,
+ FCGI_ERROR = 4,
+ FCGI_ALERT = 5,
+};
+
typedef enum _fcgi_request_type {
FCGI_BEGIN_REQUEST = 1, /* [in] */
FCGI_ABORT_REQUEST = 2, /* [in] (not supported) */
@@ -110,18 +118,94 @@ typedef struct _fcgi_end_request_rec {
typedef void (*fcgi_apply_func)(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg);
-typedef struct _fcgi_request fcgi_request;
+#define FCGI_HASH_TABLE_SIZE 128
+#define FCGI_HASH_TABLE_MASK (FCGI_HASH_TABLE_SIZE - 1)
+#define FCGI_HASH_SEG_SIZE 4096
+
+typedef struct _fcgi_hash_bucket {
+ unsigned int hash_value;
+ unsigned int var_len;
+ char *var;
+ unsigned int val_len;
+ char *val;
+ struct _fcgi_hash_bucket *next;
+ struct _fcgi_hash_bucket *list_next;
+} fcgi_hash_bucket;
+
+typedef struct _fcgi_hash_buckets {
+ unsigned int idx;
+ struct _fcgi_hash_buckets *next;
+ struct _fcgi_hash_bucket data[FCGI_HASH_TABLE_SIZE];
+} fcgi_hash_buckets;
+
+typedef struct _fcgi_data_seg {
+ char *pos;
+ char *end;
+ struct _fcgi_data_seg *next;
+ char data[1];
+} fcgi_data_seg;
+
+typedef struct _fcgi_hash {
+ fcgi_hash_bucket *hash_table[FCGI_HASH_TABLE_SIZE];
+ fcgi_hash_bucket *list;
+ fcgi_hash_buckets *buckets;
+ fcgi_data_seg *data;
+} fcgi_hash;
+
+typedef struct _fcgi_request fcgi_request;
+typedef struct _fcgi_req_hook fcgi_req_hook;
+
+struct _fcgi_req_hook {
+ void(*on_accept)();
+ void(*on_read)();
+ void(*on_close)();
+};
+
+struct _fcgi_request {
+ int listen_socket;
+ int tcp;
+ int fd;
+ int id;
+ int keep;
+#ifdef TCP_NODELAY
+ int nodelay;
+#endif
+ int closed;
+ int in_len;
+ int in_pad;
+
+ fcgi_header *out_hdr;
+
+ unsigned char *out_pos;
+ unsigned char out_buf[1024*8];
+ unsigned char reserved[sizeof(fcgi_end_request_rec)];
+
+ fcgi_req_hook hook;
+
+ int has_env;
+ fcgi_hash env;
+};
int fcgi_init(void);
void fcgi_shutdown(void);
int fcgi_is_fastcgi(void);
+int fcgi_is_closed(fcgi_request *req);
+void fcgi_close(fcgi_request *req, int force, int destroy);
int fcgi_in_shutdown(void);
void fcgi_terminate(void);
int fcgi_listen(const char *path, int backlog);
-fcgi_request* fcgi_init_request(int listen_socket);
+fcgi_request* fcgi_init_request(fcgi_request *request, int listen_socket);
void fcgi_destroy_request(fcgi_request *req);
+void fcgi_set_allowed_clients(char *ip);
int fcgi_accept_request(fcgi_request *req);
int fcgi_finish_request(fcgi_request *req, int force_close);
+const char *fcgi_get_last_client_ip();
+void fcgi_set_in_shutdown(int new_value);
+
+#ifndef HAVE_ATTRIBUTE_WEAK
+typedef void (*fcgi_logger)(int type, const char *fmt, ...);
+void fcgi_set_logger(fcgi_logger lg);
+#endif
char* fcgi_getenv(fcgi_request *req, const char* var, int var_len);
char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val);
diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c
index 85127c3379..a4c6e4a6db 100644
--- a/main/fopen_wrappers.c
+++ b/main/fopen_wrappers.c
@@ -53,10 +53,6 @@
#include <sys/socket.h>
#endif
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
-#endif
-
#ifdef PHP_WIN32
#include <winsock2.h>
#elif defined(NETWARE) && defined(USE_WINSOCK)
diff --git a/main/main.c b/main/main.c
index ebaaa2a8e4..2d58b9c99c 100644
--- a/main/main.c
+++ b/main/main.c
@@ -114,10 +114,6 @@
#endif
/* }}} */
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
-#endif
-
PHPAPI int (*php_register_internal_extensions_func)(void) = php_register_internal_extensions;
#ifndef ZTS
diff --git a/main/php_ini.c b/main/php_ini.c
index 80d34848f8..99919ca56e 100644
--- a/main/php_ini.c
+++ b/main/php_ini.c
@@ -37,10 +37,6 @@
#include <dirent.h>
#endif
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode) & S_IFMT) == S_IFREG)
-#endif
-
#ifdef PHP_WIN32
#define TRANSLATE_SLASHES_LOWER(path) \
{ \
diff --git a/main/php_variables.c b/main/php_variables.c
index 6b8a1726d5..d800a2d3c4 100644
--- a/main/php_variables.c
+++ b/main/php_variables.c
@@ -245,7 +245,6 @@ static zend_bool add_post_var(zval *arr, post_var_data_t *var, zend_bool eof)
{
char *ksep, *vsep, *val;
size_t klen, vlen;
- /* FIXME: string-size_t */
size_t new_vlen;
if (var->ptr >= var->end) {
@@ -312,6 +311,11 @@ static inline int add_post_vars(zval *arr, post_var_data_t *vars, zend_bool eof)
return SUCCESS;
}
+#ifdef PHP_WIN32
+#define SAPI_POST_HANDLER_BUFSIZ 16384
+#else
+# define SAPI_POST_HANDLER_BUFSIZ BUFSIZ
+#endif
SAPI_API SAPI_POST_HANDLER_FUNC(php_std_post_handler)
{
zval *arr = (zval *) arg;
@@ -322,8 +326,8 @@ SAPI_API SAPI_POST_HANDLER_FUNC(php_std_post_handler)
memset(&post_data, 0, sizeof(post_data));
while (!php_stream_eof(s)) {
- char buf[BUFSIZ] = {0};
- size_t len = php_stream_read(s, buf, BUFSIZ);
+ char buf[SAPI_POST_HANDLER_BUFSIZ] = {0};
+ size_t len = php_stream_read(s, buf, SAPI_POST_HANDLER_BUFSIZ);
if (len && len != (size_t) -1) {
smart_str_appendl(&post_data.str, buf, len);
@@ -334,7 +338,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(php_std_post_handler)
}
}
- if (len != BUFSIZ){
+ if (len != SAPI_POST_HANDLER_BUFSIZ){
break;
}
}
@@ -345,6 +349,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(php_std_post_handler)
}
}
}
+#undef SAPI_POST_HANDLER_BUFSIZ
SAPI_API SAPI_INPUT_FILTER_FUNC(php_default_input_filter)
{
diff --git a/main/streams/php_streams_int.h b/main/streams/php_streams_int.h
index c47c666178..0188202c91 100644
--- a/main/streams/php_streams_int.h
+++ b/main/streams/php_streams_int.h
@@ -55,10 +55,6 @@
# define EWOULDBLOCK WSAEWOULDBLOCK
#endif
-#ifndef S_ISREG
-#define S_ISREG(mode) (((mode)&S_IFMT) == S_IFREG)
-#endif
-
/* This functions transforms the first char to 'w' if it's not 'r', 'a' or 'w'
* and strips any subsequent chars except '+' and 'b'.
* Use this to sanitize stream->mode if you call e.g. fdopen, fopencookie or
diff --git a/main/win95nt.h b/main/win95nt.h
index adf9f61e34..12356eeccd 100644
--- a/main/win95nt.h
+++ b/main/win95nt.h
@@ -40,9 +40,6 @@ typedef char * caddr_t;
#define S_IFIFO _IFIFO
#define S_IFBLK _IFBLK
#define S_IFLNK _IFLNK
-#ifndef S_ISREG
-#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
-#endif
#define chdir(path) _chdir(path)
#define mkdir(a, b) _mkdir(a)
#define rmdir(a) _rmdir(a)
diff --git a/php.ini-development b/php.ini-development
index 4aaf2f8164..902d4b6b88 100644
--- a/php.ini-development
+++ b/php.ini-development
@@ -876,7 +876,6 @@ default_socket_timeout = 60
;extension=php_ldap.dll
;extension=php_mbstring.dll
;extension=php_exif.dll ; Must be after mbstring as it depends on it
-;extension=php_mysql.dll
;extension=php_mysqli.dll
;extension=php_oci8_12c.dll ; Use with Oracle Database 12c Instant Client
;extension=php_openssl.dll
@@ -1110,64 +1109,6 @@ ibase.dateformat = "%Y-%m-%d"
; Default time format.
ibase.timeformat = "%H:%M:%S"
-[MySQL]
-; Allow accessing, from PHP's perspective, local files with LOAD DATA statements
-; http://php.net/mysql.allow_local_infile
-mysql.allow_local_infile = On
-
-; Allow or prevent persistent links.
-; http://php.net/mysql.allow-persistent
-mysql.allow_persistent = On
-
-; If mysqlnd is used: Number of cache slots for the internal result set cache
-; http://php.net/mysql.cache_size
-mysql.cache_size = 2000
-
-; Maximum number of persistent links. -1 means no limit.
-; http://php.net/mysql.max-persistent
-mysql.max_persistent = -1
-
-; Maximum number of links (persistent + non-persistent). -1 means no limit.
-; http://php.net/mysql.max-links
-mysql.max_links = -1
-
-; Default port number for mysql_connect(). If unset, mysql_connect() will use
-; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the
-; compile-time value defined MYSQL_PORT (in that order). Win32 will only look
-; at MYSQL_PORT.
-; http://php.net/mysql.default-port
-mysql.default_port =
-
-; Default socket name for local MySQL connects. If empty, uses the built-in
-; MySQL defaults.
-; http://php.net/mysql.default-socket
-mysql.default_socket =
-
-; Default host for mysql_connect() (doesn't apply in safe mode).
-; http://php.net/mysql.default-host
-mysql.default_host =
-
-; Default user for mysql_connect() (doesn't apply in safe mode).
-; http://php.net/mysql.default-user
-mysql.default_user =
-
-; Default password for mysql_connect() (doesn't apply in safe mode).
-; Note that this is generally a *bad* idea to store passwords in this file.
-; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password")
-; and reveal this password! And of course, any users with read access to this
-; file will be able to reveal the password as well.
-; http://php.net/mysql.default-password
-mysql.default_password =
-
-; Maximum time (in seconds) for connect timeout. -1 means no limit
-; http://php.net/mysql.connect-timeout
-mysql.connect_timeout = 60
-
-; Trace mode. When trace_mode is active (=On), warnings for table/index scans and
-; SQL-Errors will be displayed.
-; http://php.net/mysql.trace-mode
-mysql.trace_mode = Off
-
[MySQLi]
; Maximum number of persistent links. -1 means no limit.
diff --git a/php.ini-production b/php.ini-production
index 9042d08a9d..539a89aa20 100644
--- a/php.ini-production
+++ b/php.ini-production
@@ -876,7 +876,6 @@ default_socket_timeout = 60
;extension=php_ldap.dll
;extension=php_mbstring.dll
;extension=php_exif.dll ; Must be after mbstring as it depends on it
-;extension=php_mysql.dll
;extension=php_mysqli.dll
;extension=php_oci8_12c.dll ; Use with Oracle Database 12c Instant Client
;extension=php_openssl.dll
@@ -1110,64 +1109,6 @@ ibase.dateformat = "%Y-%m-%d"
; Default time format.
ibase.timeformat = "%H:%M:%S"
-[MySQL]
-; Allow accessing, from PHP's perspective, local files with LOAD DATA statements
-; http://php.net/mysql.allow_local_infile
-mysql.allow_local_infile = On
-
-; Allow or prevent persistent links.
-; http://php.net/mysql.allow-persistent
-mysql.allow_persistent = On
-
-; If mysqlnd is used: Number of cache slots for the internal result set cache
-; http://php.net/mysql.cache_size
-mysql.cache_size = 2000
-
-; Maximum number of persistent links. -1 means no limit.
-; http://php.net/mysql.max-persistent
-mysql.max_persistent = -1
-
-; Maximum number of links (persistent + non-persistent). -1 means no limit.
-; http://php.net/mysql.max-links
-mysql.max_links = -1
-
-; Default port number for mysql_connect(). If unset, mysql_connect() will use
-; the $MYSQL_TCP_PORT or the mysql-tcp entry in /etc/services or the
-; compile-time value defined MYSQL_PORT (in that order). Win32 will only look
-; at MYSQL_PORT.
-; http://php.net/mysql.default-port
-mysql.default_port =
-
-; Default socket name for local MySQL connects. If empty, uses the built-in
-; MySQL defaults.
-; http://php.net/mysql.default-socket
-mysql.default_socket =
-
-; Default host for mysql_connect() (doesn't apply in safe mode).
-; http://php.net/mysql.default-host
-mysql.default_host =
-
-; Default user for mysql_connect() (doesn't apply in safe mode).
-; http://php.net/mysql.default-user
-mysql.default_user =
-
-; Default password for mysql_connect() (doesn't apply in safe mode).
-; Note that this is generally a *bad* idea to store passwords in this file.
-; *Any* user with PHP access can run 'echo get_cfg_var("mysql.default_password")
-; and reveal this password! And of course, any users with read access to this
-; file will be able to reveal the password as well.
-; http://php.net/mysql.default-password
-mysql.default_password =
-
-; Maximum time (in seconds) for connect timeout. -1 means no limit
-; http://php.net/mysql.connect-timeout
-mysql.connect_timeout = 60
-
-; Trace mode. When trace_mode is active (=On), warnings for table/index scans and
-; SQL-Errors will be displayed.
-; http://php.net/mysql.trace-mode
-mysql.trace_mode = Off
-
[MySQLi]
; Maximum number of persistent links. -1 means no limit.
diff --git a/run-tests.php b/run-tests.php
index 897500a58b..70d9cc3f5d 100755
--- a/run-tests.php
+++ b/run-tests.php
@@ -1662,9 +1662,15 @@ TEST $file
}
$env['REDIRECT_STATUS'] = '1';
- $env['QUERY_STRING'] = $query_string;
- $env['PATH_TRANSLATED'] = $test_file;
- $env['SCRIPT_FILENAME'] = $test_file;
+ if (empty($env['QUERY_STRING'])) {
+ $env['QUERY_STRING'] = $query_string;
+ }
+ if (empty($env['PATH_TRANSLATED'])) {
+ $env['PATH_TRANSLATED'] = $test_file;
+ }
+ if (empty($env['SCRIPT_FILENAME'])) {
+ $env['SCRIPT_FILENAME'] = $test_file;
+ }
if (array_key_exists('COOKIE', $section_text)) {
$env['HTTP_COOKIE'] = trim($section_text['COOKIE']);
@@ -1745,12 +1751,17 @@ TEST $file
} else if (array_key_exists('POST', $section_text) && !empty($section_text['POST'])) {
$post = trim($section_text['POST']);
- save_text($tmp_post, $post);
$content_length = strlen($post);
+ save_text($tmp_post, $post);
$env['REQUEST_METHOD'] = 'POST';
- $env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
- $env['CONTENT_LENGTH'] = $content_length;
+ if (empty($env['CONTENT_TYPE'])) {
+ $env['CONTENT_TYPE'] = 'application/x-www-form-urlencoded';
+ }
+
+ if (empty($env['CONTENT_LENGTH'])) {
+ $env['CONTENT_LENGTH'] = $content_length;
+ }
$cmd = "$php $pass_options $ini_settings -f \"$test_file\" 2>&1 < \"$tmp_post\"";
diff --git a/sapi/cgi/Makefile.frag b/sapi/cgi/Makefile.frag
index d3d7cb3553..75c72bf8b7 100644
--- a/sapi/cgi/Makefile.frag
+++ b/sapi/cgi/Makefile.frag
@@ -1,6 +1,6 @@
cgi: $(SAPI_CGI_PATH)
-$(SAPI_CGI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_CGI_OBJS)
+$(SAPI_CGI_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_FASTCGI_OBJS) $(PHP_CGI_OBJS)
$(BUILD_CGI)
install-cgi: $(SAPI_CGI_PATH)
diff --git a/sapi/cgi/cgi_main.c b/sapi/cgi/cgi_main.c
index b479d4df4e..c14aeb405a 100644
--- a/sapi/cgi/cgi_main.c
+++ b/sapi/cgi/cgi_main.c
@@ -219,6 +219,16 @@ static php_cgi_globals_struct php_cgi_globals;
#define TRANSLATE_SLASHES(path)
#endif
+#ifndef HAVE_ATTRIBUTE_WEAK
+static void fcgi_log(int type, const char *format, ...) {
+ va_list ap;
+
+ va_start(ap, format);
+ vfprintf(stderr, format, ap);
+ va_end(ap);
+}
+#endif
+
static int print_module_info(zval *element)
{
zend_module_entry *module = Z_PTR_P(element);
@@ -1026,12 +1036,12 @@ static int is_valid_path(const char *path)
/* }}} */
#define CGI_GETENV(name) \
- ((request) ? \
+ ((request->has_env) ? \
FCGI_GETENV(request, name) : \
getenv(name))
#define CGI_PUTENV(name, value) \
- ((request) ? \
+ ((request->has_env) ? \
FCGI_PUTENV(request, name, value) : \
_sapi_cgi_putenv(name, sizeof(name)-1, value))
@@ -1724,7 +1734,7 @@ int main(int argc, char *argv[])
int fastcgi;
char *bindpath = NULL;
int fcgi_fd = 0;
- fcgi_request *request = NULL;
+ fcgi_request request = {0};
int warmup_repeats = 0;
int repeats = 1;
int benchmark = 0;
@@ -1928,6 +1938,10 @@ consult the installation file that came with this distribution, or visit \n\
}
}
+#ifndef HAVE_ATTRIBUTE_WEAK
+ fcgi_set_logger(fcgi_log);
+#endif
+
if (bindpath) {
int backlog = 128;
if (getenv("PHP_FCGI_BACKLOG")) {
@@ -1958,109 +1972,109 @@ consult the installation file that came with this distribution, or visit \n\
php_import_environment_variables = cgi_php_import_environment_variables;
/* library is already initialized, now init our request */
- request = fcgi_init_request(fcgi_fd);
+ fcgi_init_request(&request, fcgi_fd);
#ifndef PHP_WIN32
- /* Pre-fork, if required */
- if (getenv("PHP_FCGI_CHILDREN")) {
- char * children_str = getenv("PHP_FCGI_CHILDREN");
- children = atoi(children_str);
- if (children < 0) {
- fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
- return FAILURE;
+ /* Pre-fork, if required */
+ if (getenv("PHP_FCGI_CHILDREN")) {
+ char * children_str = getenv("PHP_FCGI_CHILDREN");
+ children = atoi(children_str);
+ if (children < 0) {
+ fprintf(stderr, "PHP_FCGI_CHILDREN is not valid\n");
+ return FAILURE;
+ }
+ fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
+ /* This is the number of concurrent requests, equals FCGI_MAX_CONNS */
+ fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
+ } else {
+ fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
+ fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
}
- fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, children_str, strlen(children_str));
- /* This is the number of concurrent requests, equals FCGI_MAX_CONNS */
- fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, children_str, strlen(children_str));
- } else {
- fcgi_set_mgmt_var("FCGI_MAX_CONNS", sizeof("FCGI_MAX_CONNS")-1, "1", sizeof("1")-1);
- fcgi_set_mgmt_var("FCGI_MAX_REQS", sizeof("FCGI_MAX_REQS")-1, "1", sizeof("1")-1);
- }
- if (children) {
- int running = 0;
- pid_t pid;
+ if (children) {
+ int running = 0;
+ pid_t pid;
- /* Create a process group for ourself & children */
- setsid();
- pgroup = getpgrp();
+ /* Create a process group for ourself & children */
+ setsid();
+ pgroup = getpgrp();
#ifdef DEBUG_FASTCGI
- fprintf(stderr, "Process group %d\n", pgroup);
+ fprintf(stderr, "Process group %d\n", pgroup);
#endif
- /* Set up handler to kill children upon exit */
- act.sa_flags = 0;
- act.sa_handler = fastcgi_cleanup;
- if (sigaction(SIGTERM, &act, &old_term) ||
- sigaction(SIGINT, &act, &old_int) ||
- sigaction(SIGQUIT, &act, &old_quit)
- ) {
- perror("Can't set signals");
- exit(1);
- }
+ /* Set up handler to kill children upon exit */
+ act.sa_flags = 0;
+ act.sa_handler = fastcgi_cleanup;
+ if (sigaction(SIGTERM, &act, &old_term) ||
+ sigaction(SIGINT, &act, &old_int) ||
+ sigaction(SIGQUIT, &act, &old_quit)
+ ) {
+ perror("Can't set signals");
+ exit(1);
+ }
- if (fcgi_in_shutdown()) {
- goto parent_out;
- }
+ if (fcgi_in_shutdown()) {
+ goto parent_out;
+ }
- while (parent) {
- do {
+ while (parent) {
+ do {
#ifdef DEBUG_FASTCGI
- fprintf(stderr, "Forking, %d running\n", running);
-#endif
- pid = fork();
- switch (pid) {
- case 0:
- /* One of the children.
- * Make sure we don't go round the
- * fork loop any more
- */
- parent = 0;
+ fprintf(stderr, "Forking, %d running\n", running);
+#endif
+ pid = fork();
+ switch (pid) {
+ case 0:
+ /* One of the children.
+ * Make sure we don't go round the
+ * fork loop any more
+ */
+ parent = 0;
- /* don't catch our signals */
- sigaction(SIGTERM, &old_term, 0);
- sigaction(SIGQUIT, &old_quit, 0);
- sigaction(SIGINT, &old_int, 0);
- break;
- case -1:
- perror("php (pre-forking)");
- exit(1);
- break;
- default:
- /* Fine */
- running++;
- break;
- }
- } while (parent && (running < children));
+ /* don't catch our signals */
+ sigaction(SIGTERM, &old_term, 0);
+ sigaction(SIGQUIT, &old_quit, 0);
+ sigaction(SIGINT, &old_int, 0);
+ break;
+ case -1:
+ perror("php (pre-forking)");
+ exit(1);
+ break;
+ default:
+ /* Fine */
+ running++;
+ break;
+ }
+ } while (parent && (running < children));
- if (parent) {
+ if (parent) {
#ifdef DEBUG_FASTCGI
- fprintf(stderr, "Wait for kids, pid %d\n", getpid());
+ fprintf(stderr, "Wait for kids, pid %d\n", getpid());
#endif
- parent_waiting = 1;
- while (1) {
- if (wait(&status) >= 0) {
- running--;
- break;
- } else if (exit_signal) {
- break;
+ parent_waiting = 1;
+ while (1) {
+ if (wait(&status) >= 0) {
+ running--;
+ break;
+ } else if (exit_signal) {
+ break;
+ }
}
- }
- if (exit_signal) {
+ if (exit_signal) {
#if 0
- while (running > 0) {
- while (wait(&status) < 0) {
+ while (running > 0) {
+ while (wait(&status) < 0) {
+ }
+ running--;
}
- running--;
- }
#endif
- goto parent_out;
+ goto parent_out;
+ }
}
}
+ } else {
+ parent = 0;
}
- } else {
- parent = 0;
- }
#endif /* WIN32 */
}
@@ -2087,8 +2101,8 @@ consult the installation file that came with this distribution, or visit \n\
break;
case 'h':
case '?':
- if (request) {
- fcgi_destroy_request(request);
+ if (request.listen_socket) {
+ fcgi_destroy_request(&request);
}
fcgi_shutdown();
no_headers = 1;
@@ -2111,9 +2125,9 @@ consult the installation file that came with this distribution, or visit \n\
fcgi_impersonate();
}
#endif
- while (!fastcgi || fcgi_accept_request(request) >= 0) {
- SG(server_context) = fastcgi ? (void *) request : (void *) 1;
- init_request_info(request);
+ while (!fastcgi || fcgi_accept_request(&request) >= 0) {
+ SG(server_context) = fastcgi ? (void *)&request : (void *) 1;
+ init_request_info(&request);
if (!cgi && !fastcgi) {
while ((c = php_getopt(argc, argv, OPTIONS, &php_optarg, &php_optind, 0, 2)) != -1) {
@@ -2298,7 +2312,7 @@ consult the installation file that came with this distribution, or visit \n\
* get path_translated */
if (php_request_startup() == FAILURE) {
if (fastcgi) {
- fcgi_finish_request(request, 1);
+ fcgi_finish_request(&request, 1);
}
SG(server_context) = NULL;
php_module_shutdown();
@@ -2509,7 +2523,7 @@ fastcgi_request_done:
/* only fastcgi will get here */
requests++;
if (max_requests && (requests == max_requests)) {
- fcgi_finish_request(request, 1);
+ fcgi_finish_request(&request, 1);
if (bindpath) {
free(bindpath);
}
@@ -2521,8 +2535,9 @@ fastcgi_request_done:
}
/* end of fastcgi loop */
}
- if (request) {
- fcgi_destroy_request(request);
+
+ if (request.listen_socket) {
+ fcgi_destroy_request(&request);
}
fcgi_shutdown();
diff --git a/sapi/cgi/config.w32 b/sapi/cgi/config.w32
index daf4f05687..4e803fb1c4 100644
--- a/sapi/cgi/config.w32
+++ b/sapi/cgi/config.w32
@@ -5,6 +5,7 @@ ARG_ENABLE('cgi', 'Build CGI version of PHP', 'yes');
if (PHP_CGI == "yes") {
ADD_FLAG("LDFLAGS_CGI", "/stack:67108864");
- SAPI('cgi', 'cgi_main.c fastcgi.c', 'php-cgi.exe', '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
+ SAPI('cgi', 'cgi_main.c', 'php-cgi.exe', '/DZEND_ENABLE_STATIC_TSRMLS_CACHE=1');
+ ADD_SOURCES('main', 'fastcgi.c', 'cgi');
ADD_FLAG('LIBS_CGI', 'ws2_32.lib kernel32.lib advapi32.lib');
}
diff --git a/sapi/cgi/config9.m4 b/sapi/cgi/config9.m4
index a005f8e0ad..e2195f4ee6 100644
--- a/sapi/cgi/config9.m4
+++ b/sapi/cgi/config9.m4
@@ -50,21 +50,21 @@ if test "$PHP_CGI" != "no"; then
esac
dnl Select SAPI
- PHP_SELECT_SAPI(cgi, program, cgi_main.c fastcgi.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, '$(SAPI_CGI_PATH)')
+ PHP_SELECT_SAPI(cgi, program, cgi_main.c, -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1, '$(SAPI_CGI_PATH)')
case $host_alias in
*aix*)
if test "$php_sapi_module" = "shared"; then
- BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/.libs\/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+ BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/.libs\/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
else
- BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+ BUILD_CGI="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
fi
;;
*darwin*)
- BUILD_CGI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_CGI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+ BUILD_CGI="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_FASTCGI_OBJS:.lo=.o) \$(PHP_CGI_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
;;
*)
- BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
+ BUILD_CGI="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_CGI_OBJS) \$(EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_CGI_PATH)"
;;
esac
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index 568fc9f2d1..b07d6858da 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -91,10 +91,6 @@
# define SOCK_EADDRINUSE WSAEADDRINUSE
#endif
-#ifndef S_ISDIR
-#define S_ISDIR(mode) (((mode)&S_IFMT) == S_IFDIR)
-#endif
-
#include "ext/standard/file.h" /* for php_set_sock_blocking() :-( */
#include "zend_smart_str.h"
#include "ext/standard/html.h"
diff --git a/sapi/fpm/Makefile.frag b/sapi/fpm/Makefile.frag
index 8e3b5e9316..e39fbcb1e8 100644
--- a/sapi/fpm/Makefile.frag
+++ b/sapi/fpm/Makefile.frag
@@ -1,6 +1,6 @@
fpm: $(SAPI_FPM_PATH)
-$(SAPI_FPM_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_FPM_OBJS)
+$(SAPI_FPM_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_FASTCGI_OBJS) $(PHP_FPM_OBJS)
$(BUILD_FPM)
install-fpm: $(SAPI_FPM_PATH)
diff --git a/sapi/fpm/config.m4 b/sapi/fpm/config.m4
index b4a4f4fb33..1c496e5a9d 100644
--- a/sapi/fpm/config.m4
+++ b/sapi/fpm/config.m4
@@ -678,8 +678,7 @@ if test "$PHP_FPM" != "no"; then
PHP_FPM_CFLAGS="-I$abs_srcdir/sapi/fpm"
- PHP_FPM_FILES="fpm/fastcgi.c \
- fpm/fpm.c \
+ PHP_FPM_FILES="fpm/fpm.c \
fpm/fpm_children.c \
fpm/fpm_cleanup.c \
fpm/fpm_clock.c \
@@ -713,13 +712,13 @@ if test "$PHP_FPM" != "no"; then
case $host_alias in
*aix*)
- BUILD_FPM="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
+ BUILD_FPM="echo '\#! .' > php.sym && echo >>php.sym && nm -BCpg \`echo \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) | sed 's/\([A-Za-z0-9_]*\)\.lo/\1.o/g'\` | \$(AWK) '{ if (((\$\$2 == \"T\") || (\$\$2 == \"D\") || (\$\$2 == \"B\")) && (substr(\$\$3,1,1) != \".\")) { print \$\$3 } }' | sort -u >> php.sym && \$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) -Wl,-brtl -Wl,-bE:php.sym \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
;;
*darwin*)
- BUILD_FPM="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_FPM_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
+ BUILD_FPM="\$(CC) \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(NATIVE_RPATHS) \$(PHP_GLOBAL_OBJS:.lo=.o) \$(PHP_BINARY_OBJS:.lo=.o) \$(PHP_FASTCGI_OBJS:.lo=.o) \$(PHP_FPM_OBJS:.lo=.o) \$(PHP_FRAMEWORKS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
;;
*)
- BUILD_FPM="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
+ BUILD_FPM="\$(LIBTOOL) --mode=link \$(CC) -export-dynamic \$(CFLAGS_CLEAN) \$(EXTRA_CFLAGS) \$(EXTRA_LDFLAGS_PROGRAM) \$(LDFLAGS) \$(PHP_RPATHS) \$(PHP_GLOBAL_OBJS) \$(PHP_BINARY_OBJS) \$(PHP_FASTCGI_OBJS) \$(PHP_FPM_OBJS) \$(EXTRA_LIBS) \$(FPM_EXTRA_LIBS) \$(ZEND_EXTRA_LIBS) -o \$(SAPI_FPM_PATH)"
;;
esac
diff --git a/sapi/fpm/fpm/fastcgi.c b/sapi/fpm/fpm/fastcgi.c
deleted file mode 100644
index 71eaa78cd4..0000000000
--- a/sapi/fpm/fpm/fastcgi.c
+++ /dev/null
@@ -1,1340 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | 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. |
- +----------------------------------------------------------------------+
- | Authors: Dmitry Stogov <dmitry@zend.com> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: fastcgi.c 287777 2009-08-26 19:17:32Z pajoye $ */
-
-#include "php.h"
-#include "fastcgi.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <stdarg.h>
-#include <errno.h>
-#include <limits.h>
-
-#include <php_config.h>
-#include "fpm.h"
-#include "fpm_request.h"
-#include "zlog.h"
-
-#ifdef _WIN32
-
-#include <windows.h>
-
- struct sockaddr_un {
- short sun_family;
- char sun_path[MAXPATHLEN];
- };
-
- static HANDLE fcgi_accept_mutex = INVALID_HANDLE_VALUE;
- static int is_impersonate = 0;
-
-#define FCGI_LOCK(fd) \
- if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \
- DWORD ret; \
- while ((ret = WaitForSingleObject(fcgi_accept_mutex, 1000)) == WAIT_TIMEOUT) { \
- if (in_shutdown) return -1; \
- } \
- if (ret == WAIT_FAILED) { \
- fprintf(stderr, "WaitForSingleObject() failed\n"); \
- return -1; \
- } \
- }
-
-#define FCGI_UNLOCK(fd) \
- if (fcgi_accept_mutex != INVALID_HANDLE_VALUE) { \
- ReleaseMutex(fcgi_accept_mutex); \
- }
-
-#else
-
-# include <sys/types.h>
-# include <sys/stat.h>
-# include <unistd.h>
-# include <fcntl.h>
-# include <sys/socket.h>
-# include <sys/un.h>
-# include <netinet/in.h>
-# include <arpa/inet.h>
-# include <netdb.h>
-# include <signal.h>
-
-# define closesocket(s) close(s)
-
-# if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
-# include <sys/poll.h>
-# endif
-# if defined(HAVE_SYS_SELECT_H)
-# include <sys/select.h>
-# endif
-
-#ifndef INADDR_NONE
-#define INADDR_NONE ((unsigned long) -1)
-#endif
-
-# ifndef HAVE_SOCKLEN_T
- typedef unsigned int socklen_t;
-# endif
-
-# ifdef USE_LOCKING
-# define FCGI_LOCK(fd) \
- do { \
- struct flock lock; \
- lock.l_type = F_WRLCK; \
- lock.l_start = 0; \
- lock.l_whence = SEEK_SET; \
- lock.l_len = 0; \
- if (fcntl(fd, F_SETLKW, &lock) != -1) { \
- break; \
- } else if (errno != EINTR || in_shutdown) { \
- return -1; \
- } \
- } while (1)
-
-# define FCGI_UNLOCK(fd) \
- do { \
- int orig_errno = errno; \
- while (1) { \
- struct flock lock; \
- lock.l_type = F_UNLCK; \
- lock.l_start = 0; \
- lock.l_whence = SEEK_SET; \
- lock.l_len = 0; \
- if (fcntl(fd, F_SETLK, &lock) != -1) { \
- break; \
- } else if (errno != EINTR) { \
- return -1; \
- } \
- } \
- errno = orig_errno; \
- } while (0)
-# else
-# define FCGI_LOCK(fd)
-# define FCGI_UNLOCK(fd)
-# endif
-
-#endif
-
-typedef union _sa_t {
- struct sockaddr sa;
- struct sockaddr_un sa_unix;
- struct sockaddr_in sa_inet;
- struct sockaddr_in6 sa_inet6;
-} sa_t;
-
-static HashTable fcgi_mgmt_vars;
-
-static int is_initialized = 0;
-static int in_shutdown = 0;
-static sa_t *allowed_clients = NULL;
-
-static sa_t client_sa;
-
-/* hash table */
-
-#define FCGI_HASH_TABLE_SIZE 128
-#define FCGI_HASH_TABLE_MASK (FCGI_HASH_TABLE_SIZE - 1)
-#define FCGI_HASH_SEG_SIZE 4096
-
-typedef struct _fcgi_hash_bucket {
- unsigned int hash_value;
- unsigned int var_len;
- char *var;
- unsigned int val_len;
- char *val;
- struct _fcgi_hash_bucket *next;
- struct _fcgi_hash_bucket *list_next;
-} fcgi_hash_bucket;
-
-typedef struct _fcgi_hash_buckets {
- unsigned int idx;
- struct _fcgi_hash_buckets *next;
- struct _fcgi_hash_bucket data[FCGI_HASH_TABLE_SIZE];
-} fcgi_hash_buckets;
-
-typedef struct _fcgi_data_seg {
- char *pos;
- char *end;
- struct _fcgi_data_seg *next;
- char data[1];
-} fcgi_data_seg;
-
-typedef struct _fcgi_hash {
- fcgi_hash_bucket *hash_table[FCGI_HASH_TABLE_SIZE];
- fcgi_hash_bucket *list;
- fcgi_hash_buckets *buckets;
- fcgi_data_seg *data;
-} fcgi_hash;
-
-static void fcgi_hash_init(fcgi_hash *h)
-{
- memset(h->hash_table, 0, sizeof(h->hash_table));
- h->list = NULL;
- h->buckets = (fcgi_hash_buckets*)malloc(sizeof(fcgi_hash_buckets));
- h->buckets->idx = 0;
- h->buckets->next = NULL;
- h->data = (fcgi_data_seg*)malloc(sizeof(fcgi_data_seg) - 1 + FCGI_HASH_SEG_SIZE);
- h->data->pos = h->data->data;
- h->data->end = h->data->pos + FCGI_HASH_SEG_SIZE;
- h->data->next = NULL;
-}
-
-static void fcgi_hash_destroy(fcgi_hash *h)
-{
- fcgi_hash_buckets *b;
- fcgi_data_seg *p;
-
- b = h->buckets;
- while (b) {
- fcgi_hash_buckets *q = b;
- b = b->next;
- free(q);
- }
- p = h->data;
- while (p) {
- fcgi_data_seg *q = p;
- p = p->next;
- free(q);
- }
-}
-
-static void fcgi_hash_clean(fcgi_hash *h)
-{
- memset(h->hash_table, 0, sizeof(h->hash_table));
- h->list = NULL;
- /* delete all bucket blocks except the first one */
- while (h->buckets->next) {
- fcgi_hash_buckets *q = h->buckets;
-
- h->buckets = h->buckets->next;
- free(q);
- }
- h->buckets->idx = 0;
- /* delete all data segments except the first one */
- while (h->data->next) {
- fcgi_data_seg *q = h->data;
-
- h->data = h->data->next;
- free(q);
- }
- h->data->pos = h->data->data;
-}
-
-static inline char* fcgi_hash_strndup(fcgi_hash *h, char *str, unsigned int str_len)
-{
- char *ret;
-
- if (UNEXPECTED(h->data->pos + str_len + 1 >= h->data->end)) {
- unsigned int seg_size = (str_len + 1 > FCGI_HASH_SEG_SIZE) ? str_len + 1 : FCGI_HASH_SEG_SIZE;
- fcgi_data_seg *p = (fcgi_data_seg*)malloc(sizeof(fcgi_data_seg) - 1 + seg_size);
-
- p->pos = p->data;
- p->end = p->pos + seg_size;
- p->next = h->data;
- h->data = p;
- }
- ret = h->data->pos;
- memcpy(ret, str, str_len);
- ret[str_len] = 0;
- h->data->pos += str_len + 1;
- return ret;
-}
-
-static char* fcgi_hash_set(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len, char *val, unsigned int val_len)
-{
- unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK;
- fcgi_hash_bucket *p = h->hash_table[idx];
-
- while (UNEXPECTED(p != NULL)) {
- if (UNEXPECTED(p->hash_value == hash_value) &&
- p->var_len == var_len &&
- memcmp(p->var, var, var_len) == 0) {
-
- p->val_len = val_len;
- p->val = fcgi_hash_strndup(h, val, val_len);
- return p->val;
- }
- p = p->next;
- }
-
- if (UNEXPECTED(h->buckets->idx >= FCGI_HASH_TABLE_SIZE)) {
- fcgi_hash_buckets *b = (fcgi_hash_buckets*)malloc(sizeof(fcgi_hash_buckets));
- b->idx = 0;
- b->next = h->buckets;
- h->buckets = b;
- }
- p = h->buckets->data + h->buckets->idx;
- h->buckets->idx++;
- p->next = h->hash_table[idx];
- h->hash_table[idx] = p;
- p->list_next = h->list;
- h->list = p;
- p->hash_value = hash_value;
- p->var_len = var_len;
- p->var = fcgi_hash_strndup(h, var, var_len);
- p->val_len = val_len;
- p->val = fcgi_hash_strndup(h, val, val_len);
- return p->val;
-}
-
-static void fcgi_hash_del(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len)
-{
- unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK;
- fcgi_hash_bucket **p = &h->hash_table[idx];
-
- while (*p != NULL) {
- if ((*p)->hash_value == hash_value &&
- (*p)->var_len == var_len &&
- memcmp((*p)->var, var, var_len) == 0) {
-
- (*p)->val = NULL; /* NULL value means deleted */
- (*p)->val_len = 0;
- *p = (*p)->next;
- return;
- }
- p = &(*p)->next;
- }
-}
-
-static char *fcgi_hash_get(fcgi_hash *h, unsigned int hash_value, char *var, unsigned int var_len, unsigned int *val_len)
-{
- unsigned int idx = hash_value & FCGI_HASH_TABLE_MASK;
- fcgi_hash_bucket *p = h->hash_table[idx];
-
- while (p != NULL) {
- if (p->hash_value == hash_value &&
- p->var_len == var_len &&
- memcmp(p->var, var, var_len) == 0) {
- *val_len = p->val_len;
- return p->val;
- }
- p = p->next;
- }
- return NULL;
-}
-
-static void fcgi_hash_apply(fcgi_hash *h, fcgi_apply_func func, void *arg)
-{
- fcgi_hash_bucket *p = h->list;
-
- while (p) {
- if (EXPECTED(p->val != NULL)) {
- func(p->var, p->var_len, p->val, p->val_len, arg);
- }
- p = p->list_next;
- }
-}
-
-struct _fcgi_request {
- int listen_socket;
-#ifdef _WIN32
- int tcp;
-#endif
- int fd;
- int id;
- int keep;
-#ifdef TCP_NODELAY
- int nodelay;
-#endif
- int closed;
-
- int in_len;
- int in_pad;
-
- fcgi_header *out_hdr;
- unsigned char *out_pos;
- unsigned char out_buf[1024*8];
- unsigned char reserved[sizeof(fcgi_end_request_rec)];
-
- int has_env;
- fcgi_hash env;
-};
-
-#ifdef _WIN32
-
-static DWORD WINAPI fcgi_shutdown_thread(LPVOID arg)
-{
- HANDLE shutdown_event = (HANDLE) arg;
- WaitForSingleObject(shutdown_event, INFINITE);
- in_shutdown = 1;
- return 0;
-}
-
-#else
-
-static void fcgi_signal_handler(int signo)
-{
- if (signo == SIGUSR1 || signo == SIGTERM) {
- in_shutdown = 1;
- }
-}
-
-static void fcgi_setup_signals(void)
-{
- struct sigaction new_sa, old_sa;
-
- sigemptyset(&new_sa.sa_mask);
- new_sa.sa_flags = 0;
- new_sa.sa_handler = fcgi_signal_handler;
- sigaction(SIGUSR1, &new_sa, NULL);
- sigaction(SIGTERM, &new_sa, NULL);
- sigaction(SIGPIPE, NULL, &old_sa);
- if (old_sa.sa_handler == SIG_DFL) {
- sigaction(SIGPIPE, &new_sa, NULL);
- }
-}
-#endif
-
-int fcgi_in_shutdown(void)
-{
- return in_shutdown;
-}
-
-void fcgi_terminate(void)
-{
- in_shutdown = 1;
-}
-
-int fcgi_init(void)
-{
- if (!is_initialized) {
- zend_hash_init(&fcgi_mgmt_vars, 8, NULL, fcgi_free_mgmt_var_cb, 1);
- fcgi_set_mgmt_var("FCGI_MPXS_CONNS", sizeof("FCGI_MPXS_CONNS") - 1, "0", sizeof("0")-1);
-
- is_initialized = 1;
-#ifdef _WIN32
-# if 0
- /* TODO: Support for TCP sockets */
- WSADATA wsaData;
-
- if (WSAStartup(MAKEWORD(2,0), &wsaData)) {
- fprintf(stderr, "Error starting Windows Sockets. Error: %d", WSAGetLastError());
- return 0;
- }
-# endif
- {
- char *str;
- DWORD pipe_mode = PIPE_READMODE_BYTE | PIPE_WAIT;
- HANDLE pipe = GetStdHandle(STD_INPUT_HANDLE);
-
- SetNamedPipeHandleState(pipe, &pipe_mode, NULL, NULL);
-
- str = getenv("_FCGI_SHUTDOWN_EVENT_");
- if (str != NULL) {
- HANDLE shutdown_event = (HANDLE) atoi(str);
- if (!CreateThread(NULL, 0, fcgi_shutdown_thread,
- shutdown_event, 0, NULL)) {
- return -1;
- }
- }
- str = getenv("_FCGI_MUTEX_");
- if (str != NULL) {
- fcgi_accept_mutex = (HANDLE) atoi(str);
- }
- return 1;
- }
-#else
- fcgi_setup_signals();
- return 1;
-#endif
- }
- return 1;
-}
-
-void fcgi_set_in_shutdown(int new_value)
-{
- in_shutdown = new_value;
-}
-
-void fcgi_shutdown(void)
-{
- if (is_initialized) {
- zend_hash_destroy(&fcgi_mgmt_vars);
- }
- if (allowed_clients) {
- free(allowed_clients);
- }
-}
-
-void fcgi_set_allowed_clients(char *ip)
-{
- char *cur, *end;
- int n;
-
- if (ip) {
- ip = strdup(ip);
- cur = ip;
- n = 0;
- while (*cur) {
- if (*cur == ',') n++;
- cur++;
- }
- if (allowed_clients) free(allowed_clients);
- allowed_clients = malloc(sizeof(sa_t) * (n+2));
- n = 0;
- cur = ip;
- while (cur) {
- end = strchr(cur, ',');
- if (end) {
- *end = 0;
- end++;
- }
- if (inet_pton(AF_INET, cur, &allowed_clients[n].sa_inet.sin_addr)>0) {
- allowed_clients[n].sa.sa_family = AF_INET;
- n++;
- } else if (inet_pton(AF_INET6, cur, &allowed_clients[n].sa_inet6.sin6_addr)>0) {
- allowed_clients[n].sa.sa_family = AF_INET6;
- n++;
- } else {
- zlog(ZLOG_ERROR, "Wrong IP address '%s' in listen.allowed_clients", cur);
- }
- cur = end;
- }
- allowed_clients[n].sa.sa_family = 0;
- free(ip);
- if (!n) {
- zlog(ZLOG_ERROR, "There are no allowed addresses for this pool");
- /* don't clear allowed_clients as it will create an "open for all" security issue */
- }
- }
-}
-
-fcgi_request *fcgi_init_request(int listen_socket)
-{
- fcgi_request *req = (fcgi_request*)calloc(1, sizeof(fcgi_request));
- req->listen_socket = listen_socket;
- req->fd = -1;
- req->id = -1;
-
- req->in_len = 0;
- req->in_pad = 0;
-
- req->out_hdr = NULL;
- req->out_pos = req->out_buf;
-
-#ifdef _WIN32
- req->tcp = !GetNamedPipeInfo((HANDLE)_get_osfhandle(req->listen_socket), NULL, NULL, NULL, NULL);
-#endif
-
-#ifdef TCP_NODELAY
- req->nodelay = 0;
-#endif
-
- fcgi_hash_init(&req->env);
-
- return req;
-}
-
-void fcgi_destroy_request(fcgi_request *req)
-{
- fcgi_hash_destroy(&req->env);
- free(req);
-}
-
-static inline ssize_t safe_write(fcgi_request *req, const void *buf, size_t count)
-{
- int ret;
- size_t n = 0;
-
- do {
- errno = 0;
-#ifdef _WIN32
- if (!req->tcp) {
- ret = write(req->fd, ((char*)buf)+n, count-n);
- } else {
- ret = send(req->fd, ((char*)buf)+n, count-n, 0);
- if (ret <= 0) {
- errno = WSAGetLastError();
- }
- }
-#else
- ret = write(req->fd, ((char*)buf)+n, count-n);
-#endif
- if (ret > 0) {
- n += ret;
- } else if (ret <= 0 && errno != 0 && errno != EINTR) {
- return ret;
- }
- } while (n != count);
- return n;
-}
-
-static inline ssize_t safe_read(fcgi_request *req, const void *buf, size_t count)
-{
- int ret;
- size_t n = 0;
-
- do {
- errno = 0;
-#ifdef _WIN32
- if (!req->tcp) {
- ret = read(req->fd, ((char*)buf)+n, count-n);
- } else {
- ret = recv(req->fd, ((char*)buf)+n, count-n, 0);
- if (ret <= 0) {
- errno = WSAGetLastError();
- }
- }
-#else
- ret = read(req->fd, ((char*)buf)+n, count-n);
-#endif
- if (ret > 0) {
- n += ret;
- } else if (ret == 0 && errno == 0) {
- return n;
- } else if (ret <= 0 && errno != 0 && errno != EINTR) {
- return ret;
- }
- } while (n != count);
- return n;
-}
-
-static inline int fcgi_make_header(fcgi_header *hdr, fcgi_request_type type, int req_id, int len)
-{
- int pad = ((len + 7) & ~7) - len;
-
- hdr->contentLengthB0 = (unsigned char)(len & 0xff);
- hdr->contentLengthB1 = (unsigned char)((len >> 8) & 0xff);
- hdr->paddingLength = (unsigned char)pad;
- hdr->requestIdB0 = (unsigned char)(req_id & 0xff);
- hdr->requestIdB1 = (unsigned char)((req_id >> 8) & 0xff);
- hdr->reserved = 0;
- hdr->type = type;
- hdr->version = FCGI_VERSION_1;
- if (pad) {
- memset(((unsigned char*)hdr) + sizeof(fcgi_header) + len, 0, pad);
- }
- return pad;
-}
-
-static int fcgi_get_params(fcgi_request *req, unsigned char *p, unsigned char *end)
-{
- int name_len = 0;
- int val_len = 0;
-
- while (p < end) {
- name_len = *p++;
- if (UNEXPECTED(name_len >= 128)) {
- if (UNEXPECTED(p + 3 >= end)) return 0;
- name_len = ((name_len & 0x7f) << 24);
- name_len |= (*p++ << 16);
- name_len |= (*p++ << 8);
- name_len |= *p++;
- }
- if (UNEXPECTED(p >= end)) return 0;
- val_len = *p++;
- if (UNEXPECTED(val_len >= 128)) {
- if (UNEXPECTED(p + 3 >= end)) return 0;
- val_len = ((val_len & 0x7f) << 24);
- val_len |= (*p++ << 16);
- val_len |= (*p++ << 8);
- val_len |= *p++;
- }
- if (UNEXPECTED(name_len > (INT_MAX - val_len)) || /* would the addition overflow? */
- UNEXPECTED(name_len + val_len > end - p)) { /* would we exceed the buffer? */
- /* Malformated request */
- return 0;
- }
-
- /*
- * get the effective length of the name in case it's not a valid string
- * don't do this on the value because it can be binary data
- */
- if (UNEXPECTED(memchr(p, 0, name_len) != NULL)) {
- /* Malicious request */
- return 0;
- }
- fcgi_hash_set(&req->env, FCGI_HASH_FUNC(p, name_len), (char*)p, name_len, (char*)p + name_len, val_len);
- p += name_len + val_len;
- }
- return 1;
-}
-
-static void fcgi_free_var(zval *zv)
-{
- efree(Z_PTR_P(zv));
-}
-
-static int fcgi_read_request(fcgi_request *req)
-{
- fcgi_header hdr;
- int len, padding;
- unsigned char buf[FCGI_MAX_LENGTH+8];
-
- req->keep = 0;
- req->closed = 0;
- req->in_len = 0;
- req->out_hdr = NULL;
- req->out_pos = req->out_buf;
- req->has_env = 1;
-
- if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
- hdr.version < FCGI_VERSION_1) {
- return 0;
- }
-
- len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
- padding = hdr.paddingLength;
-
- while (hdr.type == FCGI_STDIN && len == 0) {
- if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
- hdr.version < FCGI_VERSION_1) {
- return 0;
- }
-
- len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
- padding = hdr.paddingLength;
- }
-
- if (len + padding > FCGI_MAX_LENGTH) {
- return 0;
- }
-
- req->id = (hdr.requestIdB1 << 8) + hdr.requestIdB0;
-
- if (hdr.type == FCGI_BEGIN_REQUEST && len == sizeof(fcgi_begin_request)) {
- if (safe_read(req, buf, len+padding) != len+padding) {
- return 0;
- }
-
- req->keep = (((fcgi_begin_request*)buf)->flags & FCGI_KEEP_CONN);
-#ifdef TCP_NODELAY
- if (req->keep && req->tcp && !req->nodelay) {
-# ifdef _WIN32
- BOOL on = 1;
-# else
- int on = 1;
-# endif
-
- setsockopt(req->fd, IPPROTO_TCP, TCP_NODELAY, (char*)&on, sizeof(on));
- req->nodelay = 1;
- }
-#endif
- switch ((((fcgi_begin_request*)buf)->roleB1 << 8) + ((fcgi_begin_request*)buf)->roleB0) {
- case FCGI_RESPONDER:
- fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "RESPONDER", sizeof("RESPONDER")-1);
- break;
- case FCGI_AUTHORIZER:
- fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "AUTHORIZER", sizeof("AUTHORIZER")-1);
- break;
- case FCGI_FILTER:
- fcgi_hash_set(&req->env, FCGI_HASH_FUNC("FCGI_ROLE", sizeof("FCGI_ROLE")-1), "FCGI_ROLE", sizeof("FCGI_ROLE")-1, "FILTER", sizeof("FILTER")-1);
- break;
- default:
- return 0;
- }
-
- if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
- hdr.version < FCGI_VERSION_1) {
- return 0;
- }
-
- len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
- padding = hdr.paddingLength;
-
- while (hdr.type == FCGI_PARAMS && len > 0) {
- if (len + padding > FCGI_MAX_LENGTH) {
- return 0;
- }
-
- if (safe_read(req, buf, len+padding) != len+padding) {
- req->keep = 0;
- return 0;
- }
-
- if (!fcgi_get_params(req, buf, buf+len)) {
- req->keep = 0;
- return 0;
- }
-
- if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
- hdr.version < FCGI_VERSION_1) {
- req->keep = 0;
- return 0;
- }
- len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
- padding = hdr.paddingLength;
- }
- } else if (hdr.type == FCGI_GET_VALUES) {
- unsigned char *p = buf + sizeof(fcgi_header);
- zval *value;
- unsigned int zlen;
- fcgi_hash_bucket *q;
-
- if (safe_read(req, buf, len+padding) != len+padding) {
- req->keep = 0;
- return 0;
- }
-
- if (!fcgi_get_params(req, buf, buf+len)) {
- req->keep = 0;
- return 0;
- }
-
- q = req->env.list;
- while (q != NULL) {
- if ((value = zend_hash_str_find(&fcgi_mgmt_vars, q->var, q->var_len)) == NULL) {
- q = q->list_next;
- continue;
- }
- zlen = (unsigned int)Z_STRLEN_P(value);
- if ((p + 4 + 4 + q->var_len + zlen) >= (buf + sizeof(buf))) {
- break;
- }
- if (q->var_len < 0x80) {
- *p++ = q->var_len;
- } else {
- *p++ = ((q->var_len >> 24) & 0xff) | 0x80;
- *p++ = (q->var_len >> 16) & 0xff;
- *p++ = (q->var_len >> 8) & 0xff;
- *p++ = q->var_len & 0xff;
- }
- if (zlen < 0x80) {
- *p++ = zlen;
- } else {
- *p++ = ((zlen >> 24) & 0xff) | 0x80;
- *p++ = (zlen >> 16) & 0xff;
- *p++ = (zlen >> 8) & 0xff;
- *p++ = zlen & 0xff;
- }
- memcpy(p, q->var, q->var_len);
- p += q->var_len;
- memcpy(p, Z_STRVAL_P(value), zlen);
- p += zlen;
- q = q->list_next;
- }
- len = p - buf - sizeof(fcgi_header);
- len += fcgi_make_header((fcgi_header*)buf, FCGI_GET_VALUES_RESULT, 0, len);
- if (safe_write(req, buf, sizeof(fcgi_header)+len) != (int)sizeof(fcgi_header)+len) {
- req->keep = 0;
- return 0;
- }
- return 0;
- } else {
- return 0;
- }
-
- return 1;
-}
-
-int fcgi_read(fcgi_request *req, char *str, int len)
-{
- int ret, n, rest;
- fcgi_header hdr;
- unsigned char buf[255];
-
- n = 0;
- rest = len;
- while (rest > 0) {
- if (req->in_len == 0) {
- if (safe_read(req, &hdr, sizeof(fcgi_header)) != sizeof(fcgi_header) ||
- hdr.version < FCGI_VERSION_1 ||
- hdr.type != FCGI_STDIN) {
- req->keep = 0;
- return 0;
- }
- req->in_len = (hdr.contentLengthB1 << 8) | hdr.contentLengthB0;
- req->in_pad = hdr.paddingLength;
- if (req->in_len == 0) {
- return n;
- }
- }
-
- if (req->in_len >= rest) {
- ret = safe_read(req, str, rest);
- } else {
- ret = safe_read(req, str, req->in_len);
- }
- if (ret < 0) {
- req->keep = 0;
- return ret;
- } else if (ret > 0) {
- req->in_len -= ret;
- rest -= ret;
- n += ret;
- str += ret;
- if (req->in_len == 0) {
- if (req->in_pad) {
- if (safe_read(req, buf, req->in_pad) != req->in_pad) {
- req->keep = 0;
- return ret;
- }
- }
- } else {
- return n;
- }
- } else {
- return n;
- }
- }
- return n;
-}
-
-void fcgi_close(fcgi_request *req, int force, int destroy)
-{
- if (destroy && req->has_env) {
- fcgi_hash_clean(&req->env);
- req->has_env = 0;
- }
-
-#ifdef _WIN32
- if (is_impersonate && !req->tcp) {
- RevertToSelf();
- }
-#endif
-
- if ((force || !req->keep) && req->fd >= 0) {
-#ifdef _WIN32
- if (!req->tcp) {
- HANDLE pipe = (HANDLE)_get_osfhandle(req->fd);
-
- if (!force) {
- FlushFileBuffers(pipe);
- }
- DisconnectNamedPipe(pipe);
- } else {
- if (!force) {
- char buf[8];
-
- shutdown(req->fd, 1);
- while (recv(req->fd, buf, sizeof(buf), 0) > 0) {}
- }
- closesocket(req->fd);
- }
-#else
- if (!force) {
- char buf[8];
-
- shutdown(req->fd, 1);
- while (recv(req->fd, buf, sizeof(buf), 0) > 0) {}
- }
- close(req->fd);
-#endif
-#ifdef TCP_NODELAY
- req->nodelay = 0;
-#endif
- req->fd = -1;
- fpm_request_finished();
- }
-}
-
-int fcgi_is_closed(fcgi_request *req)
-{
- return (req->fd < 0);
-}
-
-static int fcgi_is_allowed() {
- int i;
-
- if (client_sa.sa.sa_family == AF_UNIX) {
- return 1;
- }
- if (!allowed_clients) {
- return 1;
- }
- if (client_sa.sa.sa_family == AF_INET) {
- for (i=0 ; allowed_clients[i].sa.sa_family ; i++) {
- if (allowed_clients[i].sa.sa_family == AF_INET
- && !memcmp(&client_sa.sa_inet.sin_addr, &allowed_clients[i].sa_inet.sin_addr, 4)) {
- return 1;
- }
- }
- }
- if (client_sa.sa.sa_family == AF_INET6) {
- for (i=0 ; allowed_clients[i].sa.sa_family ; i++) {
- if (allowed_clients[i].sa.sa_family == AF_INET6
- && !memcmp(&client_sa.sa_inet6.sin6_addr, &allowed_clients[i].sa_inet6.sin6_addr, 12)) {
- return 1;
- }
-#ifdef IN6_IS_ADDR_V4MAPPED
- if (allowed_clients[i].sa.sa_family == AF_INET
- && IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr)
- && !memcmp(((char *)&client_sa.sa_inet6.sin6_addr)+12, &allowed_clients[i].sa_inet.sin_addr, 4)) {
- return 1;
- }
-#endif
- }
- }
-
- zlog(ZLOG_ERROR, "Connection disallowed: IP address '%s' has been dropped.", fcgi_get_last_client_ip());
- return 0;
-}
-
-int fcgi_accept_request(fcgi_request *req)
-{
-#ifdef _WIN32
- HANDLE pipe;
- OVERLAPPED ov;
-#endif
-
- while (1) {
- if (req->fd < 0) {
- while (1) {
- if (in_shutdown) {
- return -1;
- }
-#ifdef _WIN32
- if (!req->tcp) {
- pipe = (HANDLE)_get_osfhandle(req->listen_socket);
- FCGI_LOCK(req->listen_socket);
- ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
- if (!ConnectNamedPipe(pipe, &ov)) {
- errno = GetLastError();
- if (errno == ERROR_IO_PENDING) {
- while (WaitForSingleObject(ov.hEvent, 1000) == WAIT_TIMEOUT) {
- if (in_shutdown) {
- CloseHandle(ov.hEvent);
- FCGI_UNLOCK(req->listen_socket);
- return -1;
- }
- }
- } else if (errno != ERROR_PIPE_CONNECTED) {
- }
- }
- CloseHandle(ov.hEvent);
- req->fd = req->listen_socket;
- FCGI_UNLOCK(req->listen_socket);
- } else {
- SOCKET listen_socket = (SOCKET)_get_osfhandle(req->listen_socket);
-#else
- {
- int listen_socket = req->listen_socket;
-#endif
- sa_t sa;
- socklen_t len = sizeof(sa);
-
- fpm_request_accepting();
-
- FCGI_LOCK(req->listen_socket);
- req->fd = accept(listen_socket, (struct sockaddr *)&sa, &len);
- FCGI_UNLOCK(req->listen_socket);
-
- client_sa = sa;
- if (req->fd >= 0 && !fcgi_is_allowed()) {
- closesocket(req->fd);
- req->fd = -1;
- continue;
- }
- }
-
-#ifdef _WIN32
- if (req->fd < 0 && (in_shutdown || errno != EINTR)) {
-#else
- if (req->fd < 0 && (in_shutdown || (errno != EINTR && errno != ECONNABORTED))) {
-#endif
- return -1;
- }
-
-#ifdef _WIN32
- break;
-#else
- if (req->fd >= 0) {
-#if defined(HAVE_SYS_POLL_H) && defined(HAVE_POLL)
- struct pollfd fds;
- int ret;
-
- fpm_request_reading_headers();
-
- fds.fd = req->fd;
- fds.events = POLLIN;
- fds.revents = 0;
- do {
- errno = 0;
- ret = poll(&fds, 1, 5000);
- } while (ret < 0 && errno == EINTR);
- if (ret > 0 && (fds.revents & POLLIN)) {
- break;
- }
- fcgi_close(req, 1, 0);
-#else
- fpm_request_reading_headers();
-
- if (req->fd < FD_SETSIZE) {
- struct timeval tv = {5,0};
- fd_set set;
- int ret;
-
- FD_ZERO(&set);
- FD_SET(req->fd, &set);
- do {
- errno = 0;
- ret = select(req->fd + 1, &set, NULL, NULL, &tv) >= 0;
- } while (ret < 0 && errno == EINTR);
- if (ret > 0 && FD_ISSET(req->fd, &set)) {
- break;
- }
- fcgi_close(req, 1, 0);
- } else {
- zlog(ZLOG_ERROR, "Too many open file descriptors. FD_SETSIZE limit exceeded.");
- fcgi_close(req, 1, 0);
- }
-#endif
- }
-#endif
- }
- } else if (in_shutdown) {
- return -1;
- }
- if (fcgi_read_request(req)) {
-#ifdef _WIN32
- if (is_impersonate && !req->tcp) {
- pipe = (HANDLE)_get_osfhandle(req->fd);
- if (!ImpersonateNamedPipeClient(pipe)) {
- fcgi_close(req, 1, 1);
- continue;
- }
- }
-#endif
- return req->fd;
- } else {
- fcgi_close(req, 1, 1);
- }
- }
-}
-
-static inline fcgi_header* open_packet(fcgi_request *req, fcgi_request_type type)
-{
- req->out_hdr = (fcgi_header*) req->out_pos;
- req->out_hdr->type = type;
- req->out_pos += sizeof(fcgi_header);
- return req->out_hdr;
-}
-
-static inline void close_packet(fcgi_request *req)
-{
- if (req->out_hdr) {
- int len = req->out_pos - ((unsigned char*)req->out_hdr + sizeof(fcgi_header));
-
- req->out_pos += fcgi_make_header(req->out_hdr, (fcgi_request_type)req->out_hdr->type, req->id, len);
- req->out_hdr = NULL;
- }
-}
-
-int fcgi_flush(fcgi_request *req, int close)
-{
- int len;
-
- close_packet(req);
-
- len = req->out_pos - req->out_buf;
-
- if (close) {
- fcgi_end_request_rec *rec = (fcgi_end_request_rec*)(req->out_pos);
-
- fcgi_make_header(&rec->hdr, FCGI_END_REQUEST, req->id, sizeof(fcgi_end_request));
- rec->body.appStatusB3 = 0;
- rec->body.appStatusB2 = 0;
- rec->body.appStatusB1 = 0;
- rec->body.appStatusB0 = 0;
- rec->body.protocolStatus = FCGI_REQUEST_COMPLETE;
- len += sizeof(fcgi_end_request_rec);
- }
-
- if (safe_write(req, req->out_buf, len) != len) {
- req->keep = 0;
- req->out_pos = req->out_buf;
- return 0;
- }
-
- req->out_pos = req->out_buf;
- return 1;
-}
-
-ssize_t fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len)
-{
- int limit, rest;
-
- if (len <= 0) {
- return 0;
- }
-
- if (req->out_hdr && req->out_hdr->type != type) {
- close_packet(req);
- }
-
- /* Optimized version */
- limit = sizeof(req->out_buf) - (req->out_pos - req->out_buf);
- if (!req->out_hdr) {
- limit -= sizeof(fcgi_header);
- if (limit < 0) limit = 0;
- }
-
- if (len < limit) {
- if (!req->out_hdr) {
- open_packet(req, type);
- }
- memcpy(req->out_pos, str, len);
- req->out_pos += len;
- } else if (len - limit < sizeof(req->out_buf) - sizeof(fcgi_header)) {
- if (!req->out_hdr) {
- open_packet(req, type);
- }
- if (limit > 0) {
- memcpy(req->out_pos, str, limit);
- req->out_pos += limit;
- }
- if (!fcgi_flush(req, 0)) {
- return -1;
- }
- if (len > limit) {
- open_packet(req, type);
- memcpy(req->out_pos, str + limit, len - limit);
- req->out_pos += len - limit;
- }
- } else {
- int pos = 0;
- int pad;
-
- close_packet(req);
- while ((len - pos) > 0xffff) {
- open_packet(req, type);
- fcgi_make_header(req->out_hdr, type, req->id, 0xfff8);
- req->out_hdr = NULL;
- if (!fcgi_flush(req, 0)) {
- return -1;
- }
- if (safe_write(req, str + pos, 0xfff8) != 0xfff8) {
- req->keep = 0;
- return -1;
- }
- pos += 0xfff8;
- }
-
- pad = (((len - pos) + 7) & ~7) - (len - pos);
- rest = pad ? 8 - pad : 0;
-
- open_packet(req, type);
- fcgi_make_header(req->out_hdr, type, req->id, (len - pos) - rest);
- req->out_hdr = NULL;
- if (!fcgi_flush(req, 0)) {
- return -1;
- }
- if (safe_write(req, str + pos, (len - pos) - rest) != (len - pos) - rest) {
- req->keep = 0;
- return -1;
- }
- if (pad) {
- open_packet(req, type);
- memcpy(req->out_pos, str + len - rest, rest);
- req->out_pos += rest;
- }
- }
-
- return len;
-}
-
-int fcgi_finish_request(fcgi_request *req, int force_close)
-{
- int ret = 1;
-
- if (req->fd >= 0) {
- if (!req->closed) {
- ret = fcgi_flush(req, 1);
- req->closed = 1;
- }
- fcgi_close(req, force_close, 1);
- }
- return ret;
-}
-
-char* fcgi_getenv(fcgi_request *req, const char* var, int var_len)
-{
- unsigned int val_len;
-
- if (!req) return NULL;
-
- return fcgi_hash_get(&req->env, FCGI_HASH_FUNC(var, var_len), (char*)var, var_len, &val_len);
-}
-
-char* fcgi_quick_getenv(fcgi_request *req, const char* var, int var_len, unsigned int hash_value)
-{
- unsigned int val_len;
-
- return fcgi_hash_get(&req->env, hash_value, (char*)var, var_len, &val_len);
-}
-
-char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val)
-{
- if (!req) return NULL;
- if (val == NULL) {
- fcgi_hash_del(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len);
- return NULL;
- } else {
- return fcgi_hash_set(&req->env, FCGI_HASH_FUNC(var, var_len), var, var_len, val, (unsigned int)strlen(val));
- }
-}
-
-char* fcgi_quick_putenv(fcgi_request *req, char* var, int var_len, unsigned int hash_value, char* val)
-{
- if (val == NULL) {
- fcgi_hash_del(&req->env, hash_value, var, var_len);
- return NULL;
- } else {
- return fcgi_hash_set(&req->env, hash_value, var, var_len, val, (unsigned int)strlen(val));
- }
-}
-
-void fcgi_loadenv(fcgi_request *req, fcgi_apply_func func, zval *array)
-{
- fcgi_hash_apply(&req->env, func, array);
-}
-
-void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len)
-{
- zval zvalue;
- ZVAL_NEW_STR(&zvalue, zend_string_init(value, value_len, 1));
- zend_hash_str_add(&fcgi_mgmt_vars, name, name_len, &zvalue);
-}
-
-void fcgi_free_mgmt_var_cb(zval *zv)
-{
- zend_string_free(Z_STR_P(zv));
-}
-
-const char *fcgi_get_last_client_ip() /* {{{ */
-{
- static char str[INET6_ADDRSTRLEN];
-
- /* Ipv4 */
- if (client_sa.sa.sa_family == AF_INET) {
- return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet.sin_addr, str, INET6_ADDRSTRLEN);
- }
-#ifdef IN6_IS_ADDR_V4MAPPED
- /* Ipv4-Mapped-Ipv6 */
- if (client_sa.sa.sa_family == AF_INET6
- && IN6_IS_ADDR_V4MAPPED(&client_sa.sa_inet6.sin6_addr)) {
- return inet_ntop(AF_INET, ((char *)&client_sa.sa_inet6.sin6_addr)+12, str, INET6_ADDRSTRLEN);
- }
-#endif
- /* Ipv6 */
- if (client_sa.sa.sa_family == AF_INET6) {
- return inet_ntop(client_sa.sa.sa_family, &client_sa.sa_inet6.sin6_addr, str, INET6_ADDRSTRLEN);
- }
- /* Unix socket */
- return NULL;
-}
-/* }}} */
-/*
- * 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/sapi/fpm/fpm/fastcgi.h b/sapi/fpm/fpm/fastcgi.h
deleted file mode 100644
index 31419dfdd0..0000000000
--- a/sapi/fpm/fpm/fastcgi.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | 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. |
- +----------------------------------------------------------------------+
- | Authors: Dmitry Stogov <dmitry@zend.com> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id: fastcgi.h 272370 2008-12-31 11:15:49Z sebastian $ */
-
-/* FastCGI protocol */
-
-#define FCGI_VERSION_1 1
-
-#define FCGI_MAX_LENGTH 0xffff
-
-#define FCGI_KEEP_CONN 1
-
-/* this is near the perfect hash function for most useful FastCGI variables
- * which combines efficiency and minimal hash collisions
- */
-
-#define FCGI_HASH_FUNC(var, var_len) \
- (UNEXPECTED(var_len < 3) ? var_len : \
- (((unsigned int)var[3]) << 2) + \
- (((unsigned int)var[var_len-2]) << 4) + \
- (((unsigned int)var[var_len-1]) << 2) + \
- var_len)
-
-#define FCGI_GETENV(request, name) \
- fcgi_quick_getenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1))
-
-#define FCGI_PUTENV(request, name, value) \
- fcgi_quick_putenv(request, name, sizeof(name)-1, FCGI_HASH_FUNC(name, sizeof(name)-1), value)
-
-typedef enum _fcgi_role {
- FCGI_RESPONDER = 1,
- FCGI_AUTHORIZER = 2,
- FCGI_FILTER = 3
-} fcgi_role;
-
-typedef enum _fcgi_request_type {
- FCGI_BEGIN_REQUEST = 1, /* [in] */
- FCGI_ABORT_REQUEST = 2, /* [in] (not supported) */
- FCGI_END_REQUEST = 3, /* [out] */
- FCGI_PARAMS = 4, /* [in] environment variables */
- FCGI_STDIN = 5, /* [in] post data */
- FCGI_STDOUT = 6, /* [out] response */
- FCGI_STDERR = 7, /* [out] errors */
- FCGI_DATA = 8, /* [in] filter data (not supported) */
- FCGI_GET_VALUES = 9, /* [in] */
- FCGI_GET_VALUES_RESULT = 10 /* [out] */
-} fcgi_request_type;
-
-typedef enum _fcgi_protocol_status {
- FCGI_REQUEST_COMPLETE = 0,
- FCGI_CANT_MPX_CONN = 1,
- FCGI_OVERLOADED = 2,
- FCGI_UNKNOWN_ROLE = 3
-} dcgi_protocol_status;
-
-typedef struct _fcgi_header {
- unsigned char version;
- unsigned char type;
- unsigned char requestIdB1;
- unsigned char requestIdB0;
- unsigned char contentLengthB1;
- unsigned char contentLengthB0;
- unsigned char paddingLength;
- unsigned char reserved;
-} fcgi_header;
-
-typedef struct _fcgi_begin_request {
- unsigned char roleB1;
- unsigned char roleB0;
- unsigned char flags;
- unsigned char reserved[5];
-} fcgi_begin_request;
-
-typedef struct _fcgi_begin_request_rec {
- fcgi_header hdr;
- fcgi_begin_request body;
-} fcgi_begin_request_rec;
-
-typedef struct _fcgi_end_request {
- unsigned char appStatusB3;
- unsigned char appStatusB2;
- unsigned char appStatusB1;
- unsigned char appStatusB0;
- unsigned char protocolStatus;
- unsigned char reserved[3];
-} fcgi_end_request;
-
-typedef struct _fcgi_end_request_rec {
- fcgi_header hdr;
- fcgi_end_request body;
-} fcgi_end_request_rec;
-
-/* FastCGI client API */
-
-typedef void (*fcgi_apply_func)(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg);
-
-typedef struct _fcgi_request fcgi_request;
-
-int fcgi_init(void);
-void fcgi_shutdown(void);
-int fcgi_in_shutdown(void);
-void fcgi_terminate(void);
-fcgi_request* fcgi_init_request(int listen_socket);
-void fcgi_destroy_request(fcgi_request *req);
-int fcgi_accept_request(fcgi_request *req);
-int fcgi_finish_request(fcgi_request *req, int force_close);
-
-void fcgi_set_allowed_clients(char *);
-void fcgi_close(fcgi_request *req, int force, int destroy);
-int fcgi_is_closed(fcgi_request *req);
-
-char* fcgi_getenv(fcgi_request *req, const char* var, int var_len);
-char* fcgi_putenv(fcgi_request *req, char* var, int var_len, char* val);
-char* fcgi_quick_getenv(fcgi_request *req, const char* var, int var_len, unsigned int hash_value);
-char* fcgi_quick_putenv(fcgi_request *req, char* var, int var_len, unsigned int hash_value, char* val);
-void fcgi_loadenv(fcgi_request *req, fcgi_apply_func load_func, zval *array);
-
-int fcgi_read(fcgi_request *req, char *str, int len);
-
-ssize_t fcgi_write(fcgi_request *req, fcgi_request_type type, const char *str, int len);
-int fcgi_flush(fcgi_request *req, int close);
-
-void fcgi_set_mgmt_var(const char * name, size_t name_len, const char * value, size_t value_len);
-void fcgi_free_mgmt_var_cb(zval *ptr);
-
-const char *fcgi_get_last_client_ip();
-
-/*
- * 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/sapi/fpm/fpm/fpm_main.c b/sapi/fpm/fpm/fpm_main.c
index efd1f7155a..001355ec1e 100644
--- a/sapi/fpm/fpm/fpm_main.c
+++ b/sapi/fpm/fpm/fpm_main.c
@@ -219,14 +219,15 @@ static php_cgi_globals_struct php_cgi_globals;
#define TRANSLATE_SLASHES(path)
#endif
-static int print_module_info(zval *zv)
+static int print_module_info(zval *zv) /* {{{ */
{
zend_module_entry *module = Z_PTR_P(zv);
php_printf("%s\n", module->name);
return 0;
}
+/* }}} */
-static int module_name_cmp(const void *a, const void *b)
+static int module_name_cmp(const void *a, const void *b) /* {{{ */
{
Bucket *f = (Bucket *) a;
Bucket *s = (Bucket *) b;
@@ -234,8 +235,9 @@ static int module_name_cmp(const void *a, const void *b)
return strcasecmp( ((zend_module_entry *) Z_PTR(f->val))->name,
((zend_module_entry *) Z_PTR(s->val))->name);
}
+/* }}} */
-static void print_modules(void)
+static void print_modules(void) /* {{{ */
{
HashTable sorted_registry;
@@ -245,20 +247,23 @@ static void print_modules(void)
zend_hash_apply(&sorted_registry, print_module_info);
zend_hash_destroy(&sorted_registry);
}
+/* }}} */
-static int print_extension_info(zend_extension *ext, void *arg)
+static int print_extension_info(zend_extension *ext, void *arg) /* {{{ */
{
php_printf("%s\n", ext->name);
return 0;
}
+/* }}} */
-static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s)
+static int extension_name_cmp(const zend_llist_element **f, const zend_llist_element **s) /* {{{ */
{
return strcmp( ((zend_extension *)(*f)->data)->name,
((zend_extension *)(*s)->data)->name);
}
+/* }}} */
-static void print_extensions(void)
+static void print_extensions(void) /* {{{ */
{
zend_llist sorted_exts;
@@ -268,12 +273,13 @@ static void print_extensions(void)
zend_llist_apply_with_argument(&sorted_exts, (llist_apply_with_arg_func_t) print_extension_info, NULL);
zend_llist_destroy(&sorted_exts);
}
+/* }}} */
#ifndef STDOUT_FILENO
#define STDOUT_FILENO 1
#endif
-static inline size_t sapi_cgibin_single_write(const char *str, uint str_length)
+static inline size_t sapi_cgibin_single_write(const char *str, uint str_length) /* {{{ */
{
ssize_t ret;
@@ -298,8 +304,9 @@ static inline size_t sapi_cgibin_single_write(const char *str, uint str_length)
return fwrite(str, 1, MIN(str_length, 16384), stdout);
#endif
}
+/* }}} */
-static size_t sapi_cgibin_ub_write(const char *str, size_t str_length)
+static size_t sapi_cgibin_ub_write(const char *str, size_t str_length) /* {{{ */
{
const char *ptr = str;
uint remaining = str_length;
@@ -317,9 +324,9 @@ static size_t sapi_cgibin_ub_write(const char *str, size_t str_length)
return str_length;
}
+/* }}} */
-
-static void sapi_cgibin_flush(void *server_context)
+static void sapi_cgibin_flush(void *server_context) /* {{{ */
{
/* fpm has started, let use fcgi instead of stdout */
if (fpm_is_running) {
@@ -339,10 +346,11 @@ static void sapi_cgibin_flush(void *server_context)
php_handle_aborted_connection();
}
}
+/* }}} */
#define SAPI_CGI_MAX_HEADER_LENGTH 1024
-static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers)
+static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers) /* {{{ */
{
char buf[SAPI_CGI_MAX_HEADER_LENGTH];
sapi_header_struct *h;
@@ -443,12 +451,26 @@ static int sapi_cgi_send_headers(sapi_headers_struct *sapi_headers)
return SAPI_HEADER_SENT_SUCCESSFULLY;
}
+/* }}} */
#ifndef STDIN_FILENO
# define STDIN_FILENO 0
#endif
-static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes)
+#ifndef HAVE_ATTRIBUTE_WEAK
+static void fpm_fcgi_log(int type, const char *fmt, ...) /* {{{ */
+#else
+void fcgi_log(int type, const char *fmt, ...)
+#endif
+{
+ va_list args;
+ va_start(args, fmt);
+ vzlog("", 0, type, fmt, args);
+ va_end(args);
+}
+/* }}} */
+
+static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes) /* {{{ */
{
uint read_bytes = 0;
int tmp_read_bytes;
@@ -486,8 +508,9 @@ static size_t sapi_cgi_read_post(char *buffer, size_t count_bytes)
}
return read_bytes;
}
+/* }}} */
-static char *sapi_cgibin_getenv(char *name, size_t name_len)
+static char *sapi_cgibin_getenv(char *name, size_t name_len) /* {{{ */
{
/* if fpm has started, use fcgi env */
if (fpm_is_running) {
@@ -498,8 +521,10 @@ static char *sapi_cgibin_getenv(char *name, size_t name_len)
/* if fpm has not started yet, use std env */
return getenv(name);
}
+/* }}} */
-static char *_sapi_cgibin_putenv(char *name, char *value)
+#if 0
+static char *_sapi_cgibin_putenv(char *name, char *value) /* {{{ */
{
int name_len;
@@ -511,15 +536,18 @@ static char *_sapi_cgibin_putenv(char *name, char *value)
fcgi_request *request = (fcgi_request*) SG(server_context);
return fcgi_putenv(request, name, name_len, value);
}
+/* }}} */
+#endif
-static char *sapi_cgi_read_cookies(void)
+static char *sapi_cgi_read_cookies(void) /* {{{ */
{
fcgi_request *request = (fcgi_request*) SG(server_context);
return FCGI_GETENV(request, "HTTP_COOKIE");
}
+/* }}} */
-static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg)
+static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, unsigned int val_len, void *arg) /* {{{ */
{
zval *array_ptr = (zval*)arg;
int filter_arg = (Z_ARR_P(array_ptr) == Z_ARR(PG(http_globals)[TRACK_VARS_ENV]))?PARSE_ENV:PARSE_SERVER;
@@ -529,13 +557,11 @@ static void cgi_php_load_env_var(char *var, unsigned int var_len, char *val, uns
php_register_variable_safe(var, val, new_val_len, array_ptr);
}
}
+/* }}} */
-void cgi_php_import_environment_variables(zval *array_ptr)
+void cgi_php_import_environment_variables(zval *array_ptr) /* {{{ */
{
fcgi_request *request;
- zend_string *var;
- char *val;
- int filter_arg;
if (Z_TYPE(PG(http_globals)[TRACK_VARS_ENV]) == IS_ARRAY &&
Z_ARR_P(array_ptr) != Z_ARR(PG(http_globals)[TRACK_VARS_ENV]) &&
@@ -559,8 +585,9 @@ void cgi_php_import_environment_variables(zval *array_ptr)
request = (fcgi_request*) SG(server_context);
fcgi_loadenv(request, cgi_php_load_env_var, array_ptr);
}
+/* }}} */
-static void sapi_cgi_register_variables(zval *track_vars_array)
+static void sapi_cgi_register_variables(zval *track_vars_array) /* {{{ */
{
fcgi_request *request = (fcgi_request*) SG(server_context);
size_t php_self_len;
@@ -601,6 +628,7 @@ static void sapi_cgi_register_variables(zval *track_vars_array)
}
}
}
+/* }}} */
/* {{{ sapi_cgi_log_fastcgi
*
@@ -713,7 +741,7 @@ static void php_cgi_ini_activate_user_config(char *path, int path_len, const cha
}
/* }}} */
-static int sapi_cgi_activate(void)
+static int sapi_cgi_activate(void) /* {{{ */
{
fcgi_request *request = (fcgi_request*) SG(server_context);
char *path, *doc_root, *server_name;
@@ -784,8 +812,9 @@ static int sapi_cgi_activate(void)
return SUCCESS;
}
+/* }}} */
-static int sapi_cgi_deactivate(void)
+static int sapi_cgi_deactivate(void) /* {{{ */
{
/* flush only when SAPI was started. The reasons are:
1. SAPI Deactivate is called from two places: module init and request shutdown
@@ -802,14 +831,16 @@ static int sapi_cgi_deactivate(void)
}
return SUCCESS;
}
+/* }}} */
-static int php_cgi_startup(sapi_module_struct *sapi_module)
+static int php_cgi_startup(sapi_module_struct *sapi_module) /* {{{ */
{
if (php_module_startup(sapi_module, &cgi_module_entry, 1) == FAILURE) {
return FAILURE;
}
return SUCCESS;
}
+/* }}} */
/* {{{ sapi_module_struct cgi_sapi_module
*/
@@ -1360,6 +1391,14 @@ static void init_request_info(void)
}
/* }}} */
+static void fpm_init_request(fcgi_request *req, int listen_fd) /* {{{ */ {
+ fcgi_init_request(req, listen_fd);
+ req->hook.on_accept = fpm_request_accepting;
+ req->hook.on_read = fpm_request_reading_headers;
+ req->hook.on_close = fpm_request_finished;
+}
+/* }}} */
+
static void fastcgi_ini_parser(zval *arg1, zval *arg2, zval *arg3, int callback_type, void *arg) /* {{{ */
{
int *mode = (int *)arg;
@@ -1523,7 +1562,7 @@ int main(int argc, char *argv[])
int max_requests = 500;
int requests = 0;
int fcgi_fd = 0;
- fcgi_request *request;
+ fcgi_request request;
char *fpm_config = NULL;
char *fpm_prefix = NULL;
char *fpm_pid = NULL;
@@ -1553,6 +1592,10 @@ int main(int argc, char *argv[])
cgi_sapi_module.php_ini_path_override = NULL;
cgi_sapi_module.php_ini_ignore_cwd = 1;
+#ifndef HAVE_ATTRIBUTE_WEAK
+ fcgi_set_logger(fpm_fcgi_log);
+#endif
+
fcgi_init();
#ifdef PHP_WIN32
@@ -1819,21 +1862,21 @@ consult the installation file that came with this distribution, or visit \n\
php_import_environment_variables = cgi_php_import_environment_variables;
/* library is already initialized, now init our request */
- request = fcgi_init_request(fcgi_fd);
+ fpm_init_request(&request, fcgi_fd);
zend_first_try {
- while (fcgi_accept_request(request) >= 0) {
+ while (EXPECTED(fcgi_accept_request(&request) >= 0)) {
+ char *primary_script = NULL;
request_body_fd = -1;
- SG(server_context) = (void *) request;
+ SG(server_context) = (void *) &request;
init_request_info();
- char *primary_script = NULL;
fpm_request_info();
/* request startup only after we've done all we can to
* get path_translated */
- if (php_request_startup() == FAILURE) {
- fcgi_finish_request(request, 1);
+ if (UNEXPECTED(php_request_startup() == FAILURE)) {
+ fcgi_finish_request(&request, 1);
SG(server_context) = NULL;
php_module_shutdown();
return FPM_EXIT_SOFTWARE;
@@ -1841,16 +1884,16 @@ consult the installation file that came with this distribution, or visit \n\
/* check if request_method has been sent.
* if not, it's certainly not an HTTP over fcgi request */
- if (!SG(request_info).request_method) {
+ if (UNEXPECTED(!SG(request_info).request_method)) {
goto fastcgi_request_done;
}
- if (fpm_status_handle_request()) {
+ if (UNEXPECTED(fpm_status_handle_request())) {
goto fastcgi_request_done;
}
/* If path_translated is NULL, terminate here with a 404 */
- if (!SG(request_info).path_translated) {
+ if (UNEXPECTED(!SG(request_info).path_translated)) {
zend_try {
zlog(ZLOG_DEBUG, "Primary script unknown");
SG(sapi_headers).http_response_code = 404;
@@ -1860,7 +1903,7 @@ consult the installation file that came with this distribution, or visit \n\
goto fastcgi_request_done;
}
- if (fpm_php_limit_extensions(SG(request_info).path_translated)) {
+ if (UNEXPECTED(fpm_php_limit_extensions(SG(request_info).path_translated))) {
SG(sapi_headers).http_response_code = 403;
PUTS("Access denied.\n");
goto fastcgi_request_done;
@@ -1873,7 +1916,7 @@ consult the installation file that came with this distribution, or visit \n\
primary_script = estrdup(SG(request_info).path_translated);
/* path_translated exists, we can continue ! */
- if (php_fopen_primary_script(&file_handle) == FAILURE) {
+ if (UNEXPECTED(php_fopen_primary_script(&file_handle) == FAILURE)) {
zend_try {
zlog(ZLOG_ERROR, "Unable to open primary script: %s (%s)", primary_script, strerror(errno));
if (errno == EACCES) {
@@ -1897,16 +1940,16 @@ consult the installation file that came with this distribution, or visit \n\
php_execute_script(&file_handle);
fastcgi_request_done:
- if (primary_script) {
+ if (EXPECTED(primary_script)) {
efree(primary_script);
}
- if (request_body_fd != -1) {
+ if (UNEXPECTED(request_body_fd != -1)) {
close(request_body_fd);
}
request_body_fd = -2;
- if (EG(exit_status) == 255) {
+ if (UNEXPECTED(EG(exit_status) == 255)) {
if (CGIG(error_header) && *CGIG(error_header)) {
sapi_header_line ctr = {0};
@@ -1925,13 +1968,13 @@ fastcgi_request_done:
php_request_shutdown((void *) 0);
requests++;
- if (max_requests && (requests == max_requests)) {
- fcgi_finish_request(request, 1);
+ if (UNEXPECTED(max_requests && (requests == max_requests))) {
+ fcgi_finish_request(&request, 1);
break;
}
/* end of fastcgi loop */
}
- fcgi_destroy_request(request);
+ fcgi_destroy_request(&request);
fcgi_shutdown();
if (cgi_sapi_module.php_ini_path_override) {
diff --git a/sapi/fpm/fpm/zlog.c b/sapi/fpm/fpm/zlog.c
index 6f17b99133..1659c77efc 100644
--- a/sapi/fpm/fpm/zlog.c
+++ b/sapi/fpm/fpm/zlog.c
@@ -98,20 +98,20 @@ int zlog_set_level(int new_value) /* {{{ */
}
/* }}} */
-void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* {{{ */
+void vzlog(const char *function, int line, int flags, const char *fmt, va_list args) /* {{{ */
{
struct timeval tv;
char buf[MAX_LINE_LENGTH];
const size_t buf_size = MAX_LINE_LENGTH;
- va_list args;
size_t len = 0;
int truncated = 0;
int saved_errno;
if (external_logger) {
- va_start(args, fmt);
- len = vsnprintf(buf, buf_size, fmt, args);
- va_end(args);
+ va_list ap;
+ va_copy(ap, args);
+ len = vsnprintf(buf, buf_size, fmt, ap);
+ va_end(ap);
if (len >= buf_size) {
memcpy(buf + buf_size - sizeof("..."), "...", sizeof("...") - 1);
len = buf_size - 1;
@@ -157,9 +157,7 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /*
}
if (!truncated) {
- va_start(args, fmt);
len += vsnprintf(buf + len, buf_size - len, fmt, args);
- va_end(args);
if (len >= buf_size) {
truncated = 1;
}
@@ -197,3 +195,10 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /*
}
/* }}} */
+void zlog_ex(const char *function, int line, int flags, const char *fmt, ...) /* {{{ */ {
+ va_list args;
+ va_start(args, fmt);
+ vzlog(function, line, flags, fmt, args);
+ va_end(args);
+}
+/* }}} */
diff --git a/sapi/fpm/fpm/zlog.h b/sapi/fpm/fpm/zlog.h
index 1945922da5..c2bf752b93 100644
--- a/sapi/fpm/fpm/zlog.h
+++ b/sapi/fpm/fpm/zlog.h
@@ -5,6 +5,8 @@
#ifndef ZLOG_H
#define ZLOG_H 1
+#include <stdarg.h>
+
#define zlog(flags,...) zlog_ex(__func__, __LINE__, flags, __VA_ARGS__)
struct timeval;
@@ -17,6 +19,7 @@ void zlog_set_launched(void);
size_t zlog_print_time(struct timeval *tv, char *timebuf, size_t timebuf_len);
+void vzlog(const char *function, int line, int flags, const char *fmt, va_list args);
void zlog_ex(const char *function, int line, int flags, const char *fmt, ...)
__attribute__ ((format(printf,4,5)));
@@ -24,6 +27,7 @@ void zlog_ex(const char *function, int line, int flags, const char *fmt, ...)
extern const int syslog_priorities[];
#endif
+/* keep this same as FCGI_ERROR */
enum {
ZLOG_DEBUG = 1,
ZLOG_NOTICE = 2,
diff --git a/sapi/litespeed/lsapilib.c b/sapi/litespeed/lsapilib.c
index 89ef6df3fa..d6d1c107a7 100644
--- a/sapi/litespeed/lsapilib.c
+++ b/sapi/litespeed/lsapilib.c
@@ -3131,10 +3131,20 @@ static int lsapi_initSuEXEC()
if ( !s_defaultUid || !s_defaultGid )
{
pw = getpwnam( "nobody" );
- if ( !s_defaultUid )
- s_defaultUid = pw->pw_uid;
- if ( !s_defaultGid )
- s_defaultGid = pw->pw_gid;
+ if ( pw )
+ {
+ if ( !s_defaultUid )
+ s_defaultUid = pw->pw_uid;
+ if ( !s_defaultGid )
+ s_defaultGid = pw->pw_gid;
+ }
+ else
+ {
+ if ( !s_defaultUid )
+ s_defaultUid = 10000;
+ if ( !s_defaultGid )
+ s_defaultGid = 10000;
+ }
}
return 0;
}
diff --git a/sapi/nsapi/CREDITS b/sapi/nsapi/CREDITS
deleted file mode 100644
index 2a05919862..0000000000
--- a/sapi/nsapi/CREDITS
+++ /dev/null
@@ -1,2 +0,0 @@
-NSAPI
-Jayakumar Muthukumarasamy, Uwe Schindler
diff --git a/sapi/nsapi/config.m4 b/sapi/nsapi/config.m4
deleted file mode 100644
index 8923f53227..0000000000
--- a/sapi/nsapi/config.m4
+++ /dev/null
@@ -1,39 +0,0 @@
-dnl
-dnl $Id$
-dnl
-
-PHP_ARG_WITH(nsapi, for NSAPI support,
-[ --with-nsapi=DIR Build PHP as NSAPI module for Netscape/iPlanet/Sun Webserver], no, no)
-
-if test "$PHP_NSAPI" != "no"; then
- if test ! -d $PHP_NSAPI/bin ; then
- AC_MSG_ERROR(Please specify the path to the root of your Netscape/iPlanet/Sun Webserver using --with-nsapi=DIR)
- fi
- AC_MSG_CHECKING([for NSAPI include files])
- if test -d $PHP_NSAPI/include ; then
- NSAPI_INC_DIR="$PHP_NSAPI/include"
- AC_MSG_RESULT([Netscape 3.x / Sun 7.x style])
- AC_CHECK_HEADERS([$NSAPI_INC_DIR/nsapi.h])
- NSAPI_INCLUDE="-I$NSAPI_INC_DIR"
- fi
- if test -d $PHP_NSAPI/plugins/include ; then
- NSAPI_INC_DIR="$PHP_NSAPI/plugins/include"
- AC_MSG_RESULT([iPlanet 4.x / Sun 6.x style])
- AC_CHECK_HEADERS([$NSAPI_INC_DIR/nsapi.h])
- NSAPI_INCLUDE="$NSAPI_INCLUDE -I$NSAPI_INC_DIR"
- fi
- if test -z "$NSAPI_INCLUDE"; then
- AC_MSG_ERROR([Please check you have nsapi.h in either $PHP_NSAPI/include or $PHP_NSAPI/plugins/include])
- fi
-
- PHP_EVAL_INCLINE($NSAPI_INCLUDE)
- PHP_BUILD_THREAD_SAFE
- AC_DEFINE(HAVE_NSAPI, 1, [Whether you have a Netscape/iPlanet/Sun Webserver])
- PHP_SELECT_SAPI(nsapi, shared, nsapi.c)
- INSTALL_IT="\$(INSTALL) -m 0755 $SAPI_SHARED \$(INSTALL_ROOT)$PHP_NSAPI/bin/"
-fi
-
-
-dnl ## Local Variables:
-dnl ## tab-width: 4
-dnl ## End:
diff --git a/sapi/nsapi/config.w32 b/sapi/nsapi/config.w32
deleted file mode 100644
index 17b86d20e4..0000000000
--- a/sapi/nsapi/config.w32
+++ /dev/null
@@ -1,20 +0,0 @@
-// vim:ft=javascript
-// $Id$
-
-ARG_ENABLE('nsapi', 'Build NSAPI for Netscape/iPlanet/SunONE webservers', 'no');
-
-ARG_WITH('nsapi-includes', 'Where to find NSAPI headers', null);
-ARG_WITH('nsapi-libs', 'Where to find NSAPI libraries', null);
-
-if (PHP_NSAPI != "no") {
- if (PHP_ZTS == "no") {
- WARNING("NSAPI module requires an --enable-zts build of PHP");
- PHP_NSAPI = "no"
- } else if (CHECK_HEADER_ADD_INCLUDE("nsapi.h", "CFLAGS_NSAPI",
- PHP_NSAPI + ';' + PHP_NSAPI_INCLUDES) &&
- CHECK_LIB("ns-httpd*.lib", "nsapi", PHP_NSAPI + ";" + PHP_NSAPI_LIBS)) {
- SAPI('nsapi', 'nsapi.c', 'php' + PHP_VERSION + 'nsapi.dll', '/D XP_WIN32 ');
- } else {
- WARNING("Could not find NSAPI headers/libraries");
- }
-}
diff --git a/sapi/nsapi/nsapi-readme.txt b/sapi/nsapi/nsapi-readme.txt
deleted file mode 100644
index 6bf4afb83d..0000000000
--- a/sapi/nsapi/nsapi-readme.txt
+++ /dev/null
@@ -1,154 +0,0 @@
-Configuration of your Netscape/iPlanet/Sun Webserver for PHP7
------------------------------------------------------------------
-
-These instructions are targeted at Netscape Enterprise Web Server and
-SUN/Netscape Alliance iPlanet Web Server and the new Sun Java System Webserver.
-On other web servers your milage may vary.
-
-Firstly you may need to add some paths to the LD_LIBRARY_PATH
-environment for Netscape to find all the shared libs. This is best done
-in the start script for your Netscape server. Windows users can
-probably skip this step. The start script is located in:
-
- <path-to-netscape-server>/https-servername/start
-
-
-Netscape/iPlanet/Sun config files are located in:
-
- <path-to-server>/https-servername/config
-
-
-Add the following line to mime.types (you can do that by the administration server):
-
- type=magnus-internal/x-httpd-php exts=php
-
-
-Place the following two lines after mime.types init in
-<path-to-server>/https-servername/config/obj.conf (for servers < 6) or
-for iPlanet/Sun Webserver 6.0 and above however at the end of the
-<path-to-server>/https-servername/config/magnus.conf file:
-
- Init fn="load-modules" funcs="php7_init,php7_execute,php7_auth_trans" shlib="/path/to/phplibrary"
- Init fn=php7_init errorString="Failed to initialize PHP!" [php_ini="/path/to/php.ini"]
-
-The "shlib" will vary depending on your OS:
-
- Unix: "<path-to-server>/bin/libphp7.so".
- Windows: "c:/path/to/php7/php7nsapi.dll"
-
-
-In obj.conf (for virtual server classes [Sun 6.0+] in their vserver.obj.conf):
-
- <Object name="default">
- .
- .
- .
- # NOTE this next line should happen after all 'ObjectType' and before
- # all 'AddLog' lines
- # You can modify some entries in php.ini request specific by adding it to the Service
- # directive, e.g. doc_root="/path"
- # For boolean ini-keys please use 0/1 as value, NOT "On","Off",... (this will not work
- # correctly), e.g. zlib.output_compression=1 instead of zlib.output_compression="On"
-
- Service fn="php7_execute" type="magnus-internal/x-httpd-php" [inikey=value ...]
- .
- .
- .
- </Object>
-
-This is only needed if you want to configure a directory that only consists of
-PHP scripts (same like a cgi-bin directory):
-
- <Object name="x-httpd-php">
- ObjectType fn="force-type" type="magnus-internal/x-httpd-php"
- Service fn="php7_execute" [inikey=value ...]
- </Object>
-
-After that you can configure a directory in the Administration server and assign it
-the style "x-httpd-php". All files in it will get executed as PHP. This is nice to
-hide PHP usage by renaming files to .html
-
-Note: The stacksize that PHP uses depends on the configuration of the webserver. If you get
-crashes with very large PHP scripts, it is recommended to raise it with the Admin Server
-(in the section "MAGNUS EDITOR").
-
-
-Authentication configuration
-----------------------------
-
-PHP authentication cannot be used with any other authentication. ALL
-AUTHENTICATION IS PASSED TO YOUR PHP SCRIPT. To configure PHP
-Authentication for the entire server, add the following line:
-
- <Object name="default">
- AuthTrans fn=php7_auth_trans
- .
- .
- .
- .
- </Object>
-
-
-To use PHP Authentication on a single directory, add the following:
-
- <Object ppath="d:\path\to\authenticated\dir\*">
- AuthTrans fn=php7_auth_trans
- </Object>
-
-
-Special use for error pages or self-made directory listings
------------------------------------------------------------
-
-You can use PHP to generate the error pages for "404 Not Found"
-or similar. Add the following line to the object in obj.conf for
-every error page you want to overwrite:
-
- Error fn="php7_execute" code=XXX script="/path/to/script.php" [inikey=value inikey=value...]
-
-where XXX ist the HTTP error code. Please delete any other Error
-directives which could interfere with yours.
-If you want to place a page for all errors that could exist, leave
-the "code" parameter out. Your script can get the HTTP status code
-with $_SERVER['ERROR_TYPE'].
-
-Another posibility is to generate self-made directory listings.
-Just generate a PHP script which displays a directory listing and
-replace the corresponding default Service line for
-type="magnus-internal/directory" in obj.conf with the following:
-
- Service fn="php7_execute" type="magnus-internal/directory" script="/path/to/script.php" [inikey=value inikey=value...]
-
-For both error and directory listing pages the original URI and
-translated URI are in the variables $_SERVER['PATH_INFO'] and
-$_SERVER['PATH_TRANSLATED'].
-
-
-Note about nsapi_virtual() and subrequests
-------------------------------------------
-
-The NSAPI module now supports the nsapi_virtual() function (alias: virtual())
-to make subrequests on the webserver and insert the result in the webpage.
-The problem is, that this function uses some undocumented features from
-the NSAPI library.
-
-Under Unix this is not a problem, because the module automatically looks
-for the needed functions and uses them if available. If not, nsapi_virtual()
-is disabled.
-
-Under Windows limitations in the DLL handling need the use of a automatic
-detection of the most recent ns-httpdXX.dll file. This is tested for servers
-till version 6.1. If a newer version of the Sun server is used, the detection
-fails and nsapi_virtual() is disabled.
-
-If this is the case, try the following:
-Add the following parameter to php7_init in magnus.conf:
-
- Init fn=php7_init ... server_lib="ns-httpdXX.dll"
-
-where XX is the correct DLL version number. To get it, look in the server-root
-for the correct DLL name. The DLL with the biggest filesize is the right one.
-
-But be warned: SUPPORT FOR nsapi_virtual() IS EXPERIMENTAL !!!
-
-
-$Id$
diff --git a/sapi/nsapi/nsapi.c b/sapi/nsapi/nsapi.c
deleted file mode 100644
index 4c625794c7..0000000000
--- a/sapi/nsapi/nsapi.c
+++ /dev/null
@@ -1,1102 +0,0 @@
-/*
- +----------------------------------------------------------------------+
- | 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: Jayakumar Muthukumarasamy <jk@kasenna.com> |
- | Uwe Schindler <uwe@thetaphi.de> |
- +----------------------------------------------------------------------+
-*/
-
-/* $Id$ */
-
-/*
- * PHP includes
- */
-#define NSAPI 1
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "php.h"
-#include "php_variables.h"
-#include "ext/standard/info.h"
-#include "php_ini.h"
-#include "php_globals.h"
-#include "SAPI.h"
-#include "php_main.h"
-#include "php_version.h"
-#include "TSRM.h"
-#include "ext/standard/php_standard.h"
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#ifndef RTLD_DEFAULT
-#define RTLD_DEFAULT NULL
-#endif
-
-/*
- * If neither XP_UNIX not XP_WIN32 is defined use PHP_WIN32
- */
-#if !defined(XP_UNIX) && !defined(XP_WIN32)
-#ifdef PHP_WIN32
-#define XP_WIN32
-#else
-#define XP_UNIX
-#endif
-#endif
-
-/*
- * The manual define of HPUX is to fix bug #46020, nsapi.h needs this to detect HPUX
- */
-#ifdef __hpux
-#define HPUX
-#endif
-
-/*
- * NSAPI includes
- */
-#include "nsapi.h"
-
-/* fix for gcc4 visibility issue */
-#ifndef PHP_WIN32
-# undef NSAPI_PUBLIC
-# define NSAPI_PUBLIC PHPAPI
-#endif
-
-#define NSLS_D struct nsapi_request_context *request_context
-#define NSLS_DC , NSLS_D
-#define NSLS_C request_context
-#define NSLS_CC , NSLS_C
-#define NSG(v) (request_context->v)
-
-/*
- * ZTS needs to be defined for NSAPI to work
- */
-#if !defined(ZTS)
-#error "NSAPI module needs ZTS to be defined"
-#endif
-
-/*
- * Structure to encapsulate the NSAPI request in SAPI
- */
-typedef struct nsapi_request_context {
- pblock *pb;
- Session *sn;
- Request *rq;
- int read_post_bytes;
- char *path_info;
- int fixed_script; /* 0 if script is from URI, 1 if script is from "script" parameter */
- short http_error; /* 0 in normal mode; for errors the HTTP error code */
-} nsapi_request_context;
-
-/*
- * Mappings between NSAPI names and environment variables. This
- * mapping was obtained from the sample programs at the iplanet
- * website.
- */
-typedef struct nsapi_equiv {
- const char *env_var;
- const char *nsapi_eq;
-} nsapi_equiv;
-
-static nsapi_equiv nsapi_reqpb[] = {
- { "QUERY_STRING", "query" },
- { "REQUEST_LINE", "clf-request" },
- { "REQUEST_METHOD", "method" },
- { "PHP_SELF", "uri" },
- { "SERVER_PROTOCOL", "protocol" }
-};
-static size_t nsapi_reqpb_size = sizeof(nsapi_reqpb)/sizeof(nsapi_reqpb[0]);
-
-static nsapi_equiv nsapi_vars[] = {
- { "AUTH_TYPE", "auth-type" },
- { "CLIENT_CERT", "auth-cert" },
- { "REMOTE_USER", "auth-user" }
-};
-static size_t nsapi_vars_size = sizeof(nsapi_vars)/sizeof(nsapi_vars[0]);
-
-static nsapi_equiv nsapi_client[] = {
- { "HTTPS_KEYSIZE", "keysize" },
- { "HTTPS_SECRETSIZE", "secret-keysize" },
- { "REMOTE_ADDR", "ip" },
- { "REMOTE_HOST", "ip" }
-};
-static size_t nsapi_client_size = sizeof(nsapi_client)/sizeof(nsapi_client[0]);
-
-/* this parameters to "Service"/"Error" are NSAPI ones which should not be php.ini keys and are excluded */
-static char *nsapi_exclude_from_ini_entries[] = { "fn", "type", "method", "directive", "code", "reason", "script", "bucket", NULL };
-
-static void nsapi_free(void *addr)
-{
- if (addr != NULL) {
- FREE(addr);
- }
-}
-
-
-/*******************/
-/* PHP module part */
-/*******************/
-
-PHP_MINIT_FUNCTION(nsapi);
-PHP_MSHUTDOWN_FUNCTION(nsapi);
-PHP_RINIT_FUNCTION(nsapi);
-PHP_RSHUTDOWN_FUNCTION(nsapi);
-PHP_MINFO_FUNCTION(nsapi);
-
-PHP_FUNCTION(nsapi_virtual);
-PHP_FUNCTION(nsapi_request_headers);
-PHP_FUNCTION(nsapi_response_headers);
-
-ZEND_BEGIN_MODULE_GLOBALS(nsapi)
- long read_timeout;
-ZEND_END_MODULE_GLOBALS(nsapi)
-
-ZEND_DECLARE_MODULE_GLOBALS(nsapi)
-
-#define NSAPI_G(v) TSRMG(nsapi_globals_id, zend_nsapi_globals *, v)
-
-
-/* {{{ arginfo */
-ZEND_BEGIN_ARG_INFO_EX(arginfo_nsapi_virtual, 0, 0, 1)
- ZEND_ARG_INFO(0, uri)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_nsapi_request_headers, 0)
-ZEND_END_ARG_INFO()
-
-ZEND_BEGIN_ARG_INFO(arginfo_nsapi_response_headers, 0)
-ZEND_END_ARG_INFO()
-/* }}} */
-
-/* {{{ nsapi_functions[]
- *
- * Every user visible function must have an entry in nsapi_functions[].
- */
-const zend_function_entry nsapi_functions[] = {
- PHP_FE(nsapi_virtual, arginfo_nsapi_virtual) /* Make subrequest */
- PHP_FALIAS(virtual, nsapi_virtual, arginfo_nsapi_virtual) /* compatibility */
- PHP_FE(nsapi_request_headers, arginfo_nsapi_request_headers) /* get request headers */
- PHP_FALIAS(getallheaders, nsapi_request_headers, arginfo_nsapi_request_headers) /* compatibility */
- PHP_FALIAS(apache_request_headers, nsapi_request_headers, arginfo_nsapi_request_headers) /* compatibility */
- PHP_FE(nsapi_response_headers, arginfo_nsapi_response_headers) /* get response headers */
- PHP_FALIAS(apache_response_headers, nsapi_response_headers, arginfo_nsapi_response_headers) /* compatibility */
- {NULL, NULL, NULL}
-};
-/* }}} */
-
-/* {{{ nsapi_module_entry
- */
-zend_module_entry nsapi_module_entry = {
- STANDARD_MODULE_HEADER,
- "nsapi",
- nsapi_functions,
- PHP_MINIT(nsapi),
- PHP_MSHUTDOWN(nsapi),
- NULL,
- NULL,
- PHP_MINFO(nsapi),
- NO_VERSION_YET,
- STANDARD_MODULE_PROPERTIES
-};
-/* }}} */
-
-/* {{{ PHP_INI
- */
-PHP_INI_BEGIN()
- STD_PHP_INI_ENTRY("nsapi.read_timeout", "60", PHP_INI_ALL, OnUpdateLong, read_timeout, zend_nsapi_globals, nsapi_globals)
-PHP_INI_END()
-/* }}} */
-
-/* newer servers hide this functions from the programmer so redefine the functions dynamically
- thanks to Chris Elving from Sun for the function declarations */
-typedef int (*nsapi_servact_prototype)(Session *sn, Request *rq);
-nsapi_servact_prototype nsapi_servact_uri2path = NULL;
-nsapi_servact_prototype nsapi_servact_pathchecks = NULL;
-nsapi_servact_prototype nsapi_servact_fileinfo = NULL;
-nsapi_servact_prototype nsapi_servact_service = NULL;
-
-#ifdef PHP_WIN32
-/* The following dll-names for nsapi are in use at this time. The undocumented
- * servact_* functions are always in the newest one, older ones are supported by
- * the server only by wrapping the function table nothing else. So choose
- * the newest one found in process space for dynamic linking */
-static char *nsapi_dlls[] = { "ns-httpd40.dll", "ns-httpd36.dll", "ns-httpd35.dll", "ns-httpd30.dll", NULL };
-/* if user specifies an other dll name by server_lib parameter
- * it is placed in the following variable and only this DLL is
- * checked for the servact_* functions */
-char *nsapi_dll = NULL;
-#endif
-
-/* {{{ php_nsapi_init_dynamic_symbols
- */
-static void php_nsapi_init_dynamic_symbols(void)
-{
- /* find address of internal NSAPI functions */
-#ifdef PHP_WIN32
- register int i;
- DL_HANDLE module = NULL;
- if (nsapi_dll) {
- /* try user specified server_lib */
- module = GetModuleHandle(nsapi_dll);
- if (!module) {
- log_error(LOG_WARN, "php7_init", NULL, NULL, "Cannot find DLL specified by server_lib parameter: %s", nsapi_dll);
- }
- } else {
- /* find a LOADED dll module from nsapi_dlls */
- for (i=0; nsapi_dlls[i]; i++) {
- if (module = GetModuleHandle(nsapi_dlls[i])) {
- break;
- }
- }
- }
- if (!module) return;
-#else
- DL_HANDLE module = RTLD_DEFAULT;
-#endif
- nsapi_servact_uri2path = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_uri2path");
- nsapi_servact_pathchecks = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_pathchecks");
- nsapi_servact_fileinfo = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_fileinfo");
- nsapi_servact_service = (nsapi_servact_prototype)DL_FETCH_SYMBOL(module, "INTservact_service");
- if (!(nsapi_servact_uri2path && nsapi_servact_pathchecks && nsapi_servact_fileinfo && nsapi_servact_service)) {
- /* not found - could be cause they are undocumented */
- nsapi_servact_uri2path = NULL;
- nsapi_servact_pathchecks = NULL;
- nsapi_servact_fileinfo = NULL;
- nsapi_servact_service = NULL;
- }
-}
-/* }}} */
-
-/* {{{ php_nsapi_init_globals
- */
-static void php_nsapi_init_globals(zend_nsapi_globals *nsapi_globals)
-{
- nsapi_globals->read_timeout = 60;
-}
-/* }}} */
-
-/* {{{ PHP_MINIT_FUNCTION
- */
-PHP_MINIT_FUNCTION(nsapi)
-{
- php_nsapi_init_dynamic_symbols();
- ZEND_INIT_MODULE_GLOBALS(nsapi, php_nsapi_init_globals, NULL);
- REGISTER_INI_ENTRIES();
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_MSHUTDOWN_FUNCTION
- */
-PHP_MSHUTDOWN_FUNCTION(nsapi)
-{
- UNREGISTER_INI_ENTRIES();
- return SUCCESS;
-}
-/* }}} */
-
-/* {{{ PHP_MINFO_FUNCTION
- */
-PHP_MINFO_FUNCTION(nsapi)
-{
- php_info_print_table_start();
- php_info_print_table_row(2, "NSAPI Module Revision", "$Id$");
- php_info_print_table_row(2, "Server Software", system_version());
- php_info_print_table_row(2, "Sub-requests with nsapi_virtual()",
- (nsapi_servact_service)?((zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0))?"not supported with zlib.output_compression":"enabled"):"not supported on this platform" );
- php_info_print_table_end();
-
- DISPLAY_INI_ENTRIES();
-}
-/* }}} */
-
-/* {{{ proto bool nsapi_virtual(string uri)
- Perform an NSAPI sub-request */
-/* This function is equivalent to <!--#include virtual...-->
- * in SSI. It does an NSAPI sub-request. It is useful
- * for including CGI scripts or .shtml files, or anything else
- * that you'd parse through webserver.
- */
-PHP_FUNCTION(nsapi_virtual)
-{
- int uri_len,rv;
- char *uri,*value;
- Request *rq;
- nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
-
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &uri, &uri_len) == FAILURE) {
- return;
- }
-
- if (!nsapi_servact_service) {
- php_error_docref(NULL, E_WARNING, "Unable to include uri '%s' - Sub-requests not supported on this platform", uri);
- RETURN_FALSE;
- } else if (zend_ini_long("zlib.output_compression", sizeof("zlib.output_compression"), 0)) {
- php_error_docref(NULL, E_WARNING, "Unable to include uri '%s' - Sub-requests do not work with zlib.output_compression", uri);
- RETURN_FALSE;
- } else {
- php_output_end_all();
- php_header();
-
- /* do the sub-request */
- /* thanks to Chris Elving from Sun for this code sniplet */
- if ((rq = request_restart_internal(uri, NULL)) == NULL) {
- php_error_docref(NULL, E_WARNING, "Unable to include uri '%s' - Internal request creation failed", uri);
- RETURN_FALSE;
- }
-
- /* insert host of current request to get page from same vhost */
- param_free(pblock_remove("host", rq->headers));
- if (value = pblock_findval("host", rc->rq->headers)) {
- pblock_nvinsert("host", value, rq->headers);
- }
-
- /* go through the normal request stages as given in obj.conf,
- but leave out the logging/error section */
- do {
- rv = (*nsapi_servact_uri2path)(rc->sn, rq);
- if (rv != REQ_PROCEED) {
- continue;
- }
-
- rv = (*nsapi_servact_pathchecks)(rc->sn, rq);
- if (rv != REQ_PROCEED) {
- continue;
- }
-
- rv = (*nsapi_servact_fileinfo)(rc->sn, rq);
- if (rv != REQ_PROCEED) {
- continue;
- }
-
- rv = (*nsapi_servact_service)(rc->sn, rq);
- } while (rv == REQ_RESTART);
-
- if (rq->status_num != 200) {
- php_error_docref(NULL, E_WARNING, "Unable to include uri '%s' - HTTP status code %d during subrequest", uri, rq->status_num);
- request_free(rq);
- RETURN_FALSE;
- }
-
- request_free(rq);
-
- RETURN_TRUE;
- }
-}
-/* }}} */
-
-/* {{{ proto array nsapi_request_headers(void)
- Get all headers from the request */
-PHP_FUNCTION(nsapi_request_headers)
-{
- register int i;
- struct pb_entry *entry;
- nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
-
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
-
- array_init(return_value);
-
- for (i=0; i < rc->rq->headers->hsize; i++) {
- entry=rc->rq->headers->ht[i];
- while (entry) {
- add_assoc_string(return_value, entry->param->name, entry->param->value);
- entry=entry->next;
- }
- }
-}
-/* }}} */
-
-/* {{{ proto array nsapi_response_headers(void)
- Get all headers from the response */
-PHP_FUNCTION(nsapi_response_headers)
-{
- register int i;
- struct pb_entry *entry;
- nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
-
- if (zend_parse_parameters_none() == FAILURE) {
- return;
- }
-
- array_init(return_value);
-
- for (i=0; i < rc->rq->srvhdrs->hsize; i++) {
- entry=rc->rq->srvhdrs->ht[i];
- while (entry) {
- add_assoc_string(return_value, entry->param->name, entry->param->value);
- entry=entry->next;
- }
- }
-}
-/* }}} */
-
-
-/*************/
-/* SAPI part */
-/*************/
-
-static int sapi_nsapi_ub_write(const char *str, unsigned int str_length)
-{
- int retval;
- nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
-
- if (!SG(headers_sent)) {
- sapi_send_headers();
- }
-
- retval = net_write(rc->sn->csd, (char *)str, str_length);
- if (retval == IO_ERROR /* -1 */ || retval == IO_EOF /* 0 */) {
- php_handle_aborted_connection();
- }
- return retval;
-}
-
-/* modified version of apache2 */
-static void sapi_nsapi_flush(void *server_context)
-{
- nsapi_request_context *rc = (nsapi_request_context *)server_context;
-
- if (!rc) {
- /* we have no context, so no flushing needed. This fixes a SIGSEGV on shutdown */
- return;
- }
-
- if (!SG(headers_sent)) {
- sapi_send_headers();
- }
-
- /* flushing is only supported in iPlanet servers from version 6.1 on, make it conditional */
-#if NSAPI_VERSION >= 302
- if (net_flush(rc->sn->csd) < 0) {
- php_handle_aborted_connection();
- }
-#endif
-}
-
-/* callback for zend_llist_apply on SAPI_HEADER_DELETE_ALL operation */
-static int php_nsapi_remove_header(sapi_header_struct *sapi_header)
-{
- char *header_name, *p;
- nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
-
- /* copy the header, because NSAPI needs reformatting and we do not want to change the parameter */
- header_name = pool_strdup(rc->sn->pool, sapi_header->header);
-
- /* extract name, this works, if only the header without ':' is given, too */
- if (p = strchr(header_name, ':')) {
- *p = 0;
- }
-
- /* header_name to lower case because NSAPI reformats the headers and wants lowercase */
- for (p=header_name; *p; p++) {
- *p=tolower(*p);
- }
-
- /* remove the header */
- param_free(pblock_remove(header_name, rc->rq->srvhdrs));
- pool_free(rc->sn->pool, header_name);
-
- return ZEND_HASH_APPLY_KEEP;
-}
-
-static int sapi_nsapi_header_handler(sapi_header_struct *sapi_header, sapi_header_op_enum op, sapi_headers_struct *sapi_headers)
-{
- char *header_name, *header_content, *p;
- nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
-
- switch(op) {
- case SAPI_HEADER_DELETE_ALL:
- /* this only deletes headers set or overwritten by PHP, headers previously set by NSAPI are left intact */
- zend_llist_apply(&sapi_headers->headers, (llist_apply_func_t) php_nsapi_remove_header);
- return 0;
-
- case SAPI_HEADER_DELETE:
- /* reuse the zend_llist_apply callback function for this, too */
- php_nsapi_remove_header(sapi_header);
- return 0;
-
- case SAPI_HEADER_ADD:
- case SAPI_HEADER_REPLACE:
- /* copy the header, because NSAPI needs reformatting and we do not want to change the parameter */
- header_name = pool_strdup(rc->sn->pool, sapi_header->header);
-
- /* split header and align pointer for content */
- header_content = strchr(header_name, ':');
- if (header_content) {
- *header_content = 0;
- do {
- header_content++;
- } while (*header_content==' ');
-
- /* header_name to lower case because NSAPI reformats the headers and wants lowercase */
- for (p=header_name; *p; p++) {
- *p=tolower(*p);
- }
-
- /* if REPLACE, remove first. "Content-type" is always removed, as SAPI has a bug according to this */
- if (op==SAPI_HEADER_REPLACE || strcmp(header_name, "content-type")==0) {
- param_free(pblock_remove(header_name, rc->rq->srvhdrs));
- }
- /* ADD header to nsapi table */
- pblock_nvinsert(header_name, header_content, rc->rq->srvhdrs);
- }
-
- pool_free(rc->sn->pool, header_name);
- return SAPI_HEADER_ADD;
-
- default:
- return 0;
- }
-}
-
-static int sapi_nsapi_send_headers(sapi_headers_struct *sapi_headers)
-{
- int retval;
- nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
-
- if (SG(sapi_headers).send_default_content_type) {
- char *hd;
- param_free(pblock_remove("content-type", rc->rq->srvhdrs));
- hd = sapi_get_default_content_type();
- pblock_nvinsert("content-type", hd, rc->rq->srvhdrs);
- efree(hd);
- }
-
- protocol_status(rc->sn, rc->rq, SG(sapi_headers).http_response_code, NULL);
- retval = protocol_start_response(rc->sn, rc->rq);
-
- if (retval == REQ_PROCEED || retval == REQ_NOACTION) {
- return SAPI_HEADER_SENT_SUCCESSFULLY;
- } else {
- return SAPI_HEADER_SEND_FAILED;
- }
-}
-
-static int sapi_nsapi_read_post(char *buffer, uint count_bytes)
-{
- nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
- char *read_ptr = buffer, *content_length_str = NULL;
- uint bytes_read = 0;
- int length, content_length = 0;
- netbuf *nbuf = rc->sn->inbuf;
-
- /*
- * Yesss!
- */
- count_bytes = MIN(count_bytes, SG(request_info).content_length-rc->read_post_bytes);
- content_length = SG(request_info).content_length;
-
- if (content_length <= 0) {
- return 0;
- }
-
- /*
- * Gobble any pending data in the netbuf.
- */
- length = nbuf->cursize - nbuf->pos;
- length = MIN(count_bytes, length);
- if (length > 0) {
- memcpy(read_ptr, nbuf->inbuf + nbuf->pos, length);
- bytes_read += length;
- read_ptr += length;
- content_length -= length;
- nbuf->pos += length;
- }
-
- /*
- * Read the remaining from the socket.
- */
- while (content_length > 0 && bytes_read < count_bytes) {
- int bytes_to_read = count_bytes - bytes_read;
-
- if (content_length < bytes_to_read) {
- bytes_to_read = content_length;
- }
-
- length = net_read(rc->sn->csd, read_ptr, bytes_to_read, NSAPI_G(read_timeout));
-
- if (length == IO_ERROR || length == IO_EOF) {
- break;
- }
-
- bytes_read += length;
- read_ptr += length;
- content_length -= length;
- }
-
- if ( bytes_read > 0 ) {
- rc->read_post_bytes += bytes_read;
- }
- return bytes_read;
-}
-
-static char *sapi_nsapi_read_cookies(void)
-{
- char *cookie_string;
- nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
-
- cookie_string = pblock_findval("cookie", rc->rq->headers);
- return cookie_string;
-}
-
-static void sapi_nsapi_register_server_variables(zval *track_vars_array)
-{
- nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
- register size_t i;
- int pos;
- char *value,*p;
- char buf[32];
- struct pb_entry *entry;
-
- for (i = 0; i < nsapi_reqpb_size; i++) {
- value = pblock_findval(nsapi_reqpb[i].nsapi_eq, rc->rq->reqpb);
- if (value) {
- php_register_variable((char *)nsapi_reqpb[i].env_var, value, track_vars_array);
- }
- }
-
- for (i=0; i < rc->rq->headers->hsize; i++) {
- entry=rc->rq->headers->ht[i];
- while (entry) {
- if (strcasecmp(entry->param->name, "content-length")==0 || strcasecmp(entry->param->name, "content-type")==0) {
- value=estrdup(entry->param->name);
- pos = 0;
- } else {
- spprintf(&value, 0, "HTTP_%s", entry->param->name);
- pos = 5;
- }
- if (value) {
- for(p = value + pos; *p; p++) {
- *p = toupper(*p);
- if (!isalnum(*p)) {
- *p = '_';
- }
- }
- php_register_variable(value, entry->param->value, track_vars_array);
- efree(value);
- }
- entry=entry->next;
- }
- }
-
- for (i = 0; i < nsapi_vars_size; i++) {
- value = pblock_findval(nsapi_vars[i].nsapi_eq, rc->rq->vars);
- if (value) {
- php_register_variable((char *)nsapi_vars[i].env_var, value, track_vars_array);
- }
- }
-
- for (i = 0; i < nsapi_client_size; i++) {
- value = pblock_findval(nsapi_client[i].nsapi_eq, rc->sn->client);
- if (value) {
- php_register_variable((char *)nsapi_client[i].env_var, value, track_vars_array);
- }
- }
-
- if (value = session_dns(rc->sn)) {
- php_register_variable("REMOTE_HOST", value, track_vars_array);
- nsapi_free(value);
- }
-
- slprintf(buf, sizeof(buf), "%d", conf_getglobals()->Vport);
- php_register_variable("SERVER_PORT", buf, track_vars_array);
- php_register_variable("SERVER_NAME", conf_getglobals()->Vserver_hostname, track_vars_array);
-
- value = http_uri2url_dynamic("", "", rc->sn, rc->rq);
- php_register_variable("SERVER_URL", value, track_vars_array);
- nsapi_free(value);
-
- php_register_variable("SERVER_SOFTWARE", system_version(), track_vars_array);
- if (security_active) {
- php_register_variable("HTTPS", "ON", track_vars_array);
- }
- php_register_variable("GATEWAY_INTERFACE", "CGI/1.1", track_vars_array);
-
- /* DOCUMENT_ROOT */
- if (value = request_translate_uri("/", rc->sn)) {
- pos = strlen(value);
- php_register_variable_safe("DOCUMENT_ROOT", value, pos-1, track_vars_array);
- nsapi_free(value);
- }
-
- /* PATH_INFO / PATH_TRANSLATED */
- if (rc->path_info) {
- if (value = request_translate_uri(rc->path_info, rc->sn)) {
- php_register_variable("PATH_TRANSLATED", value, track_vars_array);
- nsapi_free(value);
- }
- php_register_variable("PATH_INFO", rc->path_info, track_vars_array);
- }
-
- /* Create full Request-URI & Script-Name */
- if (SG(request_info).request_uri) {
- pos = strlen(SG(request_info).request_uri);
-
- if (SG(request_info).query_string) {
- spprintf(&value, 0, "%s?%s", SG(request_info).request_uri, SG(request_info).query_string);
- if (value) {
- php_register_variable("REQUEST_URI", value, track_vars_array);
- efree(value);
- }
- } else {
- php_register_variable_safe("REQUEST_URI", SG(request_info).request_uri, pos, track_vars_array);
- }
-
- if (rc->path_info) {
- pos -= strlen(rc->path_info);
- if (pos<0) {
- pos = 0;
- }
- }
- php_register_variable_safe("SCRIPT_NAME", SG(request_info).request_uri, pos, track_vars_array);
- }
- php_register_variable("SCRIPT_FILENAME", SG(request_info).path_translated, track_vars_array);
-
- /* special variables in error mode */
- if (rc->http_error) {
- slprintf(buf, sizeof(buf), "%d", rc->http_error);
- php_register_variable("ERROR_TYPE", buf, track_vars_array);
- }
-}
-
-static void nsapi_log_message(char *message)
-{
- nsapi_request_context *rc = (nsapi_request_context *)SG(server_context);
-
- if (rc) {
- log_error(LOG_INFORM, pblock_findval("fn", rc->pb), rc->sn, rc->rq, "%s", message);
- } else {
- log_error(LOG_INFORM, "php7", NULL, NULL, "%s", message);
- }
-}
-
-static double sapi_nsapi_get_request_time(void)
-{
- return REQ_TIME( ((nsapi_request_context *)SG(server_context))->rq );
-}
-
-static int php_nsapi_startup(sapi_module_struct *sapi_module)
-{
- if (php_module_startup(sapi_module, &nsapi_module_entry, 1)==FAILURE) {
- return FAILURE;
- }
- return SUCCESS;
-}
-
-static struct stat* sapi_nsapi_get_stat(void)
-{
- return request_stat_path(
- SG(request_info).path_translated,
- ((nsapi_request_context *)SG(server_context))->rq
- );
-}
-
-static sapi_module_struct nsapi_sapi_module = {
- "nsapi", /* name */
- "NSAPI", /* pretty name */
-
- php_nsapi_startup, /* startup */
- php_module_shutdown_wrapper, /* shutdown */
-
- NULL, /* activate */
- NULL, /* deactivate */
-
- sapi_nsapi_ub_write, /* unbuffered write */
- sapi_nsapi_flush, /* flush */
- sapi_nsapi_get_stat, /* get uid/stat */
- NULL, /* getenv */
-
- php_error, /* error handler */
-
- sapi_nsapi_header_handler, /* header handler */
- sapi_nsapi_send_headers, /* send headers handler */
- NULL, /* send header handler */
-
- sapi_nsapi_read_post, /* read POST data */
- sapi_nsapi_read_cookies, /* read Cookies */
-
- sapi_nsapi_register_server_variables, /* register server variables */
- nsapi_log_message, /* Log message */
- sapi_nsapi_get_request_time, /* Get request time */
- NULL, /* Child terminate */
-
- NULL, /* Block interruptions */
- NULL, /* Unblock interruptions */
-
- STANDARD_SAPI_MODULE_PROPERTIES
-};
-
-static void nsapi_php_ini_entries(NSLS_D)
-{
- struct pb_entry *entry;
- register int i,j,ok;
-
- for (i=0; i < NSG(pb)->hsize; i++) {
- entry=NSG(pb)->ht[i];
- while (entry) {
- /* exclude standard entries given to "Service" which should not go into ini entries */
- ok=1;
- for (j=0; nsapi_exclude_from_ini_entries[j]; j++) {
- ok&=(strcasecmp(entry->param->name, nsapi_exclude_from_ini_entries[j])!=0);
- }
-
- if (ok) {
- /* change the ini entry */
- if (zend_alter_ini_entry(entry->param->name, strlen(entry->param->name)+1,
- entry->param->value, strlen(entry->param->value),
- PHP_INI_SYSTEM, PHP_INI_STAGE_ACTIVATE)==FAILURE) {
- log_error(LOG_WARN, pblock_findval("fn", NSG(pb)), NSG(sn), NSG(rq), "Cannot change php.ini key \"%s\" to \"%s\"", entry->param->name, entry->param->value);
- }
- }
- entry=entry->next;
- }
- }
-}
-
-void NSAPI_PUBLIC php7_close(void *vparam)
-{
- if (nsapi_sapi_module.shutdown) {
- nsapi_sapi_module.shutdown(&nsapi_sapi_module);
- }
-
- if (nsapi_sapi_module.php_ini_path_override) {
- free(nsapi_sapi_module.php_ini_path_override);
- }
-
-#ifdef PHP_WIN32
- if (nsapi_dll) {
- free(nsapi_dll);
- nsapi_dll = NULL;
- }
-#endif
-
- sapi_shutdown();
- tsrm_shutdown();
-
- log_error(LOG_INFORM, "php7_close", NULL, NULL, "Shutdown PHP Module");
-}
-
-/*********************************************************
-/ init SAF
-/
-/ Init fn="php7_init" [php_ini="/path/to/php.ini"] [server_lib="ns-httpdXX.dll"]
-/ Initialize the NSAPI module in magnus.conf
-/
-/ php_ini: gives path to php.ini file
-/ server_lib: (only Win32) gives name of DLL (without path) to look for
-/ servact_* functions
-/
-/*********************************************************/
-int NSAPI_PUBLIC php7_init(pblock *pb, Session *sn, Request *rq)
-{
- php_core_globals *core_globals;
- char *strval;
- int threads=128; /* default for server */
-
- /* fetch max threads from NSAPI and initialize TSRM with it */
- threads=conf_getglobals()->Vpool_maxthreads;
- if (threads<1) {
- threads=128; /* default for server */
- }
- tsrm_startup(threads, 1, 0, NULL);
-
- core_globals = ts_resource(core_globals_id);
-
- /* look if php_ini parameter is given to php7_init */
- if (strval = pblock_findval("php_ini", pb)) {
- nsapi_sapi_module.php_ini_path_override = strdup(strval);
- }
-
-#ifdef PHP_WIN32
- /* look if server_lib parameter is given to php7_init
- * (this disables the automatic search for the newest ns-httpdXX.dll) */
- if (strval = pblock_findval("server_lib", pb)) {
- nsapi_dll = strdup(strval);
- }
-#endif
-
- /* start SAPI */
- sapi_startup(&nsapi_sapi_module);
- nsapi_sapi_module.startup(&nsapi_sapi_module);
-
- daemon_atrestart(&php7_close, NULL);
-
- log_error(LOG_INFORM, pblock_findval("fn", pb), sn, rq, "Initialized PHP Module (%d threads expected)", threads);
- return REQ_PROCEED;
-}
-
-/*********************************************************
-/ normal use in Service directive:
-/
-/ Service fn="php7_execute" type=... method=... [inikey=inivalue inikey=inivalue...]
-/
-/ use in Service for a directory to supply a php-made directory listing instead of server default:
-/
-/ Service fn="php7_execute" type="magnus-internal/directory" script="/path/to/script.php" [inikey=inivalue inikey=inivalue...]
-/
-/ use in Error SAF to display php script as error page:
-/
-/ Error fn="php7_execute" code=XXX script="/path/to/script.php" [inikey=inivalue inikey=inivalue...]
-/ Error fn="php7_execute" reason="Reason" script="/path/to/script.php" [inikey=inivalue inikey=inivalue...]
-/
-/*********************************************************/
-int NSAPI_PUBLIC php7_execute(pblock *pb, Session *sn, Request *rq)
-{
- int retval;
- nsapi_request_context *request_context;
- zend_file_handle file_handle = {0};
- struct stat *fst;
-
- char *path_info;
- char *query_string = pblock_findval("query", rq->reqpb);
- char *uri = pblock_findval("uri", rq->reqpb);
- char *request_method = pblock_findval("method", rq->reqpb);
- char *content_type = pblock_findval("content-type", rq->headers);
- char *content_length = pblock_findval("content-length", rq->headers);
- char *directive = pblock_findval("Directive", pb);
- int error_directive = (directive && !strcasecmp(directive, "error"));
- int fixed_script = 1;
-
- /* try to use script parameter -> Error or Service for directory listing */
- char *path_translated = pblock_findval("script", pb);
-
-
- /* if script parameter is missing: normal use as Service SAF */
- if (!path_translated) {
- path_translated = pblock_findval("path", rq->vars);
- path_info = pblock_findval("path-info", rq->vars);
- fixed_script = 0;
- if (error_directive) {
- /* go to next error directive if script parameter is missing */
- log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Missing 'script' parameter");
- return REQ_NOACTION;
- }
- } else {
- /* in error the path_info is the uri to the requested page */
- path_info = pblock_findval("uri", rq->reqpb);
- }
-
- /* check if this uri was included in an other PHP script with nsapi_virtual()
- by looking for a request context in the current thread */
- if (SG(server_context)) {
- /* send 500 internal server error */
- log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Cannot make nesting PHP requests with nsapi_virtual()");
- if (error_directive) {
- return REQ_NOACTION;
- } else {
- protocol_status(sn, rq, 500, NULL);
- return REQ_ABORTED;
- }
- }
-
- request_context = (nsapi_request_context *)pool_malloc(sn->pool, sizeof(nsapi_request_context));
- if (!request_context) {
- log_error(LOG_CATASTROPHE, pblock_findval("fn", pb), sn, rq, "Insufficient memory to process PHP request!");
- return REQ_ABORTED;
- }
- request_context->pb = pb;
- request_context->sn = sn;
- request_context->rq = rq;
- request_context->read_post_bytes = 0;
- request_context->fixed_script = fixed_script;
- request_context->http_error = (error_directive) ? rq->status_num : 0;
- request_context->path_info = path_info;
-
- SG(server_context) = request_context;
- SG(request_info).query_string = query_string;
- SG(request_info).request_uri = uri;
- SG(request_info).request_method = request_method;
- SG(request_info).path_translated = path_translated;
- SG(request_info).content_type = content_type;
- SG(request_info).content_length = (content_length == NULL) ? 0 : strtoul(content_length, 0, 0);
- SG(sapi_headers).http_response_code = (error_directive) ? rq->status_num : 200;
-
- nsapi_php_ini_entries(NSLS_C);
-
- php_handle_auth_data(pblock_findval("authorization", rq->headers));
-
- file_handle.type = ZEND_HANDLE_FILENAME;
- file_handle.filename = SG(request_info).path_translated;
- file_handle.free_filename = 0;
- file_handle.opened_path = NULL;
-
- fst = request_stat_path(SG(request_info).path_translated, rq);
- if (fst && S_ISREG(fst->st_mode)) {
- if (php_request_startup() == SUCCESS) {
- php_execute_script(&file_handle);
- php_request_shutdown(NULL);
- retval=REQ_PROCEED;
- } else {
- /* send 500 internal server error */
- log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Cannot prepare PHP engine!");
- if (error_directive) {
- retval=REQ_NOACTION;
- } else {
- protocol_status(sn, rq, 500, NULL);
- retval=REQ_ABORTED;
- }
- }
- } else {
- /* send 404 because file not found */
- log_error(LOG_WARN, pblock_findval("fn", pb), sn, rq, "Cannot execute PHP script: %s (File not found)", SG(request_info).path_translated);
- if (error_directive) {
- retval=REQ_NOACTION;
- } else {
- protocol_status(sn, rq, 404, NULL);
- retval=REQ_ABORTED;
- }
- }
-
- pool_free(sn->pool, request_context);
- SG(server_context) = NULL;
-
- return retval;
-}
-
-/*********************************************************
-/ authentication
-/
-/ we have to make a 'fake' authenticator for netscape so it
-/ will pass authentication through to php, and allow us to
-/ check authentication with our scripts.
-/
-/ php7_auth_trans
-/ main function called from netscape server to authenticate
-/ a line in obj.conf:
-/ funcs=php7_auth_trans shlib="path/to/this/phpnsapi.dll"
-/ and:
-/ <Object ppath="path/to/be/authenticated/by/php/*">
-/ AuthTrans fn="php7_auth_trans"
-/*********************************************************/
-int NSAPI_PUBLIC php7_auth_trans(pblock * pb, Session * sn, Request * rq)
-{
- /* This is a DO NOTHING function that allows authentication
- * information
- * to be passed through to PHP scripts.
- */
- return REQ_PROCEED;
-}
-
-/*
- * 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/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c
index c8017a39d3..2e40e49d9b 100644
--- a/sapi/phpdbg/phpdbg_bp.c
+++ b/sapi/phpdbg/phpdbg_bp.c
@@ -240,7 +240,7 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num) /* {
}
path_len = strlen(path);
- phpdbg_debug("file path: %s, resolved path: %s, was compiled: %d\n", original_path, path, zend_hash_exists(&PHPDBG_G(file_sources), path, path_len));
+ phpdbg_debug("file path: %s, resolved path: %s, was compiled: %d\n", original_path, path, zend_hash_str_exists(&PHPDBG_G(file_sources), path, path_len));
if (!zend_hash_str_exists(&PHPDBG_G(file_sources), path, path_len)) {
if (php_stream_stat_path(path, &ssb) == FAILURE) {
@@ -308,7 +308,7 @@ PHPDBG_API void phpdbg_set_breakpoint_file(const char *path, long line_num) /* {
PHPDBG_API HashTable *phpdbg_resolve_pending_file_break_ex(const char *file, uint filelen, zend_string *cur, HashTable *fileht) /* {{{ */
{
- phpdbg_debug("file: %s, filelen: %u, cur: %s, curlen %u, pos: %c, memcmp: %d\n", file, filelen, cur, curlen, filelen > curlen ? file[filelen - curlen - 1] : '?', filelen > curlen ? memcmp(file + filelen - curlen, cur, curlen) : 0);
+ phpdbg_debug("file: %s, filelen: %u, cur: %s, curlen %u, pos: %c, memcmp: %d\n", file, filelen, cur->val, cur->len, filelen > cur->len ? file[filelen - cur->len - 1] : '?', filelen > cur->len ? memcmp(file + filelen - cur->len, cur->val, cur->len) : 0);
if (((cur->len < filelen && file[filelen - cur->len - 1] == '/') || filelen == cur->len) && !memcmp(file + filelen - cur->len, cur->val, cur->len)) {
phpdbg_breakfile_t *brake, new_brake;
diff --git a/sapi/phpdbg/phpdbg_io.c b/sapi/phpdbg/phpdbg_io.c
index 1f004fbae1..70709eadc1 100644
--- a/sapi/phpdbg/phpdbg_io.c
+++ b/sapi/phpdbg/phpdbg_io.c
@@ -178,11 +178,17 @@ PHPDBG_API int phpdbg_send_bytes(int sock, const char *ptr, int len) {
PHPDBG_API int phpdbg_mixed_read(int sock, char *ptr, int len, int tmo) {
+ int ret;
+
if (PHPDBG_G(flags) & PHPDBG_IS_REMOTE) {
return phpdbg_consume_bytes(sock, ptr, len, tmo);
}
- return read(sock, ptr, len);
+ do {
+ ret = read(sock, ptr, len);
+ } while (ret == -1 && errno == EINTR);
+
+ return ret;
}
diff --git a/sapi/phpdbg/phpdbg_opcode.c b/sapi/phpdbg/phpdbg_opcode.c
index 7dadc3f4b9..cff756a5ed 100644
--- a/sapi/phpdbg/phpdbg_opcode.c
+++ b/sapi/phpdbg/phpdbg_opcode.c
@@ -106,8 +106,7 @@ static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, uint32_t
} break;
case IS_UNUSED:
- asprintf(&decode, "<unused>");
- break;
+ return NULL;
}
return decode;
} /* }}} */
@@ -116,43 +115,73 @@ char *phpdbg_decode_opline(zend_op_array *ops, zend_op *op, HashTable *vars) /*{
{
char *decode[4] = {NULL, NULL, NULL, NULL};
+ /* OP1 */
switch (op->opcode) {
case ZEND_JMP:
case ZEND_GOTO:
case ZEND_FAST_CALL:
asprintf(&decode[1], "J%ld", OP_JMP_ADDR(op, op->op1) - ops->opcodes);
- goto format;
+ break;
- case ZEND_JMPZNZ:
+ case ZEND_INIT_FCALL:
+ case ZEND_RECV:
+ case ZEND_RECV_INIT:
+ case ZEND_RECV_VARIADIC:
+ asprintf(&decode[1], "%" PRIu32, op->op1.num);
+ break;
+
+ default:
decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars);
+ break;
+ }
+
+ /* OP2 */
+ switch (op->opcode) {
+ /* TODO: ZEND_FAST_CALL, ZEND_FAST_RET op2 */
+ case ZEND_JMPZNZ:
asprintf(&decode[2], "J%u or J%" PRIu32, op->op2.opline_num, op->extended_value);
- goto result;
+ break;
case ZEND_JMPZ:
case ZEND_JMPNZ:
case ZEND_JMPZ_EX:
case ZEND_JMPNZ_EX:
case ZEND_JMP_SET:
- decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars);
+ case ZEND_ASSERT_CHECK:
asprintf(&decode[2], "J%ld", OP_JMP_ADDR(op, op->op2) - ops->opcodes);
- goto result;
+ break;
- case ZEND_RECV_INIT:
- goto result;
+ case ZEND_SEND_VAL:
+ case ZEND_SEND_VAL_EX:
+ case ZEND_SEND_VAR:
+ case ZEND_SEND_VAR_NO_REF:
+ case ZEND_SEND_REF:
+ case ZEND_SEND_VAR_EX:
+ case ZEND_SEND_USER:
+ asprintf(&decode[2], "%" PRIu32, op->op2.num);
+ break;
default:
- decode[1] = phpdbg_decode_op(ops, &op->op1, op->op1_type, vars);
decode[2] = phpdbg_decode_op(ops, &op->op2, op->op2_type, vars);
-result:
+ break;
+ }
+
+ /* RESULT */
+ switch (op->opcode) {
+ case ZEND_CATCH:
+ asprintf(&decode[2], "%" PRIu32, op->result.num);
+ break;
+ default:
decode[3] = phpdbg_decode_op(ops, &op->result, op->result_type, vars);
-format:
- asprintf(&decode[0],
- "%-20s %-20s %-20s",
- decode[1] ? decode[1] : "",
- decode[2] ? decode[2] : "",
- decode[3] ? decode[3] : "");
+ break;
}
+ asprintf(&decode[0],
+ "%-20s %-20s %-20s",
+ decode[1] ? decode[1] : "",
+ decode[2] ? decode[2] : "",
+ decode[3] ? decode[3] : "");
+
if (decode[1])
free(decode[1]);
if (decode[2])
diff --git a/sapi/phpdbg/phpdbg_print.c b/sapi/phpdbg/phpdbg_print.c
index 11bfdf5a81..4013c0fd88 100644
--- a/sapi/phpdbg/phpdbg_print.c
+++ b/sapi/phpdbg/phpdbg_print.c
@@ -282,12 +282,13 @@ void phpdbg_print_opcodes_function(const char *function, size_t len) {
}
void phpdbg_print_opcodes_method(const char *class, const char *function) {
- zend_class_entry *ce = zend_hash_str_find_ptr(EG(class_table), class, strlen(class));
+ zend_class_entry *ce;
zend_function *func;
- if (!ce) {
+ if (phpdbg_safe_class_lookup(class, strlen(class), &ce) != SUCCESS) {
return;
}
+
if (ce->type != ZEND_USER_CLASS) {
phpdbg_out("function name: %s::%s (internal)\n", class, function);
return;
@@ -348,7 +349,6 @@ void phpdbg_print_opcodes_class(const char *class) {
PHPDBG_API void phpdbg_print_opcodes(char *function)
{
char *method_name;
-
strtok(function, ":");
if (function == NULL) {
@@ -376,7 +376,7 @@ PHPDBG_API void phpdbg_print_opcodes(char *function)
} ZEND_HASH_FOREACH_END();
} else if ((method_name = strtok(NULL, ":")) == NULL) {
phpdbg_print_opcodes_function(function, strlen(function));
- } else if (++method_name == NULL || ++method_name == NULL) {
+ } else if ((method_name + 1) == NULL) {
phpdbg_print_opcodes_class(function);
} else {
phpdbg_print_opcodes_method(function, method_name);
diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c
index 9d63fcf727..4cd8ce2782 100644
--- a/sapi/phpdbg/phpdbg_utils.c
+++ b/sapi/phpdbg/phpdbg_utils.c
@@ -384,7 +384,7 @@ int phpdbg_safe_class_lookup(const char *name, int name_length, zend_class_entry
efree(str_name);
}
- return ce ? SUCCESS : FAILURE;
+ return *ce ? SUCCESS : FAILURE;
}
char *phpdbg_get_property_key(char *key) {
diff --git a/sapi/phpdbg/tests/commands/0102_print.test b/sapi/phpdbg/tests/commands/0102_print.test
index 6ca60dbbad..7078b13ea2 100644
--- a/sapi/phpdbg/tests/commands/0102_print.test
+++ b/sapi/phpdbg/tests/commands/0102_print.test
@@ -6,14 +6,14 @@
#################################################
#[User Class: test (3 methods)]
#L%d-%d test::testMethod() %s - 0x%s + 1 ops
-# L%d #0 RETURN null <unused> <unused>
+# L%d #0 RETURN null
#L%d-%d test::testPrivateMethod() %s - 0x%s + 1 ops
-# L%d #0 RETURN null <unused> <unused>
+# L%d #0 RETURN null
#L%d-%d test::testProtectedMethod() %s - 0x%s + 1 ops
-# L%d #0 RETURN null <unused> <unused>
+# L%d #0 RETURN null
#[User Method testMethod (1 ops)]
#L%d-%d test::testMethod() %s - 0x%s + 1 ops
-# L%d #0 RETURN null <unused> <unused>
+# L%d #0 RETURN null
#################################################
<:
class test {
diff --git a/sapi/tests/test005.phpt b/sapi/tests/test005.phpt
index 7415b66a0a..85143d5228 100644
--- a/sapi/tests/test005.phpt
+++ b/sapi/tests/test005.phpt
@@ -22,6 +22,6 @@ END;
echo "HELLO";
?>
--EXPECTHEADERS--
-Status: 404
+Status: 404 Not Found
--EXPECT--
-No input file specified. \ No newline at end of file
+No input file specified.
diff --git a/sapi/tests/test006.phpt b/sapi/tests/test006.phpt
index 45e37811ef..16d1b2b840 100644
--- a/sapi/tests/test006.phpt
+++ b/sapi/tests/test006.phpt
@@ -67,7 +67,7 @@ Array
[type] => application/octet-stream
[tmp_name] => %s
[error] => 0
- [size] => 21
+ [size] => 19
)
)
diff --git a/tests/basic/bug51709_1.phpt b/tests/basic/bug51709_1.phpt
deleted file mode 100644
index 3f2d544e54..0000000000
--- a/tests/basic/bug51709_1.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-Bug #51709 (Can't use keywords as method names)
---FILE--
-<?php
-
-class foo {
- static function for() {
- echo "1";
- }
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Parse error: syntax error, unexpected %s, expecting %s in %sbug51709_1.php on line %d
diff --git a/tests/basic/bug51709_2.phpt b/tests/basic/bug51709_2.phpt
deleted file mode 100644
index bb1f91cc4c..0000000000
--- a/tests/basic/bug51709_2.phpt
+++ /dev/null
@@ -1,16 +0,0 @@
---TEST--
-Bug #51709 (Can't use keywords as method names)
---FILE--
-<?php
-
-class foo {
- static function goto() {
- echo "1";
- }
-}
-
-?>
-===DONE===
-<?php exit(0); ?>
---EXPECTF--
-Parse error: syntax error, unexpected %s, expecting %s in %sbug51709_2.php on line %d
diff --git a/tests/classes/autoload_009.phpt b/tests/classes/autoload_009.phpt
index 51d3e8f791..150f3ec201 100644
--- a/tests/classes/autoload_009.phpt
+++ b/tests/classes/autoload_009.phpt
@@ -16,6 +16,6 @@ Ensure type hints for unknown types do not trigger autoload.
--EXPECTF--
Fatal error: Uncaught TypeError: Argument 1 passed to f() must be an instance of UndefClass, instance of stdClass given, called in %s on line %d and defined in %s:%d
Stack trace:
-#0 %s(%d): f()
+#0 %s(%d): f(Object(stdClass))
#1 {main}
thrown in %s on line %d
diff --git a/tests/classes/type_hinting_001.phpt b/tests/classes/type_hinting_001.phpt
index d9412293e9..28d1280b79 100644
--- a/tests/classes/type_hinting_001.phpt
+++ b/tests/classes/type_hinting_001.phpt
@@ -37,6 +37,6 @@ $a->b($b);
Fatal error: Uncaught TypeError: Argument 1 passed to FooBar::a() must implement interface Foo, instance of Blort given, called in %s on line 27 and defined in %s:12
Stack trace:
-#0 %s(%d): FooBar->a()
+#0 %s(%d): FooBar->a(Object(Blort))
#1 {main}
thrown in %s on line 12
diff --git a/tests/classes/type_hinting_002.phpt b/tests/classes/type_hinting_002.phpt
index 7486824d50..6fefcc8dd4 100644
--- a/tests/classes/type_hinting_002.phpt
+++ b/tests/classes/type_hinting_002.phpt
@@ -15,6 +15,6 @@ $o->a($o);
--EXPECTF--
Fatal error: Uncaught TypeError: Argument 1 passed to Foo::a() must be an instance of NonExisting, instance of Foo given, called in %s on line %d and defined in %s:%d
Stack trace:
-#0 %s(%d): Foo->a()
+#0 %s(%d): Foo->a(Object(Foo))
#1 {main}
thrown in %s on line %d
diff --git a/tests/classes/type_hinting_003.phpt b/tests/classes/type_hinting_003.phpt
index 6038f25a50..50de31e44b 100644
--- a/tests/classes/type_hinting_003.phpt
+++ b/tests/classes/type_hinting_003.phpt
@@ -59,6 +59,6 @@ array(1) {
Fatal error: Uncaught TypeError: Argument 1 passed to Test::f1() must be of the type array, integer given, called in %s on line %d and defined in %s:%d
Stack trace:
-#0 %s(%d): Test::f1()
+#0 %s(%d): Test::f1(1)
#1 {main}
thrown in %s on line %d
diff --git a/tests/lang/bug24658.phpt b/tests/lang/bug24658.phpt
index 6229d52a64..b089569d91 100644
--- a/tests/lang/bug24658.phpt
+++ b/tests/lang/bug24658.phpt
@@ -55,7 +55,7 @@ object(foo)#%d (0) {
Fatal error: Uncaught TypeError: Argument 1 passed to typehint() must be an instance of foo, integer given in %s:%d
Stack trace:
-#0 [internal function]: typehint(1)
+#0 [internal function]: typehint(1, 1)
#1 %s(%d): array_walk(Array, 'typehint')
#2 {main}
thrown in %s on line %d
diff --git a/tests/lang/catchable_error_001.phpt b/tests/lang/catchable_error_001.phpt
index e63e0d7ccc..b11a7c8d96 100644
--- a/tests/lang/catchable_error_001.phpt
+++ b/tests/lang/catchable_error_001.phpt
@@ -21,6 +21,6 @@ Catchable fatal error [1]
--EXPECTF--
Fatal error: Uncaught TypeError: Argument 1 passed to blah() must be an instance of Foo, instance of stdClass given, called in %scatchable_error_001.php on line 15 and defined in %scatchable_error_001.php:5
Stack trace:
-#0 %s(%d): blah()
+#0 %s(%d): blah(Object(stdClass))
#1 {main}
thrown in %scatchable_error_001.php on line 5
diff --git a/tests/lang/string/unicode_escape_incomplete.phpt b/tests/lang/string/unicode_escape_incomplete.phpt
index b5baeffd6e..169e6a278c 100644
--- a/tests/lang/string/unicode_escape_incomplete.phpt
+++ b/tests/lang/string/unicode_escape_incomplete.phpt
@@ -3,6 +3,6 @@ Invalid Unicode escape sequence: Incomplete
--FILE--
<?php
-var_dunp("\u{blah");
+var_dump("\u{blah");
--EXPECTF--
Parse error: Invalid UTF-8 codepoint escape sequence in %s on line %d
diff --git a/tests/lang/type_hints_001.phpt b/tests/lang/type_hints_001.phpt
index d487a86a79..e8a2ffa9e3 100644
--- a/tests/lang/type_hints_001.phpt
+++ b/tests/lang/type_hints_001.phpt
@@ -25,6 +25,6 @@ type_hint_foo($bar);
Fatal error: Uncaught TypeError: Argument 1 passed to type_hint_foo() must be an instance of Foo, instance of Bar given, called in %s on line 16 and defined in %s:9
Stack trace:
-#0 %s(%d): type_hint_foo()
+#0 %s(%d): type_hint_foo(Object(Bar))
#1 {main}
thrown in %s on line 9
diff --git a/win32/build/Makefile b/win32/build/Makefile
index c24bd70ba6..74fd97b3b2 100644
--- a/win32/build/Makefile
+++ b/win32/build/Makefile
@@ -89,6 +89,7 @@ $(PHPDLL_RES): win32\build\template.rc
win32\build\template.rc
$(BUILD_DIR)\$(PHPDLL): generated_files $(PHPDEF) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(PHPDLL_RES) $(MCFILE)
+ @copy win32\build\default.manifest $(BUILD_DIR)\$(PHPDLL).manifest
# @$(CC) $(PHP_GLOBAL_OBJS) $(STATIC_EXT_OBJS) $(STATIC_EXT_LIBS) $(LIBS) $(PHPDLL_RES) /link /out:$(BUILD_DIR)\$(PHPDLL) $(PHP7_PGD_OPTION) $(PHP_LDFLAGS) $(LDFLAGS) $(STATIC_EXT_LDFLAGS)
@"$(LINK)" $(PHP_GLOBAL_OBJS_RESP) $(STATIC_EXT_OBJS_RESP) $(STATIC_EXT_LIBS) $(LIBS) $(PHPDLL_RES) /out:$(BUILD_DIR)\$(PHPDLL) $(PHP7_PGD_OPTION) $(PHP_LDFLAGS) $(LDFLAGS) $(STATIC_EXT_LDFLAGS)
-@$(_VC_MANIFEST_EMBED_DLL)
@@ -116,7 +117,7 @@ clean: clean-sapi
@cd $(BUILD_DIR)
@for %D in (_x $(BUILD_DIRS_SUB)) do @if exist %D @del /F /Q %D\*.* > NUL
@cd "$(PHP_SRC_DIR)"
- -@del /F /Q $(BUILD_DIR)\*.res $(BUILD_DIR)\*.lib $(BUILD_DIR)\*.ilk $(BUILD_DIR)\*.pdb $(BUILD_DIR)\*.exp $(PHPDEF) $(BUILD_DIR)\php-$(PHP_VERSION_STRING)-Win32.zip $(BUILD_DIR)\pecl-$(PHP_VERSION_STRING)-Win32.zip > NUL
+ -@del /F /Q $(BUILD_DIR)\*.res $(BUILD_DIR)\*.manifest $(BUILD_DIR)\*.lib $(BUILD_DIR)\*.ilk $(BUILD_DIR)\*.pdb $(BUILD_DIR)\*.exp $(PHPDEF) $(BUILD_DIR)\php-$(PHP_VERSION_STRING)-Win32.zip $(BUILD_DIR)\pecl-$(PHP_VERSION_STRING)-Win32.zip > NUL
-rd /s /q $(BUILD_DIR)\php-$(PHP_VERSION_STRING)
clean-pecl:
@@ -192,6 +193,7 @@ build-devel: build-headers build-lib
@copy win32\build\Makefile.phpize $(BUILD_DIR_DEV)\script\ /y >nul
@copy win32\build\phpize.bat $(BUILD_DIR_DEV)\ /y >nul
@copy win32\build\template.rc $(BUILD_DIR_DEV)\build\ /y >nul
+ @copy win32\build\default.manifest $(BUILD_DIR_DEV)\build\ /y >nul
@copy $(BUILD_DIR)\devel\config.phpize.js $(BUILD_DIR_DEV)\script\ /y >nul
@copy $(BUILD_DIR)\devel\phpize.js $(BUILD_DIR_DEV)\script\ /y >nul
@copy $(BUILD_DIR)\devel\ext_deps.js $(BUILD_DIR_DEV)\script\ /y >nul
diff --git a/win32/build/config.w32 b/win32/build/config.w32
index 3c2ff7a0a9..b7e5e49220 100644
--- a/win32/build/config.w32
+++ b/win32/build/config.w32
@@ -159,8 +159,8 @@ ADD_SOURCES("main/streams", "streams.c cast.c memory.c filter.c plain_wrapper.c
userspace.c transports.c xp_socket.c mmap.c glob_wrapper.c");
ADD_FLAG("CFLAGS_BD_MAIN_STREAMS", "/D ZEND_ENABLE_STATIC_TSRMLS_CACHE=1");
-ADD_SOURCES("win32", "glob.c readdir.c \
- registry.c select.c sendmail.c time.c winutil.c wsyslog.c globals.c");
+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");
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 180f470021..3276fea705 100644
--- a/win32/build/config.w32.h.in
+++ b/win32/build/config.w32.h.in
@@ -181,3 +181,5 @@
#define HAVE_HUGE_VAL_INF 1
+#define HAVE_GETRUSAGE
+
diff --git a/win32/build/confutils.js b/win32/build/confutils.js
index 2005571f36..121f0c2998 100644
--- a/win32/build/confutils.js
+++ b/win32/build/confutils.js
@@ -99,11 +99,11 @@ if (typeof(CWD) == "undefined") {
}
/* defaults; we pick up the precise versions from configure.in */
-var PHP_VERSION = 5;
+var PHP_VERSION = 7;
var PHP_MINOR_VERSION = 0;
var PHP_RELEASE_VERSION = 0;
var PHP_EXTRA_VERSION = "";
-var PHP_VERSION_STRING = "5.0.0";
+var PHP_VERSION_STRING = "7.0.0";
/* Get version numbers and DEFINE as a string */
function get_version_numbers()
@@ -936,6 +936,22 @@ function CHECK_HEADER_ADD_INCLUDE(header_name, flag_name, path_to_check, use_env
return p;
}
+/* XXX check whether some manifest was originally supplied, otherwise keep using the default. */
+function generate_version_info_manifest(makefiletarget)
+{
+ var manifest_name = makefiletarget + ".manifest";
+
+ if (MODE_PHPIZE) {
+ MFO.WriteLine("$(BUILD_DIR)\\" + manifest_name + ": " + PHP_DIR + "\\build\\default.manifest");
+ MFO.WriteLine("\t@copy " + PHP_DIR + "\\build\\default.manifest $(BUILD_DIR)\\" + makefiletarget + ".manifest");
+ } else {
+ MFO.WriteLine("$(BUILD_DIR)\\" + manifest_name + ": win32\\build\\default.manifest");
+ MFO.WriteLine("\t@copy $(PHP_SRC_DIR)\\win32\\build\\default.manifest $(BUILD_DIR)\\" + makefiletarget + ".manifest");
+ }
+
+ return manifest_name;
+}
+
/* Emits rule to generate version info for a SAPI
* or extension. Returns the name of the .res file
* that will be generated */
@@ -1086,13 +1102,15 @@ function SAPI(sapiname, file_list, makefiletarget, cflags, obj_dir)
/* generate a .res file containing version information */
resname = generate_version_info_resource(makefiletarget, sapiname, configure_module_dirname, true);
+
+ manifest_name = generate_version_info_manifest(makefiletarget);
MFO.WriteLine(makefiletarget + ": $(BUILD_DIR)\\" + makefiletarget);
MFO.WriteLine("\t@echo SAPI " + sapiname_for_printing + " build complete");
if (MODE_PHPIZE) {
- MFO.WriteLine("$(BUILD_DIR)\\" + makefiletarget + ": $(DEPS_" + SAPI + ") $(" + SAPI + "_GLOBAL_OBJS) $(PHPLIB) $(BUILD_DIR)\\" + resname);
+ MFO.WriteLine("$(BUILD_DIR)\\" + makefiletarget + ": $(DEPS_" + SAPI + ") $(" + SAPI + "_GLOBAL_OBJS) $(PHPLIB) $(BUILD_DIR)\\" + resname + " $(BUILD_DIR)\\" + manifest_name);
} else {
- MFO.WriteLine("$(BUILD_DIR)\\" + makefiletarget + ": $(DEPS_" + SAPI + ") $(" + SAPI + "_GLOBAL_OBJS) $(BUILD_DIR)\\$(PHPLIB) $(BUILD_DIR)\\" + resname);
+ MFO.WriteLine("$(BUILD_DIR)\\" + makefiletarget + ": $(DEPS_" + SAPI + ") $(" + SAPI + "_GLOBAL_OBJS) $(BUILD_DIR)\\$(PHPLIB) $(BUILD_DIR)\\" + resname + " $(BUILD_DIR)\\" + manifest_name);
}
if (makefiletarget.match(new RegExp("\\.dll$"))) {
@@ -1303,6 +1321,7 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir)
var resname = generate_version_info_resource(dllname, extname, configure_module_dirname, false);
var ld = '@"$(LINK)"';
+ var manifest_name = generate_version_info_manifest(dllname);
ldflags = "";
if (is_pgo_desired(extname) && (PHP_PGI == "yes" || PHP_PGO != "no")) {
@@ -1322,10 +1341,10 @@ function EXTENSION(extname, file_list, shared, cflags, dllname, obj_dir)
MFO.WriteLine("$(BUILD_DIR)\\" + libname + ": $(BUILD_DIR)\\" + dllname);
MFO.WriteBlankLines(1);
if (MODE_PHPIZE) {
- MFO.WriteLine("$(BUILD_DIR)\\" + dllname + ": $(DEPS_" + EXT + ") $(" + EXT + "_GLOBAL_OBJS) $(PHPLIB) $(BUILD_DIR)\\" + resname);
+ MFO.WriteLine("$(BUILD_DIR)\\" + dllname + ": $(DEPS_" + EXT + ") $(" + EXT + "_GLOBAL_OBJS) $(PHPLIB) $(BUILD_DIR)\\" + resname + " $(BUILD_DIR)\\" + manifest_name);
MFO.WriteLine("\t" + ld + " $(" + EXT + "_GLOBAL_OBJS_RESP) $(PHPLIB) $(LIBS_" + EXT + ") $(LIBS) $(BUILD_DIR)\\" + resname + " /out:$(BUILD_DIR)\\" + dllname + " $(DLL_LDFLAGS) $(LDFLAGS) $(LDFLAGS_" + EXT + ")");
} else {
- MFO.WriteLine("$(BUILD_DIR)\\" + dllname + ": $(DEPS_" + EXT + ") $(" + EXT + "_GLOBAL_OBJS) $(BUILD_DIR)\\$(PHPLIB) $(BUILD_DIR)\\" + resname);
+ MFO.WriteLine("$(BUILD_DIR)\\" + dllname + ": $(DEPS_" + EXT + ") $(" + EXT + "_GLOBAL_OBJS) $(BUILD_DIR)\\$(PHPLIB) $(BUILD_DIR)\\" + resname + " $(BUILD_DIR)\\" + manifest_name);
MFO.WriteLine("\t" + ld + " $(" + EXT + "_GLOBAL_OBJS_RESP) $(BUILD_DIR)\\$(PHPLIB) $(LIBS_" + EXT + ") $(LIBS) $(BUILD_DIR)\\" + resname + " /out:$(BUILD_DIR)\\" + dllname + ldflags + " $(DLL_LDFLAGS) $(LDFLAGS) $(LDFLAGS_" + EXT + ")");
}
MFO.WriteLine("\t-@$(_VC_MANIFEST_EMBED_DLL)");
@@ -2654,7 +2673,7 @@ function toolset_setup_common_ldlags()
function toolset_setup_common_libs()
{
// urlmon.lib ole32.lib oleaut32.lib uuid.lib gdi32.lib winspool.lib comdlg32.lib
- DEFINE("LIBS", "kernel32.lib ole32.lib user32.lib advapi32.lib shell32.lib ws2_32.lib Dnsapi.lib");
+ DEFINE("LIBS", "kernel32.lib ole32.lib user32.lib advapi32.lib shell32.lib ws2_32.lib Dnsapi.lib psapi.lib");
}
function toolset_setup_build_mode()
diff --git a/win32/build/default.manifest b/win32/build/default.manifest
new file mode 100644
index 0000000000..77b2a2165a
--- /dev/null
+++ b/win32/build/default.manifest
@@ -0,0 +1,17 @@
+<?xml version='1.0' encoding='UTF-8' standalone='yes'?>
+<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0" xmlns:asmv3="urn:schemas-microsoft-com:asm.v3" >
+ <compatibility xmlns="urn:schemas-microsoft-com:compatibility.v1">
+ <application>
+ <!-- Windows Vista -->
+ <supportedOS Id="{e2011457-1546-43c5-a5fe-008deee3d3f0}"/>
+ <!-- Windows 7 -->
+ <supportedOS Id="{35138b9a-5d96-4fbd-8e2d-a2440225f93a}"/>
+ <!-- Windows 8 -->
+ <supportedOS Id="{4a2f28e3-53b9-4441-ba9c-d69d4a4a6e38}"/>
+ <!-- Windows 8.1 -->
+ <supportedOS Id="{1f676c76-80e1-4239-95bb-83d0f6d0da78}"/>
+ <!-- Windows 10 -->
+ <supportedOS Id="{8e0f7a12-bfb3-4fe8-b9a5-48fd50a15a9a}"/>
+ </application>
+ </compatibility>
+</assembly>
diff --git a/win32/build/deplister.c b/win32/build/deplister.c
index eec014ca69..5b8c60cee9 100644
--- a/win32/build/deplister.c
+++ b/win32/build/deplister.c
@@ -22,6 +22,7 @@
* module to it's stdout for use by distro/installer building tools */
#include <windows.h>
+#include <stdio.h>
#include <imagehlp.h>
BOOL CALLBACK StatusRoutine(IMAGEHLP_STATUS_REASON reason,
diff --git a/win32/build/libs_version.txt b/win32/build/libs_version.txt
index 5c598fa68a..7c86290e75 100644
--- a/win32/build/libs_version.txt
+++ b/win32/build/libs_version.txt
@@ -1,7 +1,7 @@
bz2-1.0.6
cclient-2007f
freetype-2.5.5
-icu-54.1
+icu-55.1
jpeglib-9a
libcurl-7.40.0
libiconv-1.14
@@ -11,6 +11,6 @@ libpng-1.5.18
libpq-9.4.1
libssh2-1.5.0
libtidy-20090406
-libxslt-1.1.27
+libxslt-1.1.28
libxml-2.9.2
-openssl-1.0.1m
+openssl-1.0.2a
diff --git a/win32/build/mkdist.php b/win32/build/mkdist.php
index 9e4422addc..7b4c057530 100644
--- a/win32/build/mkdist.php
+++ b/win32/build/mkdist.php
@@ -342,6 +342,22 @@ foreach ($ENCHANT_DLLS as $dll) {
}
}
+$SASL_DLLS = $php_build_dir . "/bin/sasl2/sasl*.dll";
+$fls = glob($SASL_DLLS);
+if (!empty($fls)) {
+ $sasl_dest_dir = "$dist_dir/sasl2";
+ if (!file_exists($sasl_dest_dir) || !is_dir($sasl_dest_dir)) {
+ if (!mkdir("$sasl_dest_dir", 0777, true)) {
+ echo "WARNING: couldn't create '$sasl_dest_dir' for SASL2 auth plugins ";
+ }
+ }
+ foreach ($fls as $fl) {
+ if (!copy($fl, "$sasl_dest_dir/" . basename($fl))) {
+ echo "WARNING: couldn't copy $fl into the $sasl_dest_dir";
+ }
+ }
+}
+
/* and those for pecl */
foreach ($pecl_dll_deps as $dll) {
if (in_array($dll, $extra_dll_deps)) {
diff --git a/win32/dllmain.c b/win32/dllmain.c
new file mode 100644
index 0000000000..92773a0b58
--- /dev/null
+++ b/win32/dllmain.c
@@ -0,0 +1,74 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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. |
+ +----------------------------------------------------------------------+
+ | Authors: Anatol Belski <ab@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include <config.w32.h>
+
+#include <win32/time.h>
+#include <php.h>
+
+#ifdef HAVE_LIBXML
+#include <libxml/threads.h>
+#endif
+
+/* TODO this file, or part of it, could be machine generated, to
+ allow extensions and SAPIs adding their own init stuff.
+ However expected is that MINIT is enough in most cases.
+ This file is only useful for some really internal stuff,
+ eq. initializing something before the DLL even is
+ available to be called. */
+
+BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID dummy)
+{
+ BOOL ret = TRUE;
+
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ ret = ret && php_win32_init_gettimeofday();
+ if (!ret) {
+ fprintf(stderr, "gettimeofday() initialization failed");
+ return ret;
+ }
+ break;
+#if 0 /* prepared */
+ case DLL_PROCESS_DETACH:
+ /* pass */
+ break;
+
+ case DLL_THREAD_ATTACH:
+ /* pass */
+ break;
+
+ case DLL_THREAD_DETACH:
+ /* pass */
+ break;
+#endif
+ }
+
+#ifdef HAVE_LIBXML
+ /* This imply that only LIBXML_STATIC_FOR_DLL is supported ATM.
+ If that changes, this place will need some rework.
+ TODO Also this should be revisited as no initialization
+ might be needed for TS build (libxml build with TLS
+ support. */
+ ret = ret && xmlDllMain(inst, reason, dummy);
+#endif
+
+ return ret;
+}
+
diff --git a/win32/fnmatch.c b/win32/fnmatch.c
index 590d23f5f9..c3bc5bc5e2 100644
--- a/win32/fnmatch.c
+++ b/win32/fnmatch.c
@@ -196,3 +196,12 @@ rangematch(const char *pattern, char test, int flags)
}
return (ok == negate ? NULL : pattern);
}
+
+/*
+ * 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/win32/getrusage.c b/win32/getrusage.c
new file mode 100644
index 0000000000..fea9089fe6
--- /dev/null
+++ b/win32/getrusage.c
@@ -0,0 +1,84 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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. |
+ +----------------------------------------------------------------------+
+ | Authors: Kalle Sommer Nielsen <kalle@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#include <php.h>
+#include <psapi.h>
+#include "getrusage.h"
+
+/*
+ * Parts of this file is based on code from the OpenVSwitch project, that
+ * is released under the Apache 2.0 license and is copyright 2014 Nicira, Inc.
+ * and have been modified to work with PHP.
+ */
+
+static void usage_to_timeval(FILETIME *ft, struct timeval *tv)
+{
+ ULARGE_INTEGER time;
+
+ time.LowPart = ft->dwLowDateTime;
+ time.HighPart = ft->dwHighDateTime;
+
+ tv->tv_sec = (zend_long) (time.QuadPart / 10000000);
+ tv->tv_usec = (zend_long) ((time.QuadPart % 10000000) / 10);
+}
+
+PHPAPI int getrusage(int who, struct rusage *usage)
+{
+ FILETIME ctime, etime, stime, utime;
+
+ memset(usage, 0, sizeof(struct rusage));
+
+ if (who == RUSAGE_SELF) {
+ PROCESS_MEMORY_COUNTERS pmc;
+ HANDLE proc = GetCurrentProcess();
+
+ if (!GetProcessTimes(proc, &ctime, &etime, &stime, &utime)) {
+ return -1;
+ } else if(!GetProcessMemoryInfo(proc, &pmc, sizeof(pmc))) {
+ return -1;
+ }
+
+ usage_to_timeval(&stime, &usage->ru_stime);
+ usage_to_timeval(&utime, &usage->ru_utime);
+
+ usage->ru_majflt = pmc.PageFaultCount;
+ usage->ru_maxrss = pmc.PeakWorkingSetSize / 1024;
+
+ return 0;
+ } else if (who == RUSAGE_THREAD) {
+ if (!GetThreadTimes(GetCurrentThread(), &ctime, &etime, &stime, &utime)) {
+ return -1;
+ }
+
+ usage_to_timeval(&stime, &usage->ru_stime);
+ usage_to_timeval(&utime, &usage->ru_utime);
+
+ return 0;
+ } else {
+ return -1;
+ }
+}
+
+/*
+ * 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/win32/getrusage.h b/win32/getrusage.h
new file mode 100644
index 0000000000..8a6b9a7510
--- /dev/null
+++ b/win32/getrusage.h
@@ -0,0 +1,117 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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. |
+ +----------------------------------------------------------------------+
+ | Authors: Kalle Sommer Nielsen <kalle@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+#ifndef HAVE_GETRUSAGE_H
+# define HAVE_GETRUSAGE_H
+
+/*
+ * Note
+ *
+ * RUSAGE_CHILDREN is not implemented, and the RUSAGE_THREAD will
+ * therefore instead be used instead to emulate the behavior.
+ */
+
+# define RUSAGE_SELF 0
+# define RUSAGE_CHILDREN 1
+
+# define RUSAGE_THREAD RUSAGE_CHILDREN
+
+/*
+ * Implementation support
+ *
+ * RUSAGE_SELF
+ * ru_utime
+ * ru_stime
+ * ru_majflt
+ * ru_maxrss
+ *
+ * RUSAGE_THREAD
+ * ru_utime
+ * ru_stime
+ *
+ * Not implemented:
+ * ru_ixrss (unused)
+ * ru_idrss (unused)
+ * ru_isrss (unused)
+ * ru_minflt
+ * ru_nswap (unused)
+ * ru_inblock
+ * ru_oublock
+ * ru_msgsnd (unused)
+ * ru_msgrcv (unused)
+ * ru_nsignals (unused)
+ * ru_nvcsw
+ * ru_nivcsw
+ */
+
+struct rusage
+{
+ /* User time used */
+ struct timeval ru_utime;
+
+ /* System time used */
+ struct timeval ru_stime;
+
+ /* Integral max resident set size */
+ zend_long ru_maxrss;
+
+ /* Page faults */
+ zend_long ru_majflt;
+#if 0
+ /* Integral shared text memory size */
+ zend_long ru_ixrss;
+
+ /* Integral unshared data size */
+ zend_long ru_idrss;
+
+ /* Integral unshared stack size */
+ zend_long ru_isrss;
+
+ /* Page reclaims */
+ zend_long ru_minflt;
+
+ /* Swaps */
+ zend_long ru_nswap;
+
+ /* Block input operations */
+ zend_long ru_inblock;
+
+ /* Block output operations */
+ zend_long ru_oublock;
+
+ /* Messages sent */
+ zend_long ru_msgsnd;
+
+ /* Messages received */
+ zend_long ru_msgrcv;
+
+ /* Signals received */
+ zend_long ru_nsignals;
+
+ /* Voluntary context switches */
+ zend_long ru_nvcsw;
+
+ /* Involuntary context switches */
+ zend_long ru_nivcsw;
+#endif
+};
+
+PHPAPI int getrusage(int who, struct rusage *usage);
+
+#endif
+
diff --git a/win32/glob.c b/win32/glob.c
index 43884509ce..8a40f7f506 100644
--- a/win32/glob.c
+++ b/win32/glob.c
@@ -71,12 +71,6 @@
# define ARG_MAX 14500
# endif
#endif
-#ifndef S_ISDIR
-#define S_ISDIR(m) (((m) & _S_IFDIR) == _S_IFDIR)
-#endif
-#ifndef S_ISLNK
-#define S_ISLNK(m) (0)
-#endif
#endif
#include "php.h"
@@ -293,17 +287,19 @@ globexp2(ptr, pattern, pglob, rv)
}
for (i = 0, pl = pm = ptr; pm <= pe; pm++) {
+ const Char *pb;
+
switch (*pm) {
case LBRACKET:
/* Ignore everything between [] */
- for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++)
+ for (pb = pm++; *pm != RBRACKET && *pm != EOS; pm++)
;
if (*pm == EOS) {
/*
* We could not find a matching RBRACKET.
* Ignore and just look for RBRACE
*/
- pm = pl;
+ pm = pb;
}
break;
@@ -929,3 +925,12 @@ qprintf(str, s)
(void)printf("\n");
}
#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/win32/globals.c b/win32/globals.c
index 485f0f31bb..37a55bde46 100644
--- a/win32/globals.c
+++ b/win32/globals.c
@@ -78,3 +78,11 @@ PHP_RSHUTDOWN_FUNCTION(win32_core_globals)
return SUCCESS;
}
+/*
+ * 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/win32/inet.c b/win32/inet.c
index 686cf1265c..c0967f6572 100644
--- a/win32/inet.c
+++ b/win32/inet.c
@@ -1,3 +1,21 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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: Pierre Joye <pierre@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
#include "inet.h"
int inet_aton(const char *cp, struct in_addr *inp) {
@@ -9,3 +27,12 @@ int inet_aton(const char *cp, struct in_addr *inp) {
return 1;
}
+
+/*
+ * 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/win32/inet.h b/win32/inet.h
index d71723759f..f2256427ec 100644
--- a/win32/inet.h
+++ b/win32/inet.h
@@ -1,3 +1,22 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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: Pierre Joye <pierre@php.net> |
+ +----------------------------------------------------------------------+
+ */
+
+
#include <php.h>
#include <Winsock2.h>
diff --git a/win32/install.txt b/win32/install.txt
index 3c91aeafd7..d6940b9354 100644
--- a/win32/install.txt
+++ b/win32/install.txt
@@ -6,7 +6,6 @@ Installing PHP
1. General Installation Considerations
2. Installation on Windows systems
- Windows Installer
Manual Installation Steps
ActiveScript
Microsoft IIS
@@ -107,9 +106,6 @@ Chapter 2. Installation on Windows systems
refer to the supported Windows platforms as Win32. Windows 95 is no
longer supported as of PHP 4.3.0.
- There are two main ways to install PHP for Windows: either manually or
- by using the installer.
-
If you have Microsoft Visual Studio, you can also build PHP from the
original source code.
@@ -124,129 +120,6 @@ Chapter 2. Installation on Windows systems
optimised.
__________________________________________________________________
-Windows Installer (PHP 5.2 and later)
-
- The Windows PHP installer for later versions of PHP is built using MSI
- technology using the Wix Toolkit (http://wix.sourceforge.net/). It will
- install and configure PHP and all the built-in and PECL extensions, as
- well as configure many of the popular web servers such as IIS, Apache,
- and Xitami.
-
- First, install your selected HTTP (web) server on your system, and make
- sure that it works. Then proceed with one of the following install
- types.
- __________________________________________________________________
-
-Normal Install
-
- Run the MSI installer and follow the instructions provided by the
- installation wizard. You will be prompted to select the Web Server you
- wish to configure first, along with any configuration details needed.
-
- You will then be prompted to select which features and extensions you
- wish to install and enable. By selecting "Will be installed on local
- hard drive" in the drop-down menu for each item you can trigger whether
- to install the feature or not. By selecting "Entire feature will be
- installed on local hard drive", you will be able to install all
- sub-features of the included feature ( for example by selecting this
- options for the feature "PDO" you will install all PDO Drivers ).
-
- Warning
-
- It is not recommended to install all extensions by default, since many
- other them require dependencies from outside PHP in order to function
- properly. Instead, use the Installation Repair Mode that can be
- triggered thru the 'Add/Remove Programs' control panel to enable or
- disable extensions and features after installation.
-
- The installer then sets up PHP to be used in Windows and the php.ini
- file, and configures certain web servers to use PHP. The installer will
- currently configure IIS (CGI mode only), Apache, Xitami, and Sambar
- Server; if you are using a different web server you'll need to
- configure it manually.
- __________________________________________________________________
-
-Silent Install
-
- The installer also supports a silent mode, which is helpful for Systems
- Administrators to deploy PHP easily. To use silent mode:
- msiexec.exe /i php-VERSION-win32-install.msi /q
-
- You can control the install directory by passing it as a parameter to
- the install. For example, to install to e:\php:
- msiexec.exe /i php-VERSION-win32-install.msi /q INSTALLDIR=e:\php
-
- You can also use the same syntax to specify the Apache Configuration
- Directory (APACHEDIR), the Sambar Server directory (SAMBARDIR), and the
- Xitami Server directory (XITAMIDIR).
-
- You can also specify what features to install. For example, to install
- the mysqli extension and the CGI executable:
- msiexec.exe /i php-VERSION-win32-install.msi /q ADDLOCAL=cgi,ext_php_mysqli
-
- The current list of Features to install is as follows:
-MainExecutable - php.exe executable
-ScriptExecutable - php-win.exe executable
-ext_php_* - the various extensions ( for example: ext_php_mysql for MySQL )
-apache13 - Apache 1.3 module
-apache20 - Apache 2.0 module
-apache22 - Apache 2,2 module
-apacheCGI - Apache CGI executable
-iis4ISAPI - IIS ISAPI module
-iis4CGI - IIS CGI executable
-NSAPI - Sun/iPlanet/Netscape server module
-Xitami - Xitami CGI executable
-Sambar - Sambar Server ISAPI module
-CGI - php-cgi.exe executable
-PEAR - PEAR installer
-Manual - PHP Manual in CHM Format
-
- For more information on installing MSI installers from the command
- line, visit
- http://msdn.microsoft.com/library/en-us/msi/setup/command_line_options.
- asp
- __________________________________________________________________
-
-Windows Installer (PHP 5.1.0 and earlier)
-
- The Windows PHP installer is available from the downloads page at
- http://www.php.net/downloads.php. This installs the CGI version of PHP
- and for IIS and Xitami, it configures the web server as well. The
- installer does not include any extra external PHP extensions
- (php_*.dll) as you'll only find those in the Windows Zip Package and
- PECL downloads.
-
- Note: While the Windows installer is an easy way to make PHP work,
- it is restricted in many aspects as, for example, the automatic
- setup of extensions is not supported. Use of the installer isn't the
- preferred method for installing PHP.
-
- First, install your selected HTTP (web) server on your system, and make
- sure that it works.
-
- Run the executable installer and follow the instructions provided by
- the installation wizard. Two types of installation are supported -
- standard, which provides sensible defaults for all the settings it can,
- and advanced, which asks questions as it goes along.
-
- The installation wizard gathers enough information to set up the
- php.ini file, and configure certain web servers to use PHP. One of the
- web servers the PHP installer does not configure for is Apache, so
- you'll need to configure it manually.
-
- Once the installation has completed, the installer will inform you if
- you need to restart your system, restart the server, or just start
- using PHP.
-
- Warning
-
- Be aware, that this setup of PHP is not secure. If you would like to
- have a secure PHP setup, you'd better go on the manual way, and set
- every option carefully. This automatically working setup gives you an
- instantly working PHP installation, but it is not meant to be used on
- online servers.
- __________________________________________________________________
-
Manual Installation Steps
This install guide will help you manually install and configure PHP
@@ -254,11 +127,10 @@ Manual Installation Steps
download the zip binary distribution from the downloads page at
http://www.php.net/downloads.php.
- Although there are many all-in-one installation kits, and we also
- distribute a PHP installer for Microsoft Windows, we recommend you take
- the time to setup PHP yourself as this will provide you with a better
- understanding of the system, and enables you to install PHP extensions
- easily when needed.
+ Although there are many all-in-one installation kits, we recommend you
+ take the time to setup PHP yourself as this will provide you with a
+ better understanding of the system, and enables you to install PHP
+ extensions easily when needed.
Upgrading from a previous PHP version: Previous editions of the
manual suggest moving various ini and DLL files into your SYSTEM
@@ -533,10 +405,10 @@ General considerations for all installations of PHP with IIS
extensions_dir value is "c:\php\ext" and an example IIS doc_root
value is "c:\Inetpub\wwwroot".
* PHP extension DLL files, such as php_mysql.dll and php_curl.dll,
- are found in the zip package of the PHP download (not the PHP
- installer). In PHP 7, many extensions are part of PECL and can be
- downloaded in the "Collection of PECL modules" package. Files such
- as php_zip.dll and php_ssh2.dll. Download PHP files here.
+ are found in the zip package of the PHP download. In PHP 7, many
+ extensions are part of PECL and can be downloaded in the
+ "Collection of PECL modules" package. Files such as php_zip.dll and
+ php_ssh2.dll. Download PHP files here.
* When defining the executable, the 'check that file exists' box may
also be checked. For a small performance penalty, the IIS
will check that the script file exists and sort out authentication
diff --git a/win32/php_registry.h b/win32/php_registry.h
index bce2fe0978..f8a57dbac7 100644
--- a/win32/php_registry.h
+++ b/win32/php_registry.h
@@ -1,3 +1,21 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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: Zeev Suraski <zeev@zend.com> |
+ +----------------------------------------------------------------------+
+ */
+
#ifndef PHP_REGISTRY_H
#define PHP_REGISTRY_H
diff --git a/win32/readdir.c b/win32/readdir.c
index b94b570cf4..fc2c4357ff 100644
--- a/win32/readdir.c
+++ b/win32/readdir.c
@@ -166,3 +166,12 @@ int rewinddir(DIR *dp)
return 0;
}
+
+/*
+ * 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/win32/registry.c b/win32/registry.c
index 016781776c..be16e1880f 100644
--- a/win32/registry.c
+++ b/win32/registry.c
@@ -1,3 +1,21 @@
+/*
+ +----------------------------------------------------------------------+
+ | 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: Zeev Suraski <zeev@zend.com> |
+ +----------------------------------------------------------------------+
+ */
+
#include "php.h"
#include "php_ini.h"
#include "php_win32_globals.h"
@@ -281,3 +299,12 @@ char *GetIniPathFromRegistry()
}
return reg_location;
}
+
+/*
+ * 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/win32/sendmail.c b/win32/sendmail.c
index b8d18d195e..e6be028091 100644
--- a/win32/sendmail.c
+++ b/win32/sendmail.c
@@ -977,3 +977,12 @@ static int FormatEmailAddress(char* Buf, char* EmailAddress, char* FormatString)
}
return snprintf(Buf, MAIL_BUFFER_SIZE , FormatString , EmailAddress );
} /* end FormatEmailAddress() */
+
+/*
+ * 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/win32/sockets.c b/win32/sockets.c
index 4ad84ab946..e56836468a 100644
--- a/win32/sockets.c
+++ b/win32/sockets.c
@@ -90,3 +90,12 @@ error:
WSASetLastError(WSAECONNABORTED);
return -1;
}
+
+/*
+ * 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/win32/time.c b/win32/time.c
index b65a92c771..dfcc46a59b 100644
--- a/win32/time.c
+++ b/win32/time.c
@@ -29,10 +29,11 @@ typedef VOID (WINAPI *MyGetSystemTimeAsFileTime)(LPFILETIME lpSystemTimeAsFileTi
static MyGetSystemTimeAsFileTime timefunc = NULL;
+#ifdef PHP_EXPORTS
static zend_always_inline MyGetSystemTimeAsFileTime get_time_func(void)
{
MyGetSystemTimeAsFileTime timefunc = NULL;
- HMODULE hMod = LoadLibrary("kernel32.dll");
+ HMODULE hMod = GetModuleHandle("kernel32.dll");
if (hMod) {
/* Max possible resolution <1us, win8/server2012 */
@@ -47,15 +48,20 @@ static zend_always_inline MyGetSystemTimeAsFileTime get_time_func(void)
return timefunc;
}
+BOOL php_win32_init_gettimeofday(void)
+{
+ timefunc = get_time_func();
+
+ return (NULL != timefunc);
+}
+#endif
+
static zend_always_inline int getfilesystemtime(struct timeval *tv)
{
FILETIME ft;
unsigned __int64 ff = 0;
ULARGE_INTEGER fft;
- if (!timefunc) {
- timefunc = get_time_func();
- }
timefunc(&ft);
/*
@@ -116,87 +122,11 @@ PHPAPI int nanosleep( const struct timespec * rqtp, struct timespec * rmtp )
return usleep( rqtp->tv_sec * 1000000 + rqtp->tv_nsec / 1000 );
}
-#if 0 /* looks pretty ropey in here */
-#ifdef HAVE_SETITIMER
-
-
-#ifndef THREAD_SAFE
-unsigned int proftimer, virttimer, realtimer;
-extern LPMSG phpmsg;
-#endif
-
-struct timer_msg {
- int signal;
- unsigned int threadid;
-};
-
-
-LPTIMECALLBACK setitimer_timeout(UINT uTimerID, UINT info, DWORD dwUser, DWORD dw1, DWORD dw2)
-{
- struct timer_msg *msg = (struct timer_msg *) info;
-
- if (msg) {
- raise((int) msg->signal);
- PostThreadMessage(msg->threadid,
- WM_NOTIFY, msg->signal, 0);
- free(msg);
- }
- return 0;
-}
-
-PHPAPI int setitimer(int which, const struct itimerval *value, struct itimerval *ovalue)
-{
- int timeout = value->it_value.tv_sec * 1000 + value->it_value.tv_usec;
- int repeat = TIME_ONESHOT;
-
- /*make sure the message queue is initialized */
- PeekMessage(phpmsg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
- if (timeout > 0) {
- struct timer_msg *msg = malloc(sizeof(struct timer_msg));
- msg->threadid = GetCurrentThreadId();
- if (!ovalue) {
- repeat = TIME_PERIODIC;
- }
- switch (which) {
- case ITIMER_REAL:
- msg->signal = SIGALRM;
- realtimer = timeSetEvent(timeout, 100, (LPTIMECALLBACK) setitimer_timeout, (UINT) msg, repeat);
- break;
- case ITIMER_VIRT:
- msg->signal = SIGVTALRM;
- virttimer = timeSetEvent(timeout, 100, (LPTIMECALLBACK) setitimer_timeout, (UINT) msg, repeat);
- break;
- case ITIMER_PROF:
- msg->signal = SIGPROF;
- proftimer = timeSetEvent(timeout, 100, (LPTIMECALLBACK) setitimer_timeout, (UINT) msg, repeat);
- break;
- default:
- errno = EINVAL;
- return -1;
- break;
- }
- } else {
- switch (which) {
- case ITIMER_REAL:
- timeKillEvent(realtimer);
- break;
- case ITIMER_VIRT:
- timeKillEvent(virttimer);
- break;
- case ITIMER_PROF:
- timeKillEvent(proftimer);
- break;
- default:
- errno = EINVAL;
- return -1;
- break;
- }
- }
-
-
- return 0;
-}
-
-#endif
-#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/win32/time.h b/win32/time.h
index 8f39c0481c..b46c1675ca 100644
--- a/win32/time.h
+++ b/win32/time.h
@@ -52,4 +52,10 @@ PHPAPI int nanosleep( const struct timespec * rqtp, struct timespec * rmtp );
PHPAPI int usleep(unsigned int useconds);
+#ifdef PHP_EXPORTS
+/* This symbols are needed only for the DllMain, but should not be exported
+ or be available when used with PHP binaries. */
+BOOL php_win32_init_gettimeofday(void);
+#endif
+
#endif
diff --git a/win32/winutil.c b/win32/winutil.c
index 488c8cbc57..2faa0d9e7d 100644
--- a/win32/winutil.c
+++ b/win32/winutil.c
@@ -123,3 +123,11 @@ PHPAPI int php_win32_get_random_bytes(unsigned char *buf, size_t size) { /* {{{
}
/* }}} */
+/*
+ * 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/win32/wsyslog.c b/win32/wsyslog.c
index 8244fa12f7..6b0f03e8ea 100644
--- a/win32/wsyslog.c
+++ b/win32/wsyslog.c
@@ -127,3 +127,12 @@ void openlog(const char *ident, int logopt, int facility)
PW32G(log_source) = RegisterEventSource(NULL, "PHP-" PHP_VERSION);
spprintf(&PW32G(log_header), 0, (logopt & LOG_PID) ? "%s[%d]" : "%s", ident, getpid());
}
+
+/*
+ * Local variables:
+ * tab-width: 4
+ * c-basic-offset: 4
+ * End:
+ * vim600: sw=4 ts=4 fdm=marker
+ * vim<600: sw=4 ts=4
+ */