summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJakub Zelenka <bukka@php.net>2016-02-29 19:28:40 +0000
committerJakub Zelenka <bukka@php.net>2016-02-29 19:28:40 +0000
commit80015ba741fc857074050086db6c7b2a4716d6d5 (patch)
tree9e0b85868c092ae83a0df2bd4f33f79ba773aab2
parent4ea2a0fd60cdf75d746909198ea69f1e3e4ba193 (diff)
parent31dc08a904f2a91b582396b6ba118abfd12cf246 (diff)
downloadphp-git-80015ba741fc857074050086db6c7b2a4716d6d5.tar.gz
Merge branch 'PHP-7.0' into openssl_error_store
-rw-r--r--CODING_STANDARDS2
-rw-r--r--Makefile.global2
-rw-r--r--NEWS109
-rw-r--r--README.EXT_SKEL2
-rw-r--r--README.NEW-OUTPUT-API74
-rw-r--r--README.PARAMETER_PARSING_API28
-rw-r--r--README.REDIST.BINS63
-rw-r--r--README.STREAMS6
-rw-r--r--README.input_filter4
-rw-r--r--Zend/tests/bug69989_1.phpt15
-rw-r--r--Zend/tests/bug71470.phpt13
-rw-r--r--Zend/tests/bug71529.phpt23
-rw-r--r--Zend/tests/bug71622.phpt30
-rw-r--r--Zend/tests/foreach_017.phpt2
-rw-r--r--Zend/tests/generators/bug71601.phpt40
-rw-r--r--Zend/tests/generators/dangling_send_target.phpt22
-rw-r--r--Zend/tests/generators/yield_from_by_reference.phpt12
-rw-r--r--Zend/zend_API.c9
-rw-r--r--Zend/zend_alloc.c4
-rw-r--r--Zend/zend_arena.h3
-rw-r--r--Zend/zend_compile.c12
-rw-r--r--Zend/zend_execute_API.c2
-rw-r--r--Zend/zend_generators.c48
-rw-r--r--Zend/zend_vm_def.h30
-rw-r--r--Zend/zend_vm_execute.h258
-rw-r--r--configure.in2
-rw-r--r--ext/curl/interface.c13
-rw-r--r--ext/curl/tests/bug71523.phpt31
-rw-r--r--ext/date/php_date.c1
-rw-r--r--ext/date/tests/bug71525.phpt20
-rw-r--r--ext/iconv/iconv.c4
-rw-r--r--ext/intl/ERROR.CONVENTIONS20
-rw-r--r--ext/libxml/libxml.c3
-rw-r--r--ext/mcrypt/mcrypt.c4
-rw-r--r--ext/odbc/php_odbc.c41
-rw-r--r--ext/odbc/php_odbc_includes.h8
-rw-r--r--ext/odbc/tests/bug47803.phpt185
-rw-r--r--ext/odbc/tests/bug71171.phpt43
-rw-r--r--ext/odbc/tests/config.inc17
-rw-r--r--ext/opcache/Optimizer/block_pass.c10
-rw-r--r--ext/opcache/ZendAccelerator.c249
-rw-r--r--ext/opcache/ZendAccelerator.h1
-rw-r--r--ext/opcache/tests/bug66338.phpt4
-rw-r--r--ext/opcache/tests/bug67215.phpt2
-rw-r--r--ext/opcache/tests/revalidate_path_01.phpt28
-rw-r--r--ext/opcache/zend_accelerator_module.c4
-rw-r--r--ext/opcache/zend_file_cache.c20
-rw-r--r--ext/opcache/zend_persist_calc.c11
-rw-r--r--ext/opcache/zend_shared_alloc.c17
-rw-r--r--ext/opcache/zend_shared_alloc.h2
-rw-r--r--ext/openssl/openssl.c6
-rw-r--r--ext/openssl/tests/openssl_csr_new_basic.phpt10
-rw-r--r--ext/openssl/tests/openssl_x509_check_private_key_basic.phpt4
-rw-r--r--ext/openssl/tests/openssl_x509_export_basic.phpt57
-rw-r--r--ext/openssl/tests/openssl_x509_export_to_file_basic.phpt42
-rw-r--r--ext/openssl/tests/openssl_x509_fingerprint_basic.phpt2
-rw-r--r--ext/openssl/tests/openssl_x509_free_basic.phpt16
-rw-r--r--ext/openssl/tests/openssl_x509_parse_basic.phpt2
-rw-r--r--ext/openssl/tests/openssl_x509_read_basic.phpt37
-rw-r--r--ext/pcre/php_pcre.c14
-rw-r--r--ext/pcre/tests/bug71537.phpt9
-rw-r--r--ext/pdo/Makefile.frag2
-rw-r--r--ext/pdo/pdo_stmt.c11
-rw-r--r--ext/pdo_dblib/dblib_driver.c7
-rw-r--r--ext/pdo_dblib/dblib_stmt.c21
-rw-r--r--ext/pdo_dblib/tests/bug_54648.phpt26
-rw-r--r--ext/pdo_dblib/tests/bug_68957.phpt29
-rw-r--r--ext/pdo_mysql/tests/bug71569.phpt23
-rw-r--r--ext/pgsql/pgsql.c2
-rw-r--r--ext/phar/phar.c7
-rw-r--r--ext/phar/phar_object.c2
-rw-r--r--ext/phar/tests/bug71331.phpt6
-rw-r--r--ext/phar/tests/bug71625.phpt25
-rwxr-xr-xext/skeleton/create_stubs2
-rw-r--r--ext/spl/spl_array.c187
-rw-r--r--ext/spl/spl_directory.c2
-rw-r--r--ext/spl/tests/ArrayObject_clone_other_std_props.phpt23
-rw-r--r--ext/spl/tests/ArrayObject_dump_during_sort.phpt27
-rw-r--r--ext/spl/tests/ArrayObject_exchange_array_during_sorting.phpt29
-rw-r--r--ext/spl/tests/ArrayObject_illegal_offset_leak.phpt11
-rw-r--r--ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt19
-rw-r--r--ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt27
-rw-r--r--ext/spl/tests/ArrayObject_std_props_no_recursion.phpt28
-rw-r--r--ext/spl/tests/bug71617.phpt50
-rw-r--r--ext/sqlite3/sqlite3.c3
-rw-r--r--ext/standard/array.c21
-rw-r--r--ext/standard/iptc.c2
-rw-r--r--ext/standard/pack.c2
-rw-r--r--ext/standard/string.c2
-rw-r--r--ext/standard/tests/array/bug71603.phpt15
-rw-r--r--ext/standard/tests/array/bug71660.phpt18
-rw-r--r--ext/standard/tests/math/mt_rand_value.phpt44
-rw-r--r--ext/standard/var.c9
-rw-r--r--ext/xmlrpc/tests/bug71501.phpt23
-rw-r--r--ext/xmlrpc/xmlrpc-epi-php.c71
-rw-r--r--ext/xsl/tests/bug71540.phpt69
-rw-r--r--ext/xsl/xsltprocessor.c6
-rw-r--r--ext/zip/config.m41
-rw-r--r--ext/zip/config.w321
-rw-r--r--ext/zip/lib/zip_add_entry.c17
-rw-r--r--ext/zip/lib/zip_buffer.c11
-rw-r--r--ext/zip/lib/zip_close.c1
-rw-r--r--ext/zip/lib/zip_delete.c12
-rw-r--r--ext/zip/lib/zip_dirent.c109
-rw-r--r--ext/zip/lib/zip_discard.c4
-rw-r--r--ext/zip/lib/zip_error.c3
-rw-r--r--ext/zip/lib/zip_error_strerror.c3
-rw-r--r--ext/zip/lib/zip_error_to_str.c3
-rw-r--r--ext/zip/lib/zip_extra_field.c55
-rw-r--r--ext/zip/lib/zip_fdopen.c3
-rw-r--r--ext/zip/lib/zip_file_get_offset.c3
-rw-r--r--ext/zip/lib/zip_filerange_crc.c3
-rw-r--r--ext/zip/lib/zip_fopen_index.c3
-rw-r--r--ext/zip/lib/zip_fopen_index_encrypted.c3
-rw-r--r--ext/zip/lib/zip_hash.c267
-rw-r--r--ext/zip/lib/zip_io_util.c3
-rw-r--r--ext/zip/lib/zip_name_locate.c48
-rw-r--r--ext/zip/lib/zip_new.c7
-rw-r--r--ext/zip/lib/zip_open.c73
-rw-r--r--ext/zip/lib/zip_set_default_password.c3
-rw-r--r--ext/zip/lib/zip_set_name.c93
-rw-r--r--ext/zip/lib/zip_source_buffer.c5
-rw-r--r--ext/zip/lib/zip_source_crc.c100
-rw-r--r--ext/zip/lib/zip_source_file.c1
-rw-r--r--ext/zip/lib/zip_source_filep.c29
-rw-r--r--ext/zip/lib/zip_source_pkware.c4
-rw-r--r--ext/zip/lib/zip_source_stat.c4
-rw-r--r--ext/zip/lib/zip_source_supports.c4
-rw-r--r--ext/zip/lib/zip_source_win32a.c3
-rw-r--r--ext/zip/lib/zip_source_win32handle.c5
-rw-r--r--ext/zip/lib/zip_source_win32utf8.c1
-rw-r--r--ext/zip/lib/zip_source_win32w.c5
-rw-r--r--ext/zip/lib/zip_unchange.c32
-rw-r--r--ext/zip/lib/zip_unchange_all.c4
-rw-r--r--ext/zip/lib/zipconf.h6
-rw-r--r--ext/zip/lib/zipint.h59
-rw-r--r--ext/zip/php_zip.c10
-rw-r--r--ext/zip/php_zip.h3
-rw-r--r--ext/zip/zip_stream.c1
-rw-r--r--ext/zlib/zlib.c2
-rw-r--r--main/main.c3
-rw-r--r--main/output.c4
-rw-r--r--main/php.h12
-rw-r--r--main/php_streams.h8
-rw-r--r--main/php_version.h6
-rw-r--r--main/streams/memory.c4
-rw-r--r--sapi/cli/php_cli.c2
-rw-r--r--sapi/cli/php_cli_server.c13
-rw-r--r--sapi/fpm/Makefile.frag2
-rw-r--r--sapi/fpm/fpm/fpm_signals.c4
-rw-r--r--sapi/litespeed/Makefile.frag2
-rw-r--r--sapi/phpdbg/phpdbg.c8
-rw-r--r--sapi/phpdbg/phpdbg_bp.c14
-rw-r--r--sapi/phpdbg/phpdbg_frame.c2
-rw-r--r--sapi/phpdbg/phpdbg_info.c23
-rw-r--r--sapi/phpdbg/phpdbg_opcode.c4
-rw-r--r--sapi/phpdbg/phpdbg_out.h9
-rw-r--r--sapi/phpdbg/phpdbg_print.c8
-rw-r--r--sapi/phpdbg/phpdbg_prompt.c22
-rw-r--r--sapi/phpdbg/phpdbg_utils.c14
-rw-r--r--sapi/phpdbg/phpdbg_utils.h8
-rw-r--r--sapi/phpdbg/phpdbg_wait.c4
-rw-r--r--win32/build/Makefile.phpize2
-rw-r--r--win32/build/confutils.js161
164 files changed, 2876 insertions, 1073 deletions
diff --git a/CODING_STANDARDS b/CODING_STANDARDS
index 0cfcff18f6..a3b9d2b7d3 100644
--- a/CODING_STANDARDS
+++ b/CODING_STANDARDS
@@ -178,7 +178,7 @@ Internal Function Naming Convensions
Unexposed module function should be static and should not be defined in
'php_modulename.h'.
- static int php_session_destroy(TSRMLS_D)
+ static int php_session_destroy()
2. Main module source file must be named 'modulename.c'.
diff --git a/Makefile.global b/Makefile.global
index c571f3455d..9b29d5112b 100644
--- a/Makefile.global
+++ b/Makefile.global
@@ -53,7 +53,7 @@ install-headers:
paths="$$paths $(INSTALL_ROOT)$(phpincludedir)/$$i"; \
done; \
$(mkinstalldirs) $$paths && \
- echo "Installing header files: $(INSTALL_ROOT)$(phpincludedir)/" && \
+ echo "Installing header files: $(INSTALL_ROOT)$(phpincludedir)/" && \
for i in `echo $(INSTALL_HEADERS)`; do \
if test "$(PHP_PECL_EXTENSION)"; then \
src=`echo $$i | $(SED) -e "s#ext/$(PHP_PECL_EXTENSION)/##g"`; \
diff --git a/NEWS b/NEWS
index e42e479a4a..e096907e72 100644
--- a/NEWS
+++ b/NEWS
@@ -1,9 +1,51 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
-?? ??? 2016 PHP 7.0.4
+?? ??? 2016 PHP 7.0.5
- Core:
- . Fixed bug #71485 (Return typehint on interanal func causes Fatal error
+ . Fixed bug #71629 (Out-of-bounds access in php_url_decode in context
+ php_stream_url_wrap_rfc2397). (mt at debian dot org)
+ . Fixed bug #71622 (Strings used in pass-as-reference cannot be used to
+ invoke C::$callable()). (Bob)
+ . Fixed bug #71596 (Segmentation fault on ZTS with date function
+ (setlocale)). (Anatol)
+ . Fixed bug #71535 (Integer overflow in zend_mm_alloc_heap()). (Dmitry)
+ . Fixed bug #71470 (Leaked 1 hashtable iterators). (Nikita)
+
+- libxml:
+ . Fixed bug #71536 (Access Violation crashes php-cgi.exe). (Anatol)
+
+- ODBC:
+ . Fixed bug #47803, #69526 (Executing prepared statements is succesfull only
+ for the first two statements). (einavitamar at gmail dot com, Anatol)
+
+- PDO_DBlib:
+ . Bug #54648 (PDO::MSSQL forces format of datetime fields).
+ (steven dot lambeth at gmx dot de, Anatol)
+
+- Phar:
+ . Fixed bug #71625 (Crash in php7.dll with bad phar filename).
+ (Anatol)
+
+- phpdbg:
+ . Fixed crash when advancing (except step) inside an internal function. (Bob)
+
+- SPL:
+ . Fixed bug #71617 (private properties lost when unserializing ArrayObject).
+ (Nikita)
+
+- Standard:
+ . Fixed bug #71660 (array_column behaves incorrectly after foreach by
+ reference). (Laruence)
+
+- Zip:
+ . Update bundled libzip to 1.1.2. (Remi, Anatol)
+
+?? Mar 2016 PHP 7.0.4
+
+- Core:
+ . Fixed bug (Low probability segfault in zend_arena). (Laruence)
+ . Fixed bug #71485 (Return typehint on internal func causes Fatal error
when it throws exception). (Laruence)
. Fixed bug #71474 (Crash because of VM stack corruption on Magento2).
(Dmitry)
@@ -14,23 +56,58 @@ PHP NEWS
. Fixed bug #71442 (forward_static_call crash). (Laruence)
. Fixed bug #71441 (Typehinted Generator with return in try/finally crashes).
(Bob)
+ . Fixed bug #71529 (Variable references on array elements don't work when
+ using count). (Nikita)
+ . Fixed bug #71601 (finally block not executed after yield from). (Bob)
+
+- CLI server:
+ . Fixed bug #71559 (Built-in HTTP server, we can download file in web by bug).
+ (Johannes, Anatol)
+
+- CURL:
+ . Fixed bug #71523 (Copied handle with new option CURLOPT_HTTPHEADER crashes
+ while curl_multi_exec). (Laruence)
+ . Fixed memory leak in curl_getinfo(). (Leigh)
+
+- Date:
+ . Fixed bug #71525 (Calls to date_modify will mutate timelib_rel_time,
+ causing date_date_set issues). (Sean DuBois)
- Fileinfo:
. Fixed bug #71434 (finfo throws notice for specific python file). (Laruence)
- FPM:
- . Fixed bug #62172 (FPM not working with Apache httpd 2.4 balancer/fcgi setup).
- (Matt Haught, Remi)
+ . Fixed bug #62172 (FPM not working with Apache httpd 2.4 balancer/fcgi
+ setup). (Matt Haught, Remi)
+ . Fixed bug #71269 (php-fpm dumped core). (Mickaël)
+
+- Opcache:
+ . Fixed bug #71584 (Possible use-after-free of ZCG(cwd) in Zend Opcache).
+ (Yussuf Khalil)
+
+- PCRE:
+ . Fixed bug #71537 (PCRE segfault from Opcache). (Laruence)
+
+- phpdbg:
+ . Fixed inherited functions from unspecified files being included in
+ phpdbg_get_executable(). (Bob)
- Standard:
+ . Fixed bug #71603 (compact() maintains references in php7). (Laruence)
. Fixed bug #70720 (strip_tags improper php code parsing). (Julien)
+- XMLRPC:
+ . Fixed bug #71501 (xmlrpc_encode_request ignores encoding option). (Hieu Le)
+
+- Zip:
+ . Fixed bug #71561 (NULL pointer dereference in Zip::ExtractTo). (Laruence)
+
04 Feb 2016 PHP 7.0.3
- Core:
. Added support for new HTTP 451 code. (Julien)
- . Fixed bug #71039 (exec functions ignore length but look for NULL termination).
- (Anatol)
+ . Fixed bug #71039 (exec functions ignore length but look for NULL
+ termination). (Anatol)
. Fixed bug #71089 (No check to duplicate zend_extension). (Remi)
. Fixed bug #71201 (round() segfault on 64-bit builds). (Anatol)
. Fixed bug #71221 (Null pointer deref (segfault) in get_defined_vars via
@@ -57,6 +134,9 @@ PHP NEWS
. Fixed bug #71225 (curl_setopt() fails to set CURLOPT_POSTFIELDS with
reference to CURLFile). (Laruence)
+- GD:
+ . Improved fix for bug #70976. (Remi)
+
- Interbase:
. Fixed Bug #71305 (Crash when optional resource is omitted).
(Laruence, Anatol)
@@ -71,6 +151,9 @@ PHP NEWS
- OpenSSL:
. Fixed bug #71475 (openssl_seal() uninitialized memory usage). (Stas)
+- PCRE:
+ . Upgraded pcrelib to 8.38.
+
- Phar:
. Fixed bug #71354 (Heap corruption in tar/zip/phar parser). (Stas)
. Fixed bug #71391 (NULL Pointer Dereference in phar_tar_setupmetadata()).
@@ -142,10 +225,6 @@ PHP NEWS
- Filter:
. Fixed bug #71063 (filter_input(INPUT_ENV, ..) does not work). (Reeze Xia)
-- GD:
- . Fixed bug #70976 (Memory Read via gdImageRotateInterpolated Array Index
- Out of Bounds). (emmanuel dot law at gmail dot com).
-
- FPM:
. Fixed bug #70755 (fpm_log.c memory leak and buffer overflow). (Stas)
@@ -153,6 +232,10 @@ PHP NEWS
. Implemented FR #55651 (Option to ignore the returned FTP PASV address).
(abrender at elitehosts dot com)
+- GD:
+ . Fixed bug #70976 (Memory Read via gdImageRotateInterpolated Array Index
+ Out of Bounds). (emmanuel dot law at gmail dot com)
+
- Mbstring:
. Fixed bug #71066 (mb_send_mail: Program terminated with signal SIGSEGV,
Segmentation fault). (Laruence)
@@ -182,12 +265,12 @@ PHP NEWS
(emmanuel dot law at gmail dot com)
- WDDX:
- . Fixed bug #70661 (Use After Free Vulnerability in WDDX Packet Deserialization).
- (taoguangchen at icloud dot com)
+ . Fixed bug #70661 (Use After Free Vulnerability in WDDX Packet
+ Deserialization). (taoguangchen at icloud dot com)
. Fixed bug #70741 (Session WDDX Packet Deserialization Type Confusion
Vulnerability). (taoguangchen at icloud dot com)
-- XMLRPC
+- XMLRPC:
. Fixed bug #70728 (Type Confusion Vulnerability in PHP_to_XMLRPC_worker).
(Julien)
diff --git a/README.EXT_SKEL b/README.EXT_SKEL
index fdf7ad0e90..5ac48ec4fa 100644
--- a/README.EXT_SKEL
+++ b/README.EXT_SKEL
@@ -172,7 +172,7 @@ PHP_FUNCTION(module_name_drawtext)
zval *image = NULL;
zval *font = NULL;
- if (zend_parse_parameters(argc TSRMLS_CC, "rsrll|l", &image, &text, &text_len, &font, &x, &y, &color) == FAILURE)
+ if (zend_parse_parameters(argc, "rsrll|l", &image, &text, &text_len, &font, &x, &y, &color) == FAILURE)
return;
if (image) {
diff --git a/README.NEW-OUTPUT-API b/README.NEW-OUTPUT-API
index c43649a837..fa4ace05a9 100644
--- a/README.NEW-OUTPUT-API
+++ b/README.NEW-OUTPUT-API
@@ -8,98 +8,98 @@ API adjustment to the old output control code:
Checking output control layers status:
// Using OG()
- php_output_get_status(TSRMLS_C);
+ php_output_get_status();
Starting the default output handler:
- // php_start_ob_buffer(NULL, 0, 1 TSRMLS_CC);
- php_output_start_default(TSRMLS_C);
+ // php_start_ob_buffer(NULL, 0, 1);
+ php_output_start_default();
Starting an user handler by zval:
- // php_start_ob_buffer(zhandler, chunk_size, erase TSRMLS_CC);
- php_output_start_user(zhandler, chunk_size, flags TSRMLS_CC);
+ // php_start_ob_buffer(zhandler, chunk_size, erase);
+ php_output_start_user(zhandler, chunk_size, flags);
Starting an internal handler whithout context:
- // php_ob_set_internal_handler(my_php_output_handler_func_t, buffer_size, "output handler name", erase TSRMLS_CC);
- php_output_start_internal(handler_name, handler_name_len, my_php_output_handler_func_t, chunk_size, flags TSRMLS_CC);
+ // php_ob_set_internal_handler(my_php_output_handler_func_t, buffer_size, "output handler name", erase);
+ php_output_start_internal(handler_name, handler_name_len, my_php_output_handler_func_t, chunk_size, flags);
Starting an internal handler with context:
// not possible with old API
php_output_handler *h;
- h = php_output_handler_create_internal(handler_name, handler_name_len, my_php_output_handler_context_func_t, chunk_size, flags TSRMLS_CC);
+ h = php_output_handler_create_internal(handler_name, handler_name_len, my_php_output_handler_context_func_t, chunk_size, flags);
php_output_handler_set_context(h, my_context, my_context_dtor);
- php_output_handler_start(h TSRMLS_CC);
+ php_output_handler_start(h);
Testing whether a certain output handler has already been started:
- // php_ob_handler_used("output handler name" TSRMLS_CC);
- php_output_handler_started(handler_name, handler_name_len TSRMLS_CC);
+ // php_ob_handler_used("output handler name");
+ php_output_handler_started(handler_name, handler_name_len);
Flushing one output buffer:
- // php_end_ob_buffer(1, 1 TSRMLS_CC);
- php_output_flush(TSRMLS_C);
+ // php_end_ob_buffer(1, 1);
+ php_output_flush();
Flushing all output buffers:
// not possible with old API
- php_output_flush_all(TSRMLS_C);
+ php_output_flush_all();
Cleaning one output buffer:
- // php_ob_end_buffer(0, 1 TSRMLS_CC);
- php_output_clean(TSRMLS_C);
+ // php_ob_end_buffer(0, 1);
+ php_output_clean();
Cleaning all output buffers:
// not possible with old API
- php_output_clean_all(TSRMLS_C);
+ php_output_clean_all();
Discarding one output buffer:
- // php_ob_end_buffer(0, 0 TSRMLS_CC);
- php_output_discard(TSRMLS_C);
+ // php_ob_end_buffer(0, 0);
+ php_output_discard();
Discarding all output buffers:
- // php_ob_end_buffers(0 TSRMLS_CC);
- php_output_discard_all(TSRMLS_C);
+ // php_ob_end_buffers(0);
+ php_output_discard_all();
Stopping (and dropping) one output buffer:
- // php_ob_end_buffer(1, 0 TSRMLS_CC)
- php_output_end(TSRMLS_C);
+ // php_ob_end_buffer(1, 0)
+ php_output_end();
Stopping (and dropping) all output buffers:
- // php_ob_end_buffers(1, 0 TSRMLS_CC);
- php_output_end_all(TSRMLS_C);
+ // php_ob_end_buffers(1, 0);
+ php_output_end_all();
Retrieving output buffers contents:
- // php_ob_get_buffer(zstring TSRMLS_CC);
- php_output_get_contents(zstring TSRMLS_CC);
+ // php_ob_get_buffer(zstring);
+ php_output_get_contents(zstring);
Retrieving output buffers length:
- // php_ob_get_length(zlength TSRMLS_CC);
- php_output_get_length(zlength TSRMLS_CC);
+ // php_ob_get_length(zlength);
+ php_output_get_length(zlength);
Retrieving output buffering level:
// OG(nesting_level);
- php_output_get_level(TSRMLS_C);
+ php_output_get_level();
Issue a warning because of an output handler conflict:
- // php_ob_init_conflict("to be started handler name", "to be tested if already started handler name" TSRMLS_CC);
- php_output_handler_conflict(new_handler_name, new_handler_name_len, set_handler_name, set_handler_name_len TSRMLS_CC);
+ // php_ob_init_conflict("to be started handler name", "to be tested if already started handler name");
+ php_output_handler_conflict(new_handler_name, new_handler_name_len, set_handler_name, set_handler_name_len);
Registering a conflict checking function, which will be checked prior starting the handler:
// not possible with old API, unless hardcoding into output.c
- php_output_handler_conflict_register(handler_name, handler_name_len, my_php_output_handler_conflict_check_t TSRMLS_CC);
+ php_output_handler_conflict_register(handler_name, handler_name_len, my_php_output_handler_conflict_check_t);
Registering a reverse conflict checking function, which will be checked prior starting the specified foreign handler:
// not possible with old API
- php_output_handler_reverse_conflict_register(foreign_handler_name, foreign_handler_name_len, my_php_output_handler_conflict_check_t TSRMLS_CC);
+ php_output_handler_reverse_conflict_register(foreign_handler_name, foreign_handler_name_len, my_php_output_handler_conflict_check_t);
Facilitating a context from within an output handler callable with ob_start():
// not possible with old API
- php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ, (void *) &custom_ctx_ptr_ptr TSRMLS_CC);
+ php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_GET_OPAQ, (void *) &custom_ctx_ptr_ptr);
Disabling of the output handler by itself:
//not possible with old API
- php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL TSRMLS_CC);
+ php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_DISABLE, NULL);
Marking an output handler immutable by itself because of irreversibility of its operation:
// not possible with old API
- php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL TSRMLS_CC);
+ php_output_handler_hook(PHP_OUTPUT_HANDLER_HOOK_IMMUTABLE, NULL);
Restarting the output handler because of a CLEAN operation:
// not possible with old API
diff --git a/README.PARAMETER_PARSING_API b/README.PARAMETER_PARSING_API
index 097b4978a5..c344817b37 100644
--- a/README.PARAMETER_PARSING_API
+++ b/README.PARAMETER_PARSING_API
@@ -13,8 +13,8 @@ meaningful error messages.
Prototypes
----------
/* Implemented. */
-int zend_parse_parameters(int num_args TSRMLS_DC, char *type_spec, ...);
-int zend_parse_parameters_ex(int flags, int num_args TSRMLS_DC, char *type_spec, ...);
+int zend_parse_parameters(int num_args, char *type_spec, ...);
+int zend_parse_parameters_ex(int flags, int num_args, char *type_spec, ...);
The zend_parse_parameters() function takes the number of parameters
passed to the extension function, the type specifier string, and the
@@ -30,7 +30,7 @@ resources cannot be auto-converted.
PHP 5.5 includes a new function:
-int zend_parse_parameter(int flags, int arg_num TSRMLS_DC, zval **arg, const char *spec, ...);
+int zend_parse_parameter(int flags, int arg_num, zval **arg, const char *spec, ...);
This function behaves like zend_parse_parameters_ex() except that instead of
reading the arguments from the stack, it receives a single zval to convert
@@ -97,11 +97,11 @@ Both mistakes might cause memory corruptions and segfaults:
1)
char *str;
long str_len; /* XXX THIS IS WRONG!! Use size_t instead. */
- zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &str, &str_len)
+ zend_parse_parameters(ZEND_NUM_ARGS(), "s", &str, &str_len)
2)
int num; /* XXX THIS IS WRONG!! Use zend_long instead. */
- zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "l", &num)
+ zend_parse_parameters(ZEND_NUM_ARGS(), "l", &num)
If you're in doubt, use check_parameters.php script to the parameters
and their types (it can be found in ./scripts/dev/ directory of PHP sources):
@@ -116,7 +116,7 @@ zend_long l;
char *s;
size_t s_len;
zval *param;
-if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsz",
+if (zend_parse_parameters(ZEND_NUM_ARGS(), "lsz",
&l, &s, &s_len, &param) == FAILURE) {
return;
}
@@ -126,7 +126,7 @@ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "lsz",
zval *obj;
double d = 0.5;
zend_class_entry *my_ce;
-if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|d",
+if (zend_parse_parameters(ZEND_NUM_ARGS(), "O|d",
&obj, my_ce, &d) == FAILURE) {
return;
}
@@ -136,7 +136,7 @@ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "O|d",
If null is passed for object, obj will be set to NULL. */
zval *obj;
zval *arr;
-if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!a",
+if (zend_parse_parameters(ZEND_NUM_ARGS(), "o!a",
&obj, &arr) == FAILURE) {
return;
}
@@ -144,7 +144,7 @@ if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "o!a",
/* Gets a separated array which can also be null. */
zval *arr;
-if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a/!",
+if (zend_parse_parameters(ZEND_NUM_ARGS(), "a/!",
&arr) == FAILURE) {
return;
}
@@ -161,10 +161,10 @@ char *s;
*/
size_t length;
-if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
+if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(),
"lll", &l1, &l2, &l3) == SUCCESS) {
/* manipulate longs */
-} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS() TSRMLS_CC,
+} else if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(),
"s", &s, &length) == SUCCESS) {
/* manipulate string */
} else {
@@ -180,7 +180,7 @@ int i, num_varargs;
zval *varargs = NULL;
-if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "*", &varargs, &num_varargs) == FAILURE) {
+if (zend_parse_parameters(ZEND_NUM_ARGS(), "*", &varargs, &num_varargs) == FAILURE) {
return;
}
@@ -200,7 +200,7 @@ size_t str_len;
int i, num_varargs;
zval *varargs = NULL;
-if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s+", &str, &str_len, &varargs, &num_varargs) == FAILURE) {
+if (zend_parse_parameters(ZEND_NUM_ARGS(), "s+", &str, &str_len, &varargs, &num_varargs) == FAILURE) {
return;
}
@@ -214,7 +214,7 @@ zval *array;
int i, num_varargs;
zval *varargs = NULL;
-if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "a*l", &array, &varargs, &num_varargs, &num) == FAILURE) {
+if (zend_parse_parameters(ZEND_NUM_ARGS(), "a*l", &array, &varargs, &num_varargs, &num) == FAILURE) {
return;
}
diff --git a/README.REDIST.BINS b/README.REDIST.BINS
index 968c3ec0c8..9779827534 100644
--- a/README.REDIST.BINS
+++ b/README.REDIST.BINS
@@ -5,17 +5,16 @@
5. ext/standard crypt
6. ext/standard crypt's blowfish implementation
7. Sqlite/Sqlite3 ext/sqlite3 ext/sqlite
-8. ext/json/json_parser
-9. ext/standard/rand
-10. ext/standard/scanf
-11. ext/standard/strnatcmp.c
-12. ext/standard/uuencode
-13. libxmlrpc ext/xmlrpc
-14. libzip ext/zip
-15. main/snprintf.c
-16. main/strlcat
-17. main/strlcpy
-18. libgd see ext/gd/libgd/COPYING
+8. ext/standard/rand
+9. ext/standard/scanf
+10. ext/standard/strnatcmp.c
+11. ext/standard/uuencode
+12. libxmlrpc ext/xmlrpc
+13. libzip ext/zip
+14. main/snprintf.c
+15. main/strlcat
+16. main/strlcpy
+17. libgd see ext/gd/libgd/COPYING
5. ext/standard crypt
@@ -104,31 +103,7 @@ a legal notice, here is a blessing:
May you share freely, never taking more than you give.
-8. ext/json/json_parser
-Copyright (c) 2005 JSON.org
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-The Software shall be used for Good, not Evil.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
-
-
-9. ext/standard/rand
+8. ext/standard/rand
The following php_mt_...() functions are based on a C++ class MTRand by
Richard J. Wagner. For more information see the web page at
http://www-personal.engin.umich.edu/~wagnerr/MersenneTwister.html
@@ -181,7 +156,7 @@ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-10. ext/standard/scanf
+9. ext/standard/scanf
scanf.c --
This file contains the base code which implements sscanf and by extension
@@ -227,7 +202,7 @@ authors grant the U.S. Government and others acting in its behalf
permission to use and distribute the software in accordance with the
terms specified in this license.
-11. ext/standard/strnatcmp.c
+10. ext/standard/strnatcmp.c
strnatcmp.c -- Perform 'natural order' comparisons of strings in C.
Copyright (C) 2000 by Martin Pool <mbp@humbug.org.au>
@@ -248,7 +223,7 @@ freely, subject to the following restrictions:
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
-12. ext/standard/uuencode
+11. ext/standard/uuencode
Portions of this code are based on Berkeley's uuencode/uudecode
implementation.
@@ -284,7 +259,7 @@ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
SUCH DAMAGE.
-13. libxmlrpc ext/xmlrpc
+12. libxmlrpc ext/xmlrpc
Copyright 2000 Epinions, Inc.
@@ -308,7 +283,7 @@ OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING
NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH
DAMAGES.
-14. libzip ext/zip
+13. libzip ext/zip
zip.h -- exported declarations.
Copyright (C) 1999-2009 Dieter Baron and Thomas Klausner
@@ -340,7 +315,7 @@ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-15. main/snprintf.c
+14. main/snprintf.c
Copyright (c) 2002, 2006 Todd C. Miller <Todd.Miller@courtesan.com>
Permission to use, copy, modify, and distribute this software for any
@@ -413,8 +388,8 @@ This code is based on, and used with the permission of, the
SIO stdio-replacement strx_* functions by Panos Tsirigotis
<panos@alumni.cs.colorado.edu> for xinetd.
-16. main/strlcat
-17. main/strlcpy
+15. main/strlcat
+16. main/strlcpy
Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
All rights reserved.
diff --git a/README.STREAMS b/README.STREAMS
index 0046e6a754..e95950bde0 100644
--- a/README.STREAMS
+++ b/README.STREAMS
@@ -28,7 +28,7 @@ The main functions are:
PHPAPI size_t php_stream_read(php_stream * stream, char * buf, size_t count);
PHPAPI size_t php_stream_write(php_stream * stream, const char * buf, size_t
count);
-PHPAPI size_t php_stream_printf(php_stream * stream TSRMLS_DC,
+PHPAPI size_t php_stream_printf(php_stream * stream,
const char * fmt, ...);
PHPAPI int php_stream_eof(php_stream * stream);
PHPAPI int php_stream_getc(php_stream * stream);
@@ -47,7 +47,7 @@ Opening Streams
In most cases, you should use this API:
PHPAPI php_stream *php_stream_open_wrapper(const char *path, const char *mode,
- int options, char **opened_path TSRMLS_DC);
+ int options, char **opened_path);
Where:
path is the file or resource to open.
@@ -80,7 +80,7 @@ PHPAPI php_stream *php_stream_fopen_tmpfile(void);
Open a FILE * with tmpfile() and convert into a stream.
PHPAPI php_stream *php_stream_fopen_temporary_file(const char *dir,
- const char *pfx, char **opened_path TSRMLS_DC);
+ const char *pfx, char **opened_path);
Generate a temporary file name and open it.
There are some network enabled relatives in php_network.h:
diff --git a/README.input_filter b/README.input_filter
index 78e2edd2ec..be260013ac 100644
--- a/README.input_filter
+++ b/README.input_filter
@@ -138,7 +138,7 @@ SAPI_INPUT_FILTER_FUNC(my_sapi_input_filter)
strcpy(raw_var, "RAW_");
strlcat(raw_var,var,var_len+5);
- php_register_variable_ex(raw_var, &new_var, array_ptr TSRMLS_DC);
+ php_register_variable_ex(raw_var, &new_var, array_ptr);
php_strip_tags(*val, val_len, NULL, NULL, 0);
@@ -154,7 +154,7 @@ PHP_FUNCTION(my_get_raw)
zval **tmp;
zval *array_ptr = NULL;
- if(zend_parse_parameters(2 TSRMLS_CC, "ls", &arg, &var, &var_len) == FAILURE) {
+ if(zend_parse_parameters(2, "ls", &arg, &var, &var_len) == FAILURE) {
return;
}
diff --git a/Zend/tests/bug69989_1.phpt b/Zend/tests/bug69989_1.phpt
new file mode 100644
index 0000000000..816c55410e
--- /dev/null
+++ b/Zend/tests/bug69989_1.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #69989: Cycle collection for yielded values
+--FILE--
+<?php
+
+function gen() {
+ yield yield;
+}
+$gen = gen();
+$gen->send($gen);
+
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/bug71470.phpt b/Zend/tests/bug71470.phpt
new file mode 100644
index 0000000000..6f8b4f0103
--- /dev/null
+++ b/Zend/tests/bug71470.phpt
@@ -0,0 +1,13 @@
+--TEST--
+Bug #71470: Leaked 1 hashtable iterators
+--FILE--
+<?php
+
+$array = [1, 2, 3];
+foreach ($array as &$v) {
+ die("foo\n");
+}
+
+?>
+--EXPECT--
+foo
diff --git a/Zend/tests/bug71529.phpt b/Zend/tests/bug71529.phpt
new file mode 100644
index 0000000000..5a5e323414
--- /dev/null
+++ b/Zend/tests/bug71529.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Bug #71529: Variable references on array elements don't work when using count
+--FILE--
+<?php
+
+$a = [1];
+$a[] = &$a[out(count($a) - 1)];
+var_dump($a);
+
+function out($what) {
+ var_dump($what);
+ return $what;
+}
+
+?>
+--EXPECT--
+int(0)
+array(2) {
+ [0]=>
+ &int(1)
+ [1]=>
+ &int(1)
+}
diff --git a/Zend/tests/bug71622.phpt b/Zend/tests/bug71622.phpt
new file mode 100644
index 0000000000..3ef0ba80e1
--- /dev/null
+++ b/Zend/tests/bug71622.phpt
@@ -0,0 +1,30 @@
+--TEST--
+Bug #71622 (Strings used in pass-as-reference cannot be used to invoke C::$callable())
+--FILE--
+<?php
+
+function getMethodName(&$methodName) {
+ $methodName = Abc::METHOD_NAME;
+}
+
+class Abc {
+ const METHOD_NAME = "goal";
+
+ private static function goal() {
+ echo "success\n";
+ }
+
+ public static function run() {
+ $method = "foobar";
+ getMethodName($method);
+ var_dump(is_callable("self::$method"));
+ self::$method();
+ }
+}
+
+Abc::run();
+
+?>
+--EXPECT--
+bool(true)
+success
diff --git a/Zend/tests/foreach_017.phpt b/Zend/tests/foreach_017.phpt
index 55eeeb0891..e27b04c934 100644
--- a/Zend/tests/foreach_017.phpt
+++ b/Zend/tests/foreach_017.phpt
@@ -45,7 +45,7 @@ $done = 0;
$a = [0,1,2,3,4];
foreach($a as &$v) {
echo "$v\n";
- if ($done && $v == 3) {
+ if (!$done && $v == 3) {
$done = 1;
array_splice($a, 1, 2, $replacement);
}
diff --git a/Zend/tests/generators/bug71601.phpt b/Zend/tests/generators/bug71601.phpt
new file mode 100644
index 0000000000..e3f21692e7
--- /dev/null
+++ b/Zend/tests/generators/bug71601.phpt
@@ -0,0 +1,40 @@
+--TEST--
+Bug #71601 (finally block not executed after yield from)
+--FILE--
+<?php
+
+function gen1() {
+ try {
+ yield 1;
+ yield 2;
+ return true;
+ } finally {
+ echo "Inner finally\n";
+ }
+}
+
+function gen2() {
+ try {
+ echo "Entered try/catch\n";
+ var_dump(yield from gen1());
+ } finally {
+ echo "Finally\n";
+ }
+}
+
+$generator = gen2();
+
+var_dump($generator->current());
+
+unset($generator);
+
+echo "Done\n";
+
+?>
+--EXPECT--
+Entered try/catch
+int(1)
+Inner finally
+Finally
+Done
+
diff --git a/Zend/tests/generators/dangling_send_target.phpt b/Zend/tests/generators/dangling_send_target.phpt
new file mode 100644
index 0000000000..c62c24a2f5
--- /dev/null
+++ b/Zend/tests/generators/dangling_send_target.phpt
@@ -0,0 +1,22 @@
+--TEST--
+Yield from does not leave a dangling send target
+--FILE--
+<?php
+function gen1() {
+ yield from [yield];
+}
+
+$gen = gen1();
+$gen->send(new stdClass);
+
+function gen2() {
+ $x = yield;
+ yield from [1, 2, 3];
+}
+$gen = gen2();
+$gen->send(new stdClass);
+$gen->send(new stdClass);
+?>
+===DONE===
+--EXPECT--
+===DONE===
diff --git a/Zend/tests/generators/yield_from_by_reference.phpt b/Zend/tests/generators/yield_from_by_reference.phpt
new file mode 100644
index 0000000000..8412a32af5
--- /dev/null
+++ b/Zend/tests/generators/yield_from_by_reference.phpt
@@ -0,0 +1,12 @@
+--TEST--
+Yield from by reference is not supported
+--FILE--
+<?php
+
+function &gen() {
+ yield from [];
+}
+
+?>
+--EXPECTF--
+Fatal error: Cannot use "yield from" inside a by-reference generator in %s on line %d
diff --git a/Zend/zend_API.c b/Zend/zend_API.c
index 91fb09161e..a7d19f9892 100644
--- a/Zend/zend_API.c
+++ b/Zend/zend_API.c
@@ -1226,8 +1226,15 @@ ZEND_API void object_properties_load(zend_object *object, HashTable *properties)
size_t prop_name_len;
if (zend_unmangle_property_name_ex(key, &class_name, &prop_name, &prop_name_len) == SUCCESS) {
zend_string *pname = zend_string_init(prop_name, prop_name_len, 0);
+ zend_class_entry *prev_scope = EG(scope);
+ if (class_name && class_name[0] != '*') {
+ zend_string *cname = zend_string_init(class_name, strlen(class_name), 0);
+ EG(scope) = zend_lookup_class(cname);
+ zend_string_release(cname);
+ }
property_info = zend_get_property_info(object->ce, pname, 1);
zend_string_release(pname);
+ EG(scope) = prev_scope;
} else {
property_info = ZEND_WRONG_PROPERTY_INFO;
}
@@ -1638,7 +1645,7 @@ ZEND_API int array_set_zval_key(HashTable *ht, zval *key, zval *value) /* {{{ */
result = zend_symtable_update(ht, ZSTR_EMPTY_ALLOC(), value);
break;
case IS_RESOURCE:
- zend_error(E_NOTICE, "Resource ID#" ZEND_LONG_FMT " used as offset, casting to integer (%pd)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
+ zend_error(E_NOTICE, "Resource ID#%d used as offset, casting to integer (%d)", Z_RES_HANDLE_P(key), Z_RES_HANDLE_P(key));
result = zend_hash_index_update(ht, Z_RES_HANDLE_P(key), value);
break;
case IS_FALSE:
diff --git a/Zend/zend_alloc.c b/Zend/zend_alloc.c
index cfc277f136..2e0de26378 100644
--- a/Zend/zend_alloc.c
+++ b/Zend/zend_alloc.c
@@ -1353,6 +1353,10 @@ static zend_always_inline void *zend_mm_alloc_heap(zend_mm_heap *heap, size_t si
/* special handling for zero-size allocation */
size = MAX(size, 1);
size = ZEND_MM_ALIGNED_SIZE(size) + ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info));
+ if (UNEXPECTED(size < real_size)) {
+ zend_error_noreturn(E_ERROR, "Possible integer overflow in memory allocation (%zu + %zu)", ZEND_MM_ALIGNED_SIZE(real_size), ZEND_MM_ALIGNED_SIZE(sizeof(zend_mm_debug_info)));
+ return NULL;
+ }
#endif
if (size <= ZEND_MM_MAX_SMALL_SIZE) {
ptr = zend_mm_alloc_small(heap, size, ZEND_MM_SMALL_SIZE_TO_BIN(size) ZEND_FILE_LINE_RELAY_CC ZEND_FILE_LINE_ORIG_RELAY_CC);
diff --git a/Zend/zend_arena.h b/Zend/zend_arena.h
index 7456610b65..e89e06b1b0 100644
--- a/Zend/zend_arena.h
+++ b/Zend/zend_arena.h
@@ -103,11 +103,12 @@ static zend_always_inline void zend_arena_release(zend_arena **arena_ptr, void *
zend_arena *arena = *arena_ptr;
while (UNEXPECTED((char*)checkpoint > arena->end) ||
- UNEXPECTED((char*)checkpoint < (char*)arena)) {
+ UNEXPECTED((char*)checkpoint <= (char*)arena)) {
zend_arena *prev = arena->prev;
efree(arena);
*arena_ptr = arena = prev;
}
+ ZEND_ASSERT((char*)checkpoint > (char*)arena && (char*)checkpoint <= arena->end);
arena->ptr = (char*)checkpoint;
}
diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c
index 1c30b98a9f..56da2962bd 100644
--- a/Zend/zend_compile.c
+++ b/Zend/zend_compile.c
@@ -2589,14 +2589,17 @@ void zend_compile_assign_ref(znode *result, zend_ast *ast) /* {{{ */
znode target_node, source_node;
zend_op *opline;
+ uint32_t offset;
if (is_this_fetch(target_ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot re-assign $this");
}
zend_ensure_writable_variable(target_ast);
- zend_compile_var(&target_node, target_ast, BP_VAR_W);
- zend_compile_var(&source_node, source_ast, BP_VAR_REF);
+ offset = zend_delayed_compile_begin();
+ zend_delayed_compile_var(&target_node, target_ast, BP_VAR_W);
+ zend_delayed_compile_var(&source_node, source_ast, BP_VAR_REF);
+ zend_delayed_compile_end(offset);
if (source_node.op_type != IS_VAR && zend_is_call(source_ast)) {
zend_error_noreturn(E_COMPILE_ERROR, "Cannot use result of built-in function in write context");
@@ -6291,6 +6294,11 @@ void zend_compile_yield_from(znode *result, zend_ast *ast) /* {{{ */
zend_mark_function_as_generator();
+ if (CG(active_op_array)->fn_flags & ZEND_ACC_RETURN_REFERENCE) {
+ zend_error_noreturn(E_COMPILE_ERROR,
+ "Cannot use \"yield from\" inside a by-reference generator");
+ }
+
zend_compile_expr(&expr_node, expr_ast);
zend_emit_op_tmp(result, ZEND_YIELD_FROM, &expr_node, NULL);
}
diff --git a/Zend/zend_execute_API.c b/Zend/zend_execute_API.c
index 0c6f0377da..56ad4366ff 100644
--- a/Zend/zend_execute_API.c
+++ b/Zend/zend_execute_API.c
@@ -398,7 +398,7 @@ void shutdown_executor(void) /* {{{ */
zend_shutdown_fpu();
#ifdef ZEND_DEBUG
- if (EG(ht_iterators_used)) {
+ if (EG(ht_iterators_used) && !CG(unclean_shutdown)) {
zend_error(E_WARNING, "Leaked %" PRIu32 " hashtable iterators", EG(ht_iterators_used));
}
#endif
diff --git a/Zend/zend_generators.c b/Zend/zend_generators.c
index 4861e45919..646e46b676 100644
--- a/Zend/zend_generators.c
+++ b/Zend/zend_generators.c
@@ -35,11 +35,6 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
{
zend_execute_data *execute_data = generator->execute_data;
- if (generator->send_target) {
- Z_TRY_DELREF_P(generator->send_target);
- generator->send_target = NULL;
- }
-
if (execute_data->opline != execute_data->func->op_array.opcodes) {
/* -1 required because we want the last run opcode, not the next to-be-run one. */
uint32_t op_num = execute_data->opline - execute_data->func->op_array.opcodes - 1;
@@ -65,11 +60,6 @@ static void zend_generator_cleanup_unfinished_execution(zend_generator *generato
ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished_execution) /* {{{ */
{
- if (UNEXPECTED(Z_TYPE(generator->values) != IS_UNDEF)) {
- zval_ptr_dtor(&generator->values);
- ZVAL_UNDEF(&generator->values);
- }
-
if (EXPECTED(generator->execute_data)) {
zend_execute_data *execute_data = generator->execute_data;
@@ -109,6 +99,8 @@ ZEND_API void zend_generator_close(zend_generator *generator, zend_bool finished
}
/* }}} */
+static zend_generator *zend_generator_get_child(zend_generator_node *node, zend_generator *leaf);
+
static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
{
zend_generator *generator = (zend_generator*) object;
@@ -116,6 +108,22 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
uint32_t op_num, finally_op_num, finally_op_end;
int i;
+ /* leave yield from mode to properly allow finally execution */
+ if (UNEXPECTED(Z_TYPE(generator->values) != IS_UNDEF)) {
+ zval_ptr_dtor(&generator->values);
+ ZVAL_UNDEF(&generator->values);
+ }
+
+ if (EXPECTED(generator->node.children == 0)) {
+ zend_generator *root = generator->node.ptr.root, *next;
+ while (UNEXPECTED(root != generator)) {
+ next = zend_generator_get_child(&root->node, generator);
+ OBJ_RELEASE(&root->std);
+ root = next;
+ }
+ generator->node.parent = NULL;
+ }
+
if (EXPECTED(!ex) || EXPECTED(!(ex->func->op_array.fn_flags & ZEND_ACC_HAS_FINALLY_BLOCK))) {
return;
}
@@ -156,8 +164,6 @@ static void zend_generator_dtor_storage(zend_object *object) /* {{{ */
}
/* }}} */
-static zend_generator *zend_generator_get_child(zend_generator_node *node, zend_generator *leaf);
-
static void zend_generator_free_storage(zend_object *object) /* {{{ */
{
zend_generator *generator = (zend_generator*) object;
@@ -181,15 +187,15 @@ static void zend_generator_free_storage(zend_object *object) /* {{{ */
if (generator->iterator) {
zend_iterator_dtor(generator->iterator);
}
+}
+/* }}} */
- if (EXPECTED(generator->node.children == 0)) {
- zend_generator *root = generator->node.ptr.root, *next;
- while (UNEXPECTED(root != generator)) {
- next = zend_generator_get_child(&root->node, generator);
- OBJ_RELEASE(&root->std);
- root = next;
- }
- }
+static HashTable *zend_generator_get_gc(zval *object, zval **table, int *n) /* {{{ */
+{
+ zend_generator *generator = (zend_generator*) Z_OBJ_P(object);
+ *table = &generator->value;
+ *n = 3;
+ return NULL;
}
/* }}} */
@@ -873,7 +879,6 @@ ZEND_METHOD(Generator, send)
root = zend_generator_get_current(generator);
/* Put sent value in the target VAR slot, if it is used */
if (root->send_target) {
- Z_TRY_DELREF_P(root->send_target);
ZVAL_COPY(root->send_target, value);
}
@@ -1128,6 +1133,7 @@ void zend_register_generator_ce(void) /* {{{ */
memcpy(&zend_generator_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers));
zend_generator_handlers.free_obj = zend_generator_free_storage;
zend_generator_handlers.dtor_obj = zend_generator_dtor_storage;
+ zend_generator_handlers.get_gc = zend_generator_get_gc;
zend_generator_handlers.clone_obj = NULL;
zend_generator_handlers.get_constructor = zend_generator_get_constructor;
diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h
index 11cd2416bf..23aa3f3afd 100644
--- a/Zend/zend_vm_def.h
+++ b/Zend/zend_vm_def.h
@@ -2944,7 +2944,7 @@ ZEND_VM_HANDLER(112, ZEND_INIT_METHOD_CALL, CONST|TMPVAR|UNUSED|CV, CONST|TMPVAR
}
}
if (OP1_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
FREE_OP2();
HANDLE_EXCEPTION();
@@ -3053,15 +3053,22 @@ ZEND_VM_HANDLER(113, ZEND_INIT_STATIC_METHOD_CALL, CONST|VAR, CONST|TMPVAR|UNUSE
function_name = GET_OP2_ZVAL_PTR_UNDEF(BP_VAR_R);
if (OP2_TYPE != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
- if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if (OP2_TYPE & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) {
+ function_name = Z_REFVAL_P(function_name);
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ break;
+ }
+ } else if (OP2_TYPE == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
}
- }
- zend_throw_error(NULL, "Function name must be a string");
- FREE_OP2();
- HANDLE_EXCEPTION();
+ zend_throw_error(NULL, "Function name must be a string");
+ FREE_OP2();
+ HANDLE_EXCEPTION();
+ } while (0);
}
}
@@ -7316,7 +7323,7 @@ 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 (OP1_TYPE != IS_CONST) {
+ if (OP1_TYPE == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -7503,6 +7510,9 @@ ZEND_VM_HANDLER(142, ZEND_YIELD_FROM, CONST|TMP|VAR|CV, ANY)
ZVAL_NULL(EX_VAR(opline->result.var));
}
+ /* This generator has no send target (though the generator we delegate to might have one) */
+ generator->send_target = NULL;
+
/* We increment to the next op, so we are at the correct position when the
* generator is resumed. */
ZEND_VM_INC_OPCODE();
diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h
index 6f4406967c..e181246ede 100644
--- a/Zend/zend_vm_execute.h
+++ b/Zend/zend_vm_execute.h
@@ -4183,6 +4183,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CONST_HANDLER(
ZVAL_NULL(EX_VAR(opline->result.var));
}
+ /* This generator has no send target (though the generator we delegate to might have one) */
+ generator->send_target = NULL;
+
/* We increment to the next op, so we are at the correct position when the
* generator is resumed. */
ZEND_VM_INC_OPCODE();
@@ -5537,7 +5540,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CO
}
}
if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
@@ -5644,15 +5647,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
function_name = EX_CONSTANT(opline->op2);
if (IS_CONST != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if (IS_CONST & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) {
+ function_name = Z_REFVAL_P(function_name);
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ break;
+ }
+ } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
}
- }
- zend_throw_error(NULL, "Function name must be a string");
+ zend_throw_error(NULL, "Function name must be a string");
- HANDLE_EXCEPTION();
+ HANDLE_EXCEPTION();
+ } while (0);
}
}
@@ -6529,7 +6539,7 @@ 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 (IS_CONST != IS_CONST) {
+ if (IS_CONST == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -6706,7 +6716,7 @@ 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 (IS_CONST != IS_CONST) {
+ if (IS_CONST == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -7248,7 +7258,7 @@ 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 (IS_CONST != IS_CONST) {
+ if (IS_CONST == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -7625,15 +7635,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
function_name = NULL;
if (IS_UNUSED != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
- if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if (IS_UNUSED & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) {
+ function_name = Z_REFVAL_P(function_name);
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ break;
+ }
+ } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
}
- }
- zend_throw_error(NULL, "Function name must be a string");
+ zend_throw_error(NULL, "Function name must be a string");
- HANDLE_EXCEPTION();
+ HANDLE_EXCEPTION();
+ } while (0);
}
}
@@ -8139,7 +8156,7 @@ 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 (IS_CONST != IS_CONST) {
+ if (IS_CONST == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -9261,7 +9278,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_CV
}
}
if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
@@ -9368,15 +9385,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
if (IS_CV != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if (IS_CV & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) {
+ function_name = Z_REFVAL_P(function_name);
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ break;
+ }
+ } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
}
- }
- zend_throw_error(NULL, "Function name must be a string");
+ zend_throw_error(NULL, "Function name must be a string");
- HANDLE_EXCEPTION();
+ HANDLE_EXCEPTION();
+ } while (0);
}
}
@@ -9980,7 +10004,7 @@ 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 (IS_CONST != IS_CONST) {
+ if (IS_CONST == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -11068,7 +11092,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CONST_TM
}
}
if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor_nogc(free_op2);
HANDLE_EXCEPTION();
@@ -11176,15 +11200,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_C
function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) {
+ function_name = Z_REFVAL_P(function_name);
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ break;
+ }
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
}
- }
- zend_throw_error(NULL, "Function name must be a string");
- zval_ptr_dtor_nogc(free_op2);
- HANDLE_EXCEPTION();
+ zend_throw_error(NULL, "Function name must be a string");
+ zval_ptr_dtor_nogc(free_op2);
+ HANDLE_EXCEPTION();
+ } while (0);
}
}
@@ -12517,6 +12548,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_TMP_HANDLER(ZE
ZVAL_NULL(EX_VAR(opline->result.var));
}
+ /* This generator has no send target (though the generator we delegate to might have one) */
+ generator->send_target = NULL;
+
/* We increment to the next op, so we are at the correct position when the
* generator is resumed. */
ZEND_VM_INC_OPCODE();
@@ -13006,7 +13040,7 @@ 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 (IS_TMP_VAR != IS_CONST) {
+ if (IS_TMP_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -13183,7 +13217,7 @@ 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 (IS_TMP_VAR != IS_CONST) {
+ if (IS_TMP_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -13360,7 +13394,7 @@ 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 (IS_TMP_VAR != IS_CONST) {
+ if (IS_TMP_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -13730,7 +13764,7 @@ 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 (IS_TMP_VAR != IS_CONST) {
+ if (IS_TMP_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -14279,7 +14313,7 @@ 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 (IS_TMP_VAR != IS_CONST) {
+ if (IS_TMP_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -16335,6 +16369,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_VAR_HANDLER(ZE
ZVAL_NULL(EX_VAR(opline->result.var));
}
+ /* This generator has no send target (though the generator we delegate to might have one) */
+ generator->send_target = NULL;
+
/* We increment to the next op, so we are at the correct position when the
* generator is resumed. */
ZEND_VM_INC_OPCODE();
@@ -17507,15 +17544,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
function_name = EX_CONSTANT(opline->op2);
if (IS_CONST != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
- if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if (IS_CONST & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) {
+ function_name = Z_REFVAL_P(function_name);
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ break;
+ }
+ } else if (IS_CONST == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
}
- }
- zend_throw_error(NULL, "Function name must be a string");
+ zend_throw_error(NULL, "Function name must be a string");
- HANDLE_EXCEPTION();
+ HANDLE_EXCEPTION();
+ } while (0);
}
}
@@ -18010,7 +18054,7 @@ 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 (IS_VAR != IS_CONST) {
+ if (IS_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -18216,7 +18260,7 @@ 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 (IS_VAR != IS_CONST) {
+ if (IS_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -18482,7 +18526,7 @@ 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 (IS_VAR != IS_CONST) {
+ if (IS_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -19135,15 +19179,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
function_name = NULL;
if (IS_UNUSED != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
- if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if (IS_UNUSED & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) {
+ function_name = Z_REFVAL_P(function_name);
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ break;
+ }
+ } else if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
}
- }
- zend_throw_error(NULL, "Function name must be a string");
+ zend_throw_error(NULL, "Function name must be a string");
- HANDLE_EXCEPTION();
+ HANDLE_EXCEPTION();
+ } while (0);
}
}
@@ -19464,7 +19515,7 @@ 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 (IS_VAR != IS_CONST) {
+ if (IS_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -20756,15 +20807,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
function_name = _get_zval_ptr_cv_undef(execute_data, opline->op2.var);
if (IS_CV != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
- if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if (IS_CV & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) {
+ function_name = Z_REFVAL_P(function_name);
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ break;
+ }
+ } else if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
}
- }
- zend_throw_error(NULL, "Function name must be a string");
+ zend_throw_error(NULL, "Function name must be a string");
- HANDLE_EXCEPTION();
+ HANDLE_EXCEPTION();
+ } while (0);
}
}
@@ -21152,7 +21210,7 @@ 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 (IS_VAR != IS_CONST) {
+ if (IS_VAR == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -22326,15 +22384,22 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_STATIC_METHOD_CALL_SPEC_V
function_name = _get_zval_ptr_var(opline->op2.var, execute_data, &free_op2);
if ((IS_TMP_VAR|IS_VAR) != IS_CONST) {
if (UNEXPECTED(Z_TYPE_P(function_name) != IS_STRING)) {
- if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
- GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
- if (UNEXPECTED(EG(exception) != NULL)) {
- HANDLE_EXCEPTION();
+ do {
+ if ((IS_TMP_VAR|IS_VAR) & (IS_VAR|IS_CV) && Z_ISREF_P(function_name)) {
+ function_name = Z_REFVAL_P(function_name);
+ if (EXPECTED(Z_TYPE_P(function_name) == IS_STRING)) {
+ break;
+ }
+ } else if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(function_name) == IS_UNDEF)) {
+ GET_OP2_UNDEF_CV(function_name, BP_VAR_R);
+ if (UNEXPECTED(EG(exception) != NULL)) {
+ HANDLE_EXCEPTION();
+ }
}
- }
- zend_throw_error(NULL, "Function name must be a string");
- zval_ptr_dtor_nogc(free_op2);
- HANDLE_EXCEPTION();
+ zend_throw_error(NULL, "Function name must be a string");
+ zval_ptr_dtor_nogc(free_op2);
+ HANDLE_EXCEPTION();
+ } while (0);
}
}
@@ -23727,7 +23792,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
}
}
if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
@@ -24287,7 +24352,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CONST_HANDLE
value = NULL;
ZVAL_COPY_VALUE(&generator->value, value);
- if (IS_UNUSED != IS_CONST) {
+ if (IS_UNUSED == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -24428,7 +24493,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_TMP_HANDLER(
value = NULL;
ZVAL_COPY_VALUE(&generator->value, value);
- if (IS_UNUSED != IS_CONST) {
+ if (IS_UNUSED == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -24569,7 +24634,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_VAR_HANDLER(
value = NULL;
ZVAL_COPY_VALUE(&generator->value, value);
- if (IS_UNUSED != IS_CONST) {
+ if (IS_UNUSED == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -25108,7 +25173,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_UNUSED_HANDL
value = NULL;
ZVAL_COPY_VALUE(&generator->value, value);
- if (IS_UNUSED != IS_CONST) {
+ if (IS_UNUSED == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -26142,7 +26207,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_C
}
}
if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
@@ -26595,7 +26660,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_SPEC_UNUSED_CV_HANDLER(Z
value = NULL;
ZVAL_COPY_VALUE(&generator->value, value);
- if (IS_UNUSED != IS_CONST) {
+ if (IS_UNUSED == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -27634,7 +27699,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_UNUSED_T
}
}
if (IS_UNUSED == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor_nogc(free_op2);
HANDLE_EXCEPTION();
@@ -29665,6 +29730,9 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_YIELD_FROM_SPEC_CV_HANDLER(ZEN
ZVAL_NULL(EX_VAR(opline->result.var));
}
+ /* This generator has no send target (though the generator we delegate to might have one) */
+ generator->send_target = NULL;
+
/* We increment to the next op, so we are at the correct position when the
* generator is resumed. */
ZEND_VM_INC_OPCODE();
@@ -31889,7 +31957,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CONST
}
}
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
@@ -32731,7 +32799,7 @@ 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 (IS_CV != IS_CONST) {
+ if (IS_CV == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -33027,7 +33095,7 @@ 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 (IS_CV != IS_CONST) {
+ if (IS_CV == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -33700,7 +33768,7 @@ 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 (IS_CV != IS_CONST) {
+ if (IS_CV == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -34895,7 +34963,7 @@ 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 (IS_CV != IS_CONST) {
+ if (IS_CV == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -36965,7 +37033,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_CV_HA
}
}
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
@@ -37583,7 +37651,7 @@ 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 (IS_CV != IS_CONST) {
+ if (IS_CV == IS_CONST) {
if (UNEXPECTED(Z_OPT_COPYABLE(generator->value))) {
zval_copy_ctor_func(&generator->value);
}
@@ -39537,7 +39605,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_CV_TMPVA
}
}
if (IS_CV == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor_nogc(free_op2);
HANDLE_EXCEPTION();
@@ -41764,7 +41832,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
}
}
if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
@@ -43904,7 +43972,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_C
}
}
if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
HANDLE_EXCEPTION();
@@ -45042,7 +45110,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_FASTCALL ZEND_INIT_METHOD_CALL_SPEC_TMPVAR_T
}
}
if ((IS_TMP_VAR|IS_VAR) == IS_CV && UNEXPECTED(Z_TYPE_P(object) == IS_UNDEF)) {
- GET_OP1_UNDEF_CV(object, BP_VAR_R);
+ object = GET_OP1_UNDEF_CV(object, BP_VAR_R);
if (UNEXPECTED(EG(exception) != NULL)) {
zval_ptr_dtor_nogc(free_op2);
HANDLE_EXCEPTION();
diff --git a/configure.in b/configure.in
index 906534f224..11dca36755 100644
--- a/configure.in
+++ b/configure.in
@@ -119,7 +119,7 @@ int zend_sprintf(char *buffer, const char *format, ...);
PHP_MAJOR_VERSION=7
PHP_MINOR_VERSION=0
-PHP_RELEASE_VERSION=4
+PHP_RELEASE_VERSION=5
PHP_EXTRA_VERSION="-dev"
PHP_VERSION="$PHP_MAJOR_VERSION.$PHP_MINOR_VERSION.$PHP_RELEASE_VERSION$PHP_EXTRA_VERSION"
PHP_VERSION_ID=`expr [$]PHP_MAJOR_VERSION \* 10000 + [$]PHP_MINOR_VERSION \* 100 + [$]PHP_RELEASE_VERSION`
diff --git a/ext/curl/interface.c b/ext/curl/interface.c
index bd611ce42f..564d9fcb1c 100644
--- a/ext/curl/interface.c
+++ b/ext/curl/interface.c
@@ -157,7 +157,8 @@ static void _php_curl_close(zend_resource *rsrc);
#define CAAL(s, v) add_assoc_long_ex(return_value, s, sizeof(s) - 1, (zend_long) v);
#define CAAD(s, v) add_assoc_double_ex(return_value, s, sizeof(s) - 1, (double) v);
#define CAAS(s, v) add_assoc_string_ex(return_value, s, sizeof(s) - 1, (char *) (v ? v : ""));
-#define CAASTR(s, v) add_assoc_str_ex(return_value, s, sizeof(s) - 1, v ? v : ZSTR_EMPTY_ALLOC());
+#define CAASTR(s, v) add_assoc_str_ex(return_value, s, sizeof(s) - 1, \
+ v ? zend_string_copy(v) : ZSTR_EMPTY_ALLOC());
#define CAAZ(s, v) add_assoc_zval_ex(return_value, s, sizeof(s) -1 , (zval *) v);
#if defined(PHP_WIN32) || defined(__GNUC__)
@@ -2188,7 +2189,7 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{
#endif
# if defined(ZTS)
if (option == CURLOPT_DNS_USE_GLOBAL_CACHE) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "CURLOPT_DNS_USE_GLOBAL_CACHE cannot be activated when thread safety is enabled");
+ php_error_docref(NULL, E_WARNING, "CURLOPT_DNS_USE_GLOBAL_CACHE cannot be activated when thread safety is enabled");
return 1;
}
# endif
@@ -2475,7 +2476,11 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue) /* {{{
}
} ZEND_HASH_FOREACH_END();
- zend_hash_index_update_ptr(ch->to_free->slist, option, slist);
+ if ((*ch->clone) == 1) {
+ zend_hash_index_update_ptr(ch->to_free->slist, option, slist);
+ } else {
+ zend_hash_next_index_insert_ptr(ch->to_free->slist, slist);
+ }
error = curl_easy_setopt(ch->cp, option, slist);
@@ -3032,7 +3037,7 @@ PHP_FUNCTION(curl_getinfo)
}
#endif
if (ch->header.str) {
- CAASTR("request_header", zend_string_copy(ch->header.str));
+ CAASTR("request_header", ch->header.str);
}
} else {
switch (option) {
diff --git a/ext/curl/tests/bug71523.phpt b/ext/curl/tests/bug71523.phpt
new file mode 100644
index 0000000000..24aa83c620
--- /dev/null
+++ b/ext/curl/tests/bug71523.phpt
@@ -0,0 +1,31 @@
+--TEST--
+Bug #71523 (Copied handle with new option CURLOPT_HTTPHEADER crashes while curl_multi_exec)
+--SKIPIF--
+<?php
+if (!extension_loaded("curl")) {
+ exit("skip curl extension not loaded");
+}
+if (getenv("SKIP_ONLINE_TESTS")) {
+ die("skip online test");
+}
+?>
+--FILE--
+<?php
+
+$base = curl_init('http://www.google.com/');
+curl_setopt($base, CURLOPT_RETURNTRANSFER, true);
+$mh = curl_multi_init();
+
+for ($i = 0; $i < 2; ++$i) {
+ $ch = curl_copy_handle($base);
+ curl_setopt($ch, CURLOPT_HTTPHEADER, ['Foo: Bar']);
+ curl_multi_add_handle($mh, $ch);
+}
+
+do {
+ curl_multi_exec($mh, $active);
+} while ($active);
+?>
+okey
+--EXPECTF--
+okey
diff --git a/ext/date/php_date.c b/ext/date/php_date.c
index 2c548ae6f4..2fe78a0e69 100644
--- a/ext/date/php_date.c
+++ b/ext/date/php_date.c
@@ -3054,6 +3054,7 @@ static int php_date_modify(zval *object, char *modify, size_t modify_len) /* {{{
timelib_update_ts(dateobj->time, NULL);
timelib_update_from_sse(dateobj->time);
dateobj->time->have_relative = 0;
+ memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative));
return 1;
} /* }}} */
diff --git a/ext/date/tests/bug71525.phpt b/ext/date/tests/bug71525.phpt
new file mode 100644
index 0000000000..d0c99e4f84
--- /dev/null
+++ b/ext/date/tests/bug71525.phpt
@@ -0,0 +1,20 @@
+--TEST--
+Bug #71525 (Calls to date_modify will mutate timelib_rel_time, causing date_date_set issues)
+--INI--
+date.timezone=UTC
+--FILE--
+<?php
+$date = new DateTime('2011-12-25 00:00:00');
+$date->modify('first day of next month');
+$date->setDate('2012', '1', '29');
+var_dump($date);
+
+--EXPECTF--
+object(DateTime)#%d (3) {
+ ["date"]=>
+ string(26) "2012-01-29 00:00:00.000000"
+ ["timezone_type"]=>
+ int(3)
+ ["timezone"]=>
+ string(3) "UTC"
+}
diff --git a/ext/iconv/iconv.c b/ext/iconv/iconv.c
index 309258b4c7..4dd6784209 100644
--- a/ext/iconv/iconv.c
+++ b/ext/iconv/iconv.c
@@ -424,9 +424,9 @@ static int php_iconv_output_handler(void **nothing, php_output_context *output_c
char *p = strstr(get_output_encoding(), "//");
if (p) {
- len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%.*s", mimetype_len ? mimetype_len : (size_t) strlen(mimetype), mimetype, (size_t)(p - get_output_encoding()), get_output_encoding());
+ len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%.*s", mimetype_len ? mimetype_len : (int) strlen(mimetype), mimetype, (int) (p - get_output_encoding()), get_output_encoding());
} else {
- len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%s", mimetype_len ? mimetype_len : (size_t) strlen(mimetype), mimetype, get_output_encoding());
+ len = spprintf(&content_type, 0, "Content-Type:%.*s; charset=%s", mimetype_len ? mimetype_len : (int) strlen(mimetype), mimetype, get_output_encoding());
}
if (content_type && SUCCESS == sapi_add_header(content_type, (uint)len, 0)) {
SG(sapi_headers).send_default_content_type = 0;
diff --git a/ext/intl/ERROR.CONVENTIONS b/ext/intl/ERROR.CONVENTIONS
index 41cd14ec06..e053c8fbc7 100644
--- a/ext/intl/ERROR.CONVENTIONS
+++ b/ext/intl/ERROR.CONVENTIONS
@@ -21,9 +21,9 @@ intl.use_exceptions you get more fine-grained information about where the
error occurred).
The internal PHP code can set the global last error with:
-void intl_error_set_code(intl_error* err, UErrorCode err_code TSRMLS_DC);
-void intl_error_set_custom_msg(intl_error* err, char* msg, int copyMsg TSRMLS_DC);
-void intl_error_set(intl_error* err, UErrorCode code, char* msg, int copyMsg TSRMLS_DC);
+void intl_error_set_code(intl_error* err, UErrorCode err_code);
+void intl_error_set_custom_msg(intl_error* err, char* msg, int copyMsg);
+void intl_error_set(intl_error* err, UErrorCode code, char* msg, int copyMsg);
and by passing NULL as the first parameter. The last function is a combination
of the first two. If the message is not a static buffer, copyMsg should be 1.
@@ -44,9 +44,9 @@ typedef struct {
The global error and the object error can be SIMULTANEOUSLY set with these
functions:
-void intl_errors_set_custom_msg(intl_error* err, char* msg, int copyMsg TSRMLS_DC);
-void intl_errors_set_code(intl_error* err, UErrorCode err_code TSRMLS_DC);
-void intl_errors_set(intl_error* err, UErrorCode code, char* msg, int copyMsg TSRMLS_DC);
+void intl_errors_set_custom_msg(intl_error* err, char* msg, int copyMsg);
+void intl_errors_set_code(intl_error* err, UErrorCode err_code);
+void intl_errors_set(intl_error* err, UErrorCode code, char* msg, int copyMsg);
by passing a pointer to the object's intl_error structed as the first parameter.
Node the extra 's' in the functions' names ('errors', not 'error').
@@ -79,8 +79,8 @@ Errors should be lost after a function call. This is different from the way
ICU operates, where functions return immediately if an error is set.
Error resetting can be done with:
-void intl_error_reset(NULL TSRMLS_DC); /* reset global error */
-void intl_errors_reset(intl_error* err TSRMLS_DC ); /* reset global and object error */
+void intl_error_reset(NULL); /* reset global error */
+void intl_errors_reset(intl_error* err ); /* reset global and object error */
In practice, intl_errors_reset() is not used because most classes have also
plain functions mapped to the same internal functions as their instance methods.
@@ -97,10 +97,10 @@ U_CFUNC PHP_FUNCTION(breakiter_set_text)
BREAKITER_METHOD_INIT_VARS; /* macro also resets global error */
object = getThis();
- if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s",
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "s",
&text, &text_len) == FAILURE) {
intl_error_set(NULL, U_ILLEGAL_ARGUMENT_ERROR,
- "breakiter_set_text: bad arguments", 0 TSRMLS_CC);
+ "breakiter_set_text: bad arguments", 0);
RETURN_FALSE;
}
diff --git a/ext/libxml/libxml.c b/ext/libxml/libxml.c
index 5b7aca91d8..24812449ee 100644
--- a/ext/libxml/libxml.c
+++ b/ext/libxml/libxml.c
@@ -383,6 +383,9 @@ static int php_libxml_streams_IO_read(void *context, char *buffer, int len)
static int php_libxml_streams_IO_write(void *context, const char *buffer, int len)
{
+ if (CG(unclean_shutdown)) {
+ return -1;
+ }
return php_stream_write((php_stream*)context, buffer, len);
}
diff --git a/ext/mcrypt/mcrypt.c b/ext/mcrypt/mcrypt.c
index 536edde425..456c40ae71 100644
--- a/ext/mcrypt/mcrypt.c
+++ b/ext/mcrypt/mcrypt.c
@@ -564,7 +564,7 @@ PHP_FUNCTION(mcrypt_generic_init)
memset(iv_s, 0, iv_size + 1);
if (key_len > max_key_size) {
- php_error_docref(NULL, E_WARNING, "Key size too large; supplied length: %d, max: %d", key_len, max_key_size);
+ php_error_docref(NULL, E_WARNING, "Key size too large; supplied length: %zd, max: %d", key_len, max_key_size);
key_size = max_key_size;
} else {
key_size = (int)key_len;
@@ -572,7 +572,7 @@ PHP_FUNCTION(mcrypt_generic_init)
memcpy(key_s, key, key_len);
if (iv_len != iv_size) {
- php_error_docref(NULL, E_WARNING, "Iv size incorrect; supplied length: %d, needed: %d", iv_len, iv_size);
+ php_error_docref(NULL, E_WARNING, "Iv size incorrect; supplied length: %zd, needed: %d", iv_len, iv_size);
if (iv_len > iv_size) {
iv_len = iv_size;
}
diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c
index a91d7b783d..d835dfb9a0 100644
--- a/ext/odbc/php_odbc.c
+++ b/ext/odbc/php_odbc.c
@@ -445,6 +445,9 @@ static void _free_odbc_result(zend_resource *rsrc)
* zend_list_delete(res->conn_ptr->id);
*/
}
+ if (res->param_info) {
+ efree(res->param_info);
+ }
efree(res);
}
}
@@ -1184,6 +1187,7 @@ PHP_FUNCTION(odbc_prepare)
odbc_result *result = NULL;
odbc_connection *conn;
RETCODE rc;
+ int i;
#ifdef HAVE_SQL_EXTENDED_FETCH
SQLUINTEGER scrollopts;
#endif
@@ -1199,6 +1203,7 @@ PHP_FUNCTION(odbc_prepare)
result = (odbc_result *)ecalloc(1, sizeof(odbc_result));
result->numparams = 0;
+ result->param_info = NULL;
rc = PHP_ODBC_SQLALLOCSTMT(conn->hdbc, &(result->stmt));
if (rc == SQL_INVALID_HANDLE) {
@@ -1255,6 +1260,20 @@ PHP_FUNCTION(odbc_prepare)
Z_ADDREF_P(pv_conn);
result->conn_ptr = conn;
result->fetched = 0;
+
+ result->param_info = (odbc_param_info *) safe_emalloc(sizeof(odbc_param_info), result->numparams, 0);
+ for (i=0;i<result->numparams;i++) {
+ rc = SQLDescribeParam(result->stmt, (SQLUSMALLINT)(i+1), &result->param_info[i].sqltype, &result->param_info[i].precision,
+ &result->param_info[i].scale, &result->param_info[i].nullable);
+ if (rc == SQL_ERROR) {
+ odbc_sql_error(result->conn_ptr, result->stmt, "SQLDescribeParameter");
+ SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
+ efree(result->param_info);
+ efree(result);
+ RETURN_FALSE;
+ }
+ }
+
RETURN_RES(zend_register_resource(result, le_result));
}
/* }}} */
@@ -1275,9 +1294,7 @@ PHP_FUNCTION(odbc_execute)
params_t *params = NULL;
char *filename;
unsigned char otype;
- SQLSMALLINT sqltype, ctype, scale;
- SQLSMALLINT nullable;
- SQLULEN precision;
+ SQLSMALLINT ctype;
odbc_result *result;
int numArgs, i, ne;
RETCODE rc;
@@ -1337,22 +1354,10 @@ PHP_FUNCTION(odbc_execute)
RETURN_FALSE;
}
- rc = SQLDescribeParam(result->stmt, (SQLUSMALLINT)i, &sqltype, &precision, &scale, &nullable);
params[i-1].vallen = Z_STRLEN_P(tmp);
params[i-1].fp = -1;
- if (rc == SQL_ERROR) {
- odbc_sql_error(result->conn_ptr, result->stmt, "SQLDescribeParam");
- SQLFreeStmt(result->stmt, SQL_RESET_PARAMS);
- for (i = 0; i < result->numparams; i++) {
- if (params[i].fp != -1) {
- close(params[i].fp);
- }
- }
- efree(params);
- RETURN_FALSE;
- }
- if (IS_SQL_BINARY(sqltype)) {
+ if (IS_SQL_BINARY(result->param_info[i-1].sqltype)) {
ctype = SQL_C_BINARY;
} else {
ctype = SQL_C_CHAR;
@@ -1399,7 +1404,7 @@ PHP_FUNCTION(odbc_execute)
params[i-1].vallen = SQL_LEN_DATA_AT_EXEC(0);
rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT,
- ctype, sqltype, precision, scale,
+ ctype, result->param_info[i-1].sqltype, result->param_info[i-1].precision, result->param_info[i-1].scale,
(void *)(intptr_t)params[i-1].fp, 0,
&params[i-1].vallen);
} else {
@@ -1411,7 +1416,7 @@ PHP_FUNCTION(odbc_execute)
}
rc = SQLBindParameter(result->stmt, (SQLUSMALLINT)i, SQL_PARAM_INPUT,
- ctype, sqltype, precision, scale,
+ ctype, result->param_info[i-1].sqltype, result->param_info[i-1].precision, result->param_info[i-1].scale,
Z_STRVAL_P(tmp), 0,
&params[i-1].vallen);
}
diff --git a/ext/odbc/php_odbc_includes.h b/ext/odbc/php_odbc_includes.h
index dad7ff1c95..fa525ed4ad 100644
--- a/ext/odbc/php_odbc_includes.h
+++ b/ext/odbc/php_odbc_includes.h
@@ -233,6 +233,13 @@ typedef struct odbc_result_value {
SQLLEN coltype;
} odbc_result_value;
+typedef struct odbc_param_info {
+ SQLSMALLINT sqltype;
+ SQLSMALLINT scale;
+ SQLSMALLINT nullable;
+ SQLULEN precision;
+} odbc_param_info;
+
typedef struct odbc_result {
ODBC_SQL_STMT_T stmt;
odbc_result_value *values;
@@ -244,6 +251,7 @@ typedef struct odbc_result {
zend_long longreadlen;
int binmode;
int fetched;
+ odbc_param_info * param_info;
odbc_connection *conn_ptr;
} odbc_result;
diff --git a/ext/odbc/tests/bug47803.phpt b/ext/odbc/tests/bug47803.phpt
new file mode 100644
index 0000000000..9a2600dd18
--- /dev/null
+++ b/ext/odbc/tests/bug47803.phpt
@@ -0,0 +1,185 @@
+--TEST--
+Bug #47803 Executing prepared statements is succesfull only for the first two statements
+--SKIPIF--
+<?php include 'skipif.inc'; ?>
+--FILE--
+<?php
+
+include dirname(__FILE__) . "/config.inc";
+
+$create_table = "CREATE TABLE FOO(
+ [PAR_ID] [int] NOT NULL,
+ [PAR_INT] [int] NULL,
+ [PAR_CHR] [varchar](500) NULL
+)";
+
+$inserts = "INSERT INTO FOO
+ ([PAR_ID]
+ ,[PAR_INT]
+ ,[PAR_CHR])
+ VALUES
+ (1,14,''),
+ (2,30,''),
+ (3,7,''),
+ (4,7,''),
+ (5,0,''),
+ (6,0,''),
+ (7,20130901,''),
+ (8,20140201,''),
+ (9,20140201,''),
+ (10,20140620,''),
+ (11,221,'')";
+
+
+date_default_timezone_set('Europe/Warsaw');
+
+$link = odbc_connect($dsn, $user, $pass);
+
+odbc_exec($link, 'CREATE DATABASE odbcTEST');
+odbc_exec($link, $create_table);
+odbc_exec($link, $inserts);
+
+$upd_params = array(
+ array('id'=>1, 'name'=>'test 1'),
+ array('id'=>2, 'name'=>'test 2'),
+ array('id'=>3, 'name'=>'test 3'),
+ array('id'=>4, 'name'=>'test 4'),
+ array('id'=>5, 'name'=>'test 5'),
+ array('id'=>10, 'name'=>'test 10'),
+ array('id'=>9, 'name'=>'test 9'),
+ array('id'=>8, 'name'=>'test 8'),
+ array('id'=>7, 'name'=>'test 7'),
+ array('id'=>6, 'name'=>'test 6'),
+);
+$sql = "UPDATE FOO
+ SET [PAR_CHR] = ?
+ WHERE [PAR_ID] = ?";
+$result = odbc_prepare($link, $sql);
+if (!$result) {
+ print ('[sql] prep: '.$sql);
+ goto out;
+}
+foreach ($upd_params as &$k) {
+ if(!odbc_execute($result, array($k['name'], $k['id']))) {
+ print ('[sql] exec: '."array({$k['name']}, {$k['id']})");
+ goto out;
+ }
+}
+odbc_free_result($result);
+
+$sql = "SELECT * FROM FOO WHERE [PAR_ID] = ?";
+$result = odbc_prepare($link, $sql);
+if (!$result) {
+ print ('[sql] prep: '.$sql);
+ goto out;
+}
+foreach ($upd_params as $k) {
+ if(!odbc_execute($result, array($k['id']))) {
+ print ('[sql] exec: '."array({$k['id']})");
+ goto out;
+ }
+ while (($r = odbc_fetch_array($result)) !== false) {
+ var_dump($r);
+ }
+}
+
+out:
+if ($result) odbc_free_result($result);
+odbc_close($link);
+
+?>
+==DONE==
+--EXPECT--
+array(3) {
+ ["PAR_ID"]=>
+ string(1) "1"
+ ["PAR_INT"]=>
+ string(2) "14"
+ ["PAR_CHR"]=>
+ string(6) "test 1"
+}
+array(3) {
+ ["PAR_ID"]=>
+ string(1) "2"
+ ["PAR_INT"]=>
+ string(2) "30"
+ ["PAR_CHR"]=>
+ string(6) "test 2"
+}
+array(3) {
+ ["PAR_ID"]=>
+ string(1) "3"
+ ["PAR_INT"]=>
+ string(1) "7"
+ ["PAR_CHR"]=>
+ string(6) "test 3"
+}
+array(3) {
+ ["PAR_ID"]=>
+ string(1) "4"
+ ["PAR_INT"]=>
+ string(1) "7"
+ ["PAR_CHR"]=>
+ string(6) "test 4"
+}
+array(3) {
+ ["PAR_ID"]=>
+ string(1) "5"
+ ["PAR_INT"]=>
+ string(1) "0"
+ ["PAR_CHR"]=>
+ string(6) "test 5"
+}
+array(3) {
+ ["PAR_ID"]=>
+ string(2) "10"
+ ["PAR_INT"]=>
+ string(8) "20140620"
+ ["PAR_CHR"]=>
+ string(7) "test 10"
+}
+array(3) {
+ ["PAR_ID"]=>
+ string(1) "9"
+ ["PAR_INT"]=>
+ string(8) "20140201"
+ ["PAR_CHR"]=>
+ string(6) "test 9"
+}
+array(3) {
+ ["PAR_ID"]=>
+ string(1) "8"
+ ["PAR_INT"]=>
+ string(8) "20140201"
+ ["PAR_CHR"]=>
+ string(6) "test 8"
+}
+array(3) {
+ ["PAR_ID"]=>
+ string(1) "7"
+ ["PAR_INT"]=>
+ string(8) "20130901"
+ ["PAR_CHR"]=>
+ string(6) "test 7"
+}
+array(3) {
+ ["PAR_ID"]=>
+ string(1) "7"
+ ["PAR_INT"]=>
+ string(8) "20130901"
+ ["PAR_CHR"]=>
+ string(6) "test 7"
+}
+==DONE==
+--CLEAN--
+<?php
+include 'config.inc';
+
+$conn = odbc_connect($dsn, $user, $pass);
+
+odbc_exec($conn, 'DROP TABLE FOO');
+odbc_exec($conn, 'DROP DATABASE odbcTEST');
+
+odbc_close($conn);
+
+?>
diff --git a/ext/odbc/tests/bug71171.phpt b/ext/odbc/tests/bug71171.phpt
new file mode 100644
index 0000000000..94cfb4d0e8
--- /dev/null
+++ b/ext/odbc/tests/bug71171.phpt
@@ -0,0 +1,43 @@
+--TEST--
+Bug #71171 odbc_fetch_array generates SIGFAULT, variant 0
+--SKIPIF--
+<?php include 'skipif.inc'; ?>
+--FILE--
+<?php
+
+include 'config.inc';
+
+$conn = odbc_connect($dsn, $user, $pass);
+
+@odbc_exec($conn, 'CREATE DATABASE odbcTEST');
+
+odbc_exec($conn, 'CREATE TABLE FOO (ID INT, VARCHAR_COL NVARCHAR(40))');
+
+odbc_exec($conn, "INSERT INTO FOO(ID, VARCHAR_COL) VALUES (1, '" . chr(0x81) . "')");
+
+$res = odbc_exec($conn,"SELECT ID FROM FOO WHERE VARCHAR_COL = '" . chr(0x81) . "'");
+if ($res) {
+ while($record = odbc_fetch_array($res)) var_dump($record);
+}
+
+odbc_close($conn);
+?>
+==DONE==
+--EXPECT--
+array(1) {
+ ["ID"]=>
+ string(1) "1"
+}
+==DONE==
+--CLEAN--
+<?php
+include 'config.inc';
+
+$conn = odbc_connect($dsn, $user, $pass);
+
+odbc_exec($conn, 'DROP TABLE FOO');
+odbc_exec($conn, 'DROP DATABASE odbcTEST');
+
+odbc_close($conn);
+
+?>
diff --git a/ext/odbc/tests/config.inc b/ext/odbc/tests/config.inc
index a88eea4ed0..dcc4cbb3bf 100644
--- a/ext/odbc/tests/config.inc
+++ b/ext/odbc/tests/config.inc
@@ -3,6 +3,17 @@
putenv('ODBCINI=/etc/odbc.ini');
putenv('ODBCSYSINI=/etc');
-$dsn = 'myodbc3';
-$user = 'root';
-$pass = '';
+$dsn = getenv("ODBC_TEST_DSN");
+$user = getenv("ODBC_TEST_USER");
+$pass = getenv("ODBC_TEST_PASS");
+
+if (false === $dsn) {
+ $dsn = 'myodbc3';
+}
+if (false === $user) {
+ $user = 'root';
+}
+if (false == $pass) {
+ $pass = '';
+}
+
diff --git a/ext/opcache/Optimizer/block_pass.c b/ext/opcache/Optimizer/block_pass.c
index f4d65a0256..15e6511a76 100644
--- a/ext/opcache/Optimizer/block_pass.c
+++ b/ext/opcache/Optimizer/block_pass.c
@@ -925,10 +925,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
memcpy(Z_STRVAL(ZEND_OP1_LITERAL(last_op)) + old_len, Z_STRVAL(ZEND_OP1_LITERAL(opline)), Z_STRLEN(ZEND_OP1_LITERAL(opline)));
Z_STRVAL(ZEND_OP1_LITERAL(last_op))[l] = '\0';
zval_dtor(&ZEND_OP1_LITERAL(opline));
- Z_STR(ZEND_OP1_LITERAL(opline)) = zend_new_interned_string(Z_STR(ZEND_OP1_LITERAL(last_op)));
- if (!Z_REFCOUNTED(ZEND_OP1_LITERAL(opline))) {
- Z_TYPE_FLAGS(ZEND_OP1_LITERAL(opline)) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
- }
+ ZVAL_STR(&ZEND_OP1_LITERAL(opline), zend_new_interned_string(Z_STR(ZEND_OP1_LITERAL(last_op))));
ZVAL_NULL(&ZEND_OP1_LITERAL(last_op));
MAKE_NOP(last_op);
} else if ((opline->opcode == ZEND_CONCAT) &&
@@ -965,10 +962,7 @@ static void zend_optimize_block(zend_code_block *block, zend_op_array *op_array,
memcpy(Z_STRVAL(ZEND_OP2_LITERAL(src)) + old_len, Z_STRVAL(ZEND_OP2_LITERAL(opline)), Z_STRLEN(ZEND_OP2_LITERAL(opline)));
Z_STRVAL(ZEND_OP2_LITERAL(src))[l] = '\0';
zend_string_release(Z_STR(ZEND_OP2_LITERAL(opline)));
- Z_STR(ZEND_OP2_LITERAL(opline)) = zend_new_interned_string(Z_STR(ZEND_OP2_LITERAL(src)));
- if (!Z_REFCOUNTED(ZEND_OP2_LITERAL(opline))) {
- Z_TYPE_FLAGS(ZEND_OP2_LITERAL(opline)) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
- }
+ ZVAL_STR(&ZEND_OP2_LITERAL(opline), zend_new_interned_string(Z_STR(ZEND_OP2_LITERAL(src))));
ZVAL_NULL(&ZEND_OP2_LITERAL(src));
MAKE_NOP(src);
} else if ((opline->opcode == ZEND_ADD ||
diff --git a/ext/opcache/ZendAccelerator.c b/ext/opcache/ZendAccelerator.c
index 2440a56582..48b8d6a682 100644
--- a/ext/opcache/ZendAccelerator.c
+++ b/ext/opcache/ZendAccelerator.c
@@ -220,6 +220,104 @@ static ZEND_INI_MH(accel_include_path_on_modify)
return ret;
}
+static inline void accel_restart_enter(void)
+{
+#ifdef ZEND_WIN32
+ INCREMENT(restart_in);
+#else
+ static const FLOCK_STRUCTURE(restart_in_progress, F_WRLCK, SEEK_SET, 2, 1);
+
+ if (fcntl(lock_file, F_SETLK, &restart_in_progress) == -1) {
+ zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(+1): %s (%d)", strerror(errno), errno);
+ }
+#endif
+ ZCSG(restart_in_progress) = 1;
+}
+
+static inline void accel_restart_leave(void)
+{
+#ifdef ZEND_WIN32
+ ZCSG(restart_in_progress) = 0;
+ DECREMENT(restart_in);
+#else
+ static const FLOCK_STRUCTURE(restart_finished, F_UNLCK, SEEK_SET, 2, 1);
+
+ ZCSG(restart_in_progress) = 0;
+ if (fcntl(lock_file, F_SETLK, &restart_finished) == -1) {
+ zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(-1): %s (%d)", strerror(errno), errno);
+ }
+#endif
+}
+
+static inline int accel_restart_is_active(void)
+{
+ if (ZCSG(restart_in_progress)) {
+#ifndef ZEND_WIN32
+ FLOCK_STRUCTURE(restart_check, F_WRLCK, SEEK_SET, 2, 1);
+
+ if (fcntl(lock_file, F_GETLK, &restart_check) == -1) {
+ zend_accel_error(ACCEL_LOG_DEBUG, "RestartC: %s (%d)", strerror(errno), errno);
+ return FAILURE;
+ }
+ if (restart_check.l_type == F_UNLCK) {
+ ZCSG(restart_in_progress) = 0;
+ return 0;
+ } else {
+ return 1;
+ }
+#else
+ return LOCKVAL(restart_in) != 0;
+#endif
+ }
+ return 0;
+}
+
+/* Creates a read lock for SHM access */
+static inline int accel_activate_add(void)
+{
+#ifdef ZEND_WIN32
+ INCREMENT(mem_usage);
+#else
+ static const FLOCK_STRUCTURE(mem_usage_lock, F_RDLCK, SEEK_SET, 1, 1);
+
+ if (fcntl(lock_file, F_SETLK, &mem_usage_lock) == -1) {
+ zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(+1): %s (%d)", strerror(errno), errno);
+ return FAILURE;
+ }
+#endif
+ return SUCCESS;
+}
+
+/* Releases a lock for SHM access */
+static inline void accel_deactivate_sub(void)
+{
+#ifdef ZEND_WIN32
+ if (ZCG(counted)) {
+ DECREMENT(mem_usage);
+ ZCG(counted) = 0;
+ }
+#else
+ static const FLOCK_STRUCTURE(mem_usage_unlock, F_UNLCK, SEEK_SET, 1, 1);
+
+ if (fcntl(lock_file, F_SETLK, &mem_usage_unlock) == -1) {
+ zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(-1): %s (%d)", strerror(errno), errno);
+ }
+#endif
+}
+
+static inline void accel_unlock_all(void)
+{
+#ifdef ZEND_WIN32
+ accel_deactivate_sub();
+#else
+ static const FLOCK_STRUCTURE(mem_usage_unlock_all, F_UNLCK, SEEK_SET, 0, 0);
+
+ if (fcntl(lock_file, F_SETLK, &mem_usage_unlock_all) == -1) {
+ zend_accel_error(ACCEL_LOG_DEBUG, "UnlockAll: %s (%d)", strerror(errno), errno);
+ }
+#endif
+}
+
/* Interned strings support */
static zend_string *(*orig_new_interned_string)(zend_string *str);
static void (*orig_interned_strings_snapshot)(void);
@@ -291,6 +389,12 @@ static zend_string *accel_find_interned_string(zend_string *str)
/* this is already an interned string */
return str;
}
+ if (!ZCG(counted)) {
+ if (accel_activate_add() == FAILURE) {
+ return str;
+ }
+ ZCG(counted) = 1;
+ }
h = zend_string_hash_val(str);
nIndex = h | ZCSG(interned_strings).nTableMask;
@@ -492,102 +596,6 @@ static void accel_use_shm_interned_strings(void)
}
#endif
-static inline void accel_restart_enter(void)
-{
-#ifdef ZEND_WIN32
- INCREMENT(restart_in);
-#else
- static const FLOCK_STRUCTURE(restart_in_progress, F_WRLCK, SEEK_SET, 2, 1);
-
- if (fcntl(lock_file, F_SETLK, &restart_in_progress) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(+1): %s (%d)", strerror(errno), errno);
- }
-#endif
- ZCSG(restart_in_progress) = 1;
-}
-
-static inline void accel_restart_leave(void)
-{
-#ifdef ZEND_WIN32
- ZCSG(restart_in_progress) = 0;
- DECREMENT(restart_in);
-#else
- static const FLOCK_STRUCTURE(restart_finished, F_UNLCK, SEEK_SET, 2, 1);
-
- ZCSG(restart_in_progress) = 0;
- if (fcntl(lock_file, F_SETLK, &restart_finished) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "RestartC(-1): %s (%d)", strerror(errno), errno);
- }
-#endif
-}
-
-static inline int accel_restart_is_active(void)
-{
- if (ZCSG(restart_in_progress)) {
-#ifndef ZEND_WIN32
- FLOCK_STRUCTURE(restart_check, F_WRLCK, SEEK_SET, 2, 1);
-
- if (fcntl(lock_file, F_GETLK, &restart_check) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "RestartC: %s (%d)", strerror(errno), errno);
- return FAILURE;
- }
- if (restart_check.l_type == F_UNLCK) {
- ZCSG(restart_in_progress) = 0;
- return 0;
- } else {
- return 1;
- }
-#else
- return LOCKVAL(restart_in) != 0;
-#endif
- }
- return 0;
-}
-
-/* Creates a read lock for SHM access */
-static inline void accel_activate_add(void)
-{
-#ifdef ZEND_WIN32
- INCREMENT(mem_usage);
-#else
- static const FLOCK_STRUCTURE(mem_usage_lock, F_RDLCK, SEEK_SET, 1, 1);
-
- if (fcntl(lock_file, F_SETLK, &mem_usage_lock) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(+1): %s (%d)", strerror(errno), errno);
- }
-#endif
-}
-
-/* Releases a lock for SHM access */
-static inline void accel_deactivate_sub(void)
-{
-#ifdef ZEND_WIN32
- if (ZCG(counted)) {
- DECREMENT(mem_usage);
- ZCG(counted) = 0;
- }
-#else
- static const FLOCK_STRUCTURE(mem_usage_unlock, F_UNLCK, SEEK_SET, 1, 1);
-
- if (fcntl(lock_file, F_SETLK, &mem_usage_unlock) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "UpdateC(-1): %s (%d)", strerror(errno), errno);
- }
-#endif
-}
-
-static inline void accel_unlock_all(void)
-{
-#ifdef ZEND_WIN32
- accel_deactivate_sub();
-#else
- static const FLOCK_STRUCTURE(mem_usage_unlock_all, F_UNLCK, SEEK_SET, 0, 0);
-
- if (fcntl(lock_file, F_SETLK, &mem_usage_unlock_all) == -1) {
- zend_accel_error(ACCEL_LOG_DEBUG, "UnlockAll: %s (%d)", strerror(errno), errno);
- }
-#endif
-}
-
#ifndef ZEND_WIN32
static inline void kill_all_lockers(struct flock *mem_usage_check)
{
@@ -962,6 +970,7 @@ char *accel_make_persistent_key(const char *path, int path_length, int *key_len)
zend_shared_alloc_lock();
str = accel_new_interned_string(zend_string_copy(cwd_str));
if (str == cwd_str) {
+ zend_string_release(str);
str = NULL;
}
zend_shared_alloc_unlock();
@@ -1562,7 +1571,9 @@ zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int type)
}
}
+ SHM_UNPROTECT();
persistent_script = zend_file_cache_script_load(file_handle);
+ SHM_PROTECT();
if (persistent_script) {
/* see bug #15471 (old BTS) */
if (persistent_script->full_path) {
@@ -1588,8 +1599,6 @@ zend_op_array *file_cache_compile_file(zend_file_handle *file_handle, int type)
}
zend_file_handle_dtor(file_handle);
- persistent_script->dynamic_members.last_used = ZCG(request_time);
-
if (persistent_script->ping_auto_globals_mask) {
zend_accel_set_auto_globals(persistent_script->ping_auto_globals_mask);
}
@@ -1708,8 +1717,15 @@ zend_op_array *persistent_compile_file(zend_file_handle *file_handle, int type)
* each execution)
*/
if (!ZCG(counted)) {
+ if (accel_activate_add() == FAILURE) {
+#ifdef HAVE_OPCACHE_FILE_CACHE
+ if (ZCG(accel_directives).file_cache) {
+ return file_cache_compile_file(file_handle, type);
+ }
+#endif
+ return accelerator_orig_compile_file(file_handle, type);
+ }
ZCG(counted) = 1;
- accel_activate_add();
}
SHM_UNPROTECT();
@@ -1976,7 +1992,7 @@ static void accel_reset_pcre_cache(void)
ZEND_HASH_FOREACH_BUCKET(&PCRE_G(pcre_cache), p) {
/* Remove PCRE cache entries with inconsistent keys */
- if (ZSTR_IS_INTERNED(p->key)) {
+ if (zend_accel_in_shm(p->key)) {
p->key = NULL;
zend_hash_del_bucket(&PCRE_G(pcre_cache), p);
}
@@ -2277,6 +2293,19 @@ static void zend_accel_fast_shutdown(void)
}
#endif
+int accel_post_deactivate(void)
+{
+ if (!ZCG(enabled) || !accel_startup_ok) {
+ return SUCCESS;
+ }
+
+ zend_shared_alloc_safe_unlock(); /* be sure we didn't leave cache locked */
+ accel_unlock_all();
+ ZCG(counted) = 0;
+
+ return SUCCESS;
+}
+
static void accel_deactivate(void)
{
/* ensure that we restore function_table and class_table
@@ -2284,25 +2313,20 @@ static void accel_deactivate(void)
* the script is aborted abnormally, they may become messed up.
*/
+ if (ZCG(cwd)) {
+ zend_string_release(ZCG(cwd));
+ ZCG(cwd) = NULL;
+ }
+
if (!ZCG(enabled) || !accel_startup_ok) {
return;
}
- zend_shared_alloc_safe_unlock(); /* be sure we didn't leave cache locked */
- accel_unlock_all();
- ZCG(counted) = 0;
-
#if !ZEND_DEBUG
if (ZCG(accel_directives).fast_shutdown && is_zend_mm()) {
zend_accel_fast_shutdown();
}
#endif
-
- if (ZCG(cwd)) {
- zend_string_release(ZCG(cwd));
- ZCG(cwd) = NULL;
- }
-
}
static int accelerator_remove_cb(zend_extension *element1, zend_extension *element2)
@@ -2865,13 +2889,16 @@ int accelerator_shm_read_lock(void)
} else {
/* here accelerator is active but we do not hold SHM lock. This means restart was scheduled
or is in progress now */
- accel_activate_add(); /* acquire usage lock */
+ if (accel_activate_add() == FAILURE) { /* acquire usage lock */
+ return FAILURE;
+ }
/* Now if we weren't inside restart, restart would not begin until we remove usage lock */
if (ZCSG(restart_in_progress)) {
/* we already were inside restart this means it's not safe to touch shm */
accel_deactivate_now(); /* drop usage lock */
return FAILURE;
}
+ ZCG(counted) = 1;
}
return SUCCESS;
}
diff --git a/ext/opcache/ZendAccelerator.h b/ext/opcache/ZendAccelerator.h
index ca2b9f64f1..89664a2a23 100644
--- a/ext/opcache/ZendAccelerator.h
+++ b/ext/opcache/ZendAccelerator.h
@@ -318,6 +318,7 @@ extern zend_accel_globals accel_globals;
extern char *zps_api_failure_reason;
void accel_shutdown(void);
+int accel_post_deactivate(void);
void zend_accel_schedule_restart(zend_accel_restart_reason reason);
void zend_accel_schedule_restart_if_necessary(zend_accel_restart_reason reason);
accel_time_t zend_get_file_handle_timestamp(zend_file_handle *file_handle, size_t *size);
diff --git a/ext/opcache/tests/bug66338.phpt b/ext/opcache/tests/bug66338.phpt
index ed7f8ab475..6553f83f29 100644
--- a/ext/opcache/tests/bug66338.phpt
+++ b/ext/opcache/tests/bug66338.phpt
@@ -15,13 +15,13 @@ file_put_contents( "$root-Officials.inc", '<?php
file_put_contents( "$root-clientUS.php", '<?php
class LocalTerms { const GOV_LEADER = "Barack Hussein Obama II"; }
- require "'.$root.'-Officials.inc";
+ require \''.$root.'-Officials.inc\';
printf( "The President of the USA is %s\n", Officials::getLeader() );
' );
file_put_contents( "$root-clientUK.php", '<?php
class LocalTerms { const GOV_LEADER = "David William Donald Cameron"; }
- require "'.$root.'-Officials.inc";
+ require \''.$root.'-Officials.inc\';
printf( "The Prime Minister of the UK is %s\n", Officials::getLeader() );
' );
diff --git a/ext/opcache/tests/bug67215.phpt b/ext/opcache/tests/bug67215.phpt
index 24842b4e04..4a9ac7c711 100644
--- a/ext/opcache/tests/bug67215.phpt
+++ b/ext/opcache/tests/bug67215.phpt
@@ -11,7 +11,7 @@ opcache.file_update_protection=0
$file_c = __DIR__ . "/bug67215.c.php";
$file_p = __DIR__ . "/bug67215.p.php";
-file_put_contents($file_c, "<?php require \"$file_p\"; class c extends p {} ?>");
+file_put_contents($file_c, "<?php require '$file_p'; class c extends p {} ?>");
file_put_contents($file_p, '<?php class p { protected $var = ""; } ?>');
require $file_c;
$a = new c();
diff --git a/ext/opcache/tests/revalidate_path_01.phpt b/ext/opcache/tests/revalidate_path_01.phpt
index cf2ac0d829..8261633334 100644
--- a/ext/opcache/tests/revalidate_path_01.phpt
+++ b/ext/opcache/tests/revalidate_path_01.phpt
@@ -25,16 +25,30 @@ while (filemtime($file1) != filemtime($file2)) {
touch($file1);
touch($file2);
}
-@unlink($link);
-@symlink($dir1, $link);
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+ @rmdir($link);
+ $ln = str_replace('/', '\\', $link);
+ $d1 = realpath($dir1);
+ `mklink /j $ln $d1`;
+} else {
+ @unlink($link);
+ @symlink($dir1, $link);
+}
include "php_cli_server.inc";
//php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.revalidate_path=1');
php_cli_server_start('-d opcache.enable=1 -d opcache.enable_cli=1 -d opcache.revalidate_path=1 -d opcache.file_update_protection=0 -d realpath_cache_size=0');
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/main.php');
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/main.php');
-@unlink($link);
-@symlink($dir2, $link);
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+ @rmdir($link);
+ $ln = str_replace('/', '\\', $link);
+ $d2 = realpath($dir2);
+ `mklink /j $ln $d2`;
+} else {
+ @unlink($link);
+ @symlink($dir2, $link);
+}
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/main.php');
echo file_get_contents('http://' . PHP_CLI_SERVER_ADDRESS . '/main.php');
?>
@@ -48,7 +62,11 @@ $file1 = "$dir1/index.php";
$file2 = "$dir2/index.php";
$main = "$dir/main.php";
@unlink($main);
-@unlink($link);
+if (substr(PHP_OS, 0, 3) == 'WIN') {
+ @rmdir($link);
+} else {
+ @unlink($link);
+}
@unlink($file1);
@unlink($file2);
@rmdir($dir1);
diff --git a/ext/opcache/zend_accelerator_module.c b/ext/opcache/zend_accelerator_module.c
index 894ea08ac8..2fabc8cb3c 100644
--- a/ext/opcache/zend_accelerator_module.c
+++ b/ext/opcache/zend_accelerator_module.c
@@ -516,7 +516,9 @@ static zend_module_entry accel_module_entry = {
NULL,
zend_accel_info,
ACCELERATOR_VERSION "FE",
- STANDARD_MODULE_PROPERTIES
+ NO_MODULE_GLOBALS,
+ accel_post_deactivate,
+ STANDARD_MODULE_PROPERTIES_EX
};
int start_accel_module(void)
diff --git a/ext/opcache/zend_file_cache.c b/ext/opcache/zend_file_cache.c
index 410921f800..3187412423 100644
--- a/ext/opcache/zend_file_cache.c
+++ b/ext/opcache/zend_file_cache.c
@@ -224,15 +224,16 @@ static void *zend_file_cache_unserialize_interned(zend_string *str, int in_shm)
zend_string *ret;
str = (zend_string*)((char*)ZCG(mem) + ((size_t)(str) & ~Z_UL(1)));
- ret = accel_new_interned_string(str);
- if (ret == str) {
- /* String wasn't interned but we will use it as interned anyway */
- if (in_shm) {
+ if (in_shm) {
+ ret = accel_new_interned_string(str);
+ if (ret == str) {
+ /* String wasn't interned but we will use it as interned anyway */
GC_FLAGS(ret) |= IS_STR_INTERNED | IS_STR_PERMANENT;
- } else {
- GC_FLAGS(ret) |= IS_STR_INTERNED;
- GC_FLAGS(ret) &= ~IS_STR_PERMANENT;
}
+ } else {
+ ret = str;
+ GC_FLAGS(ret) |= IS_STR_INTERNED;
+ GC_FLAGS(ret) &= ~IS_STR_PERMANENT;
}
return ret;
}
@@ -1303,7 +1304,9 @@ zend_persistent_script *zend_file_cache_script_load(zend_file_handle *file_handl
return NULL;
}
- if (!ZCG(accel_directives).file_cache_only) {
+ if (!ZCG(accel_directives).file_cache_only &&
+ !ZCSG(restart_in_progress) &&
+ accelerator_shm_read_lock() == SUCCESS) {
/* exclusive lock */
zend_shared_alloc_lock();
@@ -1357,6 +1360,7 @@ use_process_mem:
if (cache_it) {
script->dynamic_members.checksum = zend_accel_script_checksum(script);
+ script->dynamic_members.last_used = ZCG(request_time);
zend_accel_hash_update(&ZCSG(hash), ZSTR_VAL(script->full_path), ZSTR_LEN(script->full_path), 0, script);
diff --git a/ext/opcache/zend_persist_calc.c b/ext/opcache/zend_persist_calc.c
index 6c721196a4..25ba69bee8 100644
--- a/ext/opcache/zend_persist_calc.c
+++ b/ext/opcache/zend_persist_calc.c
@@ -34,7 +34,9 @@
# define ADD_STRING(str) ADD_DUP_SIZE((str), _ZSTR_STRUCT_SIZE(ZSTR_LEN(str)))
# define ADD_INTERNED_STRING(str, do_free) do { \
- if (!IS_ACCEL_INTERNED(str)) { \
+ if (ZCG(current_persistent_script)->corrupted) { \
+ ADD_STRING(str); \
+ } else if (!IS_ACCEL_INTERNED(str)) { \
zend_string *tmp = accel_new_interned_string(str); \
if (tmp != (str)) { \
if (do_free) { \
@@ -126,7 +128,7 @@ static void zend_persist_zval_calc(zval *z)
case IS_CONSTANT:
flags = Z_GC_FLAGS_P(z) & ~ (IS_STR_PERSISTENT | IS_STR_INTERNED | IS_STR_PERMANENT);
ADD_INTERNED_STRING(Z_STR_P(z), 0);
- if (!Z_REFCOUNTED_P(z)) {
+ if (ZSTR_IS_INTERNED(Z_STR_P(z))) {
Z_TYPE_FLAGS_P(z) &= ~ (IS_TYPE_REFCOUNTED | IS_TYPE_COPYABLE);
}
Z_GC_FLAGS_P(z) |= flags;
@@ -385,11 +387,15 @@ uint zend_accel_script_persist_calc(zend_persistent_script *new_persistent_scrip
new_persistent_script->size = 0;
new_persistent_script->arena_mem = NULL;
new_persistent_script->arena_size = 0;
+ new_persistent_script->corrupted = 0;
ZCG(current_persistent_script) = new_persistent_script;
ADD_DUP_SIZE(new_persistent_script, sizeof(zend_persistent_script));
if (key) {
ADD_DUP_SIZE(key, key_length + 1);
+ } else {
+ /* script is not going to be saved in SHM */
+ new_persistent_script->corrupted = 1;
}
ADD_STRING(new_persistent_script->full_path);
@@ -408,6 +414,7 @@ uint zend_accel_script_persist_calc(zend_persistent_script *new_persistent_scrip
#endif
new_persistent_script->size += new_persistent_script->arena_size;
+ new_persistent_script->corrupted = 0;
ZCG(current_persistent_script) = NULL;
diff --git a/ext/opcache/zend_shared_alloc.c b/ext/opcache/zend_shared_alloc.c
index d616c7d62f..deae886991 100644
--- a/ext/opcache/zend_shared_alloc.c
+++ b/ext/opcache/zend_shared_alloc.c
@@ -507,3 +507,20 @@ void zend_accel_shared_protect(int mode)
}
#endif
}
+
+int zend_accel_in_shm(void *ptr)
+{
+ int i;
+
+ if (!smm_shared_globals) {
+ return 0;
+ }
+
+ for (i = 0; i < ZSMMG(shared_segments_count); i++) {
+ if ((char*)ptr >= (char*)ZSMMG(shared_segments)[i]->p &&
+ (char*)ptr < (char*)ZSMMG(shared_segments)[i]->p + ZSMMG(shared_segments)[i]->size) {
+ return 1;
+ }
+ }
+ return 0;
+}
diff --git a/ext/opcache/zend_shared_alloc.h b/ext/opcache/zend_shared_alloc.h
index 3993b0689e..03b82d16ac 100644
--- a/ext/opcache/zend_shared_alloc.h
+++ b/ext/opcache/zend_shared_alloc.h
@@ -128,6 +128,8 @@ void *zend_shared_alloc(size_t size);
void *_zend_shared_memdup(void *p, size_t size, zend_bool free_source);
int zend_shared_memdup_size(void *p, size_t size);
+int zend_accel_in_shm(void *ptr);
+
typedef union _align_test {
void *ptr;
double dbl;
diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c
index 26eb120253..3298efc6f7 100644
--- a/ext/openssl/openssl.c
+++ b/ext/openssl/openssl.c
@@ -5241,7 +5241,7 @@ PHP_FUNCTION(openssl_seal)
iv_len = EVP_CIPHER_iv_length(cipher);
if (!iv && iv_len > 0) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING,
+ php_error_docref(NULL, E_WARNING,
"Cipher algorithm requires an IV to be supplied as a sixth parameter");
RETURN_FALSE;
}
@@ -5523,14 +5523,14 @@ static zend_bool php_openssl_validate_iv(char **piv, size_t *piv_len, size_t iv_
}
if (*piv_len < iv_required_len) {
- php_error_docref(NULL, E_WARNING, "IV passed is only %d bytes long, cipher expects an IV of precisely %d bytes, padding with \\0", *piv_len, iv_required_len);
+ php_error_docref(NULL, E_WARNING, "IV passed is only %zd bytes long, cipher expects an IV of precisely %zd bytes, padding with \\0", *piv_len, iv_required_len);
memcpy(iv_new, *piv, *piv_len);
*piv_len = iv_required_len;
*piv = iv_new;
return 1;
}
- php_error_docref(NULL, E_WARNING, "IV passed is %d bytes long which is longer than the %d expected by selected cipher, truncating", *piv_len, iv_required_len);
+ php_error_docref(NULL, E_WARNING, "IV passed is %zd bytes long which is longer than the %zd expected by selected cipher, truncating", *piv_len, iv_required_len);
memcpy(iv_new, *piv, iv_required_len);
*piv_len = iv_required_len;
*piv = iv_new;
diff --git a/ext/openssl/tests/openssl_csr_new_basic.phpt b/ext/openssl/tests/openssl_csr_new_basic.phpt
index a3a4746b39..e0f52d739f 100644
--- a/ext/openssl/tests/openssl_csr_new_basic.phpt
+++ b/ext/openssl/tests/openssl_csr_new_basic.phpt
@@ -9,16 +9,18 @@ $a = 1;
var_dump(openssl_csr_new(1,$a));
var_dump(openssl_csr_new(1,$a,1,1));
$a = array();
-var_dump(openssl_csr_new(array(), $a, array('config' => __DIR__ . DIRECTORY_SEPARATOR . 'openssl.cnf'), array()));
+
+$conf = array('config' => dirname(__FILE__) . DIRECTORY_SEPARATOR . 'openssl.cnf');
+var_dump(openssl_csr_new(array(), $a, $conf, array()));
// this leaks
$a = array(1,2);
$b = array(1,2);
-var_dump(openssl_csr_new($a, $b, array('config' => __DIR__ . DIRECTORY_SEPARATOR . 'openssl.cnf')));
+var_dump(openssl_csr_new($a, $b, $conf));
// options type check
-$x = openssl_pkey_new();
-var_dump(openssl_csr_new(["countryName" => "DE"], $x, ["x509_extensions" => 0xDEADBEEF]));
+$x = openssl_pkey_new($conf);
+var_dump(openssl_csr_new(["countryName" => "DE"], $x, $conf + ["x509_extensions" => 0xDEADBEEF]));
echo "Done\n";
diff --git a/ext/openssl/tests/openssl_x509_check_private_key_basic.phpt b/ext/openssl/tests/openssl_x509_check_private_key_basic.phpt
index df18322453..b4842aae18 100644
--- a/ext/openssl/tests/openssl_x509_check_private_key_basic.phpt
+++ b/ext/openssl/tests/openssl_x509_check_private_key_basic.phpt
@@ -5,11 +5,11 @@ openssl_x509_check_private_key() tests
--FILE--
<?php
$fp = fopen(dirname(__FILE__) . "/cert.crt","r");
-$a = fread($fp,8192);
+$a = fread($fp, 8192);
fclose($fp);
$fp = fopen(dirname(__FILE__) . "/private_rsa_1024.key","r");
-$b = fread($fp,8192);
+$b = fread($fp, 8192);
fclose($fp);
$cert = "file://" . dirname(__FILE__) . "/cert.crt";
diff --git a/ext/openssl/tests/openssl_x509_export_basic.phpt b/ext/openssl/tests/openssl_x509_export_basic.phpt
index 712fe4ca80..4177bd7798 100644
--- a/ext/openssl/tests/openssl_x509_export_basic.phpt
+++ b/ext/openssl/tests/openssl_x509_export_basic.phpt
@@ -1,43 +1,22 @@
--TEST--
-openssl_x509_export() and openssl_x509_export_to_file() tests
+openssl_x509_export() tests
--SKIPIF--
<?php if (!extension_loaded("openssl")) print "skip"; ?>
--FILE--
<?php
-$fp = fopen(dirname(__FILE__) . "/cert.crt","r");
-$a = fread($fp,8192);
-fclose($fp);
+$cert_file = dirname(__FILE__) . "/cert.crt";
-$b = "file://" . dirname(__FILE__) . "/cert.crt";
+$a = file_get_contents($cert_file);
+$b = "file://" . $cert_file;
$c = "invalid cert";
$d = openssl_x509_read($a);
$e = array();
-var_dump(openssl_x509_export($a, $output)); // read cert as a binary string
-var_dump(openssl_x509_export($b, $output2)); // read cert from a filename string
-var_dump(openssl_x509_export($c, $output3)); // read an invalid cert, fails
-var_dump(openssl_x509_export($d, $output4)); // read cert from a resource
-var_dump(openssl_x509_export($e, $output5)); // read an array, fails
-
-$outfilename = tempnam("/tmp", "ssl");
-if ($outfilename === false) {
- die("failed to get a temporary filename!");
-}
-
-echo "---\n";
-
-var_dump(openssl_x509_export_to_file($a, $outfilename)); // read cert as a binary string
-var_dump(openssl_x509_export_to_file($b, $outfilename)); // read cert from a filename string
-var_dump(openssl_x509_export_to_file($c, $outfilename)); // read an invalid cert, fails
-var_dump(openssl_x509_export_to_file($d, $outfilename)); // read cert from a resource
-var_dump(openssl_x509_export_to_file($e, $outfilename)); // read an array, fails
-echo "---\n";
-
-var_dump($exists = file_exists($outfilename));
-if ($exists) {
- @unlink($outfilename);
-}
-echo "---\n";
+var_dump(openssl_x509_export($a, $output)); // read cert as a binary string
+var_dump(openssl_x509_export($b, $output2)); // read cert from a filename string
+var_dump(openssl_x509_export($c, $output3)); // read an invalid cert, fails
+var_dump(openssl_x509_export($d, $output4)); // read cert from a resource
+var_dump(openssl_x509_export($e, $output5)); // read an array, fails
if (PHP_EOL !== "\n") {
$a = str_replace(PHP_EOL, "\n", $a);
@@ -46,9 +25,8 @@ if (PHP_EOL !== "\n") {
var_dump(strcmp($output, $a));
var_dump(strcmp($output, $output2));
var_dump(strcmp($output, $output3));
-var_dump(strcmp($output, $output4)); // different
-var_dump(strcmp($output, $output5)); // different
-
+var_dump(strcmp($output, $output4)); // different
+var_dump(strcmp($output, $output5)); // different
?>
--EXPECTF--
bool(true)
@@ -60,19 +38,6 @@ bool(true)
Warning: openssl_x509_export(): cannot get cert from parameter 1 in %s on line %d
bool(false)
----
-bool(true)
-bool(true)
-
-Warning: openssl_x509_export_to_file(): cannot get cert from parameter 1 in %s on line %d
-bool(false)
-bool(true)
-
-Warning: openssl_x509_export_to_file(): cannot get cert from parameter 1 in %s on line %d
-bool(false)
----
-bool(true)
----
int(0)
int(0)
int(%d)
diff --git a/ext/openssl/tests/openssl_x509_export_to_file_basic.phpt b/ext/openssl/tests/openssl_x509_export_to_file_basic.phpt
new file mode 100644
index 0000000000..68ba93230d
--- /dev/null
+++ b/ext/openssl/tests/openssl_x509_export_to_file_basic.phpt
@@ -0,0 +1,42 @@
+--TEST--
+openssl_x509_export_to_file() tests
+--SKIPIF--
+<?php if (!extension_loaded("openssl")) print "skip"; ?>
+--FILE--
+<?php
+$outfilename = dirname(__FILE__) . "/openssl_x509_export_to_file__outfilename.tmp";
+$cert_file = dirname(__FILE__) . "/cert.crt";
+
+$a = file_get_contents($cert_file);
+$b = "file://" . $cert_file;
+$c = "invalid cert";
+$d = openssl_x509_read($a);
+$e = array();
+
+var_dump(openssl_x509_export_to_file($a, $outfilename)); // read cert as a binary string
+var_dump(openssl_x509_export_to_file($b, $outfilename)); // read cert from a filename string
+var_dump(openssl_x509_export_to_file($c, $outfilename)); // read an invalid cert, fails
+var_dump(openssl_x509_export_to_file($d, $outfilename)); // read cert from a resource
+var_dump(openssl_x509_export_to_file($e, $outfilename)); // read an array, fails
+echo "---\n";
+var_dump($exists = file_exists($outfilename));
+?>
+--CLEAN--
+<?php
+$outfilename = dirname(__FILE__) . "/openssl_x509_export_to_file__outfilename.tmp";
+if (file_exists($outfilename)) {
+ unlink($outfilename);
+}
+?>
+--EXPECTF--
+bool(true)
+bool(true)
+
+Warning: openssl_x509_export_to_file(): cannot get cert from parameter 1 in %s on line %d
+bool(false)
+bool(true)
+
+Warning: openssl_x509_export_to_file(): cannot get cert from parameter 1 in %s on line %d
+bool(false)
+---
+bool(true)
diff --git a/ext/openssl/tests/openssl_x509_fingerprint_basic.phpt b/ext/openssl/tests/openssl_x509_fingerprint_basic.phpt
index 6cd464a894..766b158fab 100644
--- a/ext/openssl/tests/openssl_x509_fingerprint_basic.phpt
+++ b/ext/openssl/tests/openssl_x509_fingerprint_basic.phpt
@@ -1,5 +1,5 @@
--TEST--
-Testing openssl_x509_fingerprint()
+openssl_x509_fingerprint() tests
--SKIPIF--
<?php
if (!extension_loaded("openssl")) die("skip");
diff --git a/ext/openssl/tests/openssl_x509_free_basic.phpt b/ext/openssl/tests/openssl_x509_free_basic.phpt
new file mode 100644
index 0000000000..d8b586e8b4
--- /dev/null
+++ b/ext/openssl/tests/openssl_x509_free_basic.phpt
@@ -0,0 +1,16 @@
+--TEST--
+openssl_x509_free() tests
+--SKIPIF--
+<?php if (!extension_loaded("openssl")) print "skip"; ?>
+--FILE--
+<?php
+var_dump($res = openssl_x509_read("file://" . dirname(__FILE__) . "/cert.crt"));
+openssl_x509_free($res);
+var_dump($res);
+openssl_x509_free(false);
+?>
+--EXPECTF--
+resource(%d) of type (OpenSSL X.509)
+resource(%d) of type (Unknown)
+
+Warning: openssl_x509_free() expects parameter 1 to be resource, boolean given in %s on line %d
diff --git a/ext/openssl/tests/openssl_x509_parse_basic.phpt b/ext/openssl/tests/openssl_x509_parse_basic.phpt
index 325b2ee4b9..00e32c3b60 100644
--- a/ext/openssl/tests/openssl_x509_parse_basic.phpt
+++ b/ext/openssl/tests/openssl_x509_parse_basic.phpt
@@ -1,5 +1,5 @@
--TEST--
-openssl_x509_parse() basic test
+openssl_x509_parse() tests
--SKIPIF--
<?php if (!extension_loaded("openssl")) print "skip";
if (OPENSSL_VERSION_NUMBER < 0x10000000) die("skip Output requires OpenSSL 1.0");
diff --git a/ext/openssl/tests/openssl_x509_read_basic.phpt b/ext/openssl/tests/openssl_x509_read_basic.phpt
index cc36e989c6..5f530534ff 100644
--- a/ext/openssl/tests/openssl_x509_read_basic.phpt
+++ b/ext/openssl/tests/openssl_x509_read_basic.phpt
@@ -1,5 +1,5 @@
--TEST--
-openssl_x509_read() tests with testing openssl_x509_free as well
+openssl_x509_read() tests
--SKIPIF--
<?php if (!extension_loaded("openssl")) print "skip"; ?>
--FILE--
@@ -14,47 +14,24 @@ $d = openssl_x509_read($a);
$e = array();
$f = array($b);
-var_dump($res = openssl_x509_read($a)); // read cert as a string
-openssl_x509_free($res);
-var_dump($res);
-var_dump($res = openssl_x509_read($b)); // read cert as a filename string
-openssl_x509_free($res);
-var_dump($res);
-var_dump($res = openssl_x509_read($c)); // read an invalid cert, fails
-openssl_x509_free($res);
-var_dump($res);
-var_dump($res = openssl_x509_read($d)); // read cert from a resource
-openssl_x509_free($res);
-var_dump($res);
-var_dump($res = openssl_x509_read($e)); // read an array
-openssl_x509_free($res);
-var_dump($res);
-var_dump($res = openssl_x509_read($f)); // read an array with the filename
-openssl_x509_free($res);
-var_dump($res);
+var_dump(openssl_x509_read($a)); // read cert as a string
+var_dump(openssl_x509_read($b)); // read cert as a filename string
+var_dump(openssl_x509_read($c)); // read an invalid cert, fails
+var_dump(openssl_x509_read($d)); // read cert from a resource
+var_dump(openssl_x509_read($e)); // read an array
+var_dump(openssl_x509_read($f)); // read an array with the filename
?>
--EXPECTF--
resource(%d) of type (OpenSSL X.509)
-resource(%d) of type (Unknown)
resource(%d) of type (OpenSSL X.509)
-resource(%d) of type (Unknown)
Warning: openssl_x509_read(): supplied parameter cannot be coerced into an X509 certificate! in %s on line %d
bool(false)
-
-Warning: openssl_x509_free() expects parameter 1 to be resource, boolean given in %s on line %d
-bool(false)
resource(%d) of type (OpenSSL X.509)
-resource(%d) of type (Unknown)
Warning: openssl_x509_read(): supplied parameter cannot be coerced into an X509 certificate! in %s on line %d
bool(false)
-Warning: openssl_x509_free() expects parameter 1 to be resource, boolean given in %s on line %d
-bool(false)
-
Warning: openssl_x509_read(): supplied parameter cannot be coerced into an X509 certificate! in %s on line %d
bool(false)
-Warning: openssl_x509_free() expects parameter 1 to be resource, boolean given in %s on line %d
-bool(false)
diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c
index ee3e36b6ab..93bfc00052 100644
--- a/ext/pcre/php_pcre.c
+++ b/ext/pcre/php_pcre.c
@@ -1350,7 +1350,6 @@ PHPAPI zend_string *php_pcre_replace_impl(pcre_cache_entry *pce, zend_string *su
static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *subject, int limit, int is_callable_replace, int *replace_count)
{
zval *regex_entry,
- *replace_entry = NULL,
*replace_value,
empty_replace;
zend_string *result;
@@ -1372,25 +1371,26 @@ static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *sub
/* For each entry in the regex array, get the entry */
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(regex), regex_entry) {
+ zval replace_str;
/* Make sure we're dealing with strings. */
zend_string *regex_str = zval_get_string(regex_entry);
+ ZVAL_UNDEF(&replace_str);
/* If replace is an array and not a callable construct */
if (Z_TYPE_P(replace) == IS_ARRAY && !is_callable_replace) {
/* Get current entry */
- replace_entry = NULL;
while (replace_idx < Z_ARRVAL_P(replace)->nNumUsed) {
if (Z_TYPE(Z_ARRVAL_P(replace)->arData[replace_idx].val) != IS_UNDEF) {
- replace_entry = &Z_ARRVAL_P(replace)->arData[replace_idx].val;
+ ZVAL_COPY(&replace_str, &Z_ARRVAL_P(replace)->arData[replace_idx].val);
break;
}
replace_idx++;
}
- if (replace_entry != NULL) {
+ if (!Z_ISUNDEF(replace_str)) {
if (!is_callable_replace) {
- convert_to_string_ex(replace_entry);
+ convert_to_string(&replace_str);
}
- replace_value = replace_entry;
+ replace_value = &replace_str;
replace_idx++;
} else {
/* We've run out of replacement strings, so use an empty one */
@@ -1413,10 +1413,12 @@ static zend_string *php_replace_in_subject(zval *regex, zval *replace, zval *sub
} else {
zend_string_release(subject_str);
zend_string_release(regex_str);
+ zval_dtor(&replace_str);
return NULL;
}
zend_string_release(regex_str);
+ zval_dtor(&replace_str);
} ZEND_HASH_FOREACH_END();
return subject_str;
diff --git a/ext/pcre/tests/bug71537.phpt b/ext/pcre/tests/bug71537.phpt
new file mode 100644
index 0000000000..cdc2928a28
--- /dev/null
+++ b/ext/pcre/tests/bug71537.phpt
@@ -0,0 +1,9 @@
+--TEST--
+Fixed bug #71537 (PCRE segfault from Opcache)
+--FILE--
+<?php
+
+var_dump(preg_replace(array("/Monkey/"), array(2016), "Happy Year of Monkey"));
+?>
+--EXPECT--
+string(18) "Happy Year of 2016"
diff --git a/ext/pdo/Makefile.frag b/ext/pdo/Makefile.frag
index dc25c9f70b..58125ed872 100644
--- a/ext/pdo/Makefile.frag
+++ b/ext/pdo/Makefile.frag
@@ -10,7 +10,7 @@ $(srcdir)/pdo_sql_parser.c: $(srcdir)/pdo_sql_parser.re
(cd $(top_srcdir); $(RE2C) --no-generation-date -o ext/pdo/pdo_sql_parser.c ext/pdo/pdo_sql_parser.re)
install-pdo-headers:
- @echo "Installing PDO headers: $(INSTALL_ROOT)$(phpincludedir)/ext/pdo/"
+ @echo "Installing PDO headers: $(INSTALL_ROOT)$(phpincludedir)/ext/pdo/"
@$(mkinstalldirs) $(INSTALL_ROOT)$(phpincludedir)/ext/pdo
@for f in $(PDO_HEADER_FILES); do \
if test -f "$(top_srcdir)/$$f"; then \
diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c
index 5ca20fcd5b..6019c39aba 100644
--- a/ext/pdo/pdo_stmt.c
+++ b/ext/pdo/pdo_stmt.c
@@ -2107,9 +2107,9 @@ static PHP_METHOD(PDOStatement, debugDumpParams)
RETURN_FALSE;
}
- php_stream_printf(out, "SQL: [%d] %.*s\n",
+ php_stream_printf(out, "SQL: [%zd] %.*s\n",
stmt->query_stringlen,
- stmt->query_stringlen, stmt->query_string);
+ (int) stmt->query_stringlen, stmt->query_string);
php_stream_printf(out, "Params: %d\n",
stmt->bound_params ? zend_hash_num_elements(stmt->bound_params) : 0);
@@ -2119,13 +2119,14 @@ static PHP_METHOD(PDOStatement, debugDumpParams)
zend_string *key = NULL;
ZEND_HASH_FOREACH_KEY_PTR(stmt->bound_params, num, key, param) {
if (key) {
- php_stream_printf(out, "Key: Name: [%d] %.*s\n", ZSTR_LEN(key), ZSTR_LEN(key), ZSTR_VAL(key));
+ php_stream_printf(out, "Key: Name: [%zd] %.*s\n",
+ ZSTR_LEN(key), (int) ZSTR_LEN(key), ZSTR_VAL(key));
} else {
php_stream_printf(out, "Key: Position #%pd:\n", num);
}
- php_stream_printf(out, "paramno=%pd\nname=[%d] \"%.*s\"\nis_param=%d\nparam_type=%d\n",
- param->paramno, param->name? ZSTR_LEN(param->name) : 0, param->name? ZSTR_LEN(param->name) : 0,
+ php_stream_printf(out, "paramno=%pd\nname=[%zd] \"%.*s\"\nis_param=%d\nparam_type=%d\n",
+ param->paramno, param->name ? ZSTR_LEN(param->name) : 0, param->name ? (int) ZSTR_LEN(param->name) : 0,
param->name ? ZSTR_VAL(param->name) : "",
param->is_param,
param->param_type);
diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c
index cfb386fa0d..dcbaf55a3f 100644
--- a/ext/pdo_dblib/dblib_driver.c
+++ b/ext/pdo_dblib/dblib_driver.c
@@ -331,9 +331,7 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
,{"auto",0} /* Only works with FreeTDS. Other drivers will bork */
};
-
- nvers = sizeof(tdsver)/sizeof(tdsver[0]);
-
+
struct pdo_data_src_parser vars[] = {
{ "charset", NULL, 0 }
,{ "appname", "PHP " PDO_DBLIB_FLAVOUR, 0 }
@@ -344,7 +342,8 @@ static int pdo_dblib_handle_factory(pdo_dbh_t *dbh, zval *driver_options)
};
nvars = sizeof(vars)/sizeof(vars[0]);
-
+ nvers = sizeof(tdsver)/sizeof(tdsver[0]);
+
php_pdo_parse_data_source(dbh->data_source, dbh->data_source_len, vars, nvars);
if (driver_options) {
diff --git a/ext/pdo_dblib/dblib_stmt.c b/ext/pdo_dblib/dblib_stmt.c
index 484bfbb560..0eff4945dd 100644
--- a/ext/pdo_dblib/dblib_stmt.c
+++ b/ext/pdo_dblib/dblib_stmt.c
@@ -102,7 +102,7 @@ static int pdo_dblib_stmt_cursor_closer(pdo_stmt_t *stmt)
/* Cancel any pending results */
dbcancel(H->link);
-
+
return 1;
}
@@ -268,6 +268,25 @@ static int pdo_dblib_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr,
*ptr = tmp_ptr;
break;
}
+ case SQLDATETIM4:
+ case SQLDATETIME: {
+ DBDATETIME dt;
+ DBDATEREC di;
+
+ dbconvert(H->link, coltype, (BYTE*) *ptr, -1, SQLDATETIME, (LPBYTE) &dt, -1);
+ dbdatecrack(H->link, &di, &dt);
+
+ *len = spprintf((char**) &tmp_ptr, 20, "%d-%02d-%02d %02d:%02d:%02d",
+#ifdef PHP_DBLIB_IS_MSSQL || MSDBLIB
+ di.year, di.month, di.day, di.hour, di.minute, di.second
+#else
+ di.dateyear, di.datemonth+1, di.datedmonth, di.datehour, di.dateminute, di.datesecond
+#endif
+ );
+
+ *ptr = (char*) tmp_ptr;
+ break;
+ }
default:
if (dbwillconvert(coltype, SQLCHAR)) {
tmp_len = 32 + (2 * (*len)); /* FIXME: We allocate more than we need here */
diff --git a/ext/pdo_dblib/tests/bug_54648.phpt b/ext/pdo_dblib/tests/bug_54648.phpt
new file mode 100644
index 0000000000..aa9f292669
--- /dev/null
+++ b/ext/pdo_dblib/tests/bug_54648.phpt
@@ -0,0 +1,26 @@
+--TEST--
+PDO_DBLIB: Does not force correct dateformat
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+$db->query('set dateformat ymd');
+$rs = $db->query("select cast('1950-01-18 23:00:00' as smalldatetime) as sdt, cast('2030-01-01 23:59:59' as datetime) as dt");
+var_dump($rs->fetchAll(PDO::FETCH_ASSOC));
+echo "Done.\n";
+?>
+--EXPECT--
+array(1) {
+ [0]=>
+ array(2) {
+ ["sdt"]=>
+ string(19) "1950-01-18 23:00:00"
+ ["dt"]=>
+ string(19) "2030-01-01 23:59:59"
+ }
+}
+Done.
diff --git a/ext/pdo_dblib/tests/bug_68957.phpt b/ext/pdo_dblib/tests/bug_68957.phpt
new file mode 100644
index 0000000000..3d6e2fd13d
--- /dev/null
+++ b/ext/pdo_dblib/tests/bug_68957.phpt
@@ -0,0 +1,29 @@
+--TEST--
+PDO_DBLIB bug #68957 PDO::query doesn't support several queries
+--SKIPIF--
+<?php
+if (!extension_loaded('pdo_dblib')) die('skip not loaded');
+require dirname(__FILE__) . '/config.inc';
+?>
+--FILE--
+<?php
+require dirname(__FILE__) . '/config.inc';
+
+$query = "declare @myInt int = 1; select @myInt;";
+$stmt = $db->query($query);
+$stmt->nextRowset(); // Added line
+$rows = $stmt->fetchAll();
+print_r($rows);
+
+?>
+--EXPECT--
+Array
+(
+ [0] => Array
+ (
+ [computed0] => 1
+ [0] => 1
+ )
+
+)
+
diff --git a/ext/pdo_mysql/tests/bug71569.phpt b/ext/pdo_mysql/tests/bug71569.phpt
new file mode 100644
index 0000000000..32c14b4622
--- /dev/null
+++ b/ext/pdo_mysql/tests/bug71569.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Bug #71569 (#70389 fix causes segmentation fault)
+--SKIPIF--
+<?php
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'skipif.inc');
+require_once(dirname(__FILE__) . DIRECTORY_SEPARATOR . 'mysql_pdo_test.inc');
+MySQLPDOTest::skip();
+?>
+--FILE--
+<?php
+require(dirname(__FILE__). DIRECTORY_SEPARATOR . 'config.inc');
+
+try {
+ new PDO(PDO_MYSQL_TEST_DSN, PDO_MYSQL_TEST_USER, PDO_MYSQL_TEST_PASS, [
+ PDO::MYSQL_ATTR_INIT_COMMAND => null,
+ ]);
+} catch (PDOException $e) {
+ echo $e->getMessage();
+}
+
+?>
+--EXPECT--
+SQLSTATE[42000] [1065] Query was empty
diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c
index 719ebe10d7..f84f31aed6 100644
--- a/ext/pgsql/pgsql.c
+++ b/ext/pgsql/pgsql.c
@@ -3033,7 +3033,7 @@ static void php_pgsql_data_info(INTERNAL_FUNCTION_PARAMETERS, int entry_type)
RETVAL_LONG(PQgetlength(pgsql_result, pgsql_row, field_offset));
break;
case PHP_PG_DATA_ISNULL:
- RETVAL_LONG(PQgetisnull(pgsql_result, pgsql_row, field_offset))
+ RETVAL_LONG(PQgetisnull(pgsql_result, pgsql_row, field_offset));
break;
}
}
diff --git a/ext/phar/phar.c b/ext/phar/phar.c
index 0ed34dbfcd..63feb3cfb8 100644
--- a/ext/phar/phar.c
+++ b/ext/phar/phar.c
@@ -1794,8 +1794,11 @@ static int phar_analyze_path(const char *fname, const char *ext, int ext_len, in
#ifdef PHP_WIN32
phar_unixify_path_separators(realpath, strlen(realpath));
#endif
- slash = strstr(realpath, filename) + ((ext - fname) + ext_len);
- *slash = '\0';
+ slash = strstr(realpath, filename);
+ if (slash) {
+ slash += ((ext - fname) + ext_len);
+ *slash = '\0';
+ }
slash = strrchr(realpath, '/');
if (slash) {
diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c
index 51b8b13a2a..22404dddbc 100644
--- a/ext/phar/phar_object.c
+++ b/ext/phar/phar_object.c
@@ -4085,7 +4085,7 @@ static int phar_extract_file(zend_bool overwrite, phar_entry_info *entry, char *
new_state.cwd[0] = DEFAULT_SLASH;
new_state.cwd[1] = '\0';
new_state.cwd_length = 1;
- if (virtual_file_ex(&new_state, entry->filename, NULL, CWD_EXPAND TSRMLS_CC) != 0 ||
+ if (virtual_file_ex(&new_state, entry->filename, NULL, CWD_EXPAND) != 0 ||
new_state.cwd_length <= 1) {
if (EINVAL == errno && entry->filename_len > 50) {
char *tmp = estrndup(entry->filename, 50);
diff --git a/ext/phar/tests/bug71331.phpt b/ext/phar/tests/bug71331.phpt
index 6cd850d36d..0026c406e8 100644
--- a/ext/phar/tests/bug71331.phpt
+++ b/ext/phar/tests/bug71331.phpt
@@ -8,8 +8,8 @@ $p = new PharData(__DIR__."/bug71331.tar");
?>
DONE
--EXPECTF--
-Fatal error: Uncaught UnexpectedValueException: phar error: "%s/bug71331.tar" is a corrupted tar file (invalid entry size) in %s/bug71331.php:2
+Fatal error: Uncaught UnexpectedValueException: phar error: "%s%ebug71331.tar" is a corrupted tar file (invalid entry size) in %s%ebug71331.php:2
Stack trace:
-#0 %s/bug71331.php(2): PharData->__construct('%s')
+#0 %s%ebug71331.php(2): PharData->__construct('%s')
#1 {main}
- thrown in %s/bug71331.php on line 2
+ thrown in %s%ebug71331.php on line 2
diff --git a/ext/phar/tests/bug71625.phpt b/ext/phar/tests/bug71625.phpt
new file mode 100644
index 0000000000..8e6c31f462
--- /dev/null
+++ b/ext/phar/tests/bug71625.phpt
@@ -0,0 +1,25 @@
+--TEST--
+Phar - Bug #71625 - Crash in php7.dll
+--INI--
+phar.readonly=0
+--SKIPIF--
+<?php
+
+if (!extension_loaded("phar") || !extension_loaded("zlib")) die("skip");
+if(substr(PHP_OS, 0, 3) != 'WIN' ) {
+ die('skip windows only test');
+}
+
+?>
+--FILE--
+<?php
+$phar = new Phar("A:A:.phar");
+$phar["hello_habr.txt"] = '<? Hello Habr!?>';
+?>
+DONE
+--EXPECTF--
+Fatal error: Uncaught UnexpectedValueException: Cannot create phar 'A:A:.phar', file extension (or combination) not recognised or the directory does not exist in %sbug71625.php:%d
+Stack trace:
+#0 %sbug71625.php(%d): Phar->__construct('A:A:.phar')
+#1 {main}
+ thrown in %sbug71625.php on line %d
diff --git a/ext/skeleton/create_stubs b/ext/skeleton/create_stubs
index 1163908110..a3f3d196b3 100755
--- a/ext/skeleton/create_stubs
+++ b/ext/skeleton/create_stubs
@@ -195,7 +195,7 @@ END {
if (maxargs[i]>0) {
fetchargs = "\tif (zend_parse_parameters("
ints = ints "\tint argc = ZEND_NUM_ARGS();\n"
- fetchargs = fetchargs "argc TSRMLS_CC, " specs[i]
+ fetchargs = fetchargs "argc, " specs[i]
} else {
fetchargs = fetchargs "\tif (zend_parse_parameters_none() == FAILURE) {\n\t\treturn;\n\t}"
xmlparams = xmlparams " <void/>\n"
diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c
index 67d2ccb67c..685dd27092 100644
--- a/ext/spl/spl_array.c
+++ b/ext/spl/spl_array.c
@@ -82,19 +82,29 @@ static inline spl_array_object *spl_array_from_obj(zend_object *obj) /* {{{ */ {
#define Z_SPLARRAY_P(zv) spl_array_from_obj(Z_OBJ_P((zv)))
-static inline HashTable *spl_array_get_hash_table(spl_array_object* intern, int check_std_props) { /* {{{ */
- if (intern->ar_flags & SPL_ARRAY_IS_SELF
- || (check_std_props && (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST))
- ) {
+static inline HashTable *spl_array_get_hash_table(spl_array_object* intern) { /* {{{ */
+ //??? TODO: Delay duplication for arrays; only duplicate for write operations
+ if (intern->ar_flags & SPL_ARRAY_IS_SELF) {
if (!intern->std.properties) {
rebuild_object_properties(&intern->std);
}
return intern->std.properties;
} else if (intern->ar_flags & SPL_ARRAY_USE_OTHER) {
spl_array_object *other = Z_SPLARRAY_P(&intern->array);
- return spl_array_get_hash_table(other, check_std_props);
+ return spl_array_get_hash_table(other);
+ } else if (Z_TYPE(intern->array) == IS_ARRAY) {
+ return Z_ARRVAL(intern->array);
} else {
- return HASH_OF(&intern->array);
+ zend_object *obj = Z_OBJ(intern->array);
+ if (!obj->properties) {
+ rebuild_object_properties(obj);
+ } else if (GC_REFCOUNT(obj->properties) > 1) {
+ if (EXPECTED(!(GC_FLAGS(obj->properties) & IS_ARRAY_IMMUTABLE))) {
+ GC_REFCOUNT(obj->properties)--;
+ }
+ obj->properties = zend_array_dup(obj->properties);
+ }
+ return obj->properties;
}
} /* }}} */
@@ -167,10 +177,12 @@ static zend_object *spl_array_object_new_ex(zend_class_entry *class_type, zval *
if (other->ar_flags & SPL_ARRAY_IS_SELF) {
ZVAL_UNDEF(&intern->array);
} else if (Z_OBJ_HT_P(orig) == &spl_handler_ArrayObject) {
- ZVAL_ARR(&intern->array, zend_array_dup(HASH_OF(&other->array)));
+ ZVAL_ARR(&intern->array,
+ zend_array_dup(spl_array_get_hash_table(other)));
} else {
ZEND_ASSERT(Z_OBJ_HT_P(orig) == &spl_handler_ArrayIterator);
- ZVAL_COPY(&intern->array, &other->array);
+ ZVAL_COPY(&intern->array, orig);
+ intern->ar_flags |= SPL_ARRAY_USE_OTHER;
}
} else {
ZVAL_COPY(&intern->array, orig);
@@ -269,13 +281,13 @@ static zval *spl_array_get_dimension_ptr(int check_inherited, zval *object, zval
zend_long index;
zend_string *offset_key;
spl_array_object *intern = Z_SPLARRAY_P(object);
- HashTable *ht = spl_array_get_hash_table(intern, 0);
+ HashTable *ht = spl_array_get_hash_table(intern);
if (!offset || Z_ISUNDEF_P(offset)) {
return &EG(uninitialized_zval);
}
- if ((type == BP_VAR_W || type == BP_VAR_RW) && (ht->u.v.nApplyCount > 0)) {
+ if ((type == BP_VAR_W || type == BP_VAR_RW) && intern->nApplyCount > 0) {
zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
return &EG(error_zval);
}
@@ -434,16 +446,8 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval
return;
}
- if (!offset) {
- ht = spl_array_get_hash_table(intern, 0);
- if (ht->u.v.nApplyCount > 0) {
- zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
- return;
- }
- if (Z_REFCOUNTED_P(value)) {
- Z_ADDREF_P(value);
- }
- zend_hash_next_index_insert(ht, value);
+ if (intern->nApplyCount > 0) {
+ zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
return;
}
@@ -451,14 +455,16 @@ static void spl_array_write_dimension_ex(int check_inherited, zval *object, zval
Z_ADDREF_P(value);
}
+ if (!offset) {
+ ht = spl_array_get_hash_table(intern);
+ zend_hash_next_index_insert(ht, value);
+ return;
+ }
+
try_again:
switch (Z_TYPE_P(offset)) {
case IS_STRING:
- ht = spl_array_get_hash_table(intern, 0);
- if (ht->u.v.nApplyCount > 0) {
- zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
- return;
- }
+ ht = spl_array_get_hash_table(intern);
zend_symtable_update_ind(ht, Z_STR_P(offset), value);
return;
case IS_DOUBLE:
@@ -476,19 +482,11 @@ try_again:
case IS_LONG:
index = Z_LVAL_P(offset);
num_index:
- ht = spl_array_get_hash_table(intern, 0);
- if (ht->u.v.nApplyCount > 0) {
- zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
- return;
- }
+ ht = spl_array_get_hash_table(intern);
zend_hash_index_update(ht, index, value);
return;
case IS_NULL:
- ht = spl_array_get_hash_table(intern, 0);
- if (ht->u.v.nApplyCount > 0) {
- zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
- return;
- }
+ ht = spl_array_get_hash_table(intern);
zend_hash_next_index_insert(ht, value);
return;
case IS_REFERENCE:
@@ -496,6 +494,7 @@ num_index:
goto try_again;
default:
zend_error(E_WARNING, "Illegal offset type");
+ zval_ptr_dtor(value);
return;
}
} /* }}} */
@@ -518,14 +517,15 @@ static void spl_array_unset_dimension_ex(int check_inherited, zval *object, zval
return;
}
+ if (intern->nApplyCount > 0) {
+ zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+ return;
+ }
+
try_again:
switch (Z_TYPE_P(offset)) {
case IS_STRING:
- ht = spl_array_get_hash_table(intern, 0);
- if (ht->u.v.nApplyCount > 0) {
- zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
- return;
- }
+ ht = spl_array_get_hash_table(intern);
if (ht == &EG(symbol_table)) {
if (zend_delete_global_variable(Z_STR_P(offset))) {
zend_error(E_NOTICE,"Undefined index: %s", Z_STRVAL_P(offset));
@@ -570,11 +570,7 @@ try_again:
case IS_LONG:
index = Z_LVAL_P(offset);
num_index:
- ht = spl_array_get_hash_table(intern, 0);
- if (ht->u.v.nApplyCount > 0) {
- zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
- return;
- }
+ ht = spl_array_get_hash_table(intern);
if (zend_hash_index_del(ht, index) == FAILURE) {
zend_error(E_NOTICE,"Undefined offset: %pd", index);
}
@@ -618,7 +614,7 @@ static int spl_array_has_dimension_ex(int check_inherited, zval *object, zval *o
}
if (!value) {
- HashTable *ht = spl_array_get_hash_table(intern, 0);
+ HashTable *ht = spl_array_get_hash_table(intern);
try_again:
switch (Z_TYPE_P(offset)) {
@@ -744,7 +740,7 @@ SPL_METHOD(Array, offsetSet)
void spl_array_iterator_append(zval *object, zval *append_value) /* {{{ */
{
spl_array_object *intern = Z_SPLARRAY_P(object);
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
if (!aht) {
php_error_docref(NULL, E_NOTICE, "Array was modified outside object and is no longer an array");
@@ -792,22 +788,21 @@ SPL_METHOD(Array, getArrayCopy)
zval *object = getThis();
spl_array_object *intern = Z_SPLARRAY_P(object);
- RETURN_ARR(zend_array_dup(spl_array_get_hash_table(intern, 0)));
+ RETURN_ARR(zend_array_dup(spl_array_get_hash_table(intern)));
} /* }}} */
static HashTable *spl_array_get_properties(zval *object) /* {{{ */
{
spl_array_object *intern = Z_SPLARRAY_P(object);
- HashTable *result;
- if (intern->nApplyCount > 1) {
- php_error_docref(NULL, E_ERROR, "Nesting level too deep - recursive dependency?");
+ if (intern->ar_flags & SPL_ARRAY_STD_PROP_LIST) {
+ if (!intern->std.properties) {
+ rebuild_object_properties(&intern->std);
+ }
+ return intern->std.properties;
}
- intern->nApplyCount++;
- result = spl_array_get_hash_table(intern, 1);
- intern->nApplyCount--;
- return result;
+ return spl_array_get_hash_table(intern);
} /* }}} */
static HashTable* spl_array_get_debug_info(zval *obj, int *is_temp) /* {{{ */
@@ -922,8 +917,8 @@ static int spl_array_compare_objects(zval *o1, zval *o2) /* {{{ */
intern1 = Z_SPLARRAY_P(o1);
intern2 = Z_SPLARRAY_P(o2);
- ht1 = spl_array_get_hash_table(intern1, 0);
- ht2 = spl_array_get_hash_table(intern2, 0);
+ ht1 = spl_array_get_hash_table(intern1);
+ ht2 = spl_array_get_hash_table(intern2);
result = zend_compare_symbol_tables(ht1, ht2);
/* if we just compared std.properties, don't do it again */
@@ -978,7 +973,7 @@ static int spl_array_next_ex(spl_array_object *intern, HashTable *aht) /* {{{ */
static int spl_array_next(spl_array_object *intern) /* {{{ */
{
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
return spl_array_next_ex(intern, aht);
@@ -994,7 +989,7 @@ static void spl_array_it_dtor(zend_object_iterator *iter) /* {{{ */
static int spl_array_it_valid(zend_object_iterator *iter) /* {{{ */
{
spl_array_object *object = Z_SPLARRAY_P(&iter->data);
- HashTable *aht = spl_array_get_hash_table(object, 0);
+ HashTable *aht = spl_array_get_hash_table(object);
if (object->ar_flags & SPL_ARRAY_OVERLOADED_VALID) {
return zend_user_it_valid(iter);
@@ -1011,7 +1006,7 @@ static int spl_array_it_valid(zend_object_iterator *iter) /* {{{ */
static zval *spl_array_it_get_current_data(zend_object_iterator *iter) /* {{{ */
{
spl_array_object *object = Z_SPLARRAY_P(&iter->data);
- HashTable *aht = spl_array_get_hash_table(object, 0);
+ HashTable *aht = spl_array_get_hash_table(object);
if (object->ar_flags & SPL_ARRAY_OVERLOADED_CURRENT) {
return zend_user_it_get_current_data(iter);
@@ -1028,7 +1023,7 @@ static zval *spl_array_it_get_current_data(zend_object_iterator *iter) /* {{{ */
static void spl_array_it_get_current_key(zend_object_iterator *iter, zval *key) /* {{{ */
{
spl_array_object *object = Z_SPLARRAY_P(&iter->data);
- HashTable *aht = spl_array_get_hash_table(object, 0);
+ HashTable *aht = spl_array_get_hash_table(object);
if (object->ar_flags & SPL_ARRAY_OVERLOADED_KEY) {
zend_user_it_get_current_key(iter, key);
@@ -1045,7 +1040,7 @@ static void spl_array_it_get_current_key(zend_object_iterator *iter, zval *key)
static void spl_array_it_move_forward(zend_object_iterator *iter) /* {{{ */
{
spl_array_object *object = Z_SPLARRAY_P(&iter->data);
- HashTable *aht = spl_array_get_hash_table(object, 0);
+ HashTable *aht = spl_array_get_hash_table(object);
if (object->ar_flags & SPL_ARRAY_OVERLOADED_NEXT) {
zend_user_it_move_forward(iter);
@@ -1063,7 +1058,7 @@ static void spl_array_it_move_forward(zend_object_iterator *iter) /* {{{ */
static void spl_array_rewind(spl_array_object *intern) /* {{{ */
{
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
if (!aht) {
php_error_docref(NULL, E_NOTICE, "ArrayIterator::rewind(): Array was modified outside object and is no longer an array");
@@ -1099,13 +1094,13 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar
return;
}
- zval_ptr_dtor(&intern->array);
-
if (Z_TYPE_P(array) == IS_ARRAY) {
//??? TODO: try to avoid array duplication
+ zval_ptr_dtor(&intern->array);
ZVAL_DUP(&intern->array, array);
} else {
if (Z_OBJ_HT_P(array) == &spl_handler_ArrayObject || Z_OBJ_HT_P(array) == &spl_handler_ArrayIterator) {
+ zval_ptr_dtor(&intern->array);
if (just_array) {
spl_array_object *other = Z_SPLARRAY_P(array);
ar_flags = other->ar_flags & ~SPL_ARRAY_INT_MASK;
@@ -1119,18 +1114,13 @@ static void spl_array_set_array(zval *object, spl_array_object *intern, zval *ar
}
} else {
zend_object_get_properties_t handler = Z_OBJ_HANDLER_P(array, get_properties);
- if (handler != std_object_handlers.get_properties
- || !spl_array_get_hash_table(intern, 0)) {
- ZVAL_UNDEF(&intern->array);
- zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0, "Overloaded object of type %s is not compatible with %s", Z_OBJCE_P(array)->name, intern->std.ce->name);
- }
- //??? TODO: try to avoid array duplication
- if (Z_OBJ_P(array)->properties && GC_REFCOUNT(Z_OBJ_P(array)->properties) > 1) {
- if (EXPECTED(!(GC_FLAGS(Z_OBJ_P(array)->properties) & IS_ARRAY_IMMUTABLE))) {
- GC_REFCOUNT(Z_OBJ_P(array)->properties)--;
- }
- Z_OBJ_P(array)->properties = zend_array_dup(Z_OBJ_P(array)->properties);
+ if (handler != std_object_handlers.get_properties) {
+ zend_throw_exception_ex(spl_ce_InvalidArgumentException, 0,
+ "Overloaded object of type %s is not compatible with %s",
+ ZSTR_VAL(Z_OBJCE_P(array)->name), ZSTR_VAL(intern->std.ce->name));
+ return;
}
+ zval_ptr_dtor(&intern->array);
ZVAL_COPY(&intern->array, array);
}
}
@@ -1284,7 +1274,12 @@ SPL_METHOD(Array, exchangeArray)
return;
}
- RETVAL_ARR(zend_array_dup(spl_array_get_hash_table(intern, 0)));
+ if (intern->nApplyCount > 0) {
+ zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
+ return;
+ }
+
+ RETVAL_ARR(zend_array_dup(spl_array_get_hash_table(intern)));
spl_array_set_array(object, intern, array, 0L, 1);
}
/* }}} */
@@ -1295,7 +1290,7 @@ SPL_METHOD(Array, getIterator)
{
zval *object = getThis();
spl_array_object *intern = Z_SPLARRAY_P(object);
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1332,7 +1327,7 @@ SPL_METHOD(Array, seek)
zend_long opos, position;
zval *object = getThis();
spl_array_object *intern = Z_SPLARRAY_P(object);
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
int result;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "l", &position) == FAILURE) {
@@ -1361,7 +1356,7 @@ SPL_METHOD(Array, seek)
int static spl_array_object_count_elements_helper(spl_array_object *intern, zend_long *count) /* {{{ */
{
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
HashPosition pos, *pos_ptr;
if (!aht) {
@@ -1426,7 +1421,7 @@ SPL_METHOD(Array, count)
static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fname_len, int use_arg) /* {{{ */
{
spl_array_object *intern = Z_SPLARRAY_P(getThis());
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
zval function_name, params[2], *arg = NULL;
uint32_t old_refcount;
@@ -1440,9 +1435,9 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam
ZVAL_ARR(Z_REFVAL(params[0]), aht);
if (!use_arg) {
- aht->u.v.nApplyCount++;
+ intern->nApplyCount++;
call_user_function_ex(EG(function_table), NULL, &function_name, return_value, 1, params, 1, NULL);
- aht->u.v.nApplyCount--;
+ intern->nApplyCount--;
} else if (use_arg == SPL_ARRAY_METHOD_MAY_USER_ARG) {
if (zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "|z", &arg) == FAILURE) {
zend_throw_exception(spl_ce_BadMethodCallException, "Function expects one argument at most", 0);
@@ -1451,18 +1446,18 @@ static void spl_array_method(INTERNAL_FUNCTION_PARAMETERS, char *fname, int fnam
if (arg) {
ZVAL_COPY_VALUE(&params[1], arg);
}
- aht->u.v.nApplyCount++;
+ intern->nApplyCount++;
call_user_function_ex(EG(function_table), NULL, &function_name, return_value, arg ? 2 : 1, params, 1, NULL);
- aht->u.v.nApplyCount--;
+ intern->nApplyCount--;
} else {
if (ZEND_NUM_ARGS() != 1 || zend_parse_parameters_ex(ZEND_PARSE_PARAMS_QUIET, ZEND_NUM_ARGS(), "z", &arg) == FAILURE) {
zend_throw_exception(spl_ce_BadMethodCallException, "Function expects exactly one argument", 0);
goto exit;
}
ZVAL_COPY_VALUE(&params[1], arg);
- aht->u.v.nApplyCount++;
+ intern->nApplyCount++;
call_user_function_ex(EG(function_table), NULL, &function_name, return_value, 2, params, 1, NULL);
- aht->u.v.nApplyCount--;
+ intern->nApplyCount--;
}
exit:
@@ -1515,7 +1510,7 @@ SPL_METHOD(Array, current)
zval *object = getThis();
spl_array_object *intern = Z_SPLARRAY_P(object);
zval *entry;
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1553,7 +1548,7 @@ SPL_METHOD(Array, key)
void spl_array_iterator_key(zval *object, zval *return_value) /* {{{ */
{
spl_array_object *intern = Z_SPLARRAY_P(object);
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
if (spl_array_object_verify_pos(intern, aht) == FAILURE) {
return;
@@ -1569,7 +1564,7 @@ SPL_METHOD(Array, next)
{
zval *object = getThis();
spl_array_object *intern = Z_SPLARRAY_P(object);
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1589,7 +1584,7 @@ SPL_METHOD(Array, valid)
{
zval *object = getThis();
spl_array_object *intern = Z_SPLARRAY_P(object);
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1609,7 +1604,7 @@ SPL_METHOD(Array, hasChildren)
{
zval *object = getThis(), *entry;
spl_array_object *intern = Z_SPLARRAY_P(object);
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1633,7 +1628,7 @@ SPL_METHOD(Array, getChildren)
{
zval *object = getThis(), *entry, flags;
spl_array_object *intern = Z_SPLARRAY_P(object);
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
if (zend_parse_parameters_none() == FAILURE) {
return;
@@ -1669,7 +1664,7 @@ SPL_METHOD(Array, serialize)
{
zval *object = getThis();
spl_array_object *intern = Z_SPLARRAY_P(object);
- HashTable *aht = spl_array_get_hash_table(intern, 0);
+ HashTable *aht = spl_array_get_hash_table(intern);
zval members, flags;
php_serialize_data_t var_hash;
smart_str buf = {0};
@@ -1728,7 +1723,6 @@ SPL_METHOD(Array, unserialize)
const unsigned char *p, *s;
php_unserialize_data_t var_hash;
zval *members, *zflags;
- HashTable *aht;
zend_long flags;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "s", &buf, &buf_len) == FAILURE) {
@@ -1739,8 +1733,7 @@ SPL_METHOD(Array, unserialize)
return;
}
- aht = spl_array_get_hash_table(intern, 0);
- if (aht->u.v.nApplyCount > 0) {
+ if (intern->nApplyCount > 0) {
zend_error(E_WARNING, "Modification of ArrayObject during sorting is prohibited");
return;
}
diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c
index b0ee3bc7a3..412fc54324 100644
--- a/ext/spl/spl_directory.c
+++ b/ext/spl/spl_directory.c
@@ -834,7 +834,7 @@ SPL_METHOD(DirectoryIterator, seek)
zval_ptr_dtor(&retval);
}
if (!valid) {
- zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0 TSRMLS_CC, "Seek position %ld is out of range", pos);
+ zend_throw_exception_ex(spl_ce_OutOfBoundsException, 0, "Seek position %ld is out of range", pos);
return;
}
zend_call_method_with_0_params(&EX(This), Z_OBJCE(EX(This)), &intern->u.dir.func_next, "next", NULL);
diff --git a/ext/spl/tests/ArrayObject_clone_other_std_props.phpt b/ext/spl/tests/ArrayObject_clone_other_std_props.phpt
new file mode 100644
index 0000000000..688954c3d7
--- /dev/null
+++ b/ext/spl/tests/ArrayObject_clone_other_std_props.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Clone ArrayObject using other with STD_PROP_LIST
+--FILE--
+<?php
+
+$a = new ArrayObject([1, 2, 3], ArrayObject::STD_PROP_LIST);
+$b = new ArrayObject($a);
+$c = clone $b;
+var_dump($c);
+
+?>
+--EXPECT--
+object(ArrayObject)#3 (1) {
+ ["storage":"ArrayObject":private]=>
+ array(3) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+ }
+}
diff --git a/ext/spl/tests/ArrayObject_dump_during_sort.phpt b/ext/spl/tests/ArrayObject_dump_during_sort.phpt
new file mode 100644
index 0000000000..0fb128b655
--- /dev/null
+++ b/ext/spl/tests/ArrayObject_dump_during_sort.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Dumping an ArrayObject while it is being sorted
+--FILE--
+<?php
+
+$ao = new ArrayObject([1, 2, 3]);
+$i = 0;
+$ao->uasort(function($a, $b) use ($ao, &$i) {
+ if ($i++ == 0) {
+ var_dump($ao);
+ }
+ return $a <=> $b;
+});
+
+?>
+--EXPECT--
+object(ArrayObject)#1 (1) {
+ ["storage":"ArrayObject":private]=>
+ array(3) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+ }
+}
diff --git a/ext/spl/tests/ArrayObject_exchange_array_during_sorting.phpt b/ext/spl/tests/ArrayObject_exchange_array_during_sorting.phpt
new file mode 100644
index 0000000000..225d42c1ed
--- /dev/null
+++ b/ext/spl/tests/ArrayObject_exchange_array_during_sorting.phpt
@@ -0,0 +1,29 @@
+--TEST--
+Can't use exchangeArray() while ArrayObject is being sorted
+--FILE--
+<?php
+
+$ao = new ArrayObject([1, 2, 3]);
+$i = 0;
+$ao->uasort(function($a, $b) use ($ao, &$i) {
+ if ($i++ == 0) {
+ $ao->exchangeArray([4, 5, 6]);
+ var_dump($ao);
+ }
+ return $a <=> $b;
+});
+
+?>
+--EXPECTF--
+Warning: Modification of ArrayObject during sorting is prohibited in %s on line %d
+object(ArrayObject)#1 (1) {
+ ["storage":"ArrayObject":private]=>
+ array(3) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+ }
+}
diff --git a/ext/spl/tests/ArrayObject_illegal_offset_leak.phpt b/ext/spl/tests/ArrayObject_illegal_offset_leak.phpt
new file mode 100644
index 0000000000..42c649db9f
--- /dev/null
+++ b/ext/spl/tests/ArrayObject_illegal_offset_leak.phpt
@@ -0,0 +1,11 @@
+--TEST--
+Assignments to illegal ArrayObject offsets shouldn't leak
+--FILE--
+<?php
+
+$ao = new ArrayObject([1, 2, 3]);
+$ao[[]] = new stdClass;
+
+?>
+--EXPECTF--
+Warning: Illegal offset type in %s on line %d
diff --git a/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt b/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt
new file mode 100644
index 0000000000..24c247cabd
--- /dev/null
+++ b/ext/spl/tests/ArrayObject_modify_shared_object_properties.phpt
@@ -0,0 +1,19 @@
+--TEST--
+Modifications to ArrayObjects should not affect shared properties tables
+--FILE--
+<?php
+
+$obj = (object)['a' => 1, 'b' => 2];
+$ao = new ArrayObject($obj);
+$arr = (array) $obj;
+$ao['a'] = 42;
+var_dump($arr);
+
+?>
+--EXPECT--
+array(2) {
+ ["a"]=>
+ int(1)
+ ["b"]=>
+ int(2)
+}
diff --git a/ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt b/ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt
new file mode 100644
index 0000000000..8c1121b8d0
--- /dev/null
+++ b/ext/spl/tests/ArrayObject_overloaded_object_incompatible.phpt
@@ -0,0 +1,27 @@
+--TEST--
+Objects with overloaded get_properties are incompatible with ArrayObject
+--FILE--
+<?php
+
+$ao = new ArrayObject([1, 2, 3]);
+try {
+ $ao->exchangeArray(new SplFixedArray);
+} catch (Exception $e) {
+ echo $e->getMessage(), "\n";
+}
+var_dump($ao);
+
+?>
+--EXPECT--
+Overloaded object of type SplFixedArray is not compatible with ArrayObject
+object(ArrayObject)#1 (1) {
+ ["storage":"ArrayObject":private]=>
+ array(3) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+ }
+}
diff --git a/ext/spl/tests/ArrayObject_std_props_no_recursion.phpt b/ext/spl/tests/ArrayObject_std_props_no_recursion.phpt
new file mode 100644
index 0000000000..193e972530
--- /dev/null
+++ b/ext/spl/tests/ArrayObject_std_props_no_recursion.phpt
@@ -0,0 +1,28 @@
+--TEST--
+Don't recurse into USE_OTHER when checking for STD_PROP_LIST
+--FILE--
+<?php
+
+$a = new ArrayObject([1, 2, 3], ArrayObject::STD_PROP_LIST);
+$a->prop = 'a';
+$b = new ArrayObject($a, 0);
+$b->prop = 'b';
+var_dump((array) $b);
+$c = new ArrayObject($a);
+$c->prop = 'c';
+var_dump((array) $c);
+
+?>
+--EXPECT--
+array(3) {
+ [0]=>
+ int(1)
+ [1]=>
+ int(2)
+ [2]=>
+ int(3)
+}
+array(1) {
+ ["prop"]=>
+ string(1) "c"
+}
diff --git a/ext/spl/tests/bug71617.phpt b/ext/spl/tests/bug71617.phpt
new file mode 100644
index 0000000000..412f83f541
--- /dev/null
+++ b/ext/spl/tests/bug71617.phpt
@@ -0,0 +1,50 @@
+--TEST--
+Bug #71617: private properties lost when unserializing ArrayObject
+--FILE--
+<?php
+
+class Test extends ArrayObject
+{
+
+ private $name = null;
+
+ public function __construct(array $input)
+ {
+ parent::__construct($input, ArrayObject::ARRAY_AS_PROPS);
+ }
+
+ public function setName($name)
+ {
+ $this->name = $name;
+ return $this;
+ }
+
+ public function getName()
+ {
+ return $this->name;
+ }
+}
+
+$test = new Test(['a' => 'a', 'b' => 'b']);
+$test->setName('ok');
+
+$ser = serialize($test);
+$unSer = unserialize($ser);
+
+var_dump($unSer->getName());
+var_dump($unSer);
+
+?>
+--EXPECT--
+string(2) "ok"
+object(Test)#2 (2) {
+ ["name":"Test":private]=>
+ string(2) "ok"
+ ["storage":"ArrayObject":private]=>
+ array(2) {
+ ["a"]=>
+ string(1) "a"
+ ["b"]=>
+ string(1) "b"
+ }
+}
diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c
index 6f2656ab51..912cc9cb2d 100644
--- a/ext/sqlite3/sqlite3.c
+++ b/ext/sqlite3/sqlite3.c
@@ -117,7 +117,8 @@ PHP_METHOD(sqlite3, open)
if (strlen(filename) != filename_len) {
return;
}
- if (memcmp(filename, ":memory:", sizeof(":memory:")) != 0) {
+ if (filename_len != sizeof(":memory:")-1 ||
+ memcmp(filename, ":memory:", sizeof(":memory:")-1) != 0) {
if (!(fullpath = expand_filepath(filename, NULL))) {
zend_throw_exception(zend_ce_exception, "Unable to expand filepath", 0);
return;
diff --git a/ext/standard/array.c b/ext/standard/array.c
index 62279287b6..def7d7c465 100644
--- a/ext/standard/array.c
+++ b/ext/standard/array.c
@@ -1771,7 +1771,7 @@ PHPAPI int php_prefix_varname(zval *result, zval *prefix, char *var_name, size_t
Imports variables into symbol table from an array */
PHP_FUNCTION(extract)
{
- zval *var_array, *prefix = NULL;
+ zval *var_array_param, *prefix = NULL;
zend_long extract_type = EXTR_OVERWRITE;
zval *entry;
zend_string *var_name;
@@ -1779,14 +1779,15 @@ PHP_FUNCTION(extract)
int var_exists, count = 0;
int extract_refs = 0;
zend_array *symbol_table;
+ zval var_array;
#ifndef FAST_ZPP
- if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|lz/", &var_array, &extract_type, &prefix) == FAILURE) {
+ if (zend_parse_parameters(ZEND_NUM_ARGS(), "a|lz/", &var_array_param, &extract_type, &prefix) == FAILURE) {
return;
}
#else
ZEND_PARSE_PARAMETERS_START(1, 3)
- Z_PARAM_ARRAY(var_array)
+ Z_PARAM_ARRAY(var_array_param)
Z_PARAM_OPTIONAL
Z_PARAM_LONG(extract_type)
Z_PARAM_ZVAL_EX(prefix, 0, 1)
@@ -1795,7 +1796,7 @@ PHP_FUNCTION(extract)
extract_refs = (extract_type & EXTR_REFS);
if (extract_refs) {
- SEPARATE_ZVAL(var_array);
+ SEPARATE_ZVAL(var_array_param);
}
extract_type &= 0xff;
@@ -1825,7 +1826,11 @@ PHP_FUNCTION(extract)
}
#endif
- ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL_P(var_array), num_key, var_name, entry) {
+ /* The array might be stored in a local variable that will be overwritten. To avoid losing the
+ * reference in that case we work on a copy. */
+ ZVAL_COPY(&var_array, var_array_param);
+
+ ZEND_HASH_FOREACH_KEY_VAL_IND(Z_ARRVAL(var_array), num_key, var_name, entry) {
zval final_name;
ZVAL_NULL(&final_name);
@@ -1926,6 +1931,7 @@ PHP_FUNCTION(extract)
}
zval_dtor(&final_name);
} ZEND_HASH_FOREACH_END();
+ zval_ptr_dtor(&var_array);
RETURN_LONG(count);
}
@@ -1938,6 +1944,7 @@ static void php_compact_var(HashTable *eg_active_symbol_table, zval *return_valu
ZVAL_DEREF(entry);
if (Z_TYPE_P(entry) == IS_STRING) {
if ((value_ptr = zend_hash_find_ind(eg_active_symbol_table, Z_STR_P(entry))) != NULL) {
+ ZVAL_DEREF(value_ptr);
ZVAL_COPY(&data, value_ptr);
zend_hash_update(Z_ARRVAL_P(return_value), Z_STR_P(entry), &data);
}
@@ -3491,6 +3498,10 @@ static inline zval *array_column_fetch_prop(zval *data, zval *name, zval *rv)
}
}
+ if (prop) {
+ ZVAL_DEREF(prop);
+ }
+
return prop;
}
diff --git a/ext/standard/iptc.c b/ext/standard/iptc.c
index 480da221a4..7e5a8987b4 100644
--- a/ext/standard/iptc.c
+++ b/ext/standard/iptc.c
@@ -206,7 +206,7 @@ PHP_FUNCTION(iptcembed)
}
if (iptcdata_len >= SIZE_MAX - sizeof(psheader) - 1025) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "IPTC data too large");
+ php_error_docref(NULL, E_WARNING, "IPTC data too large");
RETURN_FALSE;
}
diff --git a/ext/standard/pack.c b/ext/standard/pack.c
index ab7e9c71dc..a24ee69ad2 100644
--- a/ext/standard/pack.c
+++ b/ext/standard/pack.c
@@ -986,7 +986,7 @@ PHP_FUNCTION(unpack)
/* Reached end of input for '*' repeater */
break;
} else {
- php_error_docref(NULL, E_WARNING, "Type %c: not enough input, need %d, have %d", type, size, inputlen - inputpos);
+ php_error_docref(NULL, E_WARNING, "Type %c: not enough input, need %d, have " ZEND_LONG_FMT, type, size, inputlen - inputpos);
zval_dtor(return_value);
RETURN_FALSE;
}
diff --git a/ext/standard/string.c b/ext/standard/string.c
index 2dbe41ed5e..489006b261 100644
--- a/ext/standard/string.c
+++ b/ext/standard/string.c
@@ -4943,7 +4943,7 @@ PHPAPI size_t php_strip_tags_ex(char *rbuf, size_t len, int *stateptr, const cha
* state == 2 (PHP). Switch back to HTML.
*/
- if (state == 2 && p > buf+2 && strncasecmp(p-4, "<?xm", 4) == 0) {
+ if (state == 2 && p > buf+4 && strncasecmp(p-4, "<?xm", 4) == 0) {
state = 1; is_xml=1;
break;
}
diff --git a/ext/standard/tests/array/bug71603.phpt b/ext/standard/tests/array/bug71603.phpt
new file mode 100644
index 0000000000..0c25be660c
--- /dev/null
+++ b/ext/standard/tests/array/bug71603.phpt
@@ -0,0 +1,15 @@
+--TEST--
+Bug #71603 (compact() maintains references in php7)
+--FILE--
+<?php
+$foo = "okey";
+$foo_reference =& $foo;
+
+$array = compact('foo_reference');
+
+$foo = 'changed!';
+
+var_dump($array['foo_reference']);
+
+--EXPECT--
+string(4) "okey"
diff --git a/ext/standard/tests/array/bug71660.phpt b/ext/standard/tests/array/bug71660.phpt
new file mode 100644
index 0000000000..c2d7192378
--- /dev/null
+++ b/ext/standard/tests/array/bug71660.phpt
@@ -0,0 +1,18 @@
+--TEST--
+Bug #71660 (array_column behaves incorrectly after foreach by reference)
+--FILE--
+<?php
+$arr = array('id' => 12345, 'name' => 'sam');
+foreach ($arr as &$v) {
+ $v = $v;
+}
+
+$arr = [$arr];
+
+var_dump(array_column($arr, 'name', 'id'));
+?>
+--EXPECT--
+array(1) {
+ [12345]=>
+ string(3) "sam"
+}
diff --git a/ext/standard/tests/math/mt_rand_value.phpt b/ext/standard/tests/math/mt_rand_value.phpt
new file mode 100644
index 0000000000..772305ad63
--- /dev/null
+++ b/ext/standard/tests/math/mt_rand_value.phpt
@@ -0,0 +1,44 @@
+--TEST--
+Test mt_rand() output
+--FILE--
+<?php
+
+mt_srand(12345678);
+
+for ($i=0; $i<16; $i++) {
+ echo mt_rand().PHP_EOL;
+}
+echo PHP_EOL;
+
+$x = 0;
+for ($i=0; $i<1024; $i++) {
+ $x ^= mt_rand();
+}
+echo $x.PHP_EOL;
+
+/*
+ * Note that the output will be different from the original mt19937ar.c,
+ * because PHP's implementation contains a bug. Thus, this test actually
+ * checks to make sure that PHP's behaviour is wrong, but consistently so.
+ */
+
+?>
+--EXPECTF--
+1614640687
+1711027313
+857485497
+688176834
+1386682158
+412773096
+813703253
+898651287
+2087374214
+1382556330
+1640700129
+1863374167
+1324097651
+1923803667
+676334965
+853386222
+
+1571178311
diff --git a/ext/standard/var.c b/ext/standard/var.c
index 61a7179dbb..fcee7a9cc6 100644
--- a/ext/standard/var.c
+++ b/ext/standard/var.c
@@ -108,7 +108,7 @@ again:
php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc));
break;
case IS_STRING:
- php_printf("%sstring(%d) \"", COMMON, Z_STRLEN_P(struc));
+ php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc));
PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc));
PUTS("\"\n");
break;
@@ -278,7 +278,7 @@ again:
php_printf("%sfloat(%.*G)\n", COMMON, (int) EG(precision), Z_DVAL_P(struc));
break;
case IS_STRING:
- php_printf("%sstring(%d) \"", COMMON, Z_STRLEN_P(struc));
+ php_printf("%sstring(%zd) \"", COMMON, Z_STRLEN_P(struc));
PHPWRITE(Z_STRVAL_P(struc), Z_STRLEN_P(struc));
php_printf("\" refcount(%u)\n", Z_REFCOUNTED_P(struc) ? Z_REFCOUNT_P(struc) : 1);
break;
@@ -336,7 +336,7 @@ again:
break;
case IS_RESOURCE: {
const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(struc));
- php_printf("%sresource(" ZEND_LONG_FMT ") of type (%s) refcount(%u)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc));
+ php_printf("%sresource(%d) of type (%s) refcount(%u)\n", COMMON, Z_RES_P(struc)->handle, type_name ? type_name : "Unknown", Z_REFCOUNT_P(struc));
break;
}
case IS_REFERENCE:
@@ -1045,7 +1045,8 @@ PHP_FUNCTION(unserialize)
}
zval_ptr_dtor(return_value);
if (!EG(exception)) {
- php_error_docref(NULL, E_NOTICE, "Error at offset " ZEND_LONG_FMT " of %d bytes", (zend_long)((char*)p - buf), buf_len);
+ php_error_docref(NULL, E_NOTICE, "Error at offset " ZEND_LONG_FMT " of %zd bytes",
+ (zend_long)((char*)p - buf), buf_len);
}
RETURN_FALSE;
}
diff --git a/ext/xmlrpc/tests/bug71501.phpt b/ext/xmlrpc/tests/bug71501.phpt
new file mode 100644
index 0000000000..950d21d6d4
--- /dev/null
+++ b/ext/xmlrpc/tests/bug71501.phpt
@@ -0,0 +1,23 @@
+--TEST--
+Bug #71501 (xmlrpc_encode_request ignores encoding option)
+--SKIPIF--
+<?php
+if (!extension_loaded("xmlrpc")) print "skip";
+?>
+--FILE--
+<?php
+$params = 'Lê Trung Hiếu';
+echo xmlrpc_encode_request('foo', $params, ['encoding' => 'UTF-8', 'escaping' => 'markup']);
+?>
+--EXPECTF--
+<?xml version="1.0" encoding="UTF-8"?>
+<methodCall>
+<methodName>foo</methodName>
+<params>
+ <param>
+ <value>
+ <string>Lê Trung Hiếu</string>
+ </value>
+ </param>
+</params>
+</methodCall>
diff --git a/ext/xmlrpc/xmlrpc-epi-php.c b/ext/xmlrpc/xmlrpc-epi-php.c
index dd39047bf0..ea62bdc9a9 100644
--- a/ext/xmlrpc/xmlrpc-epi-php.c
+++ b/ext/xmlrpc/xmlrpc-epi-php.c
@@ -411,45 +411,46 @@ static void set_output_options(php_output_options* options, zval* output_opts)
}
}
- /* encoding code set */
- if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ENCODING_KEY, ENCODING_KEY_LEN)) != NULL) {
- if (Z_TYPE_P(val) == IS_STRING) {
- options->xmlrpc_out.xml_elem_opts.encoding = estrdup(Z_STRVAL_P(val));
- }
+ }
+
+ /* encoding code set */
+ if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ENCODING_KEY, ENCODING_KEY_LEN)) != NULL) {
+ if (Z_TYPE_P(val) == IS_STRING) {
+ options->xmlrpc_out.xml_elem_opts.encoding = estrdup(Z_STRVAL_P(val));
}
+ }
- /* escaping options */
- if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ESCAPING_KEY, ESCAPING_KEY_LEN)) != NULL) {
- /* multiple values allowed. check if array */
- if (Z_TYPE_P(val) == IS_ARRAY) {
- zval* iter_val;
-
- options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_no_escaping;
-
- ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(val), iter_val) {
- if (Z_TYPE_P(iter_val) == IS_STRING && Z_STRVAL_P(iter_val)) {
- if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_CDATA)) {
- options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_cdata_escaping;
- } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_ASCII)) {
- options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_ascii_escaping;
- } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_PRINT)) {
- options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_print_escaping;
- } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_MARKUP)) {
- options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_markup_escaping;
- }
+ /* escaping options */
+ if ((val = zend_hash_str_find(Z_ARRVAL_P(output_opts), ESCAPING_KEY, ESCAPING_KEY_LEN)) != NULL) {
+ /* multiple values allowed. check if array */
+ if (Z_TYPE_P(val) == IS_ARRAY) {
+ zval* iter_val;
+
+ options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_no_escaping;
+
+ ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(val), iter_val) {
+ if (Z_TYPE_P(iter_val) == IS_STRING && Z_STRVAL_P(iter_val)) {
+ if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_CDATA)) {
+ options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_cdata_escaping;
+ } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_ASCII)) {
+ options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_ascii_escaping;
+ } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_NON_PRINT)) {
+ options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_non_print_escaping;
+ } else if (!strcmp(Z_STRVAL_P(iter_val), ESCAPING_VALUE_MARKUP)) {
+ options->xmlrpc_out.xml_elem_opts.escaping |= xml_elem_markup_escaping;
}
- } ZEND_HASH_FOREACH_END();
- /* else, check for single value */
- } else if (Z_TYPE_P(val) == IS_STRING) {
- if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_CDATA)) {
- options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_cdata_escaping;
- } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_ASCII)) {
- options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_ascii_escaping;
- } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_PRINT)) {
- options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_print_escaping;
- } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_MARKUP)) {
- options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping;
}
+ } ZEND_HASH_FOREACH_END();
+ /* else, check for single value */
+ } else if (Z_TYPE_P(val) == IS_STRING) {
+ if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_CDATA)) {
+ options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_cdata_escaping;
+ } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_ASCII)) {
+ options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_ascii_escaping;
+ } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_NON_PRINT)) {
+ options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_non_print_escaping;
+ } else if (!strcmp(Z_STRVAL_P(val), ESCAPING_VALUE_MARKUP)) {
+ options->xmlrpc_out.xml_elem_opts.escaping = xml_elem_markup_escaping;
}
}
}
diff --git a/ext/xsl/tests/bug71540.phpt b/ext/xsl/tests/bug71540.phpt
new file mode 100644
index 0000000000..a268021765
--- /dev/null
+++ b/ext/xsl/tests/bug71540.phpt
@@ -0,0 +1,69 @@
+--TEST--
+Bug #71540 (NULL pointer dereference in xsl_ext_function_php())
+--SKIPIF--
+<?php
+if (!extension_loaded('xsl')) die("skip Extension XSL is required\n");
+?>
+--FILE--
+<?php
+$xml = <<<EOB
+<allusers>
+ <user>
+ <uid>bob</uid>
+ </user>
+</allusers>
+EOB;
+$xsl = <<<EOB
+<?xml version="1.0" encoding="UTF-8"?>
+<xsl:stylesheet version="1.0"
+ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
+ xmlns:php="http://php.net/xsl">
+<xsl:output method="html" encoding="utf-8" indent="yes"/>
+ <xsl:template match="allusers">
+ <html><body>
+ <h2>Users</h2>
+ <table>
+ <xsl:for-each select="user">
+ <tr><td>
+ <xsl:value-of
+ select="php:function('test',uid,test(test))"/>
+ </td></tr>
+ </xsl:for-each>
+ </table>
+ </body></html>
+ </xsl:template>
+</xsl:stylesheet>
+EOB;
+
+$xmldoc = new DOMDocument();
+$xmldoc->loadXML($xml);
+$xsldoc = new DOMDocument();
+$xsldoc->loadXML($xsl);
+
+$proc = new XSLTProcessor();
+$proc->registerPHPFunctions();
+$proc->importStyleSheet($xsldoc);
+echo $proc->transformToXML($xmldoc);
+?>
+DONE
+--EXPECTF--
+Warning: XSLTProcessor::transformToXml(): xmlXPathCompOpEval: function test not found in %sbug71540.php on line %d
+
+Warning: XSLTProcessor::transformToXml(): Unregistered function in %sbug71540.php on line %d
+
+Warning: XSLTProcessor::transformToXml(): Stack usage errror in %sbug71540.php on line %d
+
+Warning: XSLTProcessor::transformToXml(): Stack usage errror in %sbug71540.php on line %d
+
+Warning: XSLTProcessor::transformToXml(): Handler name must be a string in %sbug71540.php on line %d
+
+Warning: XSLTProcessor::transformToXml(): xmlXPathCompiledEval: 2 objects left on the stack. in %sbug71540.php on line %d
+
+Warning: XSLTProcessor::transformToXml(): runtime error: file %s line 13 element value-of in %sbug71540.php on line %d
+
+Warning: XSLTProcessor::transformToXml(): XPath evaluation returned no result. in %sbug71540.php on line %d
+<html xmlns:php="http://php.net/xsl"><body>
+<h2>Users</h2>
+<table><tr><td></td></tr></table>
+</body></html>
+DONE \ No newline at end of file
diff --git a/ext/xsl/xsltprocessor.c b/ext/xsl/xsltprocessor.c
index be46d38de1..600c7cddb0 100644
--- a/ext/xsl/xsltprocessor.c
+++ b/ext/xsl/xsltprocessor.c
@@ -231,6 +231,10 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
/* Reverse order to pop values off ctxt stack */
for (i = nargs - 2; i >= 0; i--) {
obj = valuePop(ctxt);
+ if (obj == NULL) {
+ ZVAL_NULL(&args[i]);
+ continue;
+ }
switch (obj->type) {
case XPATH_STRING:
ZVAL_STRING(&args[i], (char *)obj->stringval);
@@ -300,7 +304,7 @@ static void xsl_ext_function_php(xmlXPathParserContextPtr ctxt, int nargs, int t
obj = valuePop(ctxt);
- if (obj->stringval == NULL) {
+ if (obj == NULL || obj->stringval == NULL) {
php_error_docref(NULL, E_WARNING, "Handler name must be a string");
xmlXPathFreeObject(obj);
valuePush(ctxt, xmlXPathNewString((const xmlChar *) ""));
diff --git a/ext/zip/config.m4 b/ext/zip/config.m4
index 6dbc1e292b..81f47df556 100644
--- a/ext/zip/config.m4
+++ b/ext/zip/config.m4
@@ -122,6 +122,7 @@ if test "$PHP_ZIP" != "no"; then
lib/zip_get_archive_comment.c lib/zip_get_archive_flag.c lib/zip_get_compression_implementation.c\
lib/zip_get_encryption_implementation.c lib/zip_get_file_comment.c lib/zip_get_name.c lib/zip_get_num_entries.c \
lib/zip_get_num_files.c lib/zip_memdup.c lib/zip_name_locate.c lib/zip_new.c lib/zip_open.c lib/zip_rename.c lib/zip_replace.c\
+ lib/zip_hash.c \
lib/zip_set_archive_comment.c lib/zip_set_archive_flag.c lib/zip_set_default_password.c lib/zip_set_file_comment.c\
lib/zip_set_file_compression.c lib/zip_set_name.c lib/zip_source_buffer.c lib/zip_source_close.c lib/zip_source_crc.c\
lib/zip_source_deflate.c lib/zip_source_error.c lib/zip_source_file.c lib/zip_source_filep.c lib/zip_source_free.c\
diff --git a/ext/zip/config.w32 b/ext/zip/config.w32
index 0aa9f3eaa0..5460b6d6bd 100644
--- a/ext/zip/config.w32
+++ b/ext/zip/config.w32
@@ -21,6 +21,7 @@ if (PHP_ZIP != "no") {
zip_get_archive_comment.c zip_get_archive_flag.c zip_get_compression_implementation.c\
zip_get_encryption_implementation.c zip_get_file_comment.c zip_get_name.c zip_get_num_entries.c \
zip_get_num_files.c zip_memdup.c zip_name_locate.c zip_new.c zip_open.c zip_rename.c zip_replace.c\
+ zip_hash.c \
zip_set_archive_comment.c zip_set_archive_flag.c zip_set_default_password.c zip_set_file_comment.c\
zip_set_file_compression.c zip_set_name.c zip_source_buffer.c zip_source_close.c zip_source_crc.c\
zip_source_deflate.c zip_source_error.c zip_source_filep.c zip_source_free.c\
diff --git a/ext/zip/lib/zip_add_entry.c b/ext/zip/lib/zip_add_entry.c
index 24dbdaf47c..9a9465c5f0 100644
--- a/ext/zip/lib/zip_add_entry.c
+++ b/ext/zip/lib/zip_add_entry.c
@@ -1,6 +1,6 @@
/*
zip_add_entry.c -- create and init struct zip_entry
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -46,8 +46,19 @@ _zip_add_entry(zip_t *za)
if (za->nentry+1 >= za->nentry_alloc) {
zip_entry_t *rentries;
- zip_uint64_t nalloc = za->nentry_alloc + 16;
- zip_uint64_t realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
+ zip_uint64_t nalloc = za->nentry_alloc;
+ zip_uint64_t additional_entries = 2 * nalloc;
+ zip_uint64_t realloc_size;
+
+ if (additional_entries < 16) {
+ additional_entries = 16;
+ }
+ else if (additional_entries > 1024) {
+ additional_entries = 1024;
+ }
+ /* neither + nor * overflows can happen: nentry_alloc * sizeof(struct zip_entry) < UINT64_MAX */
+ nalloc += additional_entries;
+ realloc_size = sizeof(struct zip_entry) * (size_t)nalloc;
if (sizeof(struct zip_entry) * (size_t)za->nentry_alloc > realloc_size) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
diff --git a/ext/zip/lib/zip_buffer.c b/ext/zip/lib/zip_buffer.c
index 3d79b09f13..43864f9ba9 100644
--- a/ext/zip/lib/zip_buffer.c
+++ b/ext/zip/lib/zip_buffer.c
@@ -303,6 +303,17 @@ _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset)
}
+int
+_zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length) {
+ zip_uint64_t offset = buffer->offset + length;
+
+ if (offset < buffer->offset) {
+ buffer->ok = false;
+ return -1;
+ }
+ return _zip_buffer_set_offset(buffer, offset);
+}
+
zip_uint64_t
_zip_buffer_size(zip_buffer_t *buffer)
{
diff --git a/ext/zip/lib/zip_close.c b/ext/zip/lib/zip_close.c
index a13e4466b3..b5eca67a46 100644
--- a/ext/zip/lib/zip_close.c
+++ b/ext/zip/lib/zip_close.c
@@ -40,7 +40,6 @@
#ifdef HAVE_STRINGS_H
#include <strings.h>
#endif
-#include <errno.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
diff --git a/ext/zip/lib/zip_delete.c b/ext/zip/lib/zip_delete.c
index b3e7abb848..34520b0310 100644
--- a/ext/zip/lib/zip_delete.c
+++ b/ext/zip/lib/zip_delete.c
@@ -1,6 +1,6 @@
/*
zip_delete.c -- delete file from zip archive
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -38,6 +38,8 @@
ZIP_EXTERN int
zip_delete(zip_t *za, zip_uint64_t idx)
{
+ const char *name;
+
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
return -1;
@@ -48,6 +50,14 @@ zip_delete(zip_t *za, zip_uint64_t idx)
return -1;
}
+ if ((name=_zip_get_name(za, idx, 0, &za->error)) == NULL) {
+ return -1;
+ }
+
+ if (!_zip_hash_delete(za->names, (const zip_uint8_t *)name, &za->error)) {
+ return -1;
+ }
+
/* allow duplicate file names, because the file will
* be removed directly afterwards */
if (_zip_unchange(za, idx, 1) != 0)
diff --git a/ext/zip/lib/zip_dirent.c b/ext/zip/lib/zip_dirent.c
index e3a78b3146..630b6a49cb 100644
--- a/ext/zip/lib/zip_dirent.c
+++ b/ext/zip/lib/zip_dirent.c
@@ -1,6 +1,6 @@
/*
zip_dirent.c -- read directory entry (local or central), clean dirent
- Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -17,7 +17,7 @@
3. The names of the authors may not be used to endorse or promote
products derived from this software without specific prior
written permission.
-
+
THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
@@ -35,7 +35,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
@@ -67,7 +66,7 @@ _zip_cdir_new(zip_uint64_t nentry, zip_error_t *error)
{
zip_cdir_t *cd;
zip_uint64_t i;
-
+
if ((cd=(zip_cdir_t *)malloc(sizeof(*cd))) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
@@ -110,7 +109,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
}
offset = (zip_uint64_t)off;
- is_zip64 = 0;
+ is_zip64 = false;
for (i=0; i<survivors; i++) {
zip_entry_t *entry = za->entry+filelist[i].idx;
@@ -135,7 +134,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
return -1;
}
-
+
if (is_zip64) {
_zip_buffer_put(buffer, EOCD64_MAGIC, 4);
_zip_buffer_put_64(buffer, EOCD64LEN-12);
@@ -152,7 +151,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
_zip_buffer_put_64(buffer, offset+size);
_zip_buffer_put_32(buffer, 1);
}
-
+
_zip_buffer_put(buffer, EOCD_MAGIC, 4);
_zip_buffer_put_32(buffer, 0);
_zip_buffer_put_16(buffer, (zip_uint16_t)(survivors >= ZIP_UINT16_MAX ? ZIP_UINT16_MAX : survivors));
@@ -163,7 +162,7 @@ _zip_cdir_write(zip_t *za, const zip_filelist_t *filelist, zip_uint64_t survivor
comment = za->comment_changed ? za->comment_changes : za->comment_orig;
_zip_buffer_put_16(buffer, (zip_uint16_t)(comment ? comment->length : 0));
-
+
if (!_zip_buffer_ok(buffer)) {
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
_zip_buffer_free(buffer);
@@ -199,7 +198,7 @@ _zip_dirent_clone(const zip_dirent_t *sde)
memcpy(tde, sde, sizeof(*sde));
else
_zip_dirent_init(tde);
-
+
tde->changed = 0;
tde->cloned = 1;
@@ -289,7 +288,7 @@ _zip_dirent_new(void)
Fills the zip directory entry zde.
If buffer is non-NULL, data is taken from there; otherwise data is read from fp as needed.
-
+
If local is true, it reads a local header instead of a central directory entry.
Returns size of dirent read if successful. On error, error is filled in and -1 is returned.
@@ -304,7 +303,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
zip_uint16_t filename_len, comment_len, ef_len;
bool from_buffer = (buffer != NULL);
-
+
size = local ? LENTRYSIZE : CDENTRYSIZE;
if (buffer) {
@@ -337,19 +336,19 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
zde->version_needed = _zip_buffer_get_16(buffer);
zde->bitflags = _zip_buffer_get_16(buffer);
zde->comp_method = _zip_buffer_get_16(buffer);
-
+
/* convert to time_t */
dostime = _zip_buffer_get_16(buffer);
dosdate = _zip_buffer_get_16(buffer);
zde->last_mod = _zip_d2u_time(dostime, dosdate);
-
+
zde->crc = _zip_buffer_get_32(buffer);
zde->comp_size = _zip_buffer_get_32(buffer);
zde->uncomp_size = _zip_buffer_get_32(buffer);
-
+
filename_len = _zip_buffer_get_16(buffer);
ef_len = _zip_buffer_get_16(buffer);
-
+
if (local) {
comment_len = 0;
zde->disk_number = 0;
@@ -363,7 +362,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
zde->ext_attrib = _zip_buffer_get_32(buffer);
zde->offset = _zip_buffer_get_32(buffer);
}
-
+
if (!_zip_buffer_ok(buffer)) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
if (!from_buffer) {
@@ -386,7 +385,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
}
else {
_zip_buffer_free(buffer);
-
+
if ((buffer = _zip_buffer_new_from_source(src, variable_size, NULL, error)) == NULL) {
return -1;
}
@@ -424,7 +423,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
}
return -1;
}
- if ((zde->extra_fields=_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, error)) == NULL) {
+ if (!_zip_ef_parse(ef, ef_len, local ? ZIP_EF_LOCAL : ZIP_EF_CENTRAL, &zde->extra_fields, error)) {
free(ef);
if (!from_buffer) {
_zip_buffer_free(buffer);
@@ -471,7 +470,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
}
return -1;
}
-
+
if ((ef_buffer = _zip_buffer_new((zip_uint8_t *)ef, got_len)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
if (!from_buffer) {
@@ -479,11 +478,14 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
}
return -1;
}
-
+
if (zde->uncomp_size == ZIP_UINT32_MAX)
zde->uncomp_size = _zip_buffer_get_64(ef_buffer);
- else if (local)
- ef += 8;
+ else if (local) {
+ /* From appnote.txt: This entry in the Local header MUST
+ include BOTH original and compressed file size fields. */
+ (void)_zip_buffer_skip(ef_buffer, 8); /* error is caught by _zip_buffer_eof() call */
+ }
if (zde->comp_size == ZIP_UINT32_MAX)
zde->comp_size = _zip_buffer_get_64(ef_buffer);
if (!local) {
@@ -492,7 +494,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
if (zde->disk_number == ZIP_UINT16_MAX)
zde->disk_number = _zip_buffer_get_32(buffer);
}
-
+
if (!_zip_buffer_eof(ef_buffer)) {
zip_error_set(error, ZIP_ER_INCONS, 0);
_zip_buffer_free(ef_buffer);
@@ -503,7 +505,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
}
_zip_buffer_free(ef_buffer);
}
-
+
if (!_zip_buffer_ok(buffer)) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
if (!from_buffer) {
@@ -520,7 +522,7 @@ _zip_dirent_read(zip_dirent_t *zde, zip_source_t *src, zip_buffer_t *buffer, boo
zip_error_set(error, ZIP_ER_SEEK, EFBIG);
return -1;
}
-
+
zde->extra_fields = _zip_ef_remove_internal(zde->extra_fields);
return (zip_int64_t)(size + variable_size);
@@ -535,15 +537,15 @@ _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string
zip_buffer_t *buffer;
const zip_uint8_t *ef = _zip_ef_get_by_id(de->extra_fields, &ef_len, id, 0, ZIP_EF_BOTH, NULL);
-
+
if (ef == NULL || ef_len < 5 || ef[0] != 1) {
return str;
}
-
+
if ((buffer = _zip_buffer_new((zip_uint8_t *)ef, ef_len)) == NULL) {
return str;
}
-
+
_zip_buffer_get_8(buffer);
ef_crc = _zip_buffer_get_32(buffer);
@@ -556,9 +558,9 @@ _zip_dirent_process_ef_utf_8(const zip_dirent_t *de, zip_uint16_t id, zip_string
str = ef_str;
}
}
-
+
_zip_buffer_free(buffer);
-
+
return str;
}
@@ -578,7 +580,7 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error)
_zip_error_set_from_source(error, src);
return -1;
}
-
+
if ((buffer = _zip_buffer_new_from_source(src, local ? 4 : 6, b, error)) == NULL) {
return -1;
}
@@ -586,7 +588,7 @@ _zip_dirent_size(zip_source_t *src, zip_uint16_t flags, zip_error_t *error)
for (i=0; i<(local ? 2 : 3); i++) {
size += _zip_buffer_get_16(buffer);
}
-
+
if (!_zip_buffer_eof(buffer)) {
zip_error_set(error, ZIP_ER_INTERNAL, 0);
_zip_buffer_free(buffer);
@@ -614,16 +616,15 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
zip_uint16_t dostime, dosdate;
zip_encoding_type_t com_enc, name_enc;
zip_extra_field_t *ef;
+ zip_extra_field_t *ef64;
+ zip_uint32_t ef_total_size;
bool is_zip64;
bool is_really_zip64;
zip_uint8_t buf[CDENTRYSIZE];
zip_buffer_t *buffer;
- zip_uint32_t ef_total_size;
ef = NULL;
- is_zip64 = false;
-
name_enc = _zip_guess_encoding(de->filename, ZIP_ENCODING_UNKNOWN);
com_enc = _zip_guess_encoding(de->comment, ZIP_ENCODING_UNKNOWN);
@@ -648,20 +649,19 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
ef = ef2;
}
}
-
+
is_really_zip64 = _zip_dirent_needs_zip64(de, flags);
is_zip64 = (flags & (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64)) == (ZIP_FL_LOCAL|ZIP_FL_FORCE_ZIP64) || is_really_zip64;
-
+
if (is_zip64) {
zip_uint8_t ef_zip64[EFZIP64SIZE];
zip_buffer_t *ef_buffer = _zip_buffer_new(ef_zip64, sizeof(ef_zip64));
- zip_extra_field_t *ef64;
if (ef_buffer == NULL) {
zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
_zip_ef_free(ef);
return -1;
}
-
+
if (flags & ZIP_FL_LOCAL) {
if ((flags & ZIP_FL_FORCE_ZIP64) || de->comp_size > ZIP_UINT32_MAX || de->uncomp_size > ZIP_UINT32_MAX) {
_zip_buffer_put_64(ef_buffer, de->uncomp_size);
@@ -681,7 +681,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
}
}
}
-
+
if (!_zip_buffer_ok(ef_buffer)) {
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
_zip_buffer_free(ef_buffer);
@@ -700,9 +700,9 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
_zip_ef_free(ef);
return -1;
}
-
+
_zip_buffer_put(buffer, (flags & ZIP_FL_LOCAL) ? LOCAL_MAGIC : CENTRAL_MAGIC, 4);
-
+
if ((flags & ZIP_FL_LOCAL) == 0) {
_zip_buffer_put_16(buffer, (zip_uint16_t)(is_really_zip64 ? 45 : de->version_madeby));
}
@@ -715,7 +715,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
_zip_buffer_put_16(buffer, dosdate);
_zip_buffer_put_32(buffer, de->crc);
-
+
if (((flags & ZIP_FL_LOCAL) == ZIP_FL_LOCAL) && ((de->comp_size >= ZIP_UINT32_MAX) || (de->uncomp_size >= ZIP_UINT32_MAX))) {
/* In local headers, if a ZIP64 EF is written, it MUST contain
* both compressed and uncompressed sizes (even if one of the
@@ -744,7 +744,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
/* TODO: check for overflow */
ef_total_size = (zip_uint32_t)_zip_ef_size(de->extra_fields, flags) + (zip_uint32_t)_zip_ef_size(ef, ZIP_EF_BOTH);
_zip_buffer_put_16(buffer, (zip_uint16_t)ef_total_size);
-
+
if ((flags & ZIP_FL_LOCAL) == 0) {
_zip_buffer_put_16(buffer, _zip_string_length(de->comment));
_zip_buffer_put_16(buffer, (zip_uint16_t)de->disk_number);
@@ -755,7 +755,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
else
_zip_buffer_put_32(buffer, ZIP_UINT32_MAX);
}
-
+
if (!_zip_buffer_ok(buffer)) {
zip_error_set(&za->error, ZIP_ER_INTERNAL, 0);
_zip_buffer_free(buffer);
@@ -768,7 +768,7 @@ _zip_dirent_write(zip_t *za, zip_dirent_t *de, zip_flags_t flags)
_zip_ef_free(ef);
return -1;
}
-
+
_zip_buffer_free(buffer);
if (de->filename) {
@@ -810,10 +810,10 @@ _zip_d2u_time(zip_uint16_t dtime, zip_uint16_t ddate)
struct tm tm;
memset(&tm, 0, sizeof(tm));
-
+
/* let mktime decide if DST is in effect */
tm.tm_isdst = -1;
-
+
tm.tm_year = ((ddate>>9)&127) + 1980 - 1900;
tm.tm_mon = ((ddate>>5)&15) - 1;
tm.tm_mday = ddate&31;
@@ -834,13 +834,16 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error)
zip_buffer_t *buffer;
zip_extra_field_t *ef;
- raw = _zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL);
+ if ((raw=_zip_string_get(str, &len, ZIP_FL_ENC_RAW, NULL)) == NULL) {
+ /* error already set */
+ return NULL;
+ }
if (len+5 > ZIP_UINT16_MAX) {
zip_error_set(error, ZIP_ER_INVAL, 0); /* TODO: better error code? */
return NULL;
}
-
+
if ((buffer = _zip_buffer_new(NULL, len+5)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
return NULL;
@@ -855,7 +858,7 @@ _zip_ef_utf8(zip_uint16_t id, zip_string_t *str, zip_error_t *error)
_zip_buffer_free(buffer);
return NULL;
}
-
+
ef = _zip_ef_new(id, (zip_uint16_t)(_zip_buffer_offset(buffer)), _zip_buffer_data(buffer), ZIP_EF_BOTH);
_zip_buffer_free(buffer);
@@ -898,6 +901,10 @@ _zip_u2d_time(time_t intime, zip_uint16_t *dtime, zip_uint16_t *ddate)
struct tm *tm;
tm = localtime(&intime);
+ if (tm->tm_year < 80) {
+ tm->tm_year = 80;
+ }
+
*ddate = (zip_uint16_t)(((tm->tm_year+1900-1980)<<9) + ((tm->tm_mon+1)<<5) + tm->tm_mday);
*dtime = (zip_uint16_t)(((tm->tm_hour)<<11) + ((tm->tm_min)<<5) + ((tm->tm_sec)>>1));
diff --git a/ext/zip/lib/zip_discard.c b/ext/zip/lib/zip_discard.c
index db22370842..1876c84f0c 100644
--- a/ext/zip/lib/zip_discard.c
+++ b/ext/zip/lib/zip_discard.c
@@ -1,6 +1,6 @@
/*
zip_discard.c -- discard and free struct zip
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -58,6 +58,8 @@ zip_discard(zip_t *za)
_zip_string_free(za->comment_orig);
_zip_string_free(za->comment_changes);
+ _zip_hash_free(za->names);
+
if (za->entry) {
for (i=0; i<za->nentry; i++)
_zip_entry_finalize(za->entry+i);
diff --git a/ext/zip/lib/zip_error.c b/ext/zip/lib/zip_error.c
index a21a00bc29..43ddf4f9cb 100644
--- a/ext/zip/lib/zip_error.c
+++ b/ext/zip/lib/zip_error.c
@@ -1,6 +1,6 @@
/*
zip_error.c -- zip_error_t helper functions
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -31,7 +31,6 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
#include <stdlib.h>
#include "zipint.h"
diff --git a/ext/zip/lib/zip_error_strerror.c b/ext/zip/lib/zip_error_strerror.c
index 2f124ccd46..29efc8a91c 100644
--- a/ext/zip/lib/zip_error_strerror.c
+++ b/ext/zip/lib/zip_error_strerror.c
@@ -1,6 +1,6 @@
/*
zip_error_sterror.c -- get string representation of struct zip_error
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@
*/
-#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/ext/zip/lib/zip_error_to_str.c b/ext/zip/lib/zip_error_to_str.c
index d4119253f7..22de177842 100644
--- a/ext/zip/lib/zip_error_to_str.c
+++ b/ext/zip/lib/zip_error_to_str.c
@@ -1,6 +1,6 @@
/*
zip_error_to_str.c -- get string representation of zip error code
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@
*/
-#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/ext/zip/lib/zip_extra_field.c b/ext/zip/lib/zip_extra_field.c
index b2566c6887..035047827e 100644
--- a/ext/zip/lib/zip_extra_field.c
+++ b/ext/zip/lib/zip_extra_field.c
@@ -31,13 +31,11 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
-#include "zipint.h"
-
-#include <errno.h>
#include <stdlib.h>
#include <string.h>
+#include "zipint.h"
+
zip_extra_field_t *
_zip_ef_clone(const zip_extra_field_t *ef, zip_error_t *error)
@@ -207,20 +205,20 @@ _zip_ef_new(zip_uint16_t id, zip_uint16_t size, const zip_uint8_t *data, zip_fla
}
-zip_extra_field_t *
-_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_error_t *error)
+bool
+_zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_extra_field_t **ef_head_p, zip_error_t *error)
{
zip_buffer_t *buffer;
zip_extra_field_t *ef, *ef2, *ef_head;
if ((buffer = _zip_buffer_new((zip_uint8_t *)data, len)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
- return NULL;
+ return false;
}
ef_head = ef = NULL;
- while (_zip_buffer_ok(buffer) && !_zip_buffer_eof(buffer)) {
+ while (_zip_buffer_ok(buffer) && _zip_buffer_left(buffer) >= 4) {
zip_uint16_t fid, flen;
zip_uint8_t *ef_data;
@@ -229,14 +227,17 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_
ef_data = _zip_buffer_get(buffer, flen);
if (ef_data == NULL) {
- break;
+ zip_error_set(error, ZIP_ER_INCONS, 0);
+ _zip_buffer_free(buffer);
+ _zip_ef_free(ef_head);
+ return false;
}
if ((ef2=_zip_ef_new(fid, flen, ef_data, flags)) == NULL) {
zip_error_set(error, ZIP_ER_MEMORY, 0);
_zip_buffer_free(buffer);
_zip_ef_free(ef_head);
- return NULL;
+ return false;
}
if (ef_head) {
@@ -248,15 +249,29 @@ _zip_ef_parse(const zip_uint8_t *data, zip_uint16_t len, zip_flags_t flags, zip_
}
if (!_zip_buffer_eof(buffer)) {
- zip_error_set(error, ZIP_ER_INCONS, 0);
- _zip_buffer_free(buffer);
- _zip_ef_free(ef_head);
- return NULL;
+ /* Android APK files align stored file data with padding in extra fields; ignore. */
+ /* see https://android.googlesource.com/platform/build/+/master/tools/zipalign/ZipAlign.cpp */
+ size_t glen = _zip_buffer_left(buffer);
+ zip_uint8_t *garbage;
+ garbage = _zip_buffer_get(buffer, glen);
+ if (glen >= 4 || garbage == NULL || memcmp(garbage, "\0\0\0", glen) != 0) {
+ zip_error_set(error, ZIP_ER_INCONS, 0);
+ _zip_buffer_free(buffer);
+ _zip_ef_free(ef_head);
+ return false;
+ }
}
_zip_buffer_free(buffer);
+
+ if (ef_head_p) {
+ *ef_head_p = ef_head;
+ }
+ else {
+ _zip_ef_free(ef_head);
+ }
- return ef_head;
+ return true;
}
@@ -400,14 +415,16 @@ _zip_read_local_ef(zip_t *za, zip_uint64_t idx)
if (ef_raw == NULL)
return -1;
- if ((ef=_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &za->error)) == NULL) {
+ if (!_zip_ef_parse(ef_raw, ef_len, ZIP_EF_LOCAL, &ef, &za->error)) {
free(ef_raw);
return -1;
}
free(ef_raw);
-
- ef = _zip_ef_remove_internal(ef);
- e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
+
+ if (ef) {
+ ef = _zip_ef_remove_internal(ef);
+ e->orig->extra_fields = _zip_ef_merge(e->orig->extra_fields, ef);
+ }
}
e->orig->local_extra_fields_read = 1;
diff --git a/ext/zip/lib/zip_fdopen.c b/ext/zip/lib/zip_fdopen.c
index c5b55311d2..bbcdf4f6bf 100644
--- a/ext/zip/lib/zip_fdopen.c
+++ b/ext/zip/lib/zip_fdopen.c
@@ -33,6 +33,9 @@
#include "zipint.h"
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
ZIP_EXTERN zip_t *
diff --git a/ext/zip/lib/zip_file_get_offset.c b/ext/zip/lib/zip_file_get_offset.c
index 1aaca712d7..0257b042bc 100644
--- a/ext/zip/lib/zip_file_get_offset.c
+++ b/ext/zip/lib/zip_file_get_offset.c
@@ -1,6 +1,6 @@
/*
zip_file_get_offset.c -- get offset of file data in archive.
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -35,7 +35,6 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
-#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
diff --git a/ext/zip/lib/zip_filerange_crc.c b/ext/zip/lib/zip_filerange_crc.c
index 8e06e8fa8b..f2a27fab34 100644
--- a/ext/zip/lib/zip_filerange_crc.c
+++ b/ext/zip/lib/zip_filerange_crc.c
@@ -1,6 +1,6 @@
/*
zip_filerange_crc.c -- compute CRC32 for a range of a file
- Copyright (C) 2008-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2008-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -33,7 +33,6 @@
#include <stdio.h>
-#include <errno.h>
#include "zipint.h"
diff --git a/ext/zip/lib/zip_fopen_index.c b/ext/zip/lib/zip_fopen_index.c
index e9a169a2e1..7496f9829f 100644
--- a/ext/zip/lib/zip_fopen_index.c
+++ b/ext/zip/lib/zip_fopen_index.c
@@ -1,6 +1,6 @@
/*
zip_fopen_index.c -- open file in zip archive for reading by index
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@
*/
-#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/ext/zip/lib/zip_fopen_index_encrypted.c b/ext/zip/lib/zip_fopen_index_encrypted.c
index 21cc43333c..92258e85fe 100644
--- a/ext/zip/lib/zip_fopen_index_encrypted.c
+++ b/ext/zip/lib/zip_fopen_index_encrypted.c
@@ -1,6 +1,6 @@
/*
zip_fopen_index_encrypted.c -- open file for reading by index w/ password
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@
*/
-#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
diff --git a/ext/zip/lib/zip_hash.c b/ext/zip/lib/zip_hash.c
new file mode 100644
index 0000000000..23f9708dfd
--- /dev/null
+++ b/ext/zip/lib/zip_hash.c
@@ -0,0 +1,267 @@
+/*
+ zip_hash.c -- hash table string -> uint64
+ Copyright (C) 2015-2016 Dieter Baron and Thomas Klausner
+
+ This file is part of libzip, a library to manipulate ZIP archives.
+ The authors can be contacted at <libzip@nih.at>
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions
+ are met:
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE AUTHORS ``AS IS'' AND ANY EXPRESS
+ OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY
+ DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
+ IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+*/
+
+#include <stdlib.h>
+#include <string.h>
+#include "zipint.h"
+
+struct zip_hash_entry {
+ const zip_uint8_t *name;
+ zip_int64_t orig_index;
+ zip_int64_t current_index;
+ struct zip_hash_entry *next;
+};
+typedef struct zip_hash_entry zip_hash_entry_t;
+
+struct zip_hash {
+ zip_uint16_t table_size;
+ zip_hash_entry_t **table;
+};
+
+zip_hash_t *
+_zip_hash_new(zip_uint16_t table_size, zip_error_t *error)
+{
+ zip_hash_t *hash;
+
+ if (table_size == 0) {
+ zip_error_set(error, ZIP_ER_INTERNAL, 0);
+ return NULL;
+ }
+
+ if ((hash=(zip_hash_t *)malloc(sizeof(zip_hash_t))) == NULL) {
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
+ }
+ hash->table_size = table_size;
+ if ((hash->table=(zip_hash_entry_t**)calloc(table_size, sizeof(zip_hash_entry_t *))) == NULL) {
+ free(hash);
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return NULL;
+ }
+
+ return hash;
+}
+
+static void
+_free_list(zip_hash_entry_t *entry)
+{
+ zip_hash_entry_t *next;
+ do {
+ next = entry->next;
+ free(entry);
+ entry = next;
+ } while (entry != NULL);
+}
+
+void
+_zip_hash_free(zip_hash_t *hash)
+{
+ zip_uint16_t i;
+
+ if (hash == NULL) {
+ return;
+ }
+
+ for (i=0; i<hash->table_size; i++) {
+ if (hash->table[i] != NULL) {
+ _free_list(hash->table[i]);
+ }
+ }
+ free(hash->table);
+ free(hash);
+}
+
+static zip_uint16_t
+_hash_string(const zip_uint8_t *name, zip_uint16_t size)
+{
+#define HASH_MULTIPLIER 33
+ zip_uint16_t value = 5381;
+
+ if (name == NULL)
+ return 0;
+
+ while (*name != 0) {
+ value = (zip_uint16_t)(((value * HASH_MULTIPLIER) + (zip_uint8_t)*name) % size);
+ name++;
+ }
+
+ return value;
+}
+
+/* insert into hash, return error on existence or memory issues */
+bool
+_zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error)
+{
+ zip_uint16_t hash_value;
+ zip_hash_entry_t *entry;
+
+ if (hash == NULL || name == NULL || index > ZIP_INT64_MAX) {
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return false;
+ }
+
+ hash_value = _hash_string(name, hash->table_size);
+ for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
+ if (strcmp((const char *)name, (const char *)entry->name) == 0) {
+ if (((flags & ZIP_FL_UNCHANGED) && entry->orig_index != -1) || entry->current_index != -1) {
+ zip_error_set(error, ZIP_ER_EXISTS, 0);
+ return false;
+ }
+ else {
+ break;
+ }
+ }
+ }
+
+ if (entry == NULL) {
+ if ((entry=(zip_hash_entry_t *)malloc(sizeof(zip_hash_entry_t))) == NULL) {
+ zip_error_set(error, ZIP_ER_MEMORY, 0);
+ return false;
+ }
+ entry->name = name;
+ entry->next = hash->table[hash_value];
+ hash->table[hash_value] = entry;
+ entry->orig_index = -1;
+ }
+
+ if (flags & ZIP_FL_UNCHANGED) {
+ entry->orig_index = (zip_int64_t)index;
+ }
+ entry->current_index = (zip_int64_t)index;
+
+ return true;
+}
+
+/* remove entry from hash, error if not found */
+bool
+_zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *name, zip_error_t *error)
+{
+ zip_uint16_t hash_value;
+ zip_hash_entry_t *entry, *previous;
+
+ if (hash == NULL || name == NULL) {
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return false;
+ }
+
+ hash_value = _hash_string(name, hash->table_size);
+ previous = NULL;
+ entry = hash->table[hash_value];
+ while (entry) {
+ if (strcmp((const char *)name, (const char *)entry->name) == 0) {
+ if (entry->orig_index == -1) {
+ if (previous) {
+ previous->next = entry->next;
+ }
+ else {
+ hash->table[hash_value] = entry->next;
+ }
+ free(entry);
+ }
+ else {
+ entry->current_index = -1;
+ }
+ return true;
+ }
+ previous = entry;
+ entry = entry->next;
+ };
+
+ zip_error_set(error, ZIP_ER_NOENT, 0);
+ return false;
+}
+
+/* find value for entry in hash, -1 if not found */
+zip_int64_t
+_zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error)
+{
+ zip_uint16_t hash_value;
+ zip_hash_entry_t *entry;
+
+ if (hash == NULL || name == NULL) {
+ zip_error_set(error, ZIP_ER_INVAL, 0);
+ return -1;
+ }
+
+ hash_value = _hash_string(name, hash->table_size);
+ for (entry = hash->table[hash_value]; entry != NULL; entry = entry->next) {
+ if (strcmp((const char *)name, (const char *)entry->name) == 0) {
+ if (flags & ZIP_FL_UNCHANGED) {
+ if (entry->orig_index != -1) {
+ return entry->orig_index;
+ }
+ }
+ else {
+ if (entry->current_index != -1) {
+ return entry->current_index;
+ }
+ }
+ break;
+ }
+ }
+
+ zip_error_set(error, ZIP_ER_NOENT, 0);
+ return -1;
+}
+
+void
+_zip_hash_revert(zip_hash_t *hash)
+{
+ zip_uint16_t i;
+ zip_hash_entry_t *entry, *previous;
+
+ for (i = 0; i < hash->table_size; i++) {
+ previous = NULL;
+ entry = hash->table[i];
+ while (entry) {
+ if (entry->orig_index == -1) {
+ zip_hash_entry_t *p;
+ if (previous) {
+ previous->next = entry->next;
+ }
+ else {
+ hash->table[i] = entry->next;
+ }
+ p = entry;
+ entry = entry->next;
+ /* previous does not change */
+ free(p);
+ }
+ else {
+ entry->current_index = entry->orig_index;
+ previous = entry;
+ entry = entry->next;
+ }
+ }
+ }
+}
diff --git a/ext/zip/lib/zip_io_util.c b/ext/zip/lib/zip_io_util.c
index 4a6bc1ddc1..b16927defb 100644
--- a/ext/zip/lib/zip_io_util.c
+++ b/ext/zip/lib/zip_io_util.c
@@ -1,6 +1,6 @@
/*
zip_io_util.c -- I/O helper functions
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -31,7 +31,6 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
#include <stdlib.h>
#include <string.h>
diff --git a/ext/zip/lib/zip_name_locate.c b/ext/zip/lib/zip_name_locate.c
index 820ea0ca7f..50ca40b1a9 100644
--- a/ext/zip/lib/zip_name_locate.c
+++ b/ext/zip/lib/zip_name_locate.c
@@ -1,6 +1,6 @@
/*
zip_name_locate.c -- get index by name
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -62,27 +62,33 @@ _zip_name_locate(zip_t *za, const char *fname, zip_flags_t flags, zip_error_t *e
return -1;
}
- cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
-
- for (i=0; i<za->nentry; i++) {
- fn = _zip_get_name(za, i, flags, error);
-
- /* newly added (partially filled) entry or error */
- if (fn == NULL)
- continue;
-
- if (flags & ZIP_FL_NODIR) {
- p = strrchr(fn, '/');
- if (p)
- fn = p+1;
+ if (flags & (ZIP_FL_NOCASE|ZIP_FL_NODIR|ZIP_FL_ENC_CP437)) {
+ /* can't use hash table */
+ cmp = (flags & ZIP_FL_NOCASE) ? strcasecmp : strcmp;
+
+ for (i=0; i<za->nentry; i++) {
+ fn = _zip_get_name(za, i, flags, error);
+
+ /* newly added (partially filled) entry or error */
+ if (fn == NULL)
+ continue;
+
+ if (flags & ZIP_FL_NODIR) {
+ p = strrchr(fn, '/');
+ if (p)
+ fn = p+1;
+ }
+
+ if (cmp(fname, fn) == 0) {
+ _zip_error_clear(error);
+ return (zip_int64_t)i;
+ }
}
- if (cmp(fname, fn) == 0) {
- _zip_error_clear(error);
- return (zip_int64_t)i;
- }
+ zip_error_set(error, ZIP_ER_NOENT, 0);
+ return -1;
+ }
+ else {
+ return _zip_hash_lookup(za->names, (const zip_uint8_t *)fname, flags, error);
}
-
- zip_error_set(error, ZIP_ER_NOENT, 0);
- return -1;
}
diff --git a/ext/zip/lib/zip_new.c b/ext/zip/lib/zip_new.c
index d54a247c29..562dd76a36 100644
--- a/ext/zip/lib/zip_new.c
+++ b/ext/zip/lib/zip_new.c
@@ -1,6 +1,6 @@
/*
zip_new.c -- create and init struct zip
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -52,6 +52,11 @@ _zip_new(zip_error_t *error)
return NULL;
}
+ if ((za->names = _zip_hash_new(ZIP_HASH_TABLE_SIZE, error)) == NULL) {
+ free(za);
+ return NULL;
+ }
+
za->src = NULL;
za->open_flags = 0;
zip_error_init(&za->error);
diff --git a/ext/zip/lib/zip_open.c b/ext/zip/lib/zip_open.c
index fb9c566cb1..d6209ee1e7 100644
--- a/ext/zip/lib/zip_open.c
+++ b/ext/zip/lib/zip_open.c
@@ -33,7 +33,6 @@
#include <sys/stat.h>
-#include <errno.h>
#include <limits.h>
#include <stdio.h>
#include <stdlib.h>
@@ -184,7 +183,7 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
zip_t *za;
zip_cdir_t *cdir;
struct zip_stat st;
- zip_uint64_t len;
+ zip_uint64_t len, idx;
zip_stat_init(&st);
if (zip_source_stat(src, &st) < 0) {
@@ -223,11 +222,31 @@ _zip_open(zip_source_t *src, unsigned int flags, zip_error_t *error)
za->nentry = cdir->nentry;
za->nentry_alloc = cdir->nentry_alloc;
za->comment_orig = cdir->comment;
-
- za->ch_flags = za->flags;
free(cdir);
+ for (idx = 0; idx < za->nentry; idx++) {
+ const zip_uint8_t *name = _zip_string_get(za->entry[idx].orig->filename, NULL, 0, error);
+ if (name == NULL) {
+ /* keep src so discard does not get rid of it */
+ zip_source_keep(src);
+ zip_discard(za);
+ return NULL;
+ }
+
+ if (_zip_hash_add(za->names, name, idx, ZIP_FL_UNCHANGED, &za->error) == false) {
+ if (za->error.zip_err != ZIP_ER_EXISTS || (flags & ZIP_CHECKCONS)) {
+ _zip_error_copy(error, &za->error);
+ /* keep src so discard does not get rid of it */
+ zip_source_keep(src);
+ zip_discard(za);
+ return NULL;
+ }
+ }
+ }
+
+ za->ch_flags = za->flags;
+
return za;
}
@@ -274,11 +293,6 @@ _zip_read_cdir(zip_t *za, zip_buffer_t *buffer, zip_uint64_t buf_offset, zip_err
return NULL;
}
- if (_zip_buffer_get_32(buffer) != 0) {
- zip_error_set(error, ZIP_ER_MULTIDISK, 0);
- return NULL;
- }
-
if (eocd_offset >= EOCD64LOCLEN && memcmp(_zip_buffer_data(buffer) + eocd_offset - EOCD64LOCLEN, EOCD64LOC_MAGIC, 4) == 0) {
_zip_buffer_set_offset(buffer, eocd_offset - EOCD64LOCLEN);
cd = _zip_read_eocd64(za->src, buffer, buf_offset, za->flags, error);
@@ -649,7 +663,8 @@ _zip_memmem(const unsigned char *big, size_t biglen, const unsigned char *little
}
-static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error)
+static zip_cdir_t *
+_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset, unsigned int flags, zip_error_t *error)
{
zip_cdir_t *cd;
zip_uint64_t i, nentry, size, offset, eocd_offset;
@@ -661,7 +676,12 @@ static zip_cdir_t *_zip_read_eocd(zip_buffer_t *buffer, zip_uint64_t buf_offset,
eocd_offset = _zip_buffer_offset(buffer);
- _zip_buffer_get(buffer, 8); /* magic and number of disks already verified */
+ _zip_buffer_get(buffer, 4); /* magic already verified */
+
+ if (_zip_buffer_get_32(buffer) != 0) {
+ zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+ return NULL;
+ }
/* number of cdir-entries on this disk */
i = _zip_buffer_get_16(buffer);
@@ -711,10 +731,14 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
zip_uint64_t eocd_offset;
zip_uint64_t size, nentry, i, eocdloc_offset;
bool free_buffer;
+ zip_uint32_t num_disks, num_disks64, eocd_disk, eocd_disk64;
eocdloc_offset = _zip_buffer_offset(buffer);
- _zip_buffer_get(buffer, 8); /* magic and single disk already verified */
+ _zip_buffer_get(buffer, 4); /* magic already verified */
+
+ num_disks = _zip_buffer_get_16(buffer);
+ eocd_disk = _zip_buffer_get_16(buffer);
eocd_offset = _zip_buffer_get_64(buffer);
if (eocd_offset > ZIP_INT64_MAX || eocd_offset + EOCD64LEN < eocd_offset) {
@@ -760,8 +784,29 @@ _zip_read_eocd64(zip_source_t *src, zip_buffer_t *buffer, zip_uint64_t buf_offse
return NULL;
}
- _zip_buffer_get(buffer, 12); /* skip version made by/needed and num disks */
-
+ _zip_buffer_get(buffer, 4); /* skip version made by/needed */
+
+ num_disks64 = _zip_buffer_get_32(buffer);
+ eocd_disk64 = _zip_buffer_get_32(buffer);
+
+ /* if eocd values are 0xffff, we have to use eocd64 values.
+ otherwise, if the values are not the same, it's inconsistent;
+ in any case, if the value is not 0, we don't support it */
+ if (num_disks == 0xffff) {
+ num_disks = num_disks64;
+ }
+ if (eocd_disk == 0xffff) {
+ eocd_disk = eocd_disk64;
+ }
+ if ((flags & ZIP_CHECKCONS) && (eocd_disk != eocd_disk64 || num_disks != num_disks64)) {
+ zip_error_set(error, ZIP_ER_INCONS, 0);
+ return NULL;
+ }
+ if (num_disks != 0 || eocd_disk != 0) {
+ zip_error_set(error, ZIP_ER_MULTIDISK, 0);
+ return NULL;
+ }
+
nentry = _zip_buffer_get_64(buffer);
i = _zip_buffer_get_64(buffer);
diff --git a/ext/zip/lib/zip_set_default_password.c b/ext/zip/lib/zip_set_default_password.c
index ac098dc5fc..10b48062fd 100644
--- a/ext/zip/lib/zip_set_default_password.c
+++ b/ext/zip/lib/zip_set_default_password.c
@@ -44,8 +44,7 @@ zip_set_default_password(zip_t *za, const char *passwd)
if (za == NULL)
return -1;
- if (za->default_password)
- free(za->default_password);
+ free(za->default_password);
if (passwd) {
if ((za->default_password=strdup(passwd)) == NULL) {
diff --git a/ext/zip/lib/zip_set_name.c b/ext/zip/lib/zip_set_name.c
index 5a10381753..2a461437e2 100644
--- a/ext/zip/lib/zip_set_name.c
+++ b/ext/zip/lib/zip_set_name.c
@@ -1,6 +1,6 @@
/*
zip_set_name.c -- rename helper function
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -43,8 +43,10 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
{
zip_entry_t *e;
zip_string_t *str;
- int changed;
+ bool same_as_orig;
zip_int64_t i;
+ const zip_uint8_t *old_name, *new_name;
+ zip_string_t *old_str;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
@@ -56,7 +58,7 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
return -1;
}
- if (name && strlen(name) > 0) {
+ if (name && name[0] != '\0') {
/* TODO: check for string too long */
if ((str=_zip_string_new((const zip_uint8_t *)name, (zip_uint16_t)strlen(name), flags, &za->error)) == NULL)
return -1;
@@ -81,34 +83,75 @@ _zip_set_name(zip_t *za, zip_uint64_t idx, const char *name, zip_flags_t flags)
e = za->entry+idx;
- if (e->changes) {
- _zip_string_free(e->changes->filename);
- e->changes->filename = NULL;
- e->changes->changed &= ~ZIP_DIRENT_FILENAME;
- }
-
if (e->orig)
- changed = !_zip_string_equal(e->orig->filename, str);
+ same_as_orig = _zip_string_equal(e->orig->filename, str);
else
- changed = 1;
-
- if (changed) {
- if (e->changes == NULL) {
- if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
- zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
- _zip_string_free(str);
- return -1;
- }
- }
- e->changes->filename = str;
- e->changes->changed |= ZIP_DIRENT_FILENAME;
+ same_as_orig = false;
+
+ if (!same_as_orig && e->changes == NULL) {
+ if ((e->changes=_zip_dirent_clone(e->orig)) == NULL) {
+ zip_error_set(&za->error, ZIP_ER_MEMORY, 0);
+ _zip_string_free(str);
+ return -1;
+ }
+ }
+
+ if ((new_name = _zip_string_get(same_as_orig ? e->orig->filename : str, NULL, 0, &za->error)) == NULL) {
+ _zip_string_free(str);
+ return -1;
+ }
+
+ if (e->changes) {
+ old_str = e->changes->filename;
+ }
+ else if (e->orig) {
+ old_str = e->orig->filename;
}
else {
+ old_str = NULL;
+ }
+
+ if (old_str) {
+ if ((old_name = _zip_string_get(old_str, NULL, 0, &za->error)) == NULL) {
+ _zip_string_free(str);
+ return -1;
+ }
+ }
+ else {
+ old_name = NULL;
+ }
+
+ if (_zip_hash_add(za->names, new_name, idx, 0, &za->error) == false) {
+ _zip_string_free(str);
+ return -1;
+ }
+ if (old_name) {
+ _zip_hash_delete(za->names, old_name, NULL);
+ }
+
+ if (same_as_orig) {
+ if (e->changes) {
+ if (e->changes->changed & ZIP_DIRENT_FILENAME) {
+ _zip_string_free(e->changes->filename);
+ e->changes->changed &= ~ZIP_DIRENT_FILENAME;
+ if (e->changes->changed == 0) {
+ _zip_dirent_free(e->changes);
+ e->changes = NULL;
+ }
+ else {
+ /* TODO: what if not cloned? can that happen? */
+ e->changes->filename = e->orig->filename;
+ }
+ }
+ }
_zip_string_free(str);
- if (e->changes && e->changes->changed == 0) {
- _zip_dirent_free(e->changes);
- e->changes = NULL;
+ }
+ else {
+ if (e->changes->changed & ZIP_DIRENT_FILENAME) {
+ _zip_string_free(e->changes->filename);
}
+ e->changes->changed |= ZIP_DIRENT_FILENAME;
+ e->changes->filename = str;
}
return 0;
diff --git a/ext/zip/lib/zip_source_buffer.c b/ext/zip/lib/zip_source_buffer.c
index aadf6e40b0..f3f8ee0d58 100644
--- a/ext/zip/lib/zip_source_buffer.c
+++ b/ext/zip/lib/zip_source_buffer.c
@@ -1,6 +1,6 @@
/*
zip_source_buffer.c -- create zip data source from buffer
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -31,7 +31,6 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -376,6 +375,7 @@ static zip_int64_t
buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip_error_t *error)
{
zip_uint64_t n, i, fragment_offset;
+ zip_uint8_t **fragments;
if (buffer->offset + length + buffer->fragment_size - 1 < length) {
zip_error_set(error, ZIP_ER_INVAL, 0);
@@ -388,7 +388,6 @@ buffer_write(buffer_t *buffer, const zip_uint8_t *data, zip_uint64_t length, zip
if (needed_fragments > buffer->fragments_capacity) {
zip_uint64_t new_capacity = buffer->fragments_capacity;
- zip_uint8_t **fragments;
while (new_capacity < needed_fragments) {
new_capacity *= 2;
diff --git a/ext/zip/lib/zip_source_crc.c b/ext/zip/lib/zip_source_crc.c
index eed726616a..01f526c647 100644
--- a/ext/zip/lib/zip_source_crc.c
+++ b/ext/zip/lib/zip_source_crc.c
@@ -1,6 +1,6 @@
/*
zip_source_crc.c -- pass-through source that calculates CRC32 and size
- Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2016 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -39,10 +39,12 @@
#include "zipint.h"
struct crc_context {
- int eof;
- int validate;
+ int validate; /* whether to check CRC on EOF and return error on mismatch */
+ int crc_complete; /* whether CRC was computed for complete file */
zip_error_t error;
zip_uint64_t size;
+ zip_uint64_t position; /* current reading position */
+ zip_uint64_t crc_position; /* how far we've computed the CRC */
zip_uint32_t crc;
};
@@ -64,12 +66,13 @@ zip_source_crc(zip_t *za, zip_source_t *src, int validate)
return NULL;
}
- ctx->eof = 0;
- ctx->validate = validate;
zip_error_init(&ctx->error);
+ ctx->validate = validate;
+ ctx->crc_complete = 0;
+ ctx->crc_position = 0;
+ ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
ctx->size = 0;
- ctx->crc = 0;
-
+
return zip_source_layered(za, src, crc_read, ctx);
}
@@ -84,51 +87,50 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
switch (cmd) {
case ZIP_SOURCE_OPEN:
- ctx->eof = 0;
- ctx->crc = (zip_uint32_t)crc32(0, NULL, 0);
- ctx->size = 0;
-
+ ctx->position = 0;
return 0;
case ZIP_SOURCE_READ:
- if (ctx->eof || len == 0)
- return 0;
-
- if ((n=zip_source_read(src, data, len)) < 0) {
+ if ((n = zip_source_read(src, data, len)) < 0) {
_zip_error_set_from_source(&ctx->error, src);
return -1;
}
if (n == 0) {
- ctx->eof = 1;
- if (ctx->validate) {
- struct zip_stat st;
+ if (ctx->crc_position == ctx->position) {
+ ctx->crc_complete = 1;
+ ctx->size = ctx->position;
+
+ if (ctx->validate) {
+ struct zip_stat st;
- if (zip_source_stat(src, &st) < 0) {
- _zip_error_set_from_source(&ctx->error, src);
- return -1;
- }
+ if (zip_source_stat(src, &st) < 0) {
+ _zip_error_set_from_source(&ctx->error, src);
+ return -1;
+ }
- if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
- zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
- return -1;
- }
- if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
- zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
- return -1;
+ if ((st.valid & ZIP_STAT_CRC) && st.crc != ctx->crc) {
+ zip_error_set(&ctx->error, ZIP_ER_CRC, 0);
+ return -1;
+ }
+ if ((st.valid & ZIP_STAT_SIZE) && st.size != ctx->size) {
+ zip_error_set(&ctx->error, ZIP_ER_INCONS, 0);
+ return -1;
+ }
}
}
}
- else {
+ else if (!ctx->crc_complete && ctx->position <= ctx->crc_position) {
zip_uint64_t i, nn;
- for (i=0; i < (zip_uint64_t)n; i += nn) {
+ for (i = ctx->crc_position - ctx->position; i < (zip_uint64_t)n; i += nn) {
nn = ZIP_MIN(UINT_MAX, (zip_uint64_t)n-i);
ctx->crc = (zip_uint32_t)crc32(ctx->crc, (const Bytef *)data+i, (uInt)nn);
+ ctx->crc_position += nn;
}
- ctx->size += (zip_uint64_t)n;
}
+ ctx->position += (zip_uint64_t)n;
return n;
case ZIP_SOURCE_CLOSE:
@@ -140,7 +142,7 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
st = (zip_stat_t *)data;
- if (ctx->eof) {
+ if (ctx->crc_complete) {
/* TODO: Set comp_size, comp_method, encryption_method?
After all, this only works for uncompressed data. */
st->size = ctx->size;
@@ -161,7 +163,37 @@ crc_read(zip_source_t *src, void *_ctx, void *data, zip_uint64_t len, zip_source
return 0;
case ZIP_SOURCE_SUPPORTS:
- return zip_source_make_command_bitmap(ZIP_SOURCE_OPEN, ZIP_SOURCE_READ, ZIP_SOURCE_CLOSE, ZIP_SOURCE_STAT, ZIP_SOURCE_ERROR, ZIP_SOURCE_FREE, -1);
+ {
+ zip_int64_t mask = zip_source_supports(src);
+
+ if (mask < 0) {
+ _zip_error_set_from_source(&ctx->error, src);
+ return -1;
+ }
+
+ return mask & ~zip_source_make_command_bitmap(ZIP_SOURCE_BEGIN_WRITE, ZIP_SOURCE_COMMIT_WRITE, ZIP_SOURCE_ROLLBACK_WRITE, ZIP_SOURCE_SEEK_WRITE, ZIP_SOURCE_TELL_WRITE, ZIP_SOURCE_REMOVE, -1);
+ }
+
+ case ZIP_SOURCE_SEEK:
+ {
+ zip_int64_t new_position;
+ zip_source_args_seek_t *args = ZIP_SOURCE_GET_ARGS(zip_source_args_seek_t, data, len, &ctx->error);
+
+ if (args == NULL) {
+ return -1;
+ }
+ if (zip_source_seek(src, args->offset, args->whence) < 0 || (new_position = zip_source_tell(src)) < 0) {
+ _zip_error_set_from_source(&ctx->error, src);
+ return -1;
+ }
+
+ ctx->position = (zip_uint64_t)new_position;
+
+ return 0;
+ }
+
+ case ZIP_SOURCE_TELL:
+ return (zip_int64_t)ctx->position;
default:
zip_error_set(&ctx->error, ZIP_ER_OPNOTSUPP, 0);
diff --git a/ext/zip/lib/zip_source_file.c b/ext/zip/lib/zip_source_file.c
index 1465e1700e..b3cd7ab29f 100644
--- a/ext/zip/lib/zip_source_file.c
+++ b/ext/zip/lib/zip_source_file.c
@@ -32,7 +32,6 @@
*/
-#include <errno.h>
#include <stdio.h>
#include "zipint.h"
diff --git a/ext/zip/lib/zip_source_filep.c b/ext/zip/lib/zip_source_filep.c
index e541305d7f..70255dec41 100644
--- a/ext/zip/lib/zip_source_filep.c
+++ b/ext/zip/lib/zip_source_filep.c
@@ -31,15 +31,17 @@
IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-
-#include "zipint.h"
-
#include <sys/stat.h>
-#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "zipint.h"
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
#ifdef _WIN32
/* WIN32 needs <fcntl.h> for _O_BINARY */
#include <fcntl.h>
@@ -49,11 +51,12 @@
#ifndef S_ISREG
#define S_ISREG(m) (((m) & S_IFMT) == S_IFREG)
#endif
-#ifndef S_IRWXG
-#define S_IRWXG (S_IRWXU >> 3)
-#endif
-#ifndef S_IRWXO
-#define S_IRWXO (S_IRWXG >> 3)
+#if defined(S_IXUSR) && defined(S_IRWXG) && defined(S_IRWXO)
+#define _SAFE_MASK (S_IXUSR | S_IRWXG | S_IRWXO)
+#elif defined(_S_IWRITE)
+#define _SAFE_MASK (_S_IWRITE)
+#else
+#error do not know safe values for umask, please report this
#endif
#ifdef _MSC_VER
@@ -183,13 +186,7 @@ create_temp_output(struct read_file *ctx)
}
sprintf(temp, "%s.XXXXXX", ctx->fname);
-#ifdef _WIN32
- /* This might work under VS2015, however there's no good documentation
- about it. So let it be for now. */
- mask = 0;
-#else
- mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
-#endif
+ mask = umask(_SAFE_MASK);
if ((tfd=mkstemp(temp)) == -1) {
zip_error_set(&ctx->error, ZIP_ER_TMPOPEN, errno);
umask(mask);
diff --git a/ext/zip/lib/zip_source_pkware.c b/ext/zip/lib/zip_source_pkware.c
index ce281ac148..125e4e2c2a 100644
--- a/ext/zip/lib/zip_source_pkware.c
+++ b/ext/zip/lib/zip_source_pkware.c
@@ -1,6 +1,6 @@
/*
zip_source_pkware.c -- Traditional PKWARE de/encryption routines
- Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -107,7 +107,7 @@ decrypt(struct trad_pkware *ctx, zip_uint8_t *out, const zip_uint8_t *in,
if (!update_only) {
/* decrypt next byte */
tmp = (zip_uint16_t)(ctx->key[2] | 2);
- tmp = (zip_uint16_t)((tmp * (tmp ^ 1)) >> 8);
+ tmp = (zip_uint16_t)(((zip_uint32_t)tmp * (tmp ^ 1)) >> 8);
b ^= (Bytef)tmp;
}
diff --git a/ext/zip/lib/zip_source_stat.c b/ext/zip/lib/zip_source_stat.c
index 34cb05f452..a6b46d06a6 100644
--- a/ext/zip/lib/zip_source_stat.c
+++ b/ext/zip/lib/zip_source_stat.c
@@ -1,6 +1,6 @@
/*
zip_source_stat.c -- get meta information from zip_source
- Copyright (C) 2009-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2009-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -35,7 +35,7 @@
#include "zipint.h"
-int
+ZIP_EXTERN int
zip_source_stat(zip_source_t *src, zip_stat_t *st)
{
if (src->source_closed) {
diff --git a/ext/zip/lib/zip_source_supports.c b/ext/zip/lib/zip_source_supports.c
index 3c100fb71f..75a4a4626d 100644
--- a/ext/zip/lib/zip_source_supports.c
+++ b/ext/zip/lib/zip_source_supports.c
@@ -1,6 +1,6 @@
/*
zip_source_supports.c -- check for supported functions
- Copyright (C) 2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 2014-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -44,7 +44,7 @@ zip_source_supports(zip_source_t *src)
}
-zip_int64_t
+ZIP_EXTERN zip_int64_t
zip_source_make_command_bitmap(zip_source_cmd_t cmd0, ...)
{
zip_int64_t bitmap;
diff --git a/ext/zip/lib/zip_source_win32a.c b/ext/zip/lib/zip_source_win32a.c
index e9786c473e..85493b660e 100644
--- a/ext/zip/lib/zip_source_win32a.c
+++ b/ext/zip/lib/zip_source_win32a.c
@@ -1,6 +1,6 @@
/*
zip_source_win32a.c -- create data source from Windows file (ANSI)
-Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
#include <stdio.h>
#include "zipint.h"
diff --git a/ext/zip/lib/zip_source_win32handle.c b/ext/zip/lib/zip_source_win32handle.c
index d195a119db..35e2e67972 100644
--- a/ext/zip/lib/zip_source_win32handle.c
+++ b/ext/zip/lib/zip_source_win32handle.c
@@ -1,6 +1,6 @@
/*
zip_source_win32file.c -- create data source from HANDLE (Win32)
-Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -33,7 +33,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <wchar.h>
-#include <errno.h>
#include <stdlib.h>
#include <string.h>
@@ -409,6 +408,7 @@ _win32_read_file(void *state, void *data, zip_uint64_t len, zip_source_cmd_t cmd
static int
_win32_create_temp_file(_zip_source_win32_read_file_t *ctx)
{
+ zip_uint32_t value;
/*
Windows has GetTempFileName(), but it closes the file after
creation, leaving it open to a horrible race condition. So
@@ -423,7 +423,6 @@ _win32_create_temp_file(_zip_source_win32_read_file_t *ctx)
PSECURITY_ATTRIBUTES psa = NULL;
DWORD len;
BOOL success;
- zip_uint32_t value;
/*
Read the DACL from the original file, so we can copy it to the temp file.
diff --git a/ext/zip/lib/zip_source_win32utf8.c b/ext/zip/lib/zip_source_win32utf8.c
index e11214ba05..004c66ac2b 100644
--- a/ext/zip/lib/zip_source_win32utf8.c
+++ b/ext/zip/lib/zip_source_win32utf8.c
@@ -32,7 +32,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
#include <stdio.h>
#include "zipint.h"
diff --git a/ext/zip/lib/zip_source_win32w.c b/ext/zip/lib/zip_source_win32w.c
index 34134561f1..551aba5f37 100644
--- a/ext/zip/lib/zip_source_win32w.c
+++ b/ext/zip/lib/zip_source_win32w.c
@@ -1,6 +1,6 @@
/*
zip_source_win32w.c -- create data source from Windows file (UTF-16)
-Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -32,7 +32,6 @@ IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
-#include <errno.h>
#include <stdio.h>
#include "zipint.h"
@@ -100,7 +99,7 @@ _win32_create_temp_w(_zip_source_win32_read_file_t *ctx, void **temp, zip_uint32
return INVALID_HANDLE_VALUE;
}
}
- if (swprintf((wchar_t *)*temp, len, L"%s.%08x", (const wchar_t *)ctx->fname, value) != len - 1) {
+ if (_snwprintf((wchar_t *)*temp, len, L"%s.%08x", (const wchar_t *)ctx->fname, value) != len - 1) {
return INVALID_HANDLE_VALUE;
}
diff --git a/ext/zip/lib/zip_unchange.c b/ext/zip/lib/zip_unchange.c
index 6c8a495c78..5ef5462127 100644
--- a/ext/zip/lib/zip_unchange.c
+++ b/ext/zip/lib/zip_unchange.c
@@ -1,6 +1,6 @@
/*
zip_unchange.c -- undo changes to file in zip archive
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -48,6 +48,7 @@ int
_zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates)
{
zip_int64_t i;
+ const char *orig_name, *changed_name;
if (idx >= za->nentry) {
zip_error_set(&za->error, ZIP_ER_INVAL, 0);
@@ -55,9 +56,32 @@ _zip_unchange(zip_t *za, zip_uint64_t idx, int allow_duplicates)
}
if (!allow_duplicates && za->entry[idx].changes && (za->entry[idx].changes->changed & ZIP_DIRENT_FILENAME)) {
- i = _zip_name_locate(za, _zip_get_name(za, idx, ZIP_FL_UNCHANGED, NULL), 0, NULL);
- if (i >= 0 && (zip_uint64_t)i != idx) {
- zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
+ if (za->entry[idx].orig != NULL) {
+ if ((orig_name=_zip_get_name(za, idx, ZIP_FL_UNCHANGED, &za->error)) == NULL) {
+ return -1;
+ }
+
+ i = _zip_name_locate(za, orig_name, 0, NULL);
+ if (i >= 0 && (zip_uint64_t)i != idx) {
+ zip_error_set(&za->error, ZIP_ER_EXISTS, 0);
+ return -1;
+ }
+ }
+ else {
+ orig_name = NULL;
+ }
+
+ if ((changed_name=_zip_get_name(za, idx, 0, &za->error)) == NULL) {
+ return -1;
+ }
+
+ if (orig_name) {
+ if (_zip_hash_add(za->names, (const zip_uint8_t *)orig_name, idx, 0, &za->error) == false) {
+ return -1;
+ }
+ }
+ if (_zip_hash_delete(za->names, (const zip_uint8_t *)changed_name, &za->error) == false) {
+ _zip_hash_delete(za->names, (const zip_uint8_t *)orig_name, NULL);
return -1;
}
}
diff --git a/ext/zip/lib/zip_unchange_all.c b/ext/zip/lib/zip_unchange_all.c
index 60076838d4..dc89f7fdaf 100644
--- a/ext/zip/lib/zip_unchange_all.c
+++ b/ext/zip/lib/zip_unchange_all.c
@@ -1,6 +1,6 @@
/*
zip_unchange.c -- undo changes to all files in zip archive
- Copyright (C) 1999-2014 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -43,6 +43,8 @@ zip_unchange_all(zip_t *za)
int ret;
zip_uint64_t i;
+ _zip_hash_revert(za->names);
+
ret = 0;
for (i=0; i<za->nentry; i++)
ret |= _zip_unchange(za, i, 1);
diff --git a/ext/zip/lib/zipconf.h b/ext/zip/lib/zipconf.h
index c8716fb952..8ac2652e1d 100644
--- a/ext/zip/lib/zipconf.h
+++ b/ext/zip/lib/zipconf.h
@@ -7,10 +7,10 @@
This file was generated automatically by CMake
based on ../cmake-zipconf.h.in.
*/
-#define LIBZIP_VERSION "1.0.1"
+#define LIBZIP_VERSION "1.1.2"
#define LIBZIP_VERSION_MAJOR 1
-#define LIBZIP_VERSION_MINOR 0
-#define LIBZIP_VERSION_MICRO 1
+#define LIBZIP_VERSION_MINOR 1
+#define LIBZIP_VERSION_MICRO 2
/* #undef HAVE_INTTYPES_H_LIBZIP */
diff --git a/ext/zip/lib/zipint.h b/ext/zip/lib/zipint.h
index d13bab42ab..68b18c70a3 100644
--- a/ext/zip/lib/zipint.h
+++ b/ext/zip/lib/zipint.h
@@ -3,7 +3,7 @@
/*
zipint.h -- internal declarations.
- Copyright (C) 1999-2015 Dieter Baron and Thomas Klausner
+ Copyright (C) 1999-2016 Dieter Baron and Thomas Klausner
This file is part of libzip, a library to manipulate ZIP archives.
The authors can be contacted at <libzip@nih.at>
@@ -65,6 +65,22 @@ typedef char bool;
#define false 0
#endif
+#include <errno.h>
+
+/* at least MinGW does not provide EOPNOTSUPP, see
+ * http://sourceforge.net/p/mingw/bugs/263/
+ */
+#ifndef EOPNOTSUPP
+#define EOPNOTSUPP EINVAL
+#endif
+
+/* at least MinGW does not provide EOVERFLOW, see
+ * http://sourceforge.net/p/mingw/bugs/242/
+ */
+#ifndef EOVERFLOW
+#define EOVERFLOW EFBIG
+#endif
+
#ifdef _WIN32
#if defined(HAVE__CLOSE)
#define close _close
@@ -76,7 +92,7 @@ typedef char bool;
#if defined(HAVE__FDOPEN)
#define fdopen _fdopen
#endif
-#if defined(HAVE__FILENO)
+#if !defined(HAVE_FILENO) && defined(HAVE__FILENO)
#define fileno _fileno
#endif
/* Windows' open() doesn't understand Unix permissions */
@@ -92,6 +108,9 @@ typedef char bool;
#define strdup _strdup
#endif
#endif
+#if !defined(HAVE__SETMODE) && defined(HAVE_SETMODE)
+#define _setmode setmode
+#endif
#endif
#ifndef HAVE_FSEEKO
@@ -110,6 +129,8 @@ int _zip_mkstemp(char *);
#if !defined(HAVE_STRCASECMP)
#if defined(HAVE__STRICMP)
#define strcasecmp _stricmp
+#elif defined(HAVE_STRICMP)
+#define strcasecmp stricmp
#endif
#endif
@@ -129,12 +150,10 @@ int _zip_mkstemp(char *);
#if defined(HAVE_FTELLO) && defined(HAVE_FSEEKO)
#define ZIP_FSEEK_MAX ZIP_OFF_MAX
#define ZIP_FSEEK_MIN ZIP_OFF_MIN
-#elif SIZEOF_LONG >= 8
-#define ZIP_FSEEK_MAX (long)ZIP_INT64_MAX
-#define ZIP_FSEEK_MIN (long)ZIP_INT64_MIN
#else
-#define ZIP_FSEEK_MAX (long)ZIP_INT32_MAX
-#define ZIP_FSEEK_MIN (long)ZIP_INT32_MIN
+#include <limits.h>
+#define ZIP_FSEEK_MAX LONG_MAX
+#define ZIP_FSEEK_MIN LONG_MIN
#endif
#ifndef SIZE_MAX
@@ -255,13 +274,19 @@ enum zip_encoding_type {
typedef enum zip_encoding_type zip_encoding_type_t;
+#ifndef ZIP_HASH_TABLE_SIZE
+#define ZIP_HASH_TABLE_SIZE 8192
+#endif
+
+struct zip_hash;
+
typedef struct zip_cdir zip_cdir_t;
typedef struct zip_dirent zip_dirent_t;
typedef struct zip_entry zip_entry_t;
typedef struct zip_extra_field zip_extra_field_t;
typedef struct zip_string zip_string_t;
typedef struct zip_buffer zip_buffer_t;
-
+typedef struct zip_hash zip_hash_t;
/* zip archive, part of API */
@@ -276,7 +301,7 @@ struct zip {
char *default_password; /* password used when no other supplied */
zip_string_t *comment_orig; /* archive comment */
- zip_string_t *comment_changes; /* changed archive comment */
+ zip_string_t *comment_changes; /* changed archive comment */
bool comment_changed; /* whether archive comment was changed */
zip_uint64_t nentry; /* number of entries */
@@ -286,6 +311,8 @@ struct zip {
unsigned int nopen_source; /* number of open sources using archive */
unsigned int nopen_source_alloc; /* number of sources allocated */
zip_source_t **open_source; /* open sources using archive */
+
+ zip_hash_t *names; /* hash table for name lookup */
char *tempdir; /* custom temp dir (needed e.g. for OS X sandboxing) */
};
@@ -312,7 +339,7 @@ struct zip_file {
struct zip_dirent {
zip_uint32_t changed;
bool local_extra_fields_read; /* whether we already read in local header extra fields */
- bool cloned; /* whether this instance is cloned, and thus shares non-changed strings */
+ bool cloned; /* whether this instance is cloned, and thus shares non-changed strings */
zip_uint16_t version_madeby; /* (c) version of creator */
zip_uint16_t version_needed; /* (cl) version needed to extract */
@@ -415,7 +442,7 @@ struct zip_buffer {
struct zip_filelist {
zip_uint64_t idx;
-// TODO const char *name;
+/* TODO const char *name; */
};
typedef struct zip_filelist zip_filelist_t;
@@ -453,6 +480,7 @@ int _zip_buffer_put_16(zip_buffer_t *buffer, zip_uint16_t i);
int _zip_buffer_put_32(zip_buffer_t *buffer, zip_uint32_t i);
int _zip_buffer_put_64(zip_buffer_t *buffer, zip_uint64_t i);
int _zip_buffer_put_8(zip_buffer_t *buffer, zip_uint8_t i);
+int _zip_buffer_skip(zip_buffer_t *buffer, zip_uint64_t length);
int _zip_buffer_set_offset(zip_buffer_t *buffer, zip_uint64_t offset);
zip_uint64_t _zip_buffer_size(zip_buffer_t *buffer);
@@ -478,7 +506,7 @@ void _zip_ef_free(zip_extra_field_t *);
const zip_uint8_t *_zip_ef_get_by_id(const zip_extra_field_t *, zip_uint16_t *, zip_uint16_t, zip_uint16_t, zip_flags_t, zip_error_t *);
zip_extra_field_t *_zip_ef_merge(zip_extra_field_t *, zip_extra_field_t *);
zip_extra_field_t *_zip_ef_new(zip_uint16_t, zip_uint16_t, const zip_uint8_t *, zip_flags_t);
-zip_extra_field_t *_zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_error_t *);
+bool _zip_ef_parse(const zip_uint8_t *, zip_uint16_t, zip_flags_t, zip_extra_field_t **, zip_error_t *);
zip_extra_field_t *_zip_ef_remove_internal(zip_extra_field_t *);
zip_uint16_t _zip_ef_size(const zip_extra_field_t *, zip_flags_t);
int _zip_ef_write(zip_t *za, const zip_extra_field_t *ef, zip_flags_t flags);
@@ -505,6 +533,13 @@ zip_dirent_t *_zip_get_dirent(zip_t *, zip_uint64_t, zip_flags_t, zip_error_t *)
enum zip_encoding_type _zip_guess_encoding(zip_string_t *, enum zip_encoding_type);
zip_uint8_t *_zip_cp437_to_utf8(const zip_uint8_t * const, zip_uint32_t, zip_uint32_t *, zip_error_t *);
+bool _zip_hash_add(zip_hash_t *hash, const zip_uint8_t *name, zip_uint64_t index, zip_flags_t flags, zip_error_t *error);
+bool _zip_hash_delete(zip_hash_t *hash, const zip_uint8_t *key, zip_error_t *error);
+void _zip_hash_free(zip_hash_t *hash);
+zip_int64_t _zip_hash_lookup(zip_hash_t *hash, const zip_uint8_t *name, zip_flags_t flags, zip_error_t *error);
+zip_hash_t *_zip_hash_new(zip_uint16_t hash_size, zip_error_t *error);
+void _zip_hash_revert(zip_hash_t *hash);
+
zip_t *_zip_open(zip_source_t *, unsigned int, zip_error_t *);
int _zip_read(zip_source_t *src, zip_uint8_t *data, zip_uint64_t length, zip_error_t *error);
diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c
index c31ace1f8d..db201af634 100644
--- a/ext/zip/php_zip.c
+++ b/ext/zip/php_zip.c
@@ -16,7 +16,6 @@
+----------------------------------------------------------------------+
*/
-/* $Id$ */
#ifdef HAVE_CONFIG_H
#include "config.h"
@@ -331,7 +330,7 @@ static int php_zip_parse_options(zval *options, zend_long *remove_all_path, char
}
if (Z_STRLEN_P(option) >= MAXPATHLEN) {
- php_error_docref(NULL, E_WARNING, "remove_path string is too long (max: %i, %i given)",
+ php_error_docref(NULL, E_WARNING, "remove_path string is too long (max: %d, %zd given)",
MAXPATHLEN - 1, Z_STRLEN_P(option));
return -1;
}
@@ -351,7 +350,7 @@ static int php_zip_parse_options(zval *options, zend_long *remove_all_path, char
}
if (Z_STRLEN_P(option) >= MAXPATHLEN) {
- php_error_docref(NULL, E_WARNING, "add_path string too long (max: %i, %i given)",
+ php_error_docref(NULL, E_WARNING, "add_path string too long (max: %d, %zd given)",
MAXPATHLEN - 1, Z_STRLEN_P(option));
return -1;
}
@@ -1506,7 +1505,7 @@ static ZIPARCHIVE_METHOD(close)
ze_obj = Z_ZIP_P(self);
if ((err = zip_close(intern))) {
- php_error_docref(NULL TSRMLS_CC, E_WARNING, "%s", zip_strerror(intern));
+ php_error_docref(NULL, E_WARNING, "%s", zip_strerror(intern));
zip_discard(intern);
}
@@ -2668,7 +2667,7 @@ static ZIPARCHIVE_METHOD(extractTo)
for (i = 0; i < filecount; i++) {
char *file = (char*)zip_get_name(intern, i, ZIP_FL_UNCHANGED);
- if (!php_zip_extract_file(intern, pathto, file, strlen(file))) {
+ if (!file || !php_zip_extract_file(intern, pathto, file, strlen(file))) {
RETURN_FALSE;
}
}
@@ -3134,7 +3133,6 @@ static PHP_MINFO_FUNCTION(zip)
php_info_print_table_start();
php_info_print_table_row(2, "Zip", "enabled");
- php_info_print_table_row(2, "Extension Version","$Id$");
php_info_print_table_row(2, "Zip version", PHP_ZIP_VERSION);
php_info_print_table_row(2, "Libzip version", LIBZIP_VERSION);
diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h
index 602b1b1c44..f5df19e79a 100644
--- a/ext/zip/php_zip.h
+++ b/ext/zip/php_zip.h
@@ -16,7 +16,6 @@
+----------------------------------------------------------------------+
*/
-/* $Id$ */
#ifndef PHP_ZIP_H
#define PHP_ZIP_H
@@ -38,7 +37,7 @@ extern zend_module_entry zip_module_entry;
#define ZIP_OVERWRITE ZIP_TRUNCATE
#endif
-#define PHP_ZIP_VERSION "1.13.0"
+#define PHP_ZIP_VERSION "1.13.2"
#ifndef Z_SET_REFCOUNT_P
# if PHP_MAJOR_VERSION < 6 && (PHP_MAJOR_VERSION == 5 && PHP_MINOR_VERSION < 3)
diff --git a/ext/zip/zip_stream.c b/ext/zip/zip_stream.c
index 3b200e89d1..a1f620182c 100644
--- a/ext/zip/zip_stream.c
+++ b/ext/zip/zip_stream.c
@@ -16,7 +16,6 @@
+----------------------------------------------------------------------+
*/
-/* $Id$ */
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c
index eda939d66e..bfca0f42f7 100644
--- a/ext/zlib/zlib.c
+++ b/ext/zlib/zlib.c
@@ -1064,7 +1064,7 @@ PHP_FUNCTION(deflate_init)
case Z_DEFAULT_STRATEGY:
break;
default:
- php_error_docref(NULL, E_WARNING, "strategy must be one of ZLIB_FILTERED, ZLIB_HUFFMAN_ONLY, ZLIB_RLE, ZLIB_FIXED or ZLIB_DEFAULT_STRATEGY", strategy);
+ php_error_docref(NULL, E_WARNING, "strategy must be one of ZLIB_FILTERED, ZLIB_HUFFMAN_ONLY, ZLIB_RLE, ZLIB_FIXED or ZLIB_DEFAULT_STRATEGY");
RETURN_FALSE;
}
diff --git a/main/main.c b/main/main.c
index 77a2f64b40..ab879369bc 100644
--- a/main/main.c
+++ b/main/main.c
@@ -1566,6 +1566,9 @@ int php_request_startup(void)
#endif /* HAVE_DTRACE */
#ifdef PHP_WIN32
+# if defined(ZTS)
+ _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
+# endif
PG(com_initialized) = 0;
#endif
diff --git a/main/output.c b/main/output.c
index 2154949810..2a51100960 100644
--- a/main/output.c
+++ b/main/output.c
@@ -665,7 +665,7 @@ PHPAPI int php_output_handler_alias_register(const char *name, size_t name_len,
}
/* }}} */
-/* {{{ SUCCESS|FAILURE php_output_handler_hook(php_output_handler_hook_t type, void *arg TSMRLS_DC)
+/* {{{ SUCCESS|FAILURE php_output_handler_hook(php_output_handler_hook_t type, void *arg)
* Output handler hook for output handler functions to check/modify the current handlers abilities */
PHPAPI int php_output_handler_hook(php_output_handler_hook_t type, void *arg)
{
@@ -715,7 +715,7 @@ PHPAPI void php_output_handler_dtor(php_output_handler *handler)
}
/* }}} */
-/* {{{ void php_output_handler_free(php_output_handler **handler TSMRLS_DC)
+/* {{{ void php_output_handler_free(php_output_handler **handler)
* Destroy and free an output handler */
PHPAPI void php_output_handler_free(php_output_handler **h)
{
diff --git a/main/php.h b/main/php.h
index 14a52a6476..bb06a3edac 100644
--- a/main/php.h
+++ b/main/php.h
@@ -297,19 +297,13 @@ static inline ZEND_ATTRIBUTE_DEPRECATED void php_std_error_handling() {}
PHPAPI ZEND_COLD void php_verror(const char *docref, const char *params, int type, const char *format, va_list args) PHP_ATTRIBUTE_FORMAT(printf, 4, 0);
-#ifdef ZTS
-#define PHP_ATTR_FMT_OFFSET 1
-#else
-#define PHP_ATTR_FMT_OFFSET 0
-#endif
-
/* PHPAPI void php_error(int type, const char *format, ...); */
PHPAPI ZEND_COLD void php_error_docref0(const char *docref, int type, const char *format, ...)
- PHP_ATTRIBUTE_FORMAT(printf, PHP_ATTR_FMT_OFFSET + 3, PHP_ATTR_FMT_OFFSET + 4);
+ PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
PHPAPI ZEND_COLD void php_error_docref1(const char *docref, const char *param1, int type, const char *format, ...)
- PHP_ATTRIBUTE_FORMAT(printf, PHP_ATTR_FMT_OFFSET + 4, PHP_ATTR_FMT_OFFSET + 5);
+ PHP_ATTRIBUTE_FORMAT(printf, 4, 5);
PHPAPI ZEND_COLD void php_error_docref2(const char *docref, const char *param1, const char *param2, int type, const char *format, ...)
- PHP_ATTRIBUTE_FORMAT(printf, PHP_ATTR_FMT_OFFSET + 5, PHP_ATTR_FMT_OFFSET + 6);
+ PHP_ATTRIBUTE_FORMAT(printf, 5, 6);
#ifdef PHP_WIN32
PHPAPI ZEND_COLD void php_win32_docref2_from_error(DWORD error, const char *param1, const char *param2);
#endif
diff --git a/main/php_streams.h b/main/php_streams.h
index 0cb9849d3b..de7c280050 100644
--- a/main/php_streams.h
+++ b/main/php_streams.h
@@ -313,11 +313,7 @@ PHPAPI size_t _php_stream_write(php_stream *stream, const char *buf, size_t coun
PHPAPI void _php_stream_fill_read_buffer(php_stream *stream, size_t size);
#define php_stream_fill_read_buffer(stream, size) _php_stream_fill_read_buffer((stream), (size))
-#ifdef ZTS
-PHPAPI size_t _php_stream_printf(php_stream *stream, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
-#else
PHPAPI size_t _php_stream_printf(php_stream *stream, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3);
-#endif
/* php_stream_printf macro & function require */
#define php_stream_printf _php_stream_printf
@@ -579,11 +575,7 @@ PHPAPI const char *php_stream_locate_eol(php_stream *stream, zend_string *buf);
php_stream_open_wrapper_ex(Z_STRVAL_PP((zstream)), (mode), (options), (opened), (context)) : NULL
/* pushes an error message onto the stack for a wrapper instance */
-#ifdef ZTS
-PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int options, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 4, 5);
-#else
PHPAPI void php_stream_wrapper_log_error(php_stream_wrapper *wrapper, int options, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
-#endif
#define PHP_STREAM_UNCHANGED 0 /* orig stream was seekable anyway */
#define PHP_STREAM_RELEASED 1 /* newstream should be used; origstream is no longer valid */
diff --git a/main/php_version.h b/main/php_version.h
index 4096d9d50c..0bf06b34b4 100644
--- a/main/php_version.h
+++ b/main/php_version.h
@@ -2,7 +2,7 @@
/* edit configure.in to change version number */
#define PHP_MAJOR_VERSION 7
#define PHP_MINOR_VERSION 0
-#define PHP_RELEASE_VERSION 4
+#define PHP_RELEASE_VERSION 5
#define PHP_EXTRA_VERSION "-dev"
-#define PHP_VERSION "7.0.4-dev"
-#define PHP_VERSION_ID 70004
+#define PHP_VERSION "7.0.5-dev"
+#define PHP_VERSION_ID 70005
diff --git a/main/streams/memory.c b/main/streams/memory.c
index 09da047d86..56ffe344aa 100644
--- a/main/streams/memory.c
+++ b/main/streams/memory.c
@@ -22,7 +22,7 @@
#include "php.h"
#include "ext/standard/base64.h"
-PHPAPI int php_url_decode(char *str, int len);
+PHPAPI size_t php_url_decode(char *str, size_t len);
/* Memory streams use a dynamic memory buffer to emulate a stream.
* You can use php_stream_memory_open to create a readonly stream
@@ -730,7 +730,7 @@ static php_stream * php_stream_url_wrap_rfc2397(php_stream_wrapper *wrapper, con
ilen = (int)ZSTR_LEN(base64_comma);
} else {
comma = estrndup(comma, dlen);
- dlen = php_url_decode(comma, (int)dlen);
+ dlen = php_url_decode(comma, dlen);
ilen = (int)dlen;
}
diff --git a/sapi/cli/php_cli.c b/sapi/cli/php_cli.c
index a387059e27..907f629c01 100644
--- a/sapi/cli/php_cli.c
+++ b/sapi/cli/php_cli.c
@@ -517,7 +517,7 @@ static void php_cli_usage(char *argv0)
" -a Run interactively\n"
#endif
" -c <path>|<file> Look for php.ini file in this directory\n"
- " -n No php.ini file will be used\n"
+ " -n No configuration (ini) files will be used\n"
" -d foo[=bar] Define INI entry foo with value 'bar'\n"
" -e Generate extended information for debugger/profiler\n"
" -f <file> Parse and execute <file>.\n"
diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c
index 4ee85bf538..ac41c44def 100644
--- a/sapi/cli/php_cli_server.c
+++ b/sapi/cli/php_cli_server.c
@@ -1955,6 +1955,19 @@ static int php_cli_server_begin_send_static(php_cli_server *server, php_cli_serv
return php_cli_server_send_error_page(server, client, 400);
}
+#ifdef PHP_WIN32
+ /* The win32 namespace will cut off trailing dots and spaces. Since the
+ VCWD functionality isn't used here, a sophisticated functionality
+ would have to be reimplemented to know ahead there are no files
+ with invalid names there. The simplest is just to forbid invalid
+ filenames, which is done here. */
+ if (client->request.path_translated &&
+ ('.' == client->request.path_translated[client->request.path_translated_len-1] ||
+ ' ' == client->request.path_translated[client->request.path_translated_len-1])) {
+ return php_cli_server_send_error_page(server, client, 500);
+ }
+#endif
+
fd = client->request.path_translated ? open(client->request.path_translated, O_RDONLY): -1;
if (fd < 0) {
return php_cli_server_send_error_page(server, client, 404);
diff --git a/sapi/fpm/Makefile.frag b/sapi/fpm/Makefile.frag
index e39fbcb1e8..b0b4b34658 100644
--- a/sapi/fpm/Makefile.frag
+++ b/sapi/fpm/Makefile.frag
@@ -19,6 +19,6 @@ install-fpm: $(SAPI_FPM_PATH)
@$(mkinstalldirs) $(INSTALL_ROOT)$(mandir)/man8
@$(INSTALL_DATA) sapi/fpm/php-fpm.8 $(INSTALL_ROOT)$(mandir)/man8/php-fpm$(program_suffix).8
- @echo "Installing PHP FPM status page: $(INSTALL_ROOT)$(datadir)/fpm/"
+ @echo "Installing PHP FPM status page: $(INSTALL_ROOT)$(datadir)/fpm/"
@$(mkinstalldirs) $(INSTALL_ROOT)$(datadir)/fpm
@$(INSTALL_DATA) sapi/fpm/status.html $(INSTALL_ROOT)$(datadir)/fpm/status.html
diff --git a/sapi/fpm/fpm/fpm_signals.c b/sapi/fpm/fpm/fpm_signals.c
index c5d0692f18..a637e69e71 100644
--- a/sapi/fpm/fpm/fpm_signals.c
+++ b/sapi/fpm/fpm/fpm_signals.c
@@ -241,6 +241,10 @@ int fpm_signals_init_child() /* {{{ */
zlog(ZLOG_SYSERROR, "failed to init child signals: sigaction()");
return -1;
}
+
+#ifdef ZEND_SIGNALS
+ zend_signal_init();
+#endif
return 0;
}
/* }}} */
diff --git a/sapi/litespeed/Makefile.frag b/sapi/litespeed/Makefile.frag
index 767c2e5eb1..125a3b13da 100644
--- a/sapi/litespeed/Makefile.frag
+++ b/sapi/litespeed/Makefile.frag
@@ -4,6 +4,6 @@ $(SAPI_LITESPEED_PATH): $(PHP_GLOBAL_OBJS) $(PHP_BINARY_OBJS) $(PHP_LITESPEED_OB
$(BUILD_LITESPEED)
install-litespeed: $(SAPI_LITESPEED_PATH)
- @echo "Installing PHP LiteSpeed binary: $(INSTALL_ROOT)$(bindir)/"
+ @echo "Installing PHP LiteSpeed binary: $(INSTALL_ROOT)$(bindir)/"
@$(INSTALL) -m 0755 $(SAPI_LITESPEED_PATH) $(INSTALL_ROOT)$(bindir)/lsphp
diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c
index 8acf061983..9321eed2d3 100644
--- a/sapi/phpdbg/phpdbg.c
+++ b/sapi/phpdbg/phpdbg.c
@@ -554,11 +554,11 @@ static PHP_FUNCTION(phpdbg_get_executable)
if (ce->type == ZEND_USER_CLASS) {
if (zend_hash_exists(files, ce->info.user.filename)) {
ZEND_HASH_FOREACH_PTR(&ce->function_table, func) {
- if (func->type == ZEND_USER_FUNCTION) {
+ if (func->type == ZEND_USER_FUNCTION && zend_hash_exists(files, func->op_array.filename)) {
insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), func->op_array.filename);
if (by_function) {
- zend_string *fn_name = strpprintf(ZSTR_LEN(name) + ZSTR_LEN(func->op_array.function_name) + 2, "%.*s::%.*s", ZSTR_LEN(name), ZSTR_VAL(name), ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name));
+ zend_string *fn_name = strpprintf(ZSTR_LEN(name) + ZSTR_LEN(func->op_array.function_name) + 2, "%.*s::%.*s", (int) ZSTR_LEN(name), ZSTR_VAL(name), (int) ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name));
insert_ht = phpdbg_add_empty_array(insert_ht, fn_name);
zend_string_release(fn_name);
}
@@ -654,7 +654,7 @@ static PHP_FUNCTION(phpdbg_end_oplog)
if (last_scope == NULL) {
fn_name = zend_string_copy(last_function);
} else {
- fn_name = strpprintf(ZSTR_LEN(last_function) + ZSTR_LEN(last_scope->name) + 2, "%.*s::%.*s", ZSTR_LEN(last_scope->name), ZSTR_VAL(last_scope->name), ZSTR_LEN(last_function), ZSTR_VAL(last_function));
+ fn_name = strpprintf(ZSTR_LEN(last_function) + ZSTR_LEN(last_scope->name) + 2, "%.*s::%.*s", (int) ZSTR_LEN(last_scope->name), ZSTR_VAL(last_scope->name), (int) ZSTR_LEN(last_function), ZSTR_VAL(last_function));
}
insert_ht = phpdbg_add_empty_array(Z_ARR_P(return_value), fn_name);
zend_string_release(fn_name);
@@ -896,7 +896,7 @@ static inline size_t php_sapi_phpdbg_ub_write(const char *message, size_t length
if (PHPDBG_G(socket_fd) != -1 && !(PHPDBG_G(flags) & PHPDBG_IS_INTERACTIVE)) {
send(PHPDBG_G(socket_fd), message, length, 0);
}
- return phpdbg_script(P_STDOUT, "%.*s", length, message);
+ return phpdbg_script(P_STDOUT, "%.*s", (int) length, message);
} /* }}} */
/* beginning of struct, see main/streams/plain_wrapper.c line 111 */
diff --git a/sapi/phpdbg/phpdbg_bp.c b/sapi/phpdbg/phpdbg_bp.c
index eac67d4ac7..5436bda5db 100644
--- a/sapi/phpdbg/phpdbg_bp.c
+++ b/sapi/phpdbg/phpdbg_bp.c
@@ -563,12 +563,14 @@ PHPDBG_API int phpdbg_resolve_opline_break(phpdbg_breakopline_t *new_break) /* {
} else {
zend_execute_data *execute_data = EG(current_execute_data);
do {
- zend_op_array *op_array = &execute_data->func->op_array;
- if (op_array->function_name == NULL && op_array->scope == NULL && new_break->class_len == ZSTR_LEN(op_array->filename) && !memcmp(ZSTR_VAL(op_array->filename), new_break->class_name, new_break->class_len)) {
- if (phpdbg_resolve_op_array_break(new_break, op_array) == SUCCESS) {
- return SUCCESS;
- } else {
- return 2;
+ if (ZEND_USER_CODE(execute_data->func->common.type)) {
+ zend_op_array *op_array = &execute_data->func->op_array;
+ if (op_array->function_name == NULL && op_array->scope == NULL && new_break->class_len == ZSTR_LEN(op_array->filename) && !memcmp(ZSTR_VAL(op_array->filename), new_break->class_name, new_break->class_len)) {
+ if (phpdbg_resolve_op_array_break(new_break, op_array) == SUCCESS) {
+ return SUCCESS;
+ } else {
+ return 2;
+ }
}
}
} while ((execute_data = execute_data->prev_execute_data) != NULL);
diff --git a/sapi/phpdbg/phpdbg_frame.c b/sapi/phpdbg/phpdbg_frame.c
index 2d0c693a1e..ab1b554f76 100644
--- a/sapi/phpdbg/phpdbg_frame.c
+++ b/sapi/phpdbg/phpdbg_frame.c
@@ -218,7 +218,7 @@ void phpdbg_dump_backtrace(size_t num) /* {{{ */
while ((tmp = zend_hash_get_current_data_ex(Z_ARRVAL(zbacktrace), &position))) {
if (file) { /* userland */
phpdbg_out("frame #%d: ", i);
- phpdbg_xml("<frame %r id=\"%d\" file=\"%s\" line=\"%d\"", i, Z_STRVAL_P(file), Z_LVAL_P(line));
+ phpdbg_xml("<frame %r id=\"%d\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"", i, Z_STRVAL_P(file), Z_LVAL_P(line));
phpdbg_dump_prototype(tmp);
phpdbg_out(" at %s:%ld\n", Z_STRVAL_P(file), Z_LVAL_P(line));
i++;
diff --git a/sapi/phpdbg/phpdbg_info.c b/sapi/phpdbg/phpdbg_info.c
index 76b26ef1e0..5d7608fa76 100644
--- a/sapi/phpdbg/phpdbg_info.c
+++ b/sapi/phpdbg/phpdbg_info.c
@@ -120,12 +120,18 @@ PHPDBG_INFO(constants) /* {{{ */
phpdbg_out("Address Refs Type Constant\n");
ZEND_HASH_FOREACH_PTR(&consts, data) {
-#define VARIABLEINFO(attrs, msg, ...) phpdbg_writeln("constant", "address=\"%p\" refcount=\"%d\" type=\"%s\" name=\"%.*s\" " attrs, "%-18p %-7d %-9s %.*s" msg, &data->value, Z_REFCOUNTED(data->value) ? Z_REFCOUNT(data->value) : 1, zend_zval_type_name(&data->value), ZSTR_LEN(data->name), ZSTR_VAL(data->name), ##__VA_ARGS__)
+#define VARIABLEINFO(attrs, msg, ...) \
+ phpdbg_writeln("constant", \
+ "address=\"%p\" refcount=\"%d\" type=\"%s\" name=\"%.*s\" " attrs, \
+ "%-18p %-7d %-9s %.*s" msg, &data->value, \
+ Z_REFCOUNTED(data->value) ? Z_REFCOUNT(data->value) : 1, \
+ zend_zval_type_name(&data->value), \
+ (int) ZSTR_LEN(data->name), ZSTR_VAL(data->name), ##__VA_ARGS__)
switch (Z_TYPE(data->value)) {
case IS_STRING:
phpdbg_try_access {
- VARIABLEINFO("length=\"%d\" value=\"%.*s\"", "\nstring (%d) \"%.*s%s\"", Z_STRLEN(data->value), Z_STRLEN(data->value) < 255 ? Z_STRLEN(data->value) : 255, Z_STRVAL(data->value), Z_STRLEN(data->value) > 255 ? "..." : "");
+ VARIABLEINFO("length=\"%zd\" value=\"%.*s\"", "\nstring (%zd) \"%.*s%s\"", Z_STRLEN(data->value), Z_STRLEN(data->value) < 255 ? (int) Z_STRLEN(data->value) : 255, Z_STRVAL(data->value), Z_STRLEN(data->value) > 255 ? "..." : "");
} phpdbg_catch_access {
VARIABLEINFO("", "");
} phpdbg_end_try_access();
@@ -158,7 +164,7 @@ static int phpdbg_arm_auto_global(zval *ptrzv) {
if (auto_global->armed) {
if (PHPDBG_G(flags) & PHPDBG_IN_SIGNAL_HANDLER) {
- phpdbg_notice("variableinfo", "unreachable=\"%.*s\"", "Cannot show information about superglobal variable %.*s", ZSTR_LEN(auto_global->name), ZSTR_VAL(auto_global->name));
+ phpdbg_notice("variableinfo", "unreachable=\"%.*s\"", "Cannot show information about superglobal variable %.*s", (int) ZSTR_LEN(auto_global->name), ZSTR_VAL(auto_global->name));
} else {
auto_global->armed = auto_global->auto_global_callback(auto_global->name);
}
@@ -224,7 +230,10 @@ static int phpdbg_print_symbols(zend_bool show_globals) {
ZEND_HASH_FOREACH_STR_KEY_VAL(&vars, var, data) {
phpdbg_try_access {
const char *isref = "";
-#define VARIABLEINFO(attrs, msg, ...) phpdbg_writeln("variable", "address=\"%p\" refcount=\"%d\" type=\"%s\" refstatus=\"%s\" name=\"%.*s\" " attrs, "%-18p %-7d %-9s %s$%.*s" msg, data, Z_REFCOUNTED_P(data) ? Z_REFCOUNT_P(data) : 1, zend_zval_type_name(data), isref, ZSTR_LEN(var), ZSTR_VAL(var), ##__VA_ARGS__)
+#define VARIABLEINFO(attrs, msg, ...) \
+ phpdbg_writeln("variable", \
+ "address=\"%p\" refcount=\"%d\" type=\"%s\" refstatus=\"%s\" name=\"%.*s\" " attrs, \
+ "%-18p %-7d %-9s %s$%.*s" msg, data, Z_REFCOUNTED_P(data) ? Z_REFCOUNT_P(data) : 1, zend_zval_type_name(data), isref, (int) ZSTR_LEN(var), ZSTR_VAL(var), ##__VA_ARGS__)
retry_switch:
switch (Z_TYPE_P(data)) {
case IS_RESOURCE:
@@ -237,14 +246,14 @@ retry_switch:
break;
case IS_OBJECT:
phpdbg_try_access {
- VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (%s)\n", Z_OBJCE_P(data)->name);
+ VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (%s)\n", ZSTR_VAL(Z_OBJCE_P(data)->name));
} phpdbg_catch_access {
VARIABLEINFO("instanceof=\"%s\"", "\n|-----(instanceof)----> (unknown)\n");
} phpdbg_end_try_access();
break;
case IS_STRING:
phpdbg_try_access {
- VARIABLEINFO("length=\"%d\" value=\"%.*s\"", "\nstring (%d) \"%.*s%s\"", Z_STRLEN_P(data), Z_STRLEN_P(data) < 255 ? Z_STRLEN_P(data) : 255, Z_STRVAL_P(data), Z_STRLEN_P(data) > 255 ? "..." : "");
+ VARIABLEINFO("length=\"%zd\" value=\"%.*s\"", "\nstring (%zd) \"%.*s%s\"", Z_STRLEN_P(data), Z_STRLEN_P(data) < 255 ? (int) Z_STRLEN_P(data) : 255, Z_STRVAL_P(data), Z_STRLEN_P(data) > 255 ? "..." : "");
} phpdbg_catch_access {
VARIABLEINFO("", "");
} phpdbg_end_try_access();
@@ -369,7 +378,7 @@ static inline void phpdbg_print_class_name(zend_class_entry *ce) /* {{{ */
const char *visibility = ce->type == ZEND_USER_CLASS ? "User" : "Internal";
const char *type = (ce->ce_flags & ZEND_ACC_INTERFACE) ? "Interface" : (ce->ce_flags & ZEND_ACC_ABSTRACT) ? "Abstract Class" : "Class";
- phpdbg_writeln("class", "type=\"%s\" flags=\"%s\" name=\"%.*s\" methodcount=\"%d\"", "%s %s %.*s (%d)", visibility, type, ZSTR_LEN(ce->name), ZSTR_VAL(ce->name), zend_hash_num_elements(&ce->function_table));
+ phpdbg_writeln("class", "type=\"%s\" flags=\"%s\" name=\"%.*s\" methodcount=\"%d\"", "%s %s %.*s (%d)", visibility, type, (int) ZSTR_LEN(ce->name), ZSTR_VAL(ce->name), zend_hash_num_elements(&ce->function_table));
} /* }}} */
PHPDBG_INFO(classes) /* {{{ */
diff --git a/sapi/phpdbg/phpdbg_opcode.c b/sapi/phpdbg/phpdbg_opcode.c
index fd9c92811d..0ea4324845 100644
--- a/sapi/phpdbg/phpdbg_opcode.c
+++ b/sapi/phpdbg/phpdbg_opcode.c
@@ -49,10 +49,10 @@ static inline char *phpdbg_decode_op(zend_op_array *ops, znode_op *op, uint32_t
} break;
case IS_VAR:
- spprintf(&decode, 0, "@%td", EX_VAR_TO_NUM(op->var) - ops->last_var);
+ spprintf(&decode, 0, "@%u", EX_VAR_TO_NUM(op->var) - ops->last_var);
break;
case IS_TMP_VAR:
- spprintf(&decode, 0, "~%td", EX_VAR_TO_NUM(op->var) - ops->last_var);
+ spprintf(&decode, 0, "~%u", EX_VAR_TO_NUM(op->var) - ops->last_var);
break;
case IS_CONST: {
zval *literal = RT_CONSTANT(ops, *op);
diff --git a/sapi/phpdbg/phpdbg_out.h b/sapi/phpdbg/phpdbg_out.h
index 0a0d7c2410..a6f28da14d 100644
--- a/sapi/phpdbg/phpdbg_out.h
+++ b/sapi/phpdbg/phpdbg_out.h
@@ -34,20 +34,11 @@ enum {
P_LOG
};
-#ifdef ZTS
-PHPDBG_API int phpdbg_print(int severity, int fd, const char *tag, const char *xmlfmt, const char *strfmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 6, 7);
-PHPDBG_API int phpdbg_xml_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
-PHPDBG_API int phpdbg_log_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
-PHPDBG_API int phpdbg_out_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
-PHPDBG_API int phpdbg_rlog_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 3, 4);
-#else
PHPDBG_API int phpdbg_print(int severity, int fd, const char *tag, const char *xmlfmt, const char *strfmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 5, 6);
PHPDBG_API int phpdbg_xml_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3);
PHPDBG_API int phpdbg_log_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3);
PHPDBG_API int phpdbg_out_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3);
PHPDBG_API int phpdbg_rlog_internal(int fd, const char *fmt, ...) PHP_ATTRIBUTE_FORMAT(printf, 2, 3);
-#endif
-
#define phpdbg_error(tag, xmlfmt, strfmt, ...) phpdbg_print(P_ERROR , PHPDBG_G(io)[PHPDBG_STDOUT].fd, tag, xmlfmt, strfmt, ##__VA_ARGS__)
#define phpdbg_notice(tag, xmlfmt, strfmt, ...) phpdbg_print(P_NOTICE , PHPDBG_G(io)[PHPDBG_STDOUT].fd, tag, xmlfmt, strfmt, ##__VA_ARGS__)
diff --git a/sapi/phpdbg/phpdbg_print.c b/sapi/phpdbg/phpdbg_print.c
index 6b6c706f92..00209cb239 100644
--- a/sapi/phpdbg/phpdbg_print.c
+++ b/sapi/phpdbg/phpdbg_print.c
@@ -42,7 +42,7 @@ const phpdbg_command_t phpdbg_print_commands[] = {
PHPDBG_PRINT(opline) /* {{{ */
{
if (PHPDBG_G(in_execution) && EG(current_execute_data)) {
- phpdbg_print_opline(EG(current_execute_data), 1);
+ phpdbg_print_opline(phpdbg_user_execute_data(EG(current_execute_data)), 1);
} else {
phpdbg_error("inactive", "type=\"execution\"", "Not Executing!");
}
@@ -124,7 +124,7 @@ return SUCCESS;
PHPDBG_PRINT(stack) /* {{{ */
{
if (PHPDBG_G(in_execution) && EG(current_execute_data)) {
- zend_op_array *ops = &EG(current_execute_data)->func->op_array;
+ zend_op_array *ops = &phpdbg_user_execute_data(EG(current_execute_data))->func->op_array;
if (ops->function_name) {
if (ops->scope) {
phpdbg_notice("printinfo", "method=\"%s::%s\" num=\"%d\"", "Stack in %s::%s() (%d ops)", ZSTR_VAL(ops->scope->name), ZSTR_VAL(ops->function_name), ops->last);
@@ -278,7 +278,7 @@ void phpdbg_print_opcodes_function(const char *function, size_t len) {
return;
}
- phpdbg_out("function name: %.*s\n", ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name));
+ phpdbg_out("function name: %.*s\n", (int) ZSTR_LEN(func->op_array.function_name), ZSTR_VAL(func->op_array.function_name));
phpdbg_print_function_helper(func);
}
@@ -351,7 +351,7 @@ static void phpdbg_print_opcodes_ce(zend_class_entry *ce) {
phpdbg_out("\n");
ZEND_HASH_FOREACH_STR_KEY_PTR(&ce->function_table, method_name, method) {
- phpdbg_out("\nfunction name: %s\n", method_name);
+ phpdbg_out("\nfunction name: %s\n", ZSTR_VAL(method_name));
phpdbg_print_function_helper(method);
} ZEND_HASH_FOREACH_END();
}
diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c
index 97249765f8..558ca469b5 100644
--- a/sapi/phpdbg/phpdbg_prompt.c
+++ b/sapi/phpdbg/phpdbg_prompt.c
@@ -518,13 +518,14 @@ PHPDBG_COMMAND(continue) /* {{{ */
} /* }}} */
int phpdbg_skip_line_helper() /* {{{ */ {
- const zend_op_array *op_array = &EG(current_execute_data)->func->op_array;
+ zend_execute_data *ex = phpdbg_user_execute_data(EG(current_execute_data));
+ const zend_op_array *op_array = &ex->func->op_array;
const zend_op *opline = op_array->opcodes;
PHPDBG_G(flags) |= PHPDBG_IN_UNTIL;
- PHPDBG_G(seek_ex) = EG(current_execute_data);
+ PHPDBG_G(seek_ex) = ex;
do {
- if (opline->lineno != EG(current_execute_data)->opline->lineno
+ if (opline->lineno != ex->opline->lineno
|| opline->opcode == ZEND_RETURN
|| opline->opcode == ZEND_FAST_RET
|| opline->opcode == ZEND_GENERATOR_RETURN
@@ -562,10 +563,11 @@ PHPDBG_COMMAND(next) /* {{{ */
} /* }}} */
static void phpdbg_seek_to_end(void) /* {{{ */ {
- const zend_op_array *op_array = &EG(current_execute_data)->func->op_array;
+ zend_execute_data *ex = phpdbg_user_execute_data(EG(current_execute_data));
+ const zend_op_array *op_array = &ex->func->op_array;
const zend_op *opline = op_array->opcodes;
- PHPDBG_G(seek_ex) = EG(current_execute_data);
+ PHPDBG_G(seek_ex) = ex;
do {
switch (opline->opcode) {
case ZEND_RETURN:
@@ -588,7 +590,7 @@ PHPDBG_COMMAND(finish) /* {{{ */
}
phpdbg_seek_to_end();
- if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) EG(current_execute_data)->opline)) {
+ if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) {
zend_hash_clean(&PHPDBG_G(seek));
} else {
PHPDBG_G(flags) |= PHPDBG_IN_FINISH;
@@ -605,7 +607,7 @@ PHPDBG_COMMAND(leave) /* {{{ */
}
phpdbg_seek_to_end();
- if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) EG(current_execute_data)->opline)) {
+ if (zend_hash_index_exists(&PHPDBG_G(seek), (zend_ulong) phpdbg_user_execute_data(EG(current_execute_data))->opline)) {
zend_hash_clean(&PHPDBG_G(seek));
phpdbg_notice("leave", "type=\"end\"", "Already at the end of the function");
return SUCCESS;
@@ -1518,7 +1520,11 @@ void phpdbg_execute_ex(zend_execute_data *execute_data) /* {{{ */
line = zval_get_long(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("line"), 1, &rv));
msg = zval_get_string(zend_read_property(zend_get_exception_base(&zv), &zv, ZEND_STRL("message"), 1, &rv));
- phpdbg_error("exception", "name=\"%s\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"", "Uncaught %s in %s on line " ZEND_LONG_FMT ": %.*s", ZSTR_VAL(exception->ce->name), ZSTR_VAL(file), line, ZSTR_LEN(msg) < 80 ? ZSTR_LEN(msg) : 80, ZSTR_VAL(msg));
+ phpdbg_error("exception",
+ "name=\"%s\" file=\"%s\" line=\"" ZEND_LONG_FMT "\"",
+ "Uncaught %s in %s on line " ZEND_LONG_FMT ": %.*s",
+ ZSTR_VAL(exception->ce->name), ZSTR_VAL(file), line,
+ ZSTR_LEN(msg) < 80 ? (int) ZSTR_LEN(msg) : 80, ZSTR_VAL(msg));
zend_string_release(msg);
zend_string_release(file);
diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c
index 696e11e762..a944d256ae 100644
--- a/sapi/phpdbg/phpdbg_utils.c
+++ b/sapi/phpdbg/phpdbg_utils.c
@@ -484,11 +484,11 @@ PHPDBG_API int phpdbg_parse_variable_with_arg(char *input, size_t len, HashTable
key = ZSTR_VAL(strkey);
keylen = ZSTR_LEN(strkey);
} else {
- keylen = spprintf(&key, 0, "%llu", numkey);
+ keylen = spprintf(&key, 0, ZEND_ULONG_FMT, numkey);
}
propkey = phpdbg_get_property_key(key);
name = emalloc(i + keylen + 2);
- namelen = sprintf(name, "%.*s%.*s%s", (int) i, input, keylen - (propkey - key), propkey, input[len - 1] == ']'?"]":"");
+ namelen = sprintf(name, "%.*s%.*s%s", (int) i, input, (int) (keylen - (propkey - key)), propkey, input[len - 1] == ']'?"]":"");
if (!strkey) {
efree(key);
}
@@ -597,7 +597,7 @@ static int phpdbg_xml_array_element_dump(zval *zv, zend_string *key, zend_ulong
phpdbg_try_access {
if (key) { /* string key */
- phpdbg_xml(" name=\"%.*s\"", ZSTR_LEN(key), ZSTR_VAL(key));
+ phpdbg_xml(" name=\"%.*s\"", (int) ZSTR_LEN(key), ZSTR_VAL(key));
} else { /* numeric key */
phpdbg_xml(" name=\"%ld\"", num);
}
@@ -631,7 +631,7 @@ static int phpdbg_xml_object_property_dump(zval *zv, zend_string *key, zend_ulon
phpdbg_xml(" class=\"%s\" protection=\"private\"", class_name);
}
} else {
- phpdbg_xml(" name=\"%.*s\" protection=\"public\"", ZSTR_LEN(key), ZSTR_VAL(key));
+ phpdbg_xml(" name=\"%.*s\" protection=\"public\"", (int) ZSTR_LEN(key), ZSTR_VAL(key));
}
} else { /* numeric key */
phpdbg_xml(" name=\"%ld\" protection=\"public\"", num);
@@ -683,7 +683,7 @@ PHPDBG_API void phpdbg_xml_var_dump(zval *zv) {
phpdbg_xml("<float refstatus=\"%s\" value=\"%.*G\" />", COMMON, (int) EG(precision), Z_DVAL_P(zv));
break;
case IS_STRING:
- phpdbg_xml("<string refstatus=\"%s\" length=\"%d\" value=\"%.*s\" />", COMMON, Z_STRLEN_P(zv), Z_STRLEN_P(zv), Z_STRVAL_P(zv));
+ phpdbg_xml("<string refstatus=\"%s\" length=\"%zd\" value=\"%.*s\" />", COMMON, Z_STRLEN_P(zv), (int) Z_STRLEN_P(zv), Z_STRVAL_P(zv));
break;
case IS_ARRAY:
myht = Z_ARRVAL_P(zv);
@@ -705,7 +705,7 @@ PHPDBG_API void phpdbg_xml_var_dump(zval *zv) {
}
class_name = Z_OBJ_HANDLER_P(zv, get_class_name)(Z_OBJ_P(zv));
- phpdbg_xml("<object refstatus=\"%s\" class=\"%.*s\" id=\"%d\" num=\"%d\">", COMMON, ZSTR_LEN(class_name), ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(zv), myht ? zend_hash_num_elements(myht) : 0);
+ phpdbg_xml("<object refstatus=\"%s\" class=\"%.*s\" id=\"%d\" num=\"%d\">", COMMON, (int) ZSTR_LEN(class_name), ZSTR_VAL(class_name), Z_OBJ_HANDLE_P(zv), myht ? zend_hash_num_elements(myht) : 0);
zend_string_release(class_name);
element_dump_func = phpdbg_xml_object_property_dump;
@@ -729,7 +729,7 @@ head_done:
break;
case IS_RESOURCE: {
const char *type_name = zend_rsrc_list_get_rsrc_type(Z_RES_P(zv));
- phpdbg_xml("<resource refstatus=\"%s\" id=\"%pd\" type=\"%ld\" />", COMMON, Z_RES_P(zv)->handle, type_name ? type_name : "unknown");
+ phpdbg_xml("<resource refstatus=\"%s\" id=\"%pd\" type=\"%s\" />", COMMON, Z_RES_P(zv)->handle, type_name ? type_name : "unknown");
break;
}
default:
diff --git a/sapi/phpdbg/phpdbg_utils.h b/sapi/phpdbg/phpdbg_utils.h
index 2bd4f35d71..4ba756139b 100644
--- a/sapi/phpdbg/phpdbg_utils.h
+++ b/sapi/phpdbg/phpdbg_utils.h
@@ -99,6 +99,14 @@ char *phpdbg_short_zval_print(zval *zv, int maxlen);
PHPDBG_API zend_bool phpdbg_check_caught_ex(zend_execute_data *ex, zend_object *exception);
+static zend_always_inline zend_execute_data *phpdbg_user_execute_data(zend_execute_data *ex) {
+ while (!ex->func || !ZEND_USER_CODE(ex->func->common.type)) {
+ ex = ex->prev_execute_data;
+ ZEND_ASSERT(ex);
+ }
+ return ex;
+}
+
#ifdef ZTS
#define PHPDBG_OUTPUT_BACKUP_DEFINES() \
zend_output_globals *output_globals_ptr; \
diff --git a/sapi/phpdbg/phpdbg_wait.c b/sapi/phpdbg/phpdbg_wait.c
index 180b48c864..c3ae23b7cd 100644
--- a/sapi/phpdbg/phpdbg_wait.c
+++ b/sapi/phpdbg/phpdbg_wait.c
@@ -231,7 +231,7 @@ void phpdbg_webdata_decompress(char *msg, int len) {
} else if (mode > 0) {
// not loaded module
if (!sapi_module.name || strcmp(sapi_module.name, Z_STRVAL_P(module))) {
- phpdbg_notice("wait", "missingmodule=\"%.*s\"", "The module %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/module/%.*s.so", Z_STRLEN_P(module), Z_STRVAL_P(module), Z_STRLEN_P(module), Z_STRVAL_P(module));
+ phpdbg_notice("wait", "missingmodule=\"%.*s\"", "The module %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/module/%.*s.so", (int) Z_STRLEN_P(module), Z_STRVAL_P(module), (int) Z_STRLEN_P(module), Z_STRVAL_P(module));
}
}
} while (module);
@@ -292,7 +292,7 @@ void phpdbg_webdata_decompress(char *msg, int len) {
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(zvp), name) {
if (Z_TYPE_P(name) == IS_STRING) {
- phpdbg_notice("wait", "missingextension=\"%.*s\"", "The Zend extension %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/extension.so", Z_STRLEN_P(name), Z_STRVAL_P(name));
+ phpdbg_notice("wait", "missingextension=\"%.*s\"", "The Zend extension %.*s isn't present in " PHPDBG_NAME ", you still can load via dl /path/to/extension.so", (int) Z_STRLEN_P(name), Z_STRVAL_P(name));
}
} ZEND_HASH_FOREACH_END();
}
diff --git a/win32/build/Makefile.phpize b/win32/build/Makefile.phpize
index 1f92f7716c..cd74336039 100644
--- a/win32/build/Makefile.phpize
+++ b/win32/build/Makefile.phpize
@@ -18,11 +18,13 @@ clean-pecl:
clean-all:
@echo Cleaning standard build dirs
+ cd $(BUILD_DIR)
@for %D in (_x $(BUILD_DIRS_SUB)) do @if exist %D @rd /s /q %D
-@del /f /q $(BUILD_DIR)\*.res $(BUILD_DIR)\*.manifest $(BUILD_DIR)\*.lib $(BUILD_DIR)\*.ilk $(BUILD_DIR)\*.pdb $(BUILD_DIR)\*.exp $(PHPDEF) $(BUILD_DIR)\*.rc $(BUILD_DIR)\*.dbg $(BUILD_DIR)\*.bin $(BUILD_DIR)\php*.dll $(BUILD_DIR)\php*.exe > NUL
clean: clean-pecl
@echo Cleaning distribution build dirs
+ cd $(BUILD_DIR)
@for %D in (_x $(BUILD_DIRS_SUB)) do @if exist %D @del /F /Q %D\*.* > NUL
-@del /F /Q $(BUILD_DIR)\*.res $(BUILD_DIR)\*.lib $(BUILD_DIR)\*.ilk $(BUILD_DIR)\*.pdb $(BUILD_DIR)\*.exp $(PHPDEF) $(BUILD_DIR)\php-$(PHP_VERSION_STRING)-Win32.zip $(BUILD_DIR)\pecl-$(PHP_VERSION_STRING)-Win32.zip > NUL
diff --git a/win32/build/confutils.js b/win32/build/confutils.js
index 91af62aa5c..95f7985c3d 100644
--- a/win32/build/confutils.js
+++ b/win32/build/confutils.js
@@ -1449,79 +1449,117 @@ function ADD_SOURCES(dir, file_list, target, obj_dir)
var sub_build = "$(BUILD_DIR)\\";
- /* if module dir is not a child of the main source dir,
- * we need to tweak it; we should have detected such a
- * case in condense_path and rewritten the path to
- * be relative.
- * This probably breaks for non-sibling dirs, but that
- * is not a problem as buildconf only checks for pecl
- * as either a child or a sibling */
- if (obj_dir == null) {
- var build_dir = dir.replace(new RegExp("^..\\\\"), "");
- var mangle_dir = build_dir.replace(new RegExp("[\\\\/.-]", "g"), "_");
- var bd_flags_name = "CFLAGS_BD_" + mangle_dir.toUpperCase();
- }
- else {
- var build_dir = obj_dir.replace(new RegExp("^..\\\\"), "");
- var mangle_dir = build_dir.replace(new RegExp("[\\\\/.-]", "g"), "_");
- var bd_flags_name = "CFLAGS_BD_" + mangle_dir.toUpperCase();
- }
-
- var dirs = build_dir.split("\\");
- var i, d = "";
- for (i = 0; i < dirs.length; i++) {
- d += dirs[i];
- build_dirs[build_dirs.length] = d;
- d += "\\";
- }
- sub_build += d;
-
-
- DEFINE(bd_flags_name, "/Fp" + sub_build + " /FR" + sub_build + " ");
- if (VS_TOOLSET) {
- ADD_FLAG(bd_flags_name, "/Fd" + sub_build);
- }
+ var srcs_by_dir = {};
+ /* Parse the file list to create an aggregated structure based on the subdirs passed. */
for (i in file_list) {
src = file_list[i];
- obj = src.replace(re, ".obj");
- tv += " " + sub_build + obj;
- resp += " " + sub_build.replace('$(BUILD_DIR)', bd) + obj;
-
- if (!PHP_MP_DISABLED) {
- if (i > 0) {
- objs_line += " " + sub_build + obj;
- srcs_line += " " + dir + "\\" + src;
+
+ var _tmp = src.split("\\");
+
+ var filename = _tmp.pop();
+
+ // build the obj out dir and use it as a key
+ var dirname = _tmp.join("\\");
+
+ //WARNING("dir: " + dir + " dirname: " + dirname + " filename: " + filename);
+
+ /* if module dir is not a child of the main source dir,
+ * we need to tweak it; we should have detected such a
+ * case in condense_path and rewritten the path to
+ * be relative.
+ * This probably breaks for non-sibling dirs, but that
+ * is not a problem as buildconf only checks for pecl
+ * as either a child or a sibling */
+ if (obj_dir == null) {
+ if (MODE_PHPIZE) {
+ /* In the phpize mode, the subdirs are always relative to BUID_DIR.
+ No need to differentiate by extension, only one gets built. */
+ var build_dir = (dirname ? dirname : "").replace(new RegExp("^..\\\\"), "");
} else {
- objs_line = sub_build + obj;
- srcs_line = dir + "\\" + src;
+ var build_dir = (dirname ? (dir + "\\" + dirname) : dir).replace(new RegExp("^..\\\\"), "");
}
- } else {
- MFO.WriteLine(sub_build + obj + ": " + dir + "\\" + src);
+ }
+ else {
+ var build_dir = (dirname ? obj_dir + "\\" + dirname : obj_dir).replace(new RegExp("^..\\\\"), "");
+ }
- if (PHP_ANALYZER == "pvs") {
- MFO.WriteLine("\t@\"$(PVS_STUDIO)\" --cl-params $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " --source-file " + dir + "\\" + src
- + " --cfg PVS-Studio.conf --errors-off \"V122 V117 V111\" ");
- }
- MFO.WriteLine("\t@$(CC) $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " /Fo" + sub_build + obj);
+ obj = sub_build + build_dir + "\\" + filename.replace(re, ".obj");
+
+ if (i > 0) {
+ srcs_line += " " + dir + "\\" + src;
+ objs_line += " " + obj
+ } else {
+ srcs_line = dir + "\\" + src;
+ objs_line = obj;
}
+
+ resp += " " + obj.replace('$(BUILD_DIR)', bd);
+ tv += " " + obj;
+
+ if (!srcs_by_dir.hasOwnProperty(build_dir)) {
+ srcs_by_dir[build_dir] = [];
+ }
+
+ /* storing the index from the file_list */
+ srcs_by_dir[build_dir].push(i);
}
- if (!PHP_MP_DISABLED) {
- MFO.WriteLine(objs_line + ": " + srcs_line);
- MFO.WriteLine("\t$(CC) $(" + flags + ") $(CFLAGS) /Fo" + sub_build + " $(" + bd_flags_name + ") /c " + srcs_line);
+ /* Create makefile build targets and dependencies. */
+ MFO.WriteLine(objs_line + ": " + srcs_line);
+
+ /* Create target subdirs if any and produce the compiler calls, /mp is respected if enabled. */
+ for (var k in srcs_by_dir) {
+ var dirs = k.split("\\");
+ var i, d = "";
+ for (i = 0; i < dirs.length; i++) {
+ d += dirs[i];
+ build_dirs[build_dirs.length] = d;
+ d += "\\";
+ }
+
+ var mangle_dir = k.replace(new RegExp("[\\\\/.-]", "g"), "_");
+ var bd_flags_name = "CFLAGS_BD_" + mangle_dir.toUpperCase();
+
+ DEFINE(bd_flags_name, "/Fp" + sub_build + d + " /FR" + sub_build + d + " ");
+ if (VS_TOOLSET) {
+ ADD_FLAG(bd_flags_name, "/Fd" + sub_build + d);
+ }
+
+ if (PHP_MP_DISABLED) {
+ for (var j in srcs_by_dir[k]) {
+ src = file_list[srcs_by_dir[k][j]];
+ if (PHP_ANALYZER == "pvs") {
+ MFO.WriteLine("\t@\"$(PVS_STUDIO)\" --cl-params $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " --source-file " + dir + "\\" + src
+ + " --cfg PVS-Studio.conf --errors-off \"V122 V117 V111\" ");
+ }
+
+ var _tmp = src.split("\\");
+ var filename = _tmp.pop();
+ obj = filename.replace(re, ".obj");
+
+ MFO.WriteLine("\t@$(CC) $(" + flags + ") $(CFLAGS) $(" + bd_flags_name + ") /c " + dir + "\\" + src + " /Fo" + sub_build + d + obj);
+ }
+ } else {
+ /* TODO create a response file at least for the source files to work around the cmd line length limit. */
+ var src_line = "";
+ for (var j in srcs_by_dir[k]) {
+ src_line += dir + "\\" + file_list[srcs_by_dir[k][j]] + " ";
+ }
+
+ MFO.WriteLine("\t$(CC) $(" + flags + ") $(CFLAGS) /Fo" + sub_build + d + " $(" + bd_flags_name + ") /c " + src_line);
+ }
}
DEFINE(sym, tv);
- /* Generate the response file and define it to the Makefile. This can be
- useful when getting the "command line too long" linker errors. */
+ /* Generate the object response file and define it to the Makefile. This can be
+ useful when getting the "command line too long" linker errors.
+ TODO pack this into a function when response files are used for other kinds of info. */
var obj_lst_fh = null;
if (!FSO.FileExists(obj_lst_fn)) {
obj_lst_fh = FSO.CreateTextFile(obj_lst_fn);
- //STDOUT.WriteLine("Creating " + obj_lst_fn);
} else {
- //STDOUT.WriteLine("Appending to " + obj_lst_fn);
obj_lst_fh = FSO.OpenTextFile(obj_lst_fn, 8);
}
@@ -2109,7 +2147,16 @@ function ADD_FLAG(name, flags, target)
if (configure_subst.Exists(name)) {
var curr_flags = configure_subst.Item(name);
- if (curr_flags.indexOf(flags) >= 0) {
+ /* Prefix with a space, thus making sure the
+ current flag is not a substring of some
+ other. It's still not a complete check if
+ some flags with spaces got added.
+
+ TODO rework to use an array, so direct
+ match can be done. This will also
+ help to normalize flags and to not
+ to insert duplicates. */
+ if (curr_flags.indexOf(" " + flags) >= 0) {
return;
}