Merge branch 'master' into openssl_error_store

This commit is contained in:
Jakub Zelenka 2016-06-19 16:20:02 +01:00
commit c2b90805e8
796 changed files with 121373 additions and 44590 deletions

View file

@ -165,7 +165,7 @@ User Functions/Methods Naming Conventions
'foobar'
'foo_bar'
Internal Function Naming Convensions
Internal Function Naming Conventions
----------------------
1. Functions that are part of the external API should be named

1463
NEWS

File diff suppressed because it is too large Load diff

View file

@ -79,7 +79,7 @@ The next few rules are more of a technical nature::
should be noted in both PHP-5.4/NEWS and PHP-5.5/NEWS but
not master, which is not a public released version yet.
3. Do not commit multiple file and dump all messages in one commit. If you
3. Do not commit multiple files and dump all messages in one commit. If you
modified several unrelated files, commit each group separately and
provide a nice commit message for each one. See example below.

View file

@ -17,7 +17,7 @@ It is recommended to do so a couple of days before the packaging day, to
have enough time to investigate failures, communicate with the authors and
commit the fixes.
The RM for the branch is also responsible for keeping the CI green on
ongoing bases between the releases. Check the CI status for your branch
ongoing basis between the releases. Check the CI status for your branch
periodically and resolve the failures ASAP. See more in:
https://wiki.php.net/rfc/travis_ci
@ -31,7 +31,7 @@ team (Bjori) on hand.
6. Verify the tags to be extra sure everything was tagged properly.
7. Moving extensions from/to PECL requires write acces to the destination.
7. Moving extensions from/to PECL requires write access to the destination.
Most developers should have this.
Moving extensions from php-src to PECL
@ -271,8 +271,8 @@ to upgrade.
10. Wait an hour or two, then send a mail to php-announce@lists.php.net,
php-general@lists.php.net and internals@lists.php.net with a text similar to
http://news.php.net/php.internals/17222.
Please make sure that the mail to php-announce@ is its own completely seperate email.
This is to make sure that repiles to the announcement on php-general@ or internals@
Please make sure that the mail to php-announce@ is its own completely separate email.
This is to make sure that replies to the announcement on php-general@ or internals@
will not accidentally hit the php-announce@ mailinglist.
Re-releasing the same version (or -pl)
@ -309,6 +309,6 @@ to upgrade.
5. Wait an hour or two, then send a mail to php-announce@lists.php.net,
php-general@lists.php.net and internals@lists.php.net with a text similar to
the news entry.
Please make sure that the mail to php-announce@ is its own completely seperate email.
This is to make sure that repiles to the announcement on php-general@ or internals@
Please make sure that the mail to php-announce@ is its own completely separate email.
This is to make sure that replies to the announcement on php-general@ or internals@
will not accidentally hit the php-announce@ mailinglist.

View file

@ -10,7 +10,7 @@ Pull Requests
=============
PHP accepts pull requests via github. Discussions are done on github, but
depending on the topic can also be relayed to the official PHP developer
mailinglist internals@lists.php.net.
mailing list internals@lists.php.net.
New features require an RFC and must be accepted by the developers.
See https://wiki.php.net/rfc and https://wiki.php.net/rfc/voting for more

837
UPGRADING
View file

@ -1,4 +1,4 @@
PHP 7.0 UPGRADE NOTES
PHP 7.1 UPGRADE NOTES
1. Backward Incompatible Changes
2. New Features
@ -19,799 +19,158 @@
1. Backward Incompatible Changes
========================================
Language changes
================
Changes to variable handling
----------------------------
* Indirect variable, property and method references are now interpreted with
left-to-right semantics. Some examples:
$$foo['bar']['baz'] // interpreted as ($$foo)['bar']['baz']
$foo->$bar['baz'] // interpreted as ($foo->$bar)['baz']
$foo->$bar['baz']() // interpreted as ($foo->$bar)['baz']()
Foo::$bar['baz']() // interpreted as (Foo::$bar)['baz']()
To restore the previous behavior add explicit curly braces:
${$foo['bar']['baz']}
$foo->{$bar['baz']}
$foo->{$bar['baz']}()
Foo::{$bar['baz']}()
* The global keyword now only accepts simple variables. Instead of
global $$foo->bar;
it is now required to write the following:
global ${$foo->bar};
* Parentheses around variables or function calls no longer have any influence
on behavior. For example the following code, where the result of a function
call is passed to a by-reference function
function getArray() { return [1, 2, 3]; }
$last = array_pop(getArray());
// Strict Standards: Only variables should be passed by reference
$last = array_pop((getArray()));
// Strict Standards: Only variables should be passed by reference
will now throw a strict standards error regardless of whether parentheses
are used. Previously no notice was generated in the second case.
* Array elements or object properties that are automatically created during
by-reference assignments will now result in a different order. For example
$array = [];
$array["a"] =& $array["b"];
$array["b"] = 1;
var_dump($array);
now results in the array ["a" => 1, "b" => 1], while previously the result
was ["b" => 1, "a" => 1];
Relevant RFCs:
* https://wiki.php.net/rfc/uniform_variable_syntax
* https://wiki.php.net/rfc/abstract_syntax_tree
Changes to list()
-----------------
* list() will no longer assign variables in reverse order. For example
list($array[], $array[], $array[]) = [1, 2, 3];
var_dump($array);
will now result in $array == [1, 2, 3] rather than [3, 2, 1]. Note that only
the **order** of the assignments changed, but the assigned values stay the
same. E.g. a normal usage like
list($a, $b, $c) = [1, 2, 3];
// $a = 1; $b = 2; $c = 3;
will retain its current behavior.
* Empty list() assignments are no longer allowed. As such all of the following
are invalid:
list() = $a;
list(,,) = $a;
list($x, list(), $y) = $a;
* list() no longer supports unpacking strings (while previously this was only
supported in some cases). The code
$string = "xy";
list($x, $y) = $string;
will now result in $x == null and $y == null (without notices) instead of
$x == "x" and $y == "y". Furthermore list() is now always guaranteed to
work with objects implementing ArrayAccess, e.g.
list($a, $b) = (object) new ArrayObject([0, 1]);
will now result in $a == 0 and $b == 1. Previously both $a and $b were null.
Relevant RFCs:
* https://wiki.php.net/rfc/abstract_syntax_tree#changes_to_list
* https://wiki.php.net/rfc/fix_list_behavior_inconsistency
Changes to foreach
------------------
* Iteration with foreach() no longer has any effect on the internal array
pointer, which can be accessed through the current()/next()/etc family of
functions. For example
$array = [0, 1, 2];
foreach ($array as &$val) {
var_dump(current($array));
}
will now print the value int(0) three times. Previously the output was int(1),
int(2) and bool(false).
* When iterating arrays by-value, foreach will now always operate on a copy of
the array, as such changes to the array during iteration will not influence
iteration behavior. For example
$array = [0, 1, 2];
$ref =& $array; // Necessary to trigger the old behavior
foreach ($array as $val) {
var_dump($val);
unset($array[1]);
}
will now print all three elements (0 1 2), while previously the second element
1 was skipped (0 2).
* When iterating arrays by-reference, modifications to the array will continue
to influence the iteration. However PHP will now do a better job of
maintaining a correct position in a number of cases. E.g. appending to an
array during by-reference iteration
$array = [0];
foreach ($array as &$val) {
var_dump($val);
$array[1] = 1;
}
will now iterate over the appended element as well. As such the output of this
example will now be "int(0) int(1)", while previously it was only "int(0)".
* Iteration of plain (non-Traversable) objects by-value or by-reference will
behave like by-reference iteration of arrays. This matches the previous
behavior apart from the more accurate position management mentioned in the
previous point.
* Iteration of Traversable objects remains unchanged.
Relevant RFC: https://wiki.php.net/rfc/php7_foreach
Changes to parameter handling
-----------------------------
* It is no longer possible to define two function parameters with the same name.
For example, the following method will trigger a compile-time error:
public function foo($a, $b, $unused, $unused) {
// ...
}
Code like this should be changed to use distinct parameter names, for example:
public function foo($a, $b, $unused1, $unused2) {
// ...
}
* The func_get_arg() and func_get_args() functions will no longer return the
original value that was passed to a parameter and will instead provide the
current value (which might have been modified). For example
function foo($x) {
$x++;
var_dump(func_get_arg(0));
}
foo(1);
will now print "2" instead of "1". This code should be changed to either
perform modifications only after calling func_get_arg(s)
function foo($x) {
var_dump(func_get_arg(0));
$x++;
}
or avoid modifying the parameters altogether:
function foo($x) {
$newX = $x + 1;
var_dump(func_get_arg(0));
}
* Similarly exception backtraces will no longer display the original value that
was passed to a function and show the modified value instead. For example
function foo($x) {
$x = 42;
throw new Exception;
}
foo("string");
will now result in the stack trace
Stack trace:
#0 file.php(4): foo(42)
#1 {main}
while previously it was:
Stack trace:
#0 file.php(4): foo('string')
#1 {main}
While this should not impact runtime behavior of your code, it is worthwhile
to be aware of this difference for debugging purposes.
The same limitation also applies to debug_backtrace() and other functions
inspecting function arguments.
Relevant RFC: https://wiki.php.net/phpng
Changes to integer handling
---------------------------
* Invalid octal literals (containing digits larger than 7) now produce compile
errors. For example, the following is no longer valid:
$i = 0781; // 8 is not a valid octal digit!
Previously the invalid digits (and any following valid digits) were simply
ignored. As such $i previously held the value 7, because the last two digits
were silently discarded.
* Bitwise shifts by negative numbers will now throw an ArithmeticError:
var_dump(1 >> -1);
// ArithmeticError: Bit shift by negative number
* Left bitwise shifts by a number of bits beyond the bit width of an integer
will always result in 0:
var_dump(1 << 64); // int(0)
Previously the behavior of this code was dependent on the used CPU
architecture. For example on x86 (including x86-64) the result was int(1),
because the shift operand was wrapped.
* Similarly right bitwise shifts by a number of bits beyond the bit width of an
integer will always result in 0 or -1 (depending on sign):
var_dump(1 >> 64); // int(0)
var_dump(-1 >> 64); // int(-1)
Relevant RFC: https://wiki.php.net/rfc/integer_semantics
Changes to string handling
--------------------------
* Strings that contain hexadecimal numbers are no longer considered to be
numeric and don't receive special treatment anymore. Some examples of the
new behavior:
var_dump("0x123" == "291"); // bool(false) (previously true)
var_dump(is_numeric("0x123")); // bool(false) (previously true)
var_dump("0xe" + "0x1"); // int(0) (previously 16)
var_dump(substr("foo", "0x1")); // string(3) "foo" (previously "oo")
// Notice: A non well formed numeric value encountered
filter_var() can be used to check if a string contains a hexadecimal number
or convert such a string into an integer:
$str = "0xffff";
$int = filter_var($str, FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX);
if (false === $int) {
throw new Exception("Invalid integer!");
}
var_dump($int); // int(65535)
* Due to the addition of the Unicode Codepoint Escape Syntax for double-quoted
strings and heredocs, "\u{" followed by an invalid sequence will now result in
an error:
$str = "\u{xyz}"; // Fatal error: Invalid UTF-8 codepoint escape sequence
To avoid this the leading backslash should be escaped:
$str = "\\u{xyz}"; // Works fine
However, "\u" without a following { is unaffected. As such the following code
won't error and will work the same as before:
$str = "\u202e"; // Works fine
Relevant RFCs:
* https://wiki.php.net/rfc/remove_hex_support_in_numeric_strings
* https://wiki.php.net/rfc/unicode_escape
Changes to error handling
-------------------------
* There are now two exception classes: Exception and Error. Both classes
implement a new interface Throwable. Type hints in exception handling code
may need to be changed to account for this.
* Some fatal errors and recoverable fatal errors now throw an Error instead.
As Error is a separate class from Exception, these exceptions will not be
caught by existing try/catch blocks.
For the recoverable fatal errors which have been converted into an exception,
it is no longer possible to silently ignore the error from an error handler.
In particular, it is no longer possible to ignore type hint failures.
* Parser errors now generate a ParseError that extends Error. Error
handling for eval()s on potentially invalid code should be changed to catch
ParseError in addition to the previous return value / error_get_last()
based handling.
* Constructors of internal classes will now always throw an exception on
failure. Previously some constructors returned NULL or an unusable object.
* The error level of some E_STRICT notices has been changed.
Relevant RFCs:
* https://wiki.php.net/rfc/engine_exceptions_for_php7
* https://wiki.php.net/rfc/throwable-interface
* https://wiki.php.net/rfc/internal_constructor_behaviour
* https://wiki.php.net/rfc/reclassify_e_strict
Other language changes
----------------------
* Removed support for static calls to non-static methods from an incompatible
$this context. In this case $this will not be defined, but the call will be
allowed with a deprecation notice. An example:
class A {
public function test() { var_dump($this); }
}
// Note: Does NOT extend A
class B {
public function callNonStaticMethodOfA() { A::test(); }
}
(new B)->callNonStaticMethodOfA();
// Deprecated: Non-static method A::test() should not be called statically
// Notice: Undefined variable $this
NULL
Note that this only applies to calls from an incompatible context. If class B
extended from A the call would be allowed without any notices.
* It is no longer possible to use the following class, interface and trait names
(case-insensitive):
bool
int
float
string
null
false
true
This applies to class/interface/trait declarations, class_alias() and use
statements.
Furthermore the following class, interface and trait names are now reserved
for future use, but do not yet throw an error when used:
resource
object
mixed
numeric
* The yield language construct no longer requires parentheses when used in an
expression context. It is now a right-associative operator with precedence
between the "print" and "=>" operators. This can result in different behavior
in some cases, for example:
echo yield -1;
// Was previously interpreted as
echo (yield) - 1;
// And is now interpreted as
echo yield (-1);
yield $foo or die;
// Was previously interpreted as
yield ($foo or die);
// And is now interpreted as
(yield $foo) or die;
Such cases can always be resolved by adding additional parentheses.
. Removed ASP (<%) and script (<script language=php>) tags.
(RFC: https://wiki.php.net/rfc/remove_alternative_php_tags)
. Removed support for assigning the result of new by reference.
. Removed support for scoped calls to non-static methods from an incompatible
$this context. See details in https://wiki.php.net/rfc/incompat_ctx.
. Removed support for #-style comments in ini files. Use ;-style comments
instead.
. $HTTP_RAW_POST_DATA is no longer available. Use the php://input stream instead.
Standard library changes
========================
. substr() now returns an empty string instead of FALSE when the truncation happens on boundaries.
. call_user_method() and call_user_method_array() no longer exists.
. ob_start() no longer issues an E_ERROR, but instead an E_RECOVERABLE_ERROR in case an
output buffer is created in an output buffer handler.
. The internal sorting algorithm has been improved, what may result in
different sort order of elements that compare as equal.
. Removed dl() function on fpm-fcgi.
. setcookie() with an empty cookie name now issues a WARNING and doesn't send an empty set-cookie header line anymore.
Other
=====
- Curl:
. Removed support for disabling the CURLOPT_SAFE_UPLOAD option. All curl file
uploads must use the curl_file / CURLFile APIs.
- Date:
. Removed $is_dst parameter from mktime() and gmmktime().
- DBA
. dba_delete() now returns false if the key was not found for the inifile
handler, too.
- GMP
. Requires libgmp version 4.2 or newer now.
. gmp_setbit() and gmp_clrbit() now return FALSE for negative indices, making
them consistent with other GMP functions.
- Intl:
. Removed deprecated aliases datefmt_set_timezone_id() and
IntlDateFormatter::setTimeZoneID(). Use datefmt_set_timezone() and
IntlDateFormatter::setTimeZone() instead.
- libxml:
. Added LIBXML_BIGLINES parser option. It's available starting with libxml 2.9.0
and adds suppport for line numbers >16-bit in the error reporting.
- Mcrypt
. Removed deprecated mcrypt_generic_end() alias in favor of
mcrypt_generic_deinit().
. Removed deprecated mcrypt_ecb(), mcrypt_cbc(), mcrypt_cfb() and mcrypt_ofb()
functions in favor of mcrypt_encrypt() and mcrypt_decrypt() with an
MCRYPT_MODE_* flag.
- Session
. session_start() accepts all INI settings as array. e.g. ['cache_limiter'=>'private']
sets session.cache_limiter=private. It also supports 'read_and_close' which closes
session data immediately after read data.
. Save handler accepts validate_sid(), update_timestamp() which validates session
ID existence, updates timestamp of session data. Compatibility of old user defined
save handler is retained.
. SessionUpdateTimestampHandlerInterface is added. validateSid(), updateTimestamp()
is defined in the interface.
. session.lazy_write(default=On) INI setting enables only write session data when
session data is updated.
- Opcache
. Removed opcache.load_comments configuration directive. Now doc comments
loading costs nothing and always enabled.
- OpenSSL:
. Removed the "rsa_key_size" SSL context option in favor of automatically
setting the appropriate size given the negotiated crypto algorithm.
. Removed "CN_match" and "SNI_server_name" SSL context options. Use automatic
detection or the "peer_name" option instead.
- PCRE:
. Removed support for /e (PREG_REPLACE_EVAL) modifier. Use
preg_replace_callback() instead.
- PDO_pgsql:
. Removed PGSQL_ATTR_DISABLE_NATIVE_PREPARED_STATEMENT attribute in favor of
ATTR_EMULATE_PREPARES.
- Standard:
. Removed string category support in setlocale(). Use the LC_* constants
instead.
. Removed set_magic_quotes_runtime() and its alias magic_quotes_runtime().
- Core:
. 'void' can no longer be used as the name of a class, interface, or trait.
This applies to declarations, class_alias() and use statements.
. (int), intval() where $base is 10 or unspecified, settype(), decbin(),
decoct(), dechex(), integer operators and other conversions now always
respect scientific notation in numeric strings.
(RFC: https://wiki.php.net/rfc/invalid_strings_in_arithmetic)
. The ASCII 0x7F Delete control character is no longer permitted in unquoted
identifiers in source code.
. The following functions may no longer be called dynamically using $func(),
call_user_func(), array_map() or similar:
. extract()
. compact()
. get_defined_vars()
. func_get_args()
. func_get_arg()
. func_num_args()
. parse_str() with one argument
. mb_parse_str() with one argument
. assert() with a string argument
(RFC: https://wiki.php.net/rfc/forbid_dynamic_scope_introspection)
. If the error_log is set to syslog, the PHP error levels are mapped to the
syslog error levels. This brings finer differentiation in the error logs
in contrary to the previous approach where all the errors are loggged with
the notice level only.
- JSON:
. Rejected RFC 7159 incompatible number formats in json_decode string -
top level (07, 0xff, .1, -.1) and all levels ([1.], [1.e1])
. Calling json_decode with 1st argument equal to empty PHP string or value that
after casting to string is empty string (NULL, FALSE) results in JSON syntax error.
- Stream:
. Removed set_socket_blocking() in favor of its alias stream_set_blocking().
- XSL:
. Removed xsl.security_prefs ini option. Use XsltProcessor::setSecurityPrefs()
instead.
. When calling json_encode with JSON_UNESCAPED_UNICODE option, U+2028 and
U+2029 are escaped.
========================================
2. New Features
========================================
- Core
. Added group use declarations.
(RFC: https://wiki.php.net/rfc/group_use_declarations)
. Added null coalesce operator (??).
(RFC: https://wiki.php.net/rfc/isset_ternary)
. Support for strings with length >= 2^31 bytes in 64 bit builds.
. Closure::call() method added (works only with userland classes).
. Added \u{xxxxxx} Unicode Codepoint Escape Syntax for double-quoted strings
and heredocs.
. define() now supports arrays as constant values, fixing an oversight where
define() did not support arrays yet const syntax did.
. Added the comparison operator (<=>), aka the spaceship operator.
(RFC: https://wiki.php.net/rfc/combined-comparison-operator)
. Added the yield from operator for delegating Generators like coroutines.
(RFC: https://wiki.php.net/rfc/generator-delegation)
. Reserved keywords can now be used in various new contexts.
(RFC: https://wiki.php.net/rfc/context_sensitive_lexer)
. Added support for scalar type declarations and strict mode using
declare(strict_types=1) (RFC: https://wiki.php.net/rfc/scalar_type_hints_v5)
. Added support for cryptographically secure user land RNG
(RFC: https://wiki.php.net/rfc/easy_userland_csprng)
- Opcache
. Added second level file based opcode cache. It may be enabled by setting
opcache.file_cache=<DIR> configuration directive in php.ini. The second
level cache may improve performance when SHM is full, at server restart or
SHM reset. In addition, it's possibe to use file cache without SHM at all,
using opcache.file_cache_only=1 (this may be useful for sharing hosting),
and disable file cache consistency check, to speedup loading at the cost of
safety, using opcache.file_cache_consistency_checks=0.
. Added ability to move PHP code pages (PHP TEXT segment) into HUGE pages.
It's possible to enable/disable this feature in php.ini through
opcache.huge_code_pages=0/1. OS should be configured to provide huge pages.
. Added Windows only opcache.file_cache_fallback=1 ini option, which implies
the implemented fallback mechanism. When OPcache was not able to reattach
the shared memory segment to the desired address and opcache.file_cache
is on, opcache.file_cache_only=1 will be automatically enforced.
- OpenSSL
. Added "alpn_protocols" SSL context option allowing encrypted client/server
streams to negotiate alternative protocols using the ALPN TLS extension when
built against OpenSSL 1.0.2 or newer. Negotiated protocol information is
accessible through stream_get_meta_data() output.
- Reflection
. Added a ReflectionGenerator class (yield from Traces, current file/line,
etc.)
. Added a ReflectionType class to better support the new return type and
scalar type declarations features. The new ReflectionParameter::getType()
and ReflectionFunctionAbstract::getReturnType() methods both return an
instance of ReflectionType.
- Stream:
. New Windows only stream context options was added to allow blocking reads
on pipes. To enable it, pass array("pipe" => array("blocking" => true))
when creating the stream context. Be aware, that this option can under
circumstances cause dead locks on the pipe buffer. However it can be useful
in several CLI use case scenarios.
. Added void return type, which requires that a function not return a value.
(RFC: https://wiki.php.net/rfc/void_return_type)
. String offset access now supports negative references, which will be
counted from the end of the string.
(RFC: https://wiki.php.net/rfc/negative-string-offsets)
. Added a form of the list() construct where keys can be specified.
(RFC: https://wiki.php.net/rfc/list_keys)
. Added [] = as alternative construct to list() =.
(RFC: https://wiki.php.net/rfc/short_list_syntax)
. Number operators taking numeric strings now emit "A non well formed numeric
value encountered" E_NOTICEs for leading-numeric strings, and "A
non-numeric value encountered" E_WARNINGs for non-numeric strings.
This always applies to the +, -, *, /, **, %, << and >> operators, and
their assignment counterparts +=, -=, *=, /=, **=, %=, <<= and >>=.
For the bitwise operators |, & and ^, and their assignment counterparts
|=, &= and ^=, this only applies where only one operand is a string.
Note that this never applies to the bitwise NOT operator, ~, which does not
handle numeric strings, nor to the increment and decrement operators
++ and --, which have a unique approach to handling numeric strings.
(RFC: https://wiki.php.net/rfc/invalid_strings_in_arithmetic)
========================================
3. Changes in SAPI modules
========================================
- FPM
. Fixed bug #65933 (Cannot specify config lines longer than 1024 bytes).
. Listen = port now listen on all addresses (IPv6 and IPv4-mapped).
========================================
4. Deprecated Functionality
========================================
- Core
. PHP 4 style constructors, where the constructor name is the same as the
class name, are now deprecated.
. Static calls to non-static methods are now deprecated.
- OpenSSL
. The "capture_session_meta" SSL context option is now deprecated. Meta
data concerning active crypto on a stream resource is now accessible
through the return result from stream_get_meta_data().
========================================
5. Changed Functions
========================================
- unserialize():
. Added second parameter for unserialize function
(RFC: https://wiki.php.net/rfc/secure_unserialize) allowing to specify
acceptable classes:
unserialize($foo, ["allowed_classes" => ["MyClass", "MyClass2"]]);
- proc_open():
. The maximum number of pipes used by proc_open() was previously limited by
hardcoded value of 16. This limit is now removed and the number of pipes is
effectively limited by the amount of memory available to PHP.
. New Windows only configuration option "blocking_pipes" can be used to
force blocking reads on child process pipes. This covers several
edge cases in CLI usage however can lead to dead locks. Also, this
correlates with the new stream context options for pipes.
- array_column():
The function now supports an array of objects as well as two-dimensional
arrays. Only public properties are considered, and objects that make use of
__get() for dynamic properties must also implement __isset().
- stream_context_create()
It accepts now a Windows only configuration
array("pipe" => array("blocking" => <boolean>)) which forces blocking reads
on pipes. This option should be used carefully because due to the
platform restrictions dead locks on pipe buffers are possible.
- dirname()
A new optional argument ($levels) allow to go up various times
dirname(dirname($foo)) => dirname($foo, 2);
- debug_zval_dump
It prints now "int" instead of "long", and "float" instead of "double".
- get_headers() has an extra parameter which allows passing a custom stream
context.
- The first $varname argument for getenv() is no longer mandatory, the
current environment variables will be returned as an associative array
when omitted.
- json_encode() accepts new option JSON_UNESCAPED_LINE_TERMINATORS that
disables escaping of U+2028 and U+2029 characters when
JSON_UNESCAPED_UNICODE is supplied.
- long2ip() accepts integer as parameter now
- pg_last_notice() accepts optional long parameter to specify operation.
PGSQL_NOTICE_LAST - Get last notice (Default)
PGSQL_NOTICE_ALL - Get all stored notices
PGSQL_NOTICE_CLEAR - Remove all stored notices
It returns empty string or array on successful PGSQL_NOTICE_LAST/ALL calls.
It returned FALSE for empty notice previously.
- pg_fetch_all() accepts 2nd optional result type parameter like
pg_fetch_row().
- pg_select() accepts 4th optional result type parameter like pg_fetch_row().
- parse_url() is more restrictive now and supports RFC3986.
- unpack() accepts an additional optional $offset argument. '@' format code
(that specifes an absolute position) is applyed to input data after
the $offset argument.
- strpos(), stripos(), substr_count(), grapheme_strpos(), grapheme_stripos(),
grapheme_extract(), iconv_strpos(), mb_strimwidth(), mb_ereg_search_setpos(),
mb_strpos() and mb_stripos() now accept negative string offsets.
- substr_count() and mb_strimwidth() additionally also accept negative length.
- file_get_contents() accepts a negative seek offset if the stream is seekable.
- tempnam() throws a notice when failing back to the system temp dir.
========================================
6. New Functions
========================================
- GMP
. Added gmp_random_seed().
- PCRE:
. Added preg_replace_callback_array function
(RFC: https://wiki.php.net/rfc/preg_replace_callback_array)
- Standard
. Added intdiv() function for integer division.
. Added error_clear_last() function to reset error state.
- Zip:
. Added ZipArchive::setCompressionIndex() and ZipArchive::setCompressionName()
for setting the compression method.
- Zlib:
. Added deflate_init(), deflate_add(), inflate_init(), inflate_add()
functions allowing incremental/streaming compression/decompression.
========================================
7. New Classes and Interfaces
========================================
- ReflectionGenerator
- ReflectionType
========================================
8. Removed Extensions and SAPIs
========================================
- sapi/aolserver
- sapi/apache
- sapi/apache_hooks
- sapi/apache2filter
- sapi/caudium
- sapi/continuity
- sapi/isapi
- sapi/milter
- sapi/nsapi
- sapi/phttpd
- sapi/pi3web
- sapi/roxen
- sapi/thttpd
- sapi/tux
- sapi/webjames
- ext/mssql
- ext/mysql
- ext/sybase_ct
- ext/ereg
For more details see
https://wiki.php.net/rfc/removal_of_dead_sapis_and_exts
https://wiki.php.net/rfc/remove_deprecated_functionality_in_php7
NOTE: NSAPI was not voted in the RFC, however it was removed afterwards. It turned
out, that the corresponding SDK isn't available anymore.
========================================
9. Other Changes to Extensions
========================================
- Mhash
Mhash is not an extension anymore, use function_exists("mhash") to check whether
it is avaliable.
- GD
The bundled libgd requires libwebp instead of libvpx for the WebP functionality.
- Openssl
minimum supported OpenSSL version series was raised to 0.9.8
- SQLite3:
. Upgraded bundled SQLite lib to 3.13.0
========================================
10. New Global Constants
========================================
- Core
. PHP_INT_MIN added.
- JSON:
. JSON_UNESCAPED_LINE_TERMINATORS
- PCRE
. This error constant is added to signal errors due to stack size limitations
when PCRE JIT support is enabled:
. PREG_JIT_STACKLIMIT_ERROR
- Zlib
. These constants are added to control flush behavior with the new
incremental deflate_add() and inflate_add() functions:
. ZLIB_NO_FLUSH
. ZLIB_PARTIAL_FLUSH
. ZLIB_SYNC_FLUSH
. ZLIB_FULL_FLUSH
. ZLIB_BLOCK
. ZLIB_FINISH
- GD
. T1Lib support removed, thus lifting the optional dependency on T1Lib, the
following is therefore not available anymore:
Functions:
- imagepsbbox()
- imagepsencodefont()
- imagepsextendedfont()
- imagepsfreefont()
- imagepsloadfont()
- imagepsslantfont()
- imagepstext()
Resources:
- 'gd PS font'
- 'gd PS encoding'
- Zip
. Filename encoding flags, as of 7.0.8
- ZipArchive::FL_ENC_GUESS
- ZipArchive::FL_ENC_RAW
- ZipArchive::FL_ENC_STRICT
- ZipArchive::FL_ENC_UTF_8
- ZipArchive::FL_ENC_CP437
- Pgsql:
PGSQL_NOTICE_LAST
PGSQL_NOTICE_ALL
PGSQL_NOTICE_CLEAR
========================================
11. Changes to INI File Handling
========================================
- Core
. Removed asp_tags ini directive. Trying to enable it will result in a fatal
error.
. Removed always_populate_raw_post_data ini directive.
========================================
12. Windows Support
========================================
- Core
. Support for native 64 bit integers in 64 bit builds.
. Support for large files in 64 bit builds.
. Support for getrusage()
- Core:
. Support for ftok()
- ftp
. The ftp extension is always shipped shared
. For SSL support, the dependency on the openssl extension was abolished. Instead
it depends alone on the openssl library. If it's present at the compile time,
ftp_ssl_connect() is enabled automatically.
- FCGI
. PHP_FCGI_CHILDREN is respected. If this environment variable is defined,
the first php-fcgi.exe process will exec the specified number of children.
Those will share the same TCP socket.
- imap
. Static building of ext/imap is disabled
- readline:
. The readline extension is supported through the WinEditLine library
(http://mingweditline.sourceforge.net/). Thereby, the interactive CLI
shell is supported as well (php.exe -a).
- odbc
. The odbc extension is always shipped shared
It is well known, but nevertheless is worth mentioning again, that
the readline extension is not thread safe and will never be. Thus,
the usage of it with any true thread safe SAPI (like Apache mod_winnt) is
strongely discouraged.
========================================
13. Other Changes
========================================
- Core
. Instead of being undefined and platform-dependent, NaN and Infinity will
always be zero when cast to integer.
. Calling a method on a non-object now raises a catchable error instead of a
fatal error; see: https://wiki.php.net/rfc/catchable-call-to-member-of-non-object
. Error messages for zend_parse_parameters, type hints and conversions now
always say "integer" and "float" instead of "long" and "double".
. Output buffering now continues to work for an aborted connection if
ignore_user_abort is set to true.
. Zend Extensions API was extended with zend_extension.op_array_persist_calc()
and zend_extensions.op_array_persist() handlers. They allow to store (or
reset) associated with op_array addition information in Opcache Shared
Memory.
. zend_internal_function.reserved[] array was introduced to allow association
of aditional information with internal functions. In PHP-5 it was possible
to use zend_function.op_array.reserved[] even for internal functions, but
now we don't allocate extra space.

View file

@ -1,25 +1,7 @@
PHP 7.0 INTERNALS UPGRADE NOTES
PHP 7.1 INTERNALS UPGRADE NOTES
0. Wiki Examples
1. Internal API changes
e. New data types
f. zend_parse_parameters() specs
g. sprintf() formats
h. HashTable API
i. New portable macros for large file support
j. New portable macros for integers
k. get_class_entry object handler info
l. get_class_name object handler info
m. Other portable macros info
n. ZEND_ENGINE_2 removal
o. Updated final class modifier
p. TSRM changes
q. gc_collect_cycles() is now hookable
r. PDO uses size_t for lengths
s. Resource API changes
t. Optimized strings concatenation.
u. Streams changes
v. Sort algorithm changes
2. Build system changes
a. Unix build system changes
@ -39,219 +21,6 @@ changes. See: https://wiki.php.net/phpng-upgrading
1. Internal API changes
========================
e. New data types
String
Besides the old way of accepting the strings with 's', the new 'S' ZPP spec
was introduced. It expects an argument of the type zend_string *. String lengths
in it are bound to the size_t datatype.
Integer types
Integers do no more depend on the firm 'long' type. Instead a platform
dependent integer type is used, it is called zend_long. That datatype is
defined dynamically to guarantee the consistent 64 bit support. The zval
field representing user land integer it bound to zend_long.
Signed integer is defined as zend_long, unsigned integer as zend_ulong
inside Zend.
Other datatypes
zend_off_t - portable off_t analogue
zend_stat_t - portable 'struct stat' analogue
These datatypes are declared to be portable across platforms. Thus, direct
usage of the functions like fseek, stat, etc. as well as direct usage of
off_t and struct stat is strongly not recommended. Instead the portable
macros should be used.
zend_fseek - portable fseek equivalent
zend_ftell - portable ftell equivalent
zend_lseek - portable lseek equivalent
zend_fstat - portable fstat equivalent
zend_stat - portable stat equivalent
f. zend_parse_parameters() specs
The new spec 'S' introduced, which expects an argument of type zend_string *.
The 'l' spec expects a parameter of the type zend_long, not long anymore.
The 's' spec expects parameters of the type char * and size_t, no int anymore.
g. sprintf() formats
New printf modifier 'p' was implemented to platform independently output zend_long,
zend_ulong and php_size_t datatypes. That modifier can be used with 'd', 'u', 'x' and 'o'
printf format specs with spprintf, snprintf and the wrapping printf implementations.
%pu is sufficient for both zend_ulong and php_size_t. the code using %p spec to output
pointer address might need to be enclosed into #ifdef when it unlickily followed by 'd',
'u', 'x' or 'o'.
The only exceptions are the snprintf and zend_sprintf functions yet, because in some cases
they can use the implemenations available on the system, not the PHP one. With snprintf the
macros ZEND_LONG_FMT and ZEND_ULONG_FMT should be used.
h. HashTable API
Datatype for array indexes was changed to zend_ulong, for string keys to zend_string *.
i. New portable macros for large file support
Function(s) Alias Comment
stat, _stat64 zend_stat for use with zend_stat_t
fstat, _fstat64 zend_fstat for use with zend_stat_t
lseek, _lseeki64 zend_lseek for use with zend_off_t
ftell, _ftelli64 zend_ftell for use with zend_off_t
fseek, _fseeki64 zend_fseek for use with zend_off_t
j. New portable macros for integers
Function(s) Alias Comment
snprintf with "%ld" or "%lld", _ltoa_s, _i64toa_s ZEND_LTOA for use with zend_long
atol, atoll, _atoi64 ZEND_ATOL for use with zend_long
strtol, strtoll, _strtoi64 ZEND_STRTOL for use with zend_long
strtoul, strtoull, _strtoui64 ZEND_STRTOUL for use with zend_long
abs, llabs, _abs64 ZEND_ABS for use with zend_long
- ZEND_LONG_MAX replaces LONG_MAX where appropriate
- ZEND_LONG_MIN replaces LONG_MIN where appropriate
- ZEND_ULONG_MAX replaces ULONG_MAX where appropriate
- SIZEOF_ZEND_LONG reworked SIZEOF_ZEND_LONG representing the size of zend_long datatype
- ZEND_SIZE_MAX Max value of size_t
- Z_L casts an integral constant to zend_long
- Z_UL casts an integral constant to zend_ulong
The macro ZEND_ENABLE_ZVAL_LONG64 reveals whether zval operates on 64 or 32 bit integer.
k. The get_class_entry object handler is no longer available. Instead
zend_object.ce is always used.
l. The get_class_name object handler is now only used for displaying class
names in debugging functions like var_dump(). It is no longer used in
get_class(), get_parent_class() or similar.
The handler is now obligatory, no longer accepts a `parent` argument and
must return a non-NULL zend_string*, which will be released by the caller.
m. Other portable macros info
ZEND_SECURE_ZERO - zeroes chunk of memory
ZEND_VALID_SOCKET - validates a php_socket_t variable
ZEND_FASTCALL is defined to use __vectorcall convention on VS2013 and above
ZEND_NORETURN is defined as __declspec(noreturn) on VS
n. The ZEND_ENGINE_2 macro has been removed. A ZEND_ENGINE_3 macro has been added.
o. Removed ZEND_ACC_FINAL_CLASS in favour of ZEND_ACC_FINAL, turning final class
modifier now a different class entry flag. Update your extensions.
p. TSRM changes
The TSRM layer undergone significant changes. It is not necessary anymore to
pass the tsrm_ls pointer explicitly. The TSRMLS_* macros should not be used
in any new developments.
The recommended way accessing globals in TS builds is by implementing it
to use a local thread unique pointer to the corresponding data pool. These
are the new macros that serve to achieve this goal:
- ZEND_TSRMG - based on TSRMG and if static pointer for data pool access is
implemented, will use it
- ZEND_TSRMLS_CACHE_EXTERN - to be used in a header shared across multiple
C/C++ files
- ZEND_TSRMLS_CACHE_DEFINE - to be used in the main extension C/C++ file
- ZEND_TSRMLS_CACHE_UPDATE - to be integrated at the top of the globals
ctor or RINIT function
- ZEND_ENABLE_STATIC_TSRMLS_CACHE - to be used in the config.[m4|w32] for
enabling the globals access per thread unique pointer
- TSRMLS_CACHE - expands to the variable name which links to the thread
unique data pool
Note that usually it will work without implementing the globals access per
a thread unique pointer, however it might cause a slowdown. The reason is
that the access model to the extension/SAPI own globals as well as the
access to the core globals is determined in the compilation phase depending
on whether ZEND_ENABLE_STATIC_TSRMLS_CACHE macro is defined.
Due to the current compiler evolution state, the TSRMLS_CACHE pointer
(when implemented) has to be present and updated in every binary unit which
is not compiled statically into PHP. So any DLL, DSO, EXE, etc. has to take
care about defining and updating it's TSRMLS cache. An update should happen
before any globals was accessed.
Porting an extension or SAPI is usually as easy as removing all the TSRMLS_*
occurrences and integrating the macros mentioned above. However if tsrm_ls
is used explicitly, its usage can be considered obsolete in most cases.
Additionally, if an extension triggers its own threads, TSRMLS_CACHE shouldn't
be passed to that threads directly.
When working with CTOR/DTOR for the extension globals, only the data passed
as parameters should be touched. For example, don't use code like
free(MYEXT_G(vars)); inside globals destructor, as it possibly can destroy
the data from a wrong thread. Instead use the pointer to the data delivered
into the destructor. So the previous example could look like
free(my_struct->vars); given the income was casted to (struct my_struct *).
A new macro was introduced to simplify the declaration to the extension
globals. A simplified declaration looks as follows
#define MYEXT_G(v) ZEND_MODULE_GLOBALS_ACCESSOR(myext, v)
Another new macro ZEND_MODULE_GLOBALS_BULK(myext) delivers the corresponding
globals struct as a whole.
Two new storage specifiers was introduced.
ZEND_EXT_TLS - expand to an appropriate thread specific storage specifier in
the thread safe build, expands to empty in a non thread safe
build.
ZEND_TLS - expands to an appropriate thread specific storage specifier
with static visibility in the thread safe build, expands to
static specifier in a non thread safe build.
Variables declared with these storage specifiers can not be shared across
threads. While ZEND_TLS enforces the local scope visibility, ZEND_EXT_TLS
pertains to the visiblity across several compilation units. In both cases,
there's no portable way to achieve the visibility across shared objects.
Thus, these specifiers are not compatible with ZEND_API and PHPAPI specifiers.
q. gc_collect_cycles() is now a function pointer, and can be replaced in the
same manner as zend_execute_ex() if needed (for example, to include the
time spent in the garbage collector in a profiler). The default
implementation has been renamed to zend_gc_collect_cycles(), and is
exported with ZEND_API.
r. In accordance with general use of size_t as string length, all PDO API
functions now use size_t for string length.
s. Removed ZEND_REGISTER/FETCH_RESOURCE, use zend_fetch_resource and
and zend_register_resource instead, zend_fetch_resource accepts a zend_resource *
as first argument, if you still need to fetch a resource from zval, use
zend_fetch_resource_ex. More details can be found in Zend/zend_list.c.
t. Optimized strings concatenation.
ZEND_ADD_STRING/VAR/CHAR are replaced with ZEND_ROPE_INIT, ZEND_ROPE_ADD,
ZEND_ROPE_END.
Instead of reallocation and copying string on each ZEND_ADD_STRING/VAR/CAHR,
collect all the strings and then allocate and construct the resulting string once.
u. Streams changes
- It is possible to do blocking reads on Windows pipes. It can be done either
using context stream option PHP_STREAM_OPTION_PIPE_BLOCKING or
adding STREAM_USE_BLOCKING_PIPE when opening the stream.
v. Sort algorithm changes
- Improved zend_qsort(using hybrid sorting algo) for better performance,
and also renamed zend_qsort to zend_sort.
- Added stable sorting algo zend_insert_sort.
w. Tick functions internal API change
Tick functions have different declaration now. They expect a single
parameter while before they were parameterless. When registering the
tick function a value for this parameter must be passed. This value will be
provided to the tick function on every execution.
========================
2. Build system changes
========================
@ -260,65 +29,7 @@ changes. See: https://wiki.php.net/phpng-upgrading
b. Windows build system changes
- Besides Visual Studio, building with Clang or Intel Composer is now
possible. To enable an alternative toolset, add the option
--with-toolset=[vs,clang,icc] to the configure line. The default
toolset is vs. Still clang or icc need the correct environment
which involves many tools from the vs toolset.
The toolset option is supported by phpize as well.
AWARENESS The only recommended and supported toolset to produce production
ready binaries is Visual Studio. Still other compilers can be used now for
testing and analyzing purposes.
- configure.js now produces response files which are passed to the linker
and library manager. This solves the issues with the long command lines
which can exceed the OS limit.
- with clang toolset, an option --with-uncritical-warn-choke is available,
which suppresses the most frequent false positive warnings
- the --with-mp option will by default utilize all the available cores. It's
enabled by default for release builds and can be disabled with the special
"disable" keyword.
========================
3. Module changes
========================
Session:
- PS_MOD_UPDATE_TIMESTAMP() session save handler definition is added. New
save handler should use PS_MOD_UPDATE_TIMESTAMP() definition. Save handler
must not refer/change PS() variables directly from save handler. Use
parameters.
- PS_MOD()/PS_MOD_SID() macro exist only for transition. Beware these
save handlers are less secure and slower than PS_MOD_UPDATE_TIMESTAMP().
- PS(invalid_session_id) was removed. It was never worked as it supposed.
To report invalid session ID, use PS_VALIDATE_SID() handler.
- PS_VALIDATE_SID() defines session ID validation handler. This handler
must validate if requested session ID exists in session data storage or not.
Do not access PS(id) directly, but use this handler and it's parameter.
- PS_UPDATE_TIMESTAMP() defines timestamp updating handler. This handler
must update session data timestamp for GC if it is needed. e.g. Memcache
updates timestamp on read, so it does not need to update timestamp. Return
SUCCESS simply for this case.
- PS_CREATE_SID() should check session ID collision. Return NULL for failure.
- More documentation can be found in ext/session/mod_files.c as comments.
mod_files.c may be used as reference implementation.
Openssl:
- several ext/openssl functions require the inclusion of the applink shim
as documented in the OpenSSL FAQ https://www.openssl.org/support/faq.html#PROG2
to properly work on Windows. While this primarily affects the OpenSSL
functionality, the shim needs to be included into the executable file
which loads the extension DLL, not into the extension DLL itself. Alternatively
it can be compiled and linked with the main program as a separate object file.
More information and explanation in the linked OpenSSL FAQ.
Thus, this primarily affects any WAMP or other redistributions bundling the
official PHP release zipballs or building from sources. The applink shim is
already integrated with all the PHP executables from the official distribution
starting with 7.0.0beta1.

View file

@ -17,11 +17,20 @@ function test3($a, $b) {
test1();
test2(1);
test2();
try {
test2();
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
test3(1,2);
call_user_func("test1");
call_user_func("test3", 1);
try {
call_user_func("test3", 1);
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
call_user_func("test3", 1, 2);
class test {
@ -38,14 +47,10 @@ echo "Done\n";
--EXPECTF--
int(0)
int(1)
Warning: Missing argument 1 for test2(), called in %s on line %d
int(0)
Exception: Too few arguments to function test2(), 0 passed in %s001.php on line 18 and exactly 1 expected
int(2)
int(0)
Warning: Missing argument 2 for test3()%s
int(1)
Exception: Too few arguments to function test3(), 1 passed in %s001.php on line 27 and exactly 2 expected
int(2)
int(1)

View file

@ -23,11 +23,19 @@ function test3($a, $b) {
test1();
test1(10);
test2(1);
test2();
try {
test2();
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
test3(1,2);
call_user_func("test1");
call_user_func("test3", 1);
try {
call_user_func("test3", 1);
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
call_user_func("test3", 1, 2);
class test {
@ -62,14 +70,7 @@ int(1)
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
bool(false)
Warning: Missing argument 1 for test2(), called in %s on line %d and defined in %s on line %d
Warning: func_get_arg(): Argument 0 not passed to function in %s on line %d
bool(false)
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
bool(false)
Exception: Too few arguments to function test2(), 0 passed in %s002.php on line %d and exactly 1 expected
int(1)
int(2)
@ -84,15 +85,7 @@ bool(false)
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
bool(false)
Warning: Missing argument 2 for test3()%s
int(1)
Warning: func_get_arg(): Argument 1 not passed to function in %s on line %d
bool(false)
Warning: func_get_arg(): Argument 2 not passed to function in %s on line %d
bool(false)
Exception: Too few arguments to function test3(), 1 passed in %s002.php on line %d and exactly 2 expected
int(1)
int(2)

View file

@ -18,11 +18,19 @@ function test3($a, $b) {
test1();
test1(10);
test2(1);
test2();
try {
test2();
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
test3(1,2);
call_user_func("test1");
call_user_func("test3", 1);
try {
call_user_func("test3", 1);
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
call_user_func("test3", 1, 2);
class test {
@ -47,10 +55,7 @@ array(1) {
[0]=>
int(1)
}
Warning: Missing argument 1 for test2(), called in %s on line %d and defined in %s on line %d
array(0) {
}
Exception: Too few arguments to function test2(), 0 passed in %s003.php on line %d and exactly 1 expected
array(2) {
[0]=>
int(1)
@ -59,12 +64,7 @@ array(2) {
}
array(0) {
}
Warning: Missing argument 2 for test3()%s
array(1) {
[0]=>
int(1)
}
Exception: Too few arguments to function test3(), 1 passed in %s003.php on line %d and exactly 2 expected
array(2) {
[0]=>
int(1)

View file

@ -31,40 +31,4 @@ $test->bar();
?>
--EXPECTF--
object(Exception)#%d (7) {
["message":protected]=>
string(3) "foo"
["string":"Exception":private]=>
string(0) ""
["code":protected]=>
int(0)
["file":protected]=>
string(%d) "%s030.php"
["line":protected]=>
int(%d)
["trace":"Exception":private]=>
array(1) {
[0]=>
array(6) {
["file"]=>
string(%d) "%s030.php"
["line"]=>
int(%d)
["function"]=>
string(3) "bar"
["class"]=>
string(3) "foo"
["type"]=>
string(2) "->"
["args"]=>
array(0) {
}
}
}
["previous":"Exception":private]=>
NULL
}
'test' => '0'
'test_2' => '1'
'test_3' => '2'
ok
Fatal error: Cannot re-assign $this in %s030.php on line 11

View file

@ -38,11 +38,19 @@ var_dump($c);
echo "Done\n";
?>
--EXPECTF--
Warning: A non-numeric value encountered in %s on line %d
int(75636)
Notice: A non well formed numeric value encountered in %s on line %d
int(951858)
int(48550510)
float(75661.68)
Warning: A non-numeric value encountered in %s on line %d
int(75636)
Notice: A non well formed numeric value encountered in %s on line %d
int(951858)
int(48550510)
float(75661.68)

View file

@ -19,8 +19,13 @@ var_dump($c);
echo "Done\n";
?>
--EXPECTF--
Warning: A non-numeric value encountered in %s on line %d
Exception: Unsupported operand types
Warning: A non-numeric value encountered in %s on line %d
Fatal error: Uncaught Error: Unsupported operand types in %s:%d
Stack trace:
#0 {main}

15
Zend/tests/anon/013.phpt Normal file
View file

@ -0,0 +1,15 @@
--TEST--
closure binding to anonymous class
--FILE--
<?php
$class = new class {};
$foo = function() {
return $this;
};
$closure = Closure::bind($foo, $class, $class);
var_dump($closure());
?>
--EXPECTF--
object(class@anonymous)#1 (0) {
}

16
Zend/tests/anon/014.phpt Normal file
View file

@ -0,0 +1,16 @@
--TEST--
anonymous class trait binding
--FILE--
<?php
trait TaskTrait {
function run() {
return 'Running...';
}
}
$class = new class() {
use TaskTrait;
};
var_dump($class->run());
?>
--EXPECTF--
string(10) "Running..."

View file

@ -154,7 +154,7 @@ Warning: assert(): assert(0 && ($a = function () {
$x = $a ? $b : $c;
$x = $a ?: $c;
$x = $a ?? $b;
list($a, $b, $c) = [1, 2 => 'x', 'z' => 'c'];
[$a, $b, $c] = [1, 2 => 'x', 'z' => 'c'];
@foo();
$y = clone $x;
yield 1 => 2;

View file

@ -0,0 +1,19 @@
--TEST--
Misoptimization when variable is modified by assert()
--INI--
zend.assertions=1
--FILE--
<?php
function test() {
$i = 0;
assert('$i = new stdClass');
$i += 1;
var_dump($i);
}
test();
?>
--EXPECTF--
Notice: Object of class stdClass could not be converted to int in %s on line %d
int(2)

View file

@ -6,9 +6,16 @@ $a = new stdClass();
$x = "";
$a->$x = "string('')";
var_dump($a);
$a->{"\0"} = 42;
var_dump($a);
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot access empty property in %sbug29015.php:4
object(stdClass)#1 (1) {
[""]=>
string(10) "string('')"
}
Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
Stack trace:
#0 {main}
thrown in %sbug29015.php on line 4
thrown in %s on line %d

View file

@ -3,7 +3,7 @@ Bug #29883 (isset gives invalid values on strings)
--FILE--
<?php
$x = "bug";
var_dump(isset($x[-1]));
var_dump(isset($x[-10]));
var_dump(isset($x["1"]));
echo $x["1"]."\n";
?>

View file

@ -18,7 +18,7 @@ var_dump(isset($a['b']));
$simpleString = "Bogus String Text";
echo isset($simpleString->wrong)?"bug\n":"ok\n";
echo isset($simpleString["wrong"])?"bug\n":"ok\n";
echo isset($simpleString[-1])?"bug\n":"ok\n";
echo isset($simpleString[-20])?"bug\n":"ok\n";
echo isset($simpleString[0])?"ok\n":"bug\n";
echo isset($simpleString["0"])?"ok\n":"bug\n";
echo isset($simpleString["16"])?"ok\n":"bug\n";

View file

@ -19,15 +19,19 @@ function NormalTest($a)
echo "Hi!";
}
NormalTest();
FooTest();
try {
NormalTest();
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
try {
FooTest();
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
FooTest(new Foo());
?>
--EXPECTF--
Warning: Missing argument 1 for NormalTest(), called in %sbug33996.php on line %d and defined in %sbug33996.php on line %d
Hi!
Fatal error: Uncaught TypeError: Argument 1 passed to FooTest() must be an instance of Foo, none given, called in %sbug33996.php on line %d and defined in %sbug33996.php:%d
Stack trace:
#0 %s(%d): FooTest()
#1 {main}
thrown in %sbug33996.php on line %d
Exception: Too few arguments to function NormalTest(), 0 passed in %sbug33996.php on line 18 and exactly 1 expected
Exception: Too few arguments to function FooTest(), 0 passed in %sbug33996.php on line 23 and exactly 1 expected
Hello!

View file

@ -43,7 +43,9 @@ Non-static method A::A_ftk() should not be called statically
1 %sbug38047.php:13 get_error_context()
2 %sbug38047.php:36 kalus_error_handler()
Missing argument 1 for A::A_ftk(), called in %sbug38047.php on line 36 and defined
1 %sbug38047.php:13 get_error_context()
2 %sbug38047.php:7 kalus_error_handler()
3 %sbug38047.php:36 A_ftk()
Fatal error: Uncaught Error: Too few arguments to function A::A_ftk(), 0 passed in %sbug38047.php on line 36 and exactly 1 expected in %sbug38047.php:7
Stack trace:
#0 %sbug38047.php(36): A::A_ftk()
#1 {main}
thrown in %sbug38047.php on line 7

View file

@ -9,7 +9,7 @@ $foo[0]->bar = "xyz";
echo "Done\n";
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot use string offset as an array in %s:%d
Fatal error: Uncaught Error: Cannot use string offset as an object in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d

View file

@ -7,7 +7,7 @@ $b = &$a[1];
$b = "f";
echo $a;
--EXPECTF--
Fatal error: Uncaught Error: Cannot create references to/from string offsets nor overloaded objects in %sbug49866.php:3
Fatal error: Uncaught Error: Cannot create references to/from string offsets in %sbug49866.php:3
Stack trace:
#0 {main}
thrown in %sbug49866.php on line 3

View file

@ -10,14 +10,14 @@ class A {
}
$a = new A();
$prop = null;
$prop = "\0";
unset($a->$prop);
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot access empty property in %s:%d
Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
Stack trace:
#0 %s(%d): A->__unset('')
#0 %s(%d): A->__unset('\x00')
#1 {main}
thrown in %s on line %d

View file

@ -10,14 +10,14 @@ class A {
}
$a = new A();
$prop = null;
$prop = "\0";
$a->$prop = 2;
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot access empty property in %s:%d
Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
Stack trace:
#0 %s(%d): A->__set('', 2)
#0 %s(%d): A->__set('\x00', 2)
#1 {main}
thrown in %s on line %d

View file

@ -10,14 +10,14 @@ class A {
}
$a = new A();
$prop = null;
$prop = "\0";
var_dump($a->$prop);
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot access empty property in %s:%d
Fatal error: Uncaught Error: Cannot access property started with '\0' in %s:%d
Stack trace:
#0 %s(%d): A->__get('')
#0 %s(%d): A->__get('\x00')
#1 {main}
thrown in %s on line %d

View file

@ -8,7 +8,7 @@ class MyClass {
$this->myRef = $value;
}
}
$myGlobal=new MyClass($myGlobal);
$myGlobal=new MyClass();
$myGlobal->myRef=&$myGlobal;
$myGlobal->myNonExistentProperty="ok\n";
echo $myGlobal;

65
Zend/tests/bug53432.phpt Normal file
View file

@ -0,0 +1,65 @@
--TEST--
Bug #53432: Assignment via string index access on an empty string converts to array
--FILE--
<?php
$str = '';
var_dump($str[0] = 'a');
var_dump($str);
$str = '';
var_dump($str[5] = 'a');
var_dump($str);
$str = '';
var_dump($str[-1] = 'a');
var_dump($str);
$str = '';
var_dump($str['foo'] = 'a');
var_dump($str);
$str = '';
try {
var_dump($str[] = 'a');
} catch (Error $e) {
echo "Error: {$e->getMessage()}\n";
}
var_dump($str);
$str = '';
try {
var_dump($str[0] += 1);
} catch (Error $e) {
echo "Error: {$e->getMessage()}\n";
}
var_dump($str);
$str = '';
try {
var_dump($str[0][0] = 'a');
} catch (Error $e) {
echo "Error: {$e->getMessage()}\n";
}
var_dump($str);
?>
--EXPECTF--
string(1) "a"
string(1) "a"
string(1) "a"
string(6) " a"
Warning: Illegal string offset: -1 in %s on line %d
NULL
string(0) ""
Warning: Illegal string offset 'foo' in %s on line %d
string(1) "a"
string(1) "a"
Error: [] operator not supported for strings
string(0) ""
Error: Cannot use assign-op operators with string offsets
string(0) ""
Error: Cannot use string offset as an array
string(0) ""

View file

@ -6,7 +6,7 @@ function f(callable $c) {}
f();
?>
--EXPECTF--
Fatal error: Uncaught TypeError: Argument 1 passed to f() must be callable, none given, called in %s on line 3 and defined in %s:%d
Fatal error: Uncaught Error: Too few arguments to function f(), 0 passed in %s on line 3 and exactly 1 expected in %s:2
Stack trace:
#0 %s(%d): f()
#1 {main}

20
Zend/tests/bug62814.phpt Normal file
View file

@ -0,0 +1,20 @@
--TEST--
Bug #62814: It is possible to stiffen child class members visibility
--FILE--
<?php
class A {
private function test() { }
}
class B extends A {
protected function test() { }
}
class C extends B {
private function test() { }
}
?>
--EXPECTF--
Fatal error: Access level to C::test() must be protected (as in class B) or weaker in %s on line %d

View file

@ -57,8 +57,13 @@ $bar = foo3();
string(9) "not catch"
NULL
Fatal error: Uncaught Error: Class 'NotExists' not found in %sbug65784.php:%d
Fatal error: Uncaught Exception: not catched in %sbug65784.php:42
Stack trace:
#0 %s(%d): foo3()
#0 %sbug65784.php(52): foo3()
#1 {main}
thrown in %sbug65784.php on line %d
Next Error: Class 'NotExists' not found in %sbug65784.php:46
Stack trace:
#0 %sbug65784.php(52): foo3()
#1 {main}
thrown in %sbug65784.php on line 46

View file

@ -13,6 +13,4 @@ $x = $c->test();
print_r($x);
unset($c, $x);
--EXPECTF--
Array
(
)
Fatal error: Cannot unset $this in %sbug68370.php on line 4

View file

@ -28,6 +28,7 @@ class Bar {
}
public function __destruct() {
if (!isset(self::$instance)) return;
Foo::getInstance();
}
}

View file

@ -0,0 +1,42 @@
--TEST--
Collection of some cycles on unfinished generators
--FILE--
<?php
// CV
function gen1() {
$gen = yield;
yield;
}
$gen = gen1();
$gen->send($gen);
// This
class Test {
public $gen;
public function gen2() {
yield;
}
}
$test = new Test;
$test->gen = $test->gen2();
// Closure object
$gen3 = (function() use (&$gen3) {
yield;
})();
// Yield from array
function gen4() {
yield from [yield];
}
$gen = gen4();
$gen->send($gen);
?>
===DONE===
--EXPECT--
===DONE===

View file

@ -0,0 +1,44 @@
--TEST--
Generator cycle collection edge cases
--FILE--
<?php
// Extra args
function gen1() {
yield;
}
$obj = new stdClass;
$obj->gen = gen1($obj);
// Symtable
function gen2() {
$varName = 'a';
$$varName = yield;
yield;
}
$gen = gen2();
$gen->send($gen);
// Symtable indirect
function gen3() {
$varName = 'a';
$$varName = 42;
$var = yield;
yield;
}
$gen = gen3();
$gen->send($gen);
// Yield from root
function gen4() {
yield from yield;
}
$gen = gen4();
$gen2 = gen4($gen);
$gen2->send([1, 2, 3]);
$gen->send($gen2);
?>
===DONE===
--EXPECT--
===DONE===

View file

@ -34,4 +34,4 @@ try {
string(36) "Cannot use string offset as an array"
string(27) "Cannot unset string offsets"
string(41) "Only variables can be passed by reference"
string(64) "Cannot increment/decrement overloaded objects nor string offsets"
string(41) "Cannot increment/decrement string offsets"

View file

@ -15,7 +15,7 @@ var_dump($c);
?>
--EXPECTF--
Warning: Cannot bind internal method SplDoublyLinkedList::count() to object of class cls in %s on line %d
Warning: Cannot bind method SplDoublyLinkedList::count() to object of class cls in %s on line %d
NULL
Warning: Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure() in %s on line %d

View file

@ -19,4 +19,8 @@ try {
?>
--EXPECTF--
Missing argument 1 for foo(), called in %sbug70689.php on line %d and defined
Fatal error: Uncaught Error: Too few arguments to function foo(), 0 passed in %sbug70689.php on line 12 and exactly 1 expected in %sbug70689.php:3
Stack trace:
#0 %sbug70689.php(12): foo()
#1 {main}
thrown in %sbug70689.php on line 3

47
Zend/tests/bug70918.phpt Normal file
View file

@ -0,0 +1,47 @@
--TEST--
Bug #70918 (Segfault using static outside of class scope)
--FILE--
<?php
try {
static::x;
} catch (Error $e) {
var_dump($e->getMessage());
}
try {
parent::x;
} catch (Error $e) {
var_dump($e->getMessage());
}
try {
self::x;
} catch (Error $e) {
var_dump($e->getMessage());
}
try {
new static;
} catch (Error $e) {
var_dump($e->getMessage());
}
try {
static::x();
} catch (Error $e) {
var_dump($e->getMessage());
}
try {
static::$i;
} catch (Error $e) {
var_dump($e->getMessage());
}
?>
--EXPECT--
string(52) "Cannot access static:: when no class scope is active"
string(52) "Cannot access parent:: when no class scope is active"
string(50) "Cannot access self:: when no class scope is active"
string(52) "Cannot access static:: when no class scope is active"
string(52) "Cannot access static:: when no class scope is active"
string(52) "Cannot access static:: when no class scope is active"

13
Zend/tests/bug71196.phpt Normal file
View file

@ -0,0 +1,13 @@
--TEST--
Bug #71196 (Memory leak with out-of-order live ranges)
--FILE--
<?php
try {
$a = "1";
[1, (y().$a.$a) . ($a.$a)];
} catch (Error $e) {
var_dump($e->getMessage());
}
?>
--EXPECT--
string(30) "Call to undefined function y()"

22
Zend/tests/bug71266.phpt Normal file
View file

@ -0,0 +1,22 @@
--TEST--
Bug #71266 (Missing separation of properties HT in foreach etc)
--FILE--
<?php
$one = 1;
$two = 2;
$arr = ['foo' => $one, 'bar' => $two];
$obj = (object) $arr;
foreach ($obj as $val) {
var_dump($val);
$obj->bar = 42;
}
$arr = ['foo' => $one, 'bar' => $two];
$obj = (object) $arr;
next($obj);
var_dump(current($arr));
?>
--EXPECT--
int(1)
int(42)
int(1)

View file

@ -1,7 +1,5 @@
--TEST--
bug #71428.1: inheritance with null default values
--XFAIL--
This is a BC break
--FILE--
<?php
class A {
@ -11,5 +9,5 @@ class B extends A {
public function m(array $a = []) {}
}
--EXPECTF--
Warning: Declaration of B::m(array $a = Array) should be compatible with A::m(array $a = NULL) in %sbug71428.1.php on line 7
Warning: Declaration of B::m(array $a = Array) should be compatible with A::m(?array $a = NULL) in %sbug71428.1.php on line 7

View file

@ -1,7 +1,5 @@
--TEST--
bug #71428: Validation type inheritance with = NULL
--XFAIL--
This is a BC break
--FILE--
<?php
class A { }
@ -9,5 +7,5 @@ class B { public function m(A $a = NULL, $n) { echo "B.m";} };
class C extends B { public function m(A $a , $n) { echo "C.m";} };
?>
--EXPECTF--
Warning: Declaration of C::m(A $a, $n) should be compatible with B::m(A $a = NULL, $n) in %sbug71428.3.php on line 4
Warning: Declaration of C::m(A $a, $n) should be compatible with B::m(?A $a, $n) in %sbug71428.3.php on line 4

27
Zend/tests/bug71572.phpt Normal file
View file

@ -0,0 +1,27 @@
--TEST--
Bug #71572: String offset assignment from an empty string inserts null byte
--FILE--
<?php
$str = "abc";
var_dump($str{0} = "");
var_dump($str{1} = "");
var_dump($str{3} = "");
var_dump($str{10} = "");
var_dump($str);
?>
==DONE==
--EXPECTF--
Warning: Cannot assign an empty string to a string offset in %s on line %d
NULL
Warning: Cannot assign an empty string to a string offset in %s on line %d
NULL
Warning: Cannot assign an empty string to a string offset in %s on line %d
NULL
Warning: Cannot assign an empty string to a string offset in %s on line %d
NULL
string(3) "abc"
==DONE==

14
Zend/tests/bug72107.phpt Normal file
View file

@ -0,0 +1,14 @@
--TEST--
Bug #72107: Segfault when using func_get_args as error handler
--FILE--
<?php
set_error_handler('func_get_args');
function test($a) {
echo $undef;
}
test(1);
?>
--EXPECTF--
Warning: Cannot call func_get_args() dynamically in %s on line %d
Notice: Undefined variable: undef in %s on line %d

View file

@ -14,5 +14,6 @@ class Hello implements Foo {
}
echo "OK\n";
?>
--EXPECT--
OK
--EXPECTF--
Fatal error: Declaration of Hello::bar(array $baz = Array) must be compatible with Foo::bar(?array $baz = NULL) in %s on line %d

35
Zend/tests/bug72177.phpt Normal file
View file

@ -0,0 +1,35 @@
--TEST--
Bug #72177 Scope issue in __destruct after ReflectionProperty::setValue()
--FILE--
<?php
class Child
{
protected $bar;
public function __destruct()
{
$this->bar = null;
}
}
class Parnt
{
protected $child;
public function doSomething()
{
$this->child = new Child();
$prop = new \ReflectionProperty($this, 'child');
$prop->setAccessible(true);
$prop->setValue($this, null);
}
}
$p = new Parnt();
$p->doSomething();
echo "OK\n";
?>
--EXPECT--
OK

View file

@ -0,0 +1,34 @@
--TEST--
Bug #72177 Scope issue in __destruct after ReflectionProperty::setValue()
--FILE--
<?php
class Foo
{
private $bar = 'bar';
public function __construct()
{
unset($this->bar);
}
}
class Bar extends Foo
{
private $baz = 'baz';
private static $tab = 'tab';
public function __get(string $name)
{
var_dump($this->baz);
var_dump(self::$tab);
return $name;
}
}
$r = new ReflectionProperty(Foo::class, 'bar');
$r->setAccessible(true);
echo "OK\n";
?>
--EXPECT--
OK

27
Zend/tests/bug72188.phpt Normal file
View file

@ -0,0 +1,27 @@
--TEST--
Bug #72188 (Nested try/finally blocks losing return value)
--FILE--
<?php
function test() {
try {
return 5;
} finally {
try {
echo 1;
} finally {
echo 2;
}
}
}
$a = test();
if($a !== 5) {
echo "FAILED: expected 5, received ", var_export($a), PHP_EOL;
} else {
echo "Passed", PHP_EOL;
}
?>
--EXPECT--
12Passed

11
Zend/tests/bug72221.phpt Normal file
View file

@ -0,0 +1,11 @@
--TEST--
Bug #72221 (Segmentation fault in stream_get_line / zend_memnstr_ex)
--FILE--
<?php
$fp = fopen("php://memory", "r+");
fwrite($fp, str_repeat("baad", 1024*1024));
rewind($fp);
stream_get_line($fp, 1024*1024*2, "aaaa");
echo "Done\n";
--EXPECT--
Done

18
Zend/tests/bug72335.phpt Normal file
View file

@ -0,0 +1,18 @@
--TEST--
Misoptimize due to type narrowing
--FILE--
<?php
function test() {
$b = false;
$x = (1<<53)+1;
do {
$x = 1.0 * ($x - (1<<53));
} while ($b);
return $x;
}
var_dump(test());
?>
--EXPECT--
float(1)

20
Zend/tests/bug72373.phpt Normal file
View file

@ -0,0 +1,20 @@
--TEST--
Bug #72373: TypeError after Generator function w/declared return type finishes
--FILE--
<?php
function foo() : Generator {
yield 1;
yield 2;
yield 3;
}
foreach (foo() as $bar) {
echo $bar . "\n";
}
?>
--EXPECT--
1
2
3

10
Zend/tests/bug72395.phpt Normal file
View file

@ -0,0 +1,10 @@
--TEST--
Bug #72395 (list() regression)
--FILE--
<?php
list(,,$a,,$b,) = array(1, 2, 3, 4, 5, 6);
var_dump($a, $b);
?>
--EXPECT--
int(3)
int(5)

14
Zend/tests/bug72441.phpt Normal file
View file

@ -0,0 +1,14 @@
--TEST--
Bug #72441 (Segmentation fault: RFC list_keys)
--FILE--
<?php
$array = [];
list(
'' => $foo,
$bar
) = $array;
?>
--EXPECTF--
Fatal error: Cannot mix keyed and unkeyed array entries in assignments in %sbug72441.php on line %d

View file

@ -13,7 +13,11 @@ test(function() { return new stdclass; });
test(function() { });
$a = function($x) use ($y) {};
test($a);
try {
test($a);
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
test(new stdclass);
@ -24,9 +28,7 @@ object(stdClass)#%d (0) {
NULL
Notice: Undefined variable: y in %s on line %d
Warning: Missing argument 1 for {closure}(), called in %s on line %d and defined in %s on line %d
NULL
Exception: Too few arguments to function {closure}(), 0 passed in %s on line %d and exactly 1 expected
Fatal error: Uncaught TypeError: Argument 1 passed to test() must be an instance of Closure, instance of stdClass given, called in %s on line %d and defined in %s:%d
Stack trace:

View file

@ -184,7 +184,7 @@ bindTo(new ClsChild, Cls::class):
Success!
bindTo(new ClsUnrelated, Cls::class):
Success!
Cannot bind method Cls::method() to object of class ClsUnrelated
bindTo(new Cls, null):
Cannot rebind scope of closure created by ReflectionFunctionAbstract::getClosure()
@ -205,7 +205,7 @@ bindTo(new SplStack, SplDoublyLinkedList::class):
Success!
bindTo(new ClsUnrelated, SplDoublyLinkedList::class):
Cannot bind internal method SplDoublyLinkedList::count() to object of class ClsUnrelated
Cannot bind method SplDoublyLinkedList::count() to object of class ClsUnrelated
bindTo(null, null):
Cannot unbind $this of internal method

View file

@ -0,0 +1,16 @@
--TEST--
Cannot use() auto-global
--FILE--
<?php
function test() {
$fn = function() use($GLOBALS) {
var_dump($GLOBALS);
};
$fn();
}
test();
?>
--EXPECTF--
Fatal error: Cannot use auto-global as lexical variable in %s on line %d

View file

@ -0,0 +1,14 @@
--TEST--
Can't use name of lexical variable for parameter
--FILE--
<?php
$a = 1;
$fn = function ($a) use ($a) {
var_dump($a);
};
$fn(2);
?>
--EXPECTF--
Fatal error: Cannot use lexical variable $a as a parameter name in %s on line %d

View file

@ -0,0 +1,15 @@
--TEST--
Closure cannot use one variable twice
--FILE--
<?php
$a = 1;
$fn = function() use ($a, &$a) {
$a = 2;
};
$fn();
var_dump($a);
?>
--EXPECTF--
Fatal error: Cannot use variable $a twice in %s on line %d

View file

@ -44,7 +44,9 @@ var_dump(
);
?>
--EXPECT--
--EXPECTF--
Warning: A non-numeric value encountered in %s on line %d
int(3)
string(4) "1foo"
bool(false)

View file

@ -9,7 +9,7 @@ class A {
var_dump(A::FOO);
?>
--EXPECTF--
Fatal error: Uncaught Error: Cannot declare self-referencing constant 'self::FOO' in %s:%d
Fatal error: Uncaught Error: Cannot declare self-referencing constant 'self::BAR' in %s:%d
Stack trace:
#0 {main}
thrown in %s on line %d

View file

@ -0,0 +1,29 @@
--TEST--
Dynamic calls to scope introspection functions are forbidden
--FILE--
<?php
function test_calls($func) {
$i = 1;
array_map($func, [['i' => new stdClass]]);
var_dump($i);
$func(['i' => new stdClass]);
var_dump($i);
call_user_func($func, ['i' => new stdClass]);
var_dump($i);
}
test_calls('extract');
?>
--EXPECTF--
Warning: Cannot call extract() dynamically in %s on line %d
int(1)
Warning: Cannot call extract() dynamically in %s on line %d
int(1)
Warning: Cannot call extract() dynamically in %s on line %d
int(1)

View file

@ -0,0 +1,48 @@
--TEST--
Dynamic calls to scope introspection functions are forbidden (function variations)
--FILE--
<?php
function test() {
$func = 'extract';
$func(['a' => 'b']);
$func = 'compact';
$func(['a']);
$func = 'parse_str';
$func('a=b');
$func = 'get_defined_vars';
$func();
$func = 'assert';
$func('1==2');
$func = 'func_get_args';
$func();
$func = 'func_get_arg';
$func(1);
$func = 'func_num_args';
$func();
}
test();
?>
--EXPECTF--
Warning: Cannot call extract() dynamically in %s on line %d
Warning: Cannot call compact() dynamically in %s on line %d
Warning: Cannot call parse_str() with a single argument dynamically in %s on line %d
Warning: Cannot call get_defined_vars() dynamically in %s on line %d
Warning: Cannot call assert() with string argument dynamically in %s on line %d
Warning: Cannot call func_get_args() dynamically in %s on line %d
Warning: Cannot call func_get_arg() dynamically in %s on line %d
Warning: Cannot call func_num_args() dynamically in %s on line %d

View file

@ -0,0 +1,17 @@
--TEST--
Dynamic calls to scope introspection functions are forbidden (misoptimization)
--FILE--
<?php
function test() {
$i = 1;
array_map('extract', [['i' => new stdClass]]);
$i += 1;
var_dump($i);
}
test();
?>
--EXPECTF--
Warning: Cannot call extract() dynamically in %s on line %d
int(2)

View file

@ -0,0 +1,13 @@
--TEST--
Don't optimize dynamic call to non-dynamic one if it drops the warning
--FILE--
<?php
function test() {
((string) 'extract')(['a' => 42]);
}
test();
?>
--EXPECTF--
Warning: Cannot call extract() dynamically in %s on line %d

View file

@ -8,6 +8,8 @@ print "- empty ---\n";
$str = "test0123";
var_dump(empty($str[-1]));
var_dump(empty($str[-10]));
var_dump(empty($str[-4])); // 0
var_dump(empty($str[0]));
var_dump(empty($str[1]));
var_dump(empty($str[4])); // 0
@ -17,6 +19,8 @@ var_dump(empty($str[10000]));
// non-numeric offsets
print "- string ---\n";
var_dump(empty($str['-1']));
var_dump(empty($str['-10']));
var_dump(empty($str['-4'])); // 0
var_dump(empty($str['0']));
var_dump(empty($str['1']));
var_dump(empty($str['4'])); // 0
@ -31,6 +35,8 @@ print "- null ---\n";
var_dump(empty($str[null]));
print "- double ---\n";
var_dump(empty($str[-1.1]));
var_dump(empty($str[-10.5]));
var_dump(empty($str[-4.1]));
var_dump(empty($str[-0.8]));
var_dump(empty($str[-0.1]));
var_dump(empty($str[0.2]));
@ -50,6 +56,8 @@ print "done\n";
?>
--EXPECTF--
- empty ---
bool(false)
bool(true)
bool(true)
bool(false)
bool(false)
@ -58,6 +66,8 @@ bool(false)
bool(true)
bool(true)
- string ---
bool(false)
bool(true)
bool(true)
bool(false)
bool(false)
@ -72,6 +82,8 @@ bool(true)
- null ---
bool(false)
- double ---
bool(false)
bool(true)
bool(true)
bool(false)
bool(false)

View file

@ -0,0 +1,33 @@
--TEST--
For SSA form the entry block should have no predecessors
--FILE--
<?php
function test() {
while (true) {
var_dump($a + 1);
$a = 1;
if (@$i++) {
break;
}
}
}
function test2() {
while (true) {
$a = 42;
if (@$i++ > 1) {
break;
}
$a = new stdClass;
}
}
test();
test2();
?>
--EXPECTF--
Notice: Undefined variable: a in %s on line %d
int(1)
int(2)

View file

@ -11,7 +11,7 @@ function foo1($arg) {
function foo2($arg) {
}
function foo3($arg) {
function foo3() {
echo $undef3;
throw new Exception("test");
}

View file

@ -11,7 +11,7 @@ function foo1($arg) {
function foo2($arg) {
}
function foo3($arg) {
function foo3() {
echo $undef3;
throw new Exception("test");
}

View file

@ -11,7 +11,7 @@ function foo1($arg) {
function foo2($arg) {
}
function foo3($arg) {
function foo3() {
error_reporting(E_ALL|E_STRICT);
echo $undef3;
throw new Exception("test");

View file

@ -0,0 +1,36 @@
--TEST--
foreach with list syntax, keyed
--FILE--
<?php
$points = [
["x" => 1, "y" => 2],
["x" => 2, "y" => 1]
];
foreach ($points as list("x" => $x, "y" => $y)) {
var_dump($x, $y);
}
echo PHP_EOL;
$invertedPoints = [
"x" => [1, 2],
"y" => [2, 1]
];
foreach ($invertedPoints as list(0 => $row1, 1 => $row2)) {
var_dump($row1, $row2);
}
?>
--EXPECT--
int(1)
int(2)
int(2)
int(1)
int(1)
int(2)
int(2)
int(1)

View file

@ -5,7 +5,7 @@ Calling method from array
class Hello {
public function world($x) {
echo "Hello, $x\n"; return $this;
echo "Hello, $x\n";return $this;
}
}
@ -37,8 +37,16 @@ class Magic3 {
}
$f = array('Hello','world');
var_dump($f('you'));
var_dump(call_user_func($f, 'you'));
try {
var_dump($f('you'));
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
try {
var_dump(call_user_func($f, 'you'));
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
printf("-----\n");
@ -101,35 +109,31 @@ var_dump(call_user_func($f, 'you'));
--EXPECTF--
Deprecated: Non-static method Hello::world() should not be called statically in %s on line %d
Hello, you
Notice: Undefined variable: this in %s on line %d
NULL
Exception: Using $this when not in object context
Deprecated: %son-static method Hello::world() should not be called statically in %s on line %d
Hello, you
Notice: Undefined variable: this in %s on line %d
NULL
Exception: Using $this when not in object context
-----
Hello, again
object(Hello)#1 (0) {
object(Hello)#%d (0) {
}
Hello, again
object(Hello)#1 (0) {
object(Hello)#%d (0) {
}
-----
Hello, there
object(Hello)#2 (0) {
object(Hello)#%d (0) {
}
Hello, there
object(Hello)#2 (0) {
object(Hello)#%d (0) {
}
-----
Hello, devs
object(Hello)#4 (0) {
object(Hello)#%d (0) {
}
Hello, devs
object(Hello)#4 (0) {
object(Hello)#%d (0) {
}
-----
Magic::__call called (foo)!

View file

@ -0,0 +1,10 @@
--TEST--
Testing func_get_args()
--FILE--
<?php
func_get_args();
?>
--EXPECTF--
Warning: func_get_args(): Called from the global scope - no function context in %s on line 3

View file

@ -10,9 +10,9 @@ for ($i = 0; $i < 10001; $i++) {
}
$a[] = "xxx";
unset($a);
var_dump(gc_collect_cycles());
var_dump(gc_collect_cycles() > 0);
echo "ok\n";
?>
--EXPECT--
int(2)
bool(true)
ok

View file

@ -12,9 +12,9 @@ for ($i = 0; $i < 10001; $i++) {
unset($b);
$a->b = "xxx";
unset($a);
var_dump(gc_collect_cycles());
var_dump(gc_collect_cycles() > 0);
echo "ok\n";
?>
--EXPECT--
int(2)
bool(true)
ok

View file

@ -12,9 +12,9 @@ $a->b = "xxx";
unset($c);
unset($a);
unset($b);
var_dump(gc_collect_cycles());
var_dump(gc_collect_cycles() > 0);
echo "ok\n";
?>
--EXPECT--
int(2)
bool(true)
ok

View file

@ -10,7 +10,6 @@ class Node {
public $parent;
function __construct($name) {
$this->name = $name;
$this->children = array();
$this->parent = null;
}
function insert($node) {
@ -32,12 +31,12 @@ $a->insert($c);
unset($a);
unset($b);
unset($c);
var_dump(gc_collect_cycles());
var_dump(gc_collect_cycles() >= 7);
echo "ok\n"
?>
--EXPECTF--
string(1) "%s"
string(1) "%s"
string(1) "%s"
int(10)
bool(true)
ok

View file

@ -0,0 +1,45 @@
--TEST--
Verify yield from on generators being properly cycle collected
--FILE--
<?php
function root() {
global $gens; // create cyclic reference to root
try {
yield 1;
} finally {
var_dump($gens);
}
}
function gen($x) {
global $gens;
yield from $gens[] = $x ? gen(--$x) : root();
}
$gen = $gens[] = gen(2);
var_dump($gen->current());
unset($gen, $gens);
print "collect\n";
gc_collect_cycles();
print "end\n";
?>
--EXPECT--
int(1)
collect
array(4) {
[0]=>
object(Generator)#1 (0) {
}
[1]=>
object(Generator)#2 (0) {
}
[2]=>
object(Generator)#3 (0) {
}
[3]=>
object(Generator)#4 (0) {
}
}
end

View file

@ -0,0 +1,12 @@
--TEST--
Generators with arguments unpacking
--FILE--
<?php
(function() { yield; })(...range(1, 16384));
call_user_func_array(function() { yield; }, range(1, 16384));
$g = (function() { yield; })(...range(1, 16384));
$g = call_user_func_array(function() { yield; }, range(1, 16384));
echo "OK\n";
?>
--EXPECT--
OK

View file

@ -0,0 +1,13 @@
--TEST--
Generator wit type check
--FILE--
<?php
function gen(array $a) { yield; }
gen(42);
?>
--EXPECTF--
Fatal error: Uncaught TypeError: Argument 1 passed to gen() must be of the type array, integer given, called in %sgenerator_with_type_check.php on line 3 and defined in %sgenerator_with_type_check.php:2
Stack trace:
#0 %sgenerator_with_type_check.php(3): gen(42)
#1 {main}
thrown in %sgenerator_with_type_check.php on line 2

View file

@ -0,0 +1,22 @@
--TEST--
Generator wit type check
--FILE--
<?php
function gen(array $a) { yield; }
try {
gen(42);
} catch (TypeError $e) {
echo $e->getMessage()."\n";
}
try {
foreach (gen(42) as $val) {
var_dump($val);
}
} catch (TypeError $e) {
echo $e->getMessage()."\n";
}
?>
--EXPECTF--
Argument 1 passed to gen() must be of the type array, integer given, called in %sgenerator_with_type_check_2.php on line 4
Argument 1 passed to gen() must be of the type array, integer given, called in %sgenerator_with_type_check_2.php on line 10

View file

@ -0,0 +1,17 @@
--TEST--
yield from with an IteratorAggregate
--FILE--
<?php
class foo implements \IteratorAggregate {
public $prop = 1;
function getIterator() {
var_dump($this->prop);
yield;
}
}
(function(){
yield from new foo;
})()->next();
?>
--EXPECT--
int(1)

View file

@ -0,0 +1,22 @@
--TEST--
Global variable import using a name with side effects
--FILE--
<?php
function sf($arg) {
echo "called\n";
return $arg;
}
function test() {
global ${sf("a")};
var_dump($a);
}
$a = 42;
test();
?>
--EXPECT--
called
int(42)

View file

@ -10,11 +10,12 @@ class B {
function bar() { A::foo(); }
}
$b = new B;
$b->bar();
try {
$b->bar();
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
?>
--EXPECTF--
Deprecated: Non-static method A::foo() should not be called statically in %s on line %d
Notice: Undefined variable: this in %s on line %d
string(1) "A"
Exception: Using $this when not in object context

View file

@ -12,7 +12,7 @@ foreach ($testvalues as $testvalue) {
}
echo "\n*** Indexing - Testing reference assignment with key ***\n";
$testvalues=array(null, 0, 1, true, false,'',0.1,array());
$testvalues=array(null, 0, 1, true, false,0.1,array());
foreach ($testvalues as $testvalue) {
$testvalue['foo']=&$array;
@ -20,7 +20,7 @@ foreach ($testvalues as $testvalue) {
}
echo "*** Indexing - Testing value assignment no key ***\n";
$array=array(1);
$testvalues=array(null, 0, 1, true, false,'',0.1,array());
$testvalues=array(null, 0, 1, true, false,0.1,array());
foreach ($testvalues as $testvalue) {
$testvalue[]=$array;
@ -28,7 +28,7 @@ foreach ($testvalues as $testvalue) {
}
echo "\n*** Indexing - Testing reference assignment no key ***\n";
$testvalues=array(null, 0, 1, true, false,'',0.1,array());
$testvalues=array(null, 0, 1, true, false,0.1,array());
foreach ($testvalues as $testvalue) {
$testvalue[]=&$array;
@ -63,13 +63,11 @@ array(1) {
int(1)
}
}
array(1) {
["foo"]=>
array(1) {
[0]=>
int(1)
}
}
Warning: Illegal string offset 'foo' in %s on line %d
Notice: Array to string conversion in %s on line %d
string(1) "A"
Warning: Illegal string offset 'foo' in %s on line %d
@ -110,13 +108,6 @@ array(1) {
int(1)
}
}
array(1) {
["foo"]=>
&array(1) {
[0]=>
int(1)
}
}
Warning: Cannot use a scalar value as an array in %s on line %d
float(0.1)
@ -151,13 +142,6 @@ array(1) {
int(1)
}
}
array(1) {
[0]=>
array(1) {
[0]=>
int(1)
}
}
Warning: Cannot use a scalar value as an array in %s on line %d
float(0.1)
@ -193,13 +177,6 @@ array(1) {
int(1)
}
}
array(1) {
[0]=>
&array(1) {
[0]=>
int(1)
}
}
Warning: Cannot use a scalar value as an array in %s on line %d
float(0.1)
@ -211,4 +188,4 @@ array(1) {
}
}
Done
Done

View file

@ -17,8 +17,11 @@ class foo {
}
$arr = array('foo', 'abc');
$arr();
try {
$arr();
} catch (Throwable $e) {
echo "Exception: " . $e->getMessage() . "\n";
}
$foo = new foo;
$arr = array($foo, 'abc');
$arr();
@ -28,9 +31,7 @@ $arr();
--EXPECTF--
From foo::__callStatic:
string(3) "abc"
Notice: Undefined variable: this in %s on line %d
NULL
Exception: Using $this when not in object context
From foo::__call:
string(3) "abc"
object(foo)#%d (0) {

View file

@ -0,0 +1,17 @@
--TEST--
Type inference should not result in infinite loop
--FILE--
<?php
function test() {
$b = false;
do {
$a = $a + PHP_INT_MAX + 2;
$a = 0;
} while ($b);
}
test();
?>
--EXPECTF--
Notice: Undefined variable: a in %s on line %d

View file

@ -0,0 +1,52 @@
--TEST--
Integer conversion from scientific notation
--FILE--
<?php
var_dump((int)"1.2345e9");
var_dump((int)"-1.2345e9");
var_dump(intval("1.2345e9"));
var_dump(intval("-1.2345e9"));
var_dump("1.2345e9" % PHP_INT_MAX);
var_dump("-1.2345e9" % PHP_INT_MIN);
var_dump("1.2345e9" | 0);
var_dump("-1.2345e9" | 0);
echo PHP_EOL;
var_dump((int)" 1.2345e9 abc");
var_dump((int)" -1.2345e9 abc");
var_dump(intval(" 1.2345e9 abc"));
var_dump(intval(" -1.2345e9 abc"));
var_dump(" 1.2345e9 abc" % PHP_INT_MAX);
var_dump(" -1.2345e9 abc" % PHP_INT_MIN);
var_dump(" 1.2345e9 abc" | 0);
var_dump(" -1.2345e9 abc" | 0);
?>
--EXPECTF--
int(1234500000)
int(-1234500000)
int(1234500000)
int(-1234500000)
int(1234500000)
int(-1234500000)
int(1234500000)
int(-1234500000)
int(1234500000)
int(-1234500000)
int(1234500000)
int(-1234500000)
Notice: A non well formed numeric value encountered in %s on line %d
int(1234500000)
Notice: A non well formed numeric value encountered in %s on line %d
int(-1234500000)
Notice: A non well formed numeric value encountered in %s on line %d
int(1234500000)
Notice: A non well formed numeric value encountered in %s on line %d
int(-1234500000)

View file

@ -8,6 +8,7 @@ print "- isset ---\n";
$str = "test0123";
var_dump(isset($str[-1]));
var_dump(isset($str[-10]));
var_dump(isset($str[0]));
var_dump(isset($str[1]));
var_dump(isset($str[4])); // 0
@ -17,6 +18,7 @@ var_dump(isset($str[10000]));
// non-numeric offsets
print "- string ---\n";
var_dump(isset($str['-1']));
var_dump(isset($str['-10']));
var_dump(isset($str['0']));
var_dump(isset($str['1']));
var_dump(isset($str['4'])); // 0
@ -31,6 +33,7 @@ print "- null ---\n";
var_dump(isset($str[null]));
print "- double ---\n";
var_dump(isset($str[-1.1]));
var_dump(isset($str[-10.5]));
var_dump(isset($str[-0.8]));
var_dump(isset($str[-0.1]));
var_dump(isset($str[0.2]));
@ -50,6 +53,7 @@ print "done\n";
?>
--EXPECTF--
- isset ---
bool(true)
bool(false)
bool(true)
bool(true)
@ -58,6 +62,7 @@ bool(true)
bool(false)
bool(false)
- string ---
bool(true)
bool(false)
bool(true)
bool(true)
@ -72,6 +77,7 @@ bool(false)
- null ---
bool(true)
- double ---
bool(true)
bool(false)
bool(true)
bool(true)

27
Zend/tests/jump16.phpt Normal file
View file

@ -0,0 +1,27 @@
--TEST--
jump 16: goto into try/catch
--FILE--
<?php
goto a;
try {
echo "1";
a:
echo "2";
throw new Exception();
} catch (Exception $e) {
echo "3";
}
echo "4";
goto b;
try {
echo "5";
throw new Exception();
} catch (Exception $e) {
echo "6";
b:
echo "7";
}
echo "8\n";
?>
--EXPECT--
23478

22
Zend/tests/jump17.phpt Normal file
View file

@ -0,0 +1,22 @@
--TEST--
jump 17: goto into try/catch with finally
--FILE--
<?php
goto b;
try {
echo "1";
a:
echo "2";
throw new Exception();
} catch (Exception $e) {
echo "3";
b:
echo "4";
} finally {
echo "5";
c:
echo "6";
}
echo "7\n";
--EXPECT--
4567

View file

@ -5,6 +5,8 @@
list($a, list($b)) = array(new stdclass, array(new stdclass));
var_dump($a, $b);
[$a, [$b]] = array(new stdclass, array(new stdclass));
var_dump($a, $b);
?>
--EXPECT--
@ -12,3 +14,7 @@ object(stdClass)#1 (0) {
}
object(stdClass)#2 (0) {
}
object(stdClass)#3 (0) {
}
object(stdClass)#4 (0) {
}

10
Zend/tests/list_008.phpt Normal file
View file

@ -0,0 +1,10 @@
--TEST--
Assignment to invalid list() value
--FILE--
<?php
[42] = [1];
?>
--EXPECTF--
Fatal error: Assignments can only happen to writable values in %s on line %d

14
Zend/tests/list_009.phpt Normal file
View file

@ -0,0 +1,14 @@
--TEST--
list with by-reference assignment should fail
--FILE--
<?php
$a = [1];
[&$foo] = $a;
$foo = 2;
var_dump($a);
?>
--EXPECTF--
Fatal error: [] and list() assignments cannot be by reference in %s on line %d

11
Zend/tests/list_010.phpt Normal file
View file

@ -0,0 +1,11 @@
--TEST--
Do not allow mixing [] and list()
--FILE--
<?php
list([$a]) = [[1]];
var_dump($a);
?>
--EXPECTF--
Fatal error: Cannot mix [] and list() in %s on line %d

10
Zend/tests/list_011.phpt Normal file
View file

@ -0,0 +1,10 @@
--TEST--
Disallow list() usage as if it were an array
--FILE--
<?php
var_dump(list(1, 2, 3));
?>
--EXPECTF--
Parse error: syntax error, unexpected ')', expecting '=' in %s on line %d

10
Zend/tests/list_012.phpt Normal file
View file

@ -0,0 +1,10 @@
--TEST--
Disallow empty elements in normal arrays
--FILE--
<?php
var_dump([, 1, 2]);
?>
--EXPECTF--
Fatal error: Cannot use empty array elements in arrays in %s on line %d

10
Zend/tests/list_013.phpt Normal file
View file

@ -0,0 +1,10 @@
--TEST--
Disallow tail empty elements in normal arrays
--FILE--
<?php
var_dump([1, 2, ,]);
?>
--EXPECTF--
Fatal error: Cannot use empty array elements in arrays in %s on line %d

View file

@ -0,0 +1,71 @@
--TEST--
list() with keys
--FILE--
<?php
$antonyms = [
"good" => "bad",
"happy" => "sad",
];
list("good" => $good_antonym, "happy" => $happy_antonym) = $antonyms;
var_dump($good_antonym, $happy_antonym);
echo PHP_EOL;
$powersOfTwo = [
1 => 2,
2 => 4,
3 => 8
];
list(1 => $two_1, 2 => $two_2, 3 => $two_3) = $powersOfTwo;
var_dump($two_1, $two_2, $two_3);
echo PHP_EOL;
$contrivedMixedKeyTypesExample = [
7 => "the best PHP version",
"elePHPant" => "the cutest mascot"
];
list(7 => $seven, "elePHPant" => $elePHPant) = $contrivedMixedKeyTypesExample;
var_dump($seven, $elePHPant);
echo PHP_EOL;
$allTogetherNow = [
"antonyms" => $antonyms,
"powersOfTwo" => $powersOfTwo,
"contrivedMixedKeyTypesExample" => $contrivedMixedKeyTypesExample
];
list(
"antonyms" => list("good" => $good_antonym, "happy" => $happy_antonym),
"powersOfTwo" => list(1 => $two_1, 2 => $two_2, 3 => $two_3),
"contrivedMixedKeyTypesExample" => list(7 => $seven, "elePHPant" => $elePHPant)
) = $allTogetherNow;
var_dump($good_antonym, $happy_antonym);
var_dump($two_1, $two_2, $two_3);
var_dump($seven, $elePHPant);
?>
--EXPECT--
string(3) "bad"
string(3) "sad"
int(2)
int(4)
int(8)
string(20) "the best PHP version"
string(17) "the cutest mascot"
string(3) "bad"
string(3) "sad"
int(2)
int(4)
int(8)
string(20) "the best PHP version"
string(17) "the cutest mascot"

Some files were not shown because too many files have changed in this diff Show more