Compare commits

..
343 Commits
Author SHA1 Message Date
Gabriel Caruso a66aeecc2c Update versions for PHP 8.0.2 2021-02-02 19:24:50 +00:00
Nikita Popov 3424432ec9 Fix build 2021-02-02 16:19:14 -03:00
Stanislav Malyshev f733ee1954 Fix bug #80672 - Null Dereference in SoapClient 2021-02-02 16:18:44 -03:00
Gabriel Caruso 5070a0f689 Update NEWS for PHP 8.0.2 2021-02-02 11:10:39 +00:00
Gabriel Caruso b4814d7456 [ci-skip] Fix typo in placeholder 2021-02-02 08:05:49 -03:00
Gabriel Caruso 08b44a47ca [ci-skip] Remove RC suffix to release non-RC 2021-02-02 08:02:36 -03:00
Gabriel Caruso 966ee42d34 [ci-skip] Fix placeholder for non-RC release 2021-02-02 07:56:25 -03:00
Stanislav Malyshev 946e00afd6 Rm unneeded function 2021-02-02 07:46:30 -03:00
Christoph M. Becker 605d9f55ad Alternative fix for bug 77423
That bug report originally was about `parse_url()` misbehaving, but the
security aspect was actually only regarding `FILTER_VALIDATE_URL`.
Since the changes to `parse_url_ex()` apparently affect userland code
which is relying on the sloppy URL parsing[1], this alternative
restores the old parsing behavior, but ensures that the userinfo is
checked for correctness for `FILTER_VALIDATE_URL`.

[1] <https://github.com/php/php-src/commit/5174de7cd33c3d4fa591c9c93859ff9989b07e8c#commitcomment-45967652>
2021-02-02 07:45:26 -03:00
Gabriel Caruso 5e21867c55 Update NEWS for PHP 8.0.2RC1 2021-01-19 15:41:46 +00:00
Gabriel Caruso 9ce200f6cb Fix NEWS placeholder for the next version
This aligns with the PHP-7.4 and PHP-7.3 branches, and should
fix the `sgolemon/php-release` script run for releasing 8.0.2.
2021-01-19 12:32:17 -03:00
Derick Rethans b5599a37d7 Merge branch 'PHP-7.4' into PHP-8.0 2021-01-19 14:59:19 +00:00
Derick Rethans a33d0c3aae Update NEWS and version 2021-01-19 14:58:38 +00:00
Derick Rethans e8a89c49db Update NEWS for PHP 7.4.15RC1 2021-01-19 14:44:32 +00:00
Nikita Popov f3415758d1 Fix observer tests on Windows
Use %e instead of a hardcoded forward slash.
2021-01-19 15:27:14 +01:00
Nikita Popov 05d168013a Fixed bug #80644: ResourceBundle::get() doesn't reset error state 2021-01-19 15:20:55 +01:00
Nikita Popov 1bdd8f7ae4 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #42560
2021-01-19 11:44:22 +01:00
sj-i 5d31ee302d Fixed bug #42560
Check open_basedir after the fallback to the system's temporary
directory in tempnam().

In order to preserve the current behavior of upload_tmp_dir
(do not check explicitly specified dir, but check fallback),
new flags are added to check open_basedir for explicit dir
and for fallback.

Closes GH-6526.
2021-01-19 11:41:58 +01:00
Christoph M. Becker f33105dcb6 ldap_search() and friends can return array
See the description of <https://www.php.net/ldap-search>, and also the
implementation.

Closes GH-6620.
2021-01-19 10:35:17 +01:00
Christoph M. Becker cfae999f1b Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #69279: Compressed ZIP Phar extractTo() creates garbage files
2021-01-19 10:30:28 +01:00
Christoph M. BeckerandAnna Filina 68f5289e9e Fix #69279: Compressed ZIP Phar extractTo() creates garbage files
When extracting compressed files from an uncompressed Phar, we must not
use the direct file pointer, but rather get an uncompressed file
pointer.

We also add a test to show that deflated and stored entries are
properly extracted.

This also fixes #79912, which appears to be a duplicate of #69279.

Co-authored-by: Anna Filina <afilina@gmail.com>

Closes GH-6599.
2021-01-19 10:28:54 +01:00
Dylan K. Taylor 872f302b8d Keep JIT region executable under ZTS
When one thread tries to compile a script, another thread may
already be executing JITed code. In this case we can't make the
memory non-executable.

This violates the W^X principle, but doesn't seem to be avoidable
for ZTS builds for now. The same problem does not exist for NTS,
as it's a different process executing there, which has it's own
memory protection mapping.

Closes GH-6595.
2021-01-19 10:25:42 +01:00
Nikita Popov fbd8e20ed5 Observe unused return values in JIT
Even if the return value is not used, it should still be available
to the observer.
2021-01-19 10:09:53 +01:00
Nikita Popov dd7d829896 Disable opcache optimizations during some observer tests
Opcache inlines functions that only return a constant. Disable
optimizations to prevent differences in tests where such functions
are used (or rewrite the test to not depend on it).
2021-01-19 10:02:08 +01:00
Nikita Popov f2364f316d SplFileObject::fgets() cannot return false
spl_filesystem_file_read() is called with silent=0, so it will
throw on failure.
2021-01-18 16:47:21 +01:00
Nikita Popov 7290dc4dcf Sync gzgets signature with fgets 2021-01-18 15:47:12 +01:00
Nikita Popov ebf461a025 Sync datefmt_get_calendar_object signature
In this case, it's only a matter of using the same type order
in both cases.
2021-01-18 14:39:32 +01:00
Nikita Popov 39077deea5 Sync intlcal_create_instance() and IntlCalendar::createInstance()
Remove the explicit mention of IntlGregorianCalendar in the latter.
It is a subclass of IntlCalendar, and as such covered if only
IntlCalendar is used as the return type.
2021-01-18 14:39:32 +01:00
Nikita Popov c31f9f7ee4 Sync date_diff and DateTime::diff return type
This function/method cannot return false.
2021-01-18 14:39:32 +01:00
Nikita Popov 48e2e5324e Fix parameter name of PharData::getMetadata()
The name should be the same as for Phar::getMetadata().
2021-01-18 14:09:00 +01:00
Dylan K. Taylor 0aad77418d Fix stub for Phar::setStub()
This fixes multiple issues:
 * The first parameter may be resource|string.
 * It's an overloaded signature. The second parameter cannot be
   passed if the first one is a string. Use UNKNOWN default
   value for that reason.
 * Make parameter names in PharData::setStub() match those in
   Phar.

Closes GH-6596.
2021-01-18 12:59:18 +01:00
Christoph M. Becker c321896a37 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #80595: Resetting POSTFIELDS to empty array breaks request
2021-01-18 11:01:01 +01:00
Christoph M. Becker 38ad37ad43 Fix #80595: Resetting POSTFIELDS to empty array breaks request
This is mainly to work around https://github.com/curl/curl/issues/6455,
but not building the mime structure for empty hashtables is a general
performance optimization, so we do not restrict it to affected cURL
versions (7.56.0 to 7.75.0).

The minor change to bug79033.phpt is unexpected, but should not matter
in practice.

Closes GH-6606.
2021-01-18 10:57:56 +01:00
Nikita Popov 880bf62224 Fixed bug #80617: Type narrowing warning in ZEND_TYPE_INIT_CODE 2021-01-14 10:08:22 +01:00
Daniil Gentili f9fbba41b6 Fixed bug #80596: Fix anonymous class union typehint errors
Cut off part after null byte when resolving the class name, to
avoid cutting off a larger part lateron.

Closes GH-6601.
2021-01-14 10:04:27 +01:00
Dmitry Stogov 3edf5c969a Fixed bug #80422 (php_opcache.dll crashes when using Apache 2.4 with JIT) 2021-01-14 08:16:27 +03:00
Christoph M. Becker 41e9a8ebdc socket_create_pair() can no longer return NULL
Closes GH-6592.
2021-01-12 12:08:31 +01:00
David CARLIER 7a049cd6a4 Use arc4random_buf on macOS
macOS uses an AES based arc4random_buf implementation since at least
macOS 10.2.

Closes GH-6591.
2021-01-12 10:42:09 +01:00
Nikita Popov 973138f39d Add support for union types for internal functions
This closes the last hole in the supported types for internal
function arginfo types. It's now possible to represent unions of
multiple classes. This is done by storing them as TypeA|TypeB and
PHP will then convert this into an appropriate union type list.

Closes GH-6581.
2021-01-12 10:14:41 +01:00
Nikita Popov bc0f78a2da Use ephemeral port in socket_create_listen_used.phpt
Avoid parallelism issues.
2021-01-12 10:09:30 +01:00
Jens de Nies 94a151a018 Fixed bug #80545
This converts the remaining "non well-formed" warnings in bcmath
to ValueErrors, in line with the other warning promotions that
have been performed in this extension.

Closes GH-80545.
2021-01-12 09:50:27 +01:00
Christoph M. Becker 95a13ca989 Revert fix for bug 76813 and re2c version bump
CentOS 7 ships with re2c 0.13.5 by default, so we should not have
bumped the required re2c version to 0.13.7.  However, 0.13.5 does not
support default rules, so we cannot use them to fix bug 76813.

This reverts commit 420184ad52 and
5e15c9c41f.

Closes GH-6593.
2021-01-11 17:19:52 +01:00
Christoph M. Becker 52ed45745e Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Revert "Fix #76813: Access violation near NULL on source operand"
2021-01-11 13:21:56 +01:00
Christoph M. Becker 25103c37aa Revert "Fix #76813: Access violation near NULL on source operand"
This reverts commit 5e15c9c41f, since
re2c default rules are only available as of re2c 0.13.7.
2021-01-11 13:21:12 +01:00
Dmitry Stogov 35e0506a2e Add guard if lvalue of assignment may be a reference, but wasn't a reference during recording 2021-01-11 15:12:27 +03:00
George Peter Banyard f40838eaaa Rename `zip_ent parameter to zip_entry` for consistency
All other functions use ``zip_entry``
2021-01-08 22:26:24 +00:00
Christoph M. Becker 8ae02c8a95 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Avoid modifying the return value of readline_completion_function()
2021-01-07 13:48:17 +01:00
Christoph M. Becker 9450893dc6 Avoid modifying the return value of readline_completion_function()
The internal function `_readline_command_generator()` modifies the
internal array pointer of `readline_completion_function()`'s return
value.  We therefore separate the array, what also avoids failing
assertions regarding the array refcount.

Closes GH-6582.
2021-01-07 13:46:09 +01:00
Dharman 34ef804b04 Make fetch_* OO same as func
Clsoses GH-6580.
2021-01-06 15:02:52 +01:00
Christoph M. Becker f674a3343c Fix #80592: all floats are the same in ODBC parameters
We must not release the strings until we are done with them.

Closes GH-6579.
2021-01-06 13:56:02 +01:00
Dharman 44a311dbbe Fix/improve mysqli stubs
* mysqli_commit $flags default value is 0, not -1.
* A number of functions cannot actually return null.
* mysqli_poll parameter names were incorrect, as this function
  has a different signature from select.
* fetch functions apart from fetch_all can return false on failure.
2021-01-06 11:28:45 +01:00
Christoph M. Becker 90081c5391 Add missing SKIPIF clause for require_hash.phpt 2021-01-06 11:00:10 +01:00
Christoph M. Becker 66a74f2f4a Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #77565: Incorrect locator detection in ZIP-based phars
2021-01-05 23:46:05 +01:00
Christoph M. Becker d1b1c04398 Fix #77565: Incorrect locator detection in ZIP-based phars
We must not assume that the first end of central dir signature in a ZIP
archive actually designates the end of central directory record, since
the data in the archive may contain arbitrary byte patterns.  Thus, we
better search from the end of the data, what is also slightly more
efficient.

There is, however, no way to detect the end of central directory
signature by searching from the end of the ZIP archive with absolute
certainty, since the signature could be part of the trailing comment.
To mitigate, we check that the comment length fits to the found
position, but that might still not be the correct position in rare
cases.

Closes GH-6507.
2021-01-05 23:40:24 +01:00
Christoph M. Becker b7689db7ab Prevent double-free of Phar ZIP stream
We must not alias the closed stream to `phar_archive_data.fp`, and use
PHAR_ZIP_FAIL() for consistency with the rest of this function.

Closes GH-6578.
2021-01-05 14:31:43 +01:00
Christoph M. Becker afc69e46b8 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix memory leak in Phar::webPhar() on Windows
2021-01-05 14:25:44 +01:00
Christoph M. Becker 5c963731e2 Fix memory leak in Phar::webPhar() on Windows
Closes GH-6574.
2021-01-05 14:21:35 +01:00
Nikita Popov dd335359e9 Fix infinite recursion in unlinked_instanceof
I suspect this is only a partial fix for the issue, it's probably
possible to recurse through a more complex pathway as well.

Fixes oss-fuzz #28961.
2021-01-05 13:03:41 +01:00
Nikita Popov 5e57f37247 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  gdbinit: use ____print_str to print htable keys
2021-01-05 10:12:43 +01:00
Dylan K. Taylor 6b631f073d gdbinit: use ____print_str to print htable keys
I noticed this problem while dumping the contents of EG(function_table),
where keys for closures start with a null byte. printf interprets this
as a zero-length string and emits nothing. This allows the key to be
rendered properly in readable form.

Closes GH-6577.
2021-01-05 10:11:56 +01:00
Christoph M. Becker 121790eaff [ci skip] Add forgotten NEWS entry (bug 80560) 2021-01-04 18:19:45 +01:00
George Peter Banyard 764b7bf108 Fix bug #80584: 0x and 0X are considered valid hex numbers by filter_var()
Closes GH-6573
2021-01-04 18:07:47 +01:00
Christoph M. Becker 9f96b2bdc8 Fix #76929: zip-based phar does not respect phar.require_hash
Based on the patch provided by david at bamsoftware.

Closes GH-6517.
2021-01-04 17:48:45 +01:00
Nikita Popov 821eaaf0b4 Fix newly added GMP test 2021-01-04 15:27:20 +01:00
George Peter Banyard 1b5c62facd Fix GMP comparison object handler
gmp_cmp() doesn't return false anymore in PHP 8 but will throw
an Error if compared to a non numeric string or another type of object.

Closes GH-6553
2021-01-04 14:47:50 +01:00
Nikita Popov af7445b9ac Try to fix intermittent failures of stream_server_reneg_limit.phpt on macos
Make sure the server has started up before we try to connect to it.
2021-01-04 14:31:42 +01:00
Nikita Popov 65f14b0d6c Throw ValueError instead of TypeError for malformed GMP number
If the passed argument has correct type (string) but does not
have a well-formed value, throw ValueError instead of TypeError.

Closes GH-6572.
2021-01-04 14:30:08 +01:00
Christoph M. Becker abe23bd9a3 SQLite3::query() cannot return null 2021-01-04 12:13:06 +01:00
David CARLIER 6e90c75507 Mac M1 crc32 detection support
Closes GH-6556.
2021-01-04 11:41:52 +01:00
Nikita Popov 151fce1129 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Disable non-cron travis jobs
2021-01-04 10:55:50 +01:00
Stanislav Malyshev bf2bb39eac Fix test name 2021-01-04 01:52:59 -08:00
Nikita Popov 46d6daea7a Disable non-cron travis jobs
This was already done for PHP-8.0 and master, do it for PHP-7.4
as well.
2021-01-04 10:52:37 +01:00
Stanislav Malyshev 4d1c1e4554 [ci skip] Update NEWS 2021-01-04 01:47:47 -08:00
Stanislav Malyshev ced4c0bfe6 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  [ci skip] Update NEWS
  [ci skip] Fix order
  [ci skip] Unpdate NEWS
  Fix #77423: parse_url() will deliver a wrong host to user
2021-01-04 01:47:09 -08:00
Stanislav Malyshev e65932060a [ci skip] Update NEWS 2021-01-04 01:46:32 -08:00
Stanislav Malyshev ec589a27da Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  [ci skip] Fix order
2021-01-04 01:46:11 -08:00
Stanislav Malyshev 65d7ade684 [ci skip] Fix order 2021-01-04 01:45:15 -08:00
Stanislav Malyshev 2498385dd9 Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  [ci skip] Unpdate NEWS
2021-01-04 01:44:18 -08:00
Stanislav Malyshev 8967e66559 [ci skip] Unpdate NEWS 2021-01-04 01:43:45 -08:00
Stanislav Malyshev 8768621149 Fix bug #79405 - gethostbyname() silently truncates after a null byte 2021-01-04 01:19:21 -08:00
Christoph M. Becker b132da7f9d Fix #77423: parse_url() will deliver a wrong host to user
To avoid that `parse_url()` returns an erroneous host, which would be
valid for `FILTER_VALIDATE_URL`, we make sure that only userinfo which
is valid according to RFC 3986 is treated as such.

For consistency with the existing url parsing code, we use ctype
functions, although that is not necessarily correct.
2021-01-04 01:19:18 -08:00
Christoph M. Becker aab23282fc Fix imap stubs
Closes GH-6559.
2021-01-03 16:15:46 +01:00
Christoph M. Becker e470f9b389 ZipArchive methods do not return NULL
Closes GH-6563.
2021-01-03 16:12:10 +01:00
Stanislav Malyshev 434c2b1bdb Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  Fix #77423: parse_url() will deliver a wrong host to user
2021-01-01 21:29:08 -08:00
Stanislav Malyshev 128fca4037 Merge branch 'PHP-7.2' into PHP-7.3
* PHP-7.2:
  Fix #77423: parse_url() will deliver a wrong host to user
2021-01-01 21:06:07 -08:00
Christoph M. Becker 2d3d72412a Fix #77423: parse_url() will deliver a wrong host to user
To avoid that `parse_url()` returns an erroneous host, which would be
valid for `FILTER_VALIDATE_URL`, we make sure that only userinfo which
is valid according to RFC 3986 is treated as such.

For consistency with the existing url parsing code, we use ctype
functions, although that is not necessarily correct.
2021-01-01 20:08:01 -08:00
Christoph M. Becker cae0bcbab5 Fix parameter name
Levenshtein is about insertion, replacement and deletion.

Closes GH-6560.
2021-01-01 23:04:28 +01:00
Christoph M. Becker b2fba0ef62 Fix build
We cannot `RETURN_THROWS()` here, since `return_value` is not defined.
2021-01-01 17:41:48 +01:00
Máté Kocsis b23c865d15 Use RETURN_THROWS() in a few places 2021-01-01 16:52:48 +01:00
Christoph M. Becker 82f9e004da Fix ReflectionClass::getConstants() stub
If `zval_update_constant_ex()` fails, an exception has already been
thrown, so we clarify that in the implementation as well.

Closes GH-6557.
2021-01-01 14:46:28 +01:00
Christoph M. Becker 2e854791af [ci skip] Fix pgsql constant names in UPGRADING 2020-12-31 00:30:16 +01:00
Máté Kocsis 446ad04524 Fix refentry attribute replacing 2020-12-30 18:26:24 +01:00
George Peter Banyard abecaab09f Fix #80560: Strings containing only a base prefix return 0 object
Closes GH-6549.
2020-12-30 12:50:04 +01:00
Dmitry Stogov da0ca53f39 Initialize EX(call)->func by single instruction 2020-12-29 13:20:10 +03:00
Dmitry Stogov 56fde2a381 Reuse value stored in %r0 instead of immediate operand 2020-12-29 13:18:56 +03:00
Christoph M. Becker 13f898b56a Fix ffi stubs
Closes GH-6543.
2020-12-28 19:04:47 +01:00
Máté Kocsis 46a2c6a8d7 Fix return type of DateTimeImmutable::__set_state() 2020-12-28 14:45:13 +01:00
Máté Kocsis 9cec093b7f Add support for generating methodsynopses from stubs
Closes GH-6367
2020-12-28 14:44:43 +01:00
Christoph M. Becker 420184ad52 Bump minimum re2c version to 0.13.7
Closes GH-6516.
2020-12-28 13:43:31 +01:00
Christoph M. Becker 45b638afe0 php_formatted_print() throws on failure
Closes GH-6542.
2020-12-27 22:40:25 +01:00
Christoph M. Becker 57430e6f1e Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Replace sort() function calls with ksort() in basic ksort test
2020-12-27 18:32:03 +01:00
haszi 0db6f5267c Replace sort() function calls with ksort() in basic ksort test
Closes GH-6541.
2020-12-27 18:30:58 +01:00
Christoph M. Becker 269936e680 DateTime*::getOffset() no longer returns false as of PHP 8.0.0
Cf. <https://github.com/php/doc-en/pull/282>.

Closes GH-6539.
2020-12-26 15:13:05 +01:00
Dmitry Stogov 23bbff2b05 Eliminate redundand comparison insructions 2020-12-24 16:58:54 +03:00
Máté Kocsis ab4c5976d7 Fix the signature of FFI::typeof() and FFI::memcmp() 2020-12-24 11:45:32 +01:00
Máté Kocsis c1d766171b Add a few other RETURN_THROWS() 2020-12-24 11:44:15 +01:00
Máté Kocsis ed19cb6518 Fix the signature of FFI::sizeof() and FFI::alignof() 2020-12-24 11:39:09 +01:00
Christopher Jones 34aefa36f4 Fix PDO_OCI test 2020-12-24 17:48:39 +11:00
Semen Dubina 959d3c9636 Add regression test for bug #76770
Closes GH-3514.
2020-12-23 16:47:08 +01:00
Christoph M. Becker 7d9ddd61ec Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #80384: limit read buffer size
2020-12-23 13:52:45 +01:00
Adam SeitzandChristoph M. Becker 70dfbe0068 Fix #80384: limit read buffer size
In the case of a stream with no filters, php_stream_fill_read_buffer
only reads stream->chunk_size into the read buffer. If the stream has
filters attached, it could unnecessarily buffer a large amount of data.

With this change, php_stream_fill_read_buffer only proceeds until either
the requested size or stream->chunk_size is available in the read buffer.

Co-authored-by: Christoph M. Becker <cmbecker69@gmx.de>

Closes GH-6444.
2020-12-23 13:49:56 +01:00
Derick Rethans 288332077f Fixed bug #80376 (last day of the month causes runway cpu usage) 2020-12-21 10:31:41 +00:00
Derick Rethans b043759cb4 Fixed bug #80376 (last day of the month causes runway cpu usage) 2020-12-21 10:30:40 +00:00
Nikita Popov 27e250880b Fix bug #80537
This is an unavoidable breaking change to both the type and
parameter name.

The assertion that was supposed to prevent this was overly lax
and accepted any object type for string parameters.
2020-12-21 10:21:50 +01:00
Christopher Jones d6731d69bd Description typo 2020-12-21 15:46:26 +11:00
Christopher Jones 74959b47cd Bundle PECL OCI8 3.0.1 2020-12-21 15:15:16 +11:00
Christopher Jones 2877642037 Retrofit NEWS 2020-12-21 15:07:40 +11:00
Christoph M. Becker 32c6c29d79 Revert "DateTime:: and DateTimeImmutable::getTimestamp() may return false"
This reverts commit b67c232189.
2020-12-20 23:07:02 +01:00
Christoph M. Becker b67c232189 DateTime:: and DateTimeImmutable::getTimestamp() may return false 2020-12-20 19:32:12 +01:00
Christoph M. Becker 3c68f43251 Fix ext/date stubs
Closes GH-6523.
2020-12-20 18:14:20 +01:00
Nikita Popov 51f57e7b81 PDO MySQL: Handle boolean parameter binding with libmysql
Previously boolean parameters were simply silently ignored...
2020-12-18 11:01:26 +01:00
Nikita Popov ab84623108 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  MySQLnd: Support cursors in store/get result
2020-12-18 10:20:13 +01:00
Nikita Popov bc166844e3 MySQLnd: Support cursors in store/get result
This fixes two related issues:

1. When a PS with cursor is used in store_result/get_result,
   perform a COM_FETCH with maximum number of rows rather than
   silently switching to an unbuffered result set (in the case of
   store_result) or erroring (in the case of get_result).
   In the future, we might want to make get_result unbuffered for
   PS with cursors, as using cursors with buffered result sets
   doesn't really make sense. Unlike store_result, get_result
   isn't very explicit about what kind of result set is desired.
2. If the client did not request a cursor, but the server reports
   that a cursor exists, ignore this and treat the PS as if it
   has no cursor (i.e. to not use COM_FETCH). It appears to be a
   server side bug that a cursor used inside an SP will be reported
   to the client, even though the client cannot use the cursor.

Fixes bug #64638, bug #72862, bug #77935.

Closes GH-6518.
2020-12-18 10:19:13 +01:00
Christoph M. Becker 1860ef22eb Fix #80521: Parameters with underscores no longer recognized
We have to use the proper value for the bitmask.
2020-12-16 20:04:52 +01:00
Nikita Popov c56701690a Detect overlarge step for character range()
This was done for int and float ranges, but not char ranges.

Fixes oss-fuzz #28666.
2020-12-16 17:01:15 +01:00
Nikita Popov 205d209de9 PDO MySQL: Use mysqlnd column names
mysqlnd already creates interned zend_strings for us, so let's
make use of them.

This also required updating the PDO case changing code to work
with potentially shared strings. For the lowercasing, use the
optimized zend_string_tolower() implementation.
2020-12-16 15:17:13 +01:00
Nikita Popov 1a66d64717 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #67983
2020-12-16 10:53:48 +01:00
Nikita Popov 315f3f8dc9 Fixed bug #67983
We need to check the BIT case first, otherwise it will get skipped
in INT_AND_FLOAT_NATIVE mode.
2020-12-16 10:52:27 +01:00
Nikita Popov f6bd3dfdbc Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix bug #80523
2020-12-16 10:20:43 +01:00
Nikita Popov 118ff03335 Fix bug #80523
Don't truncate the file length to unsigned int...

I have no idea whether that fully fixes the problem because the
process gets OOM killed before finishing, but at least the
immediate parse error is gone now.
2020-12-16 10:20:20 +01:00
Derick Rethans e586a35fc7 Merge branch 'PHP-7.4' into PHP-8.0 2020-12-15 14:13:43 +00:00
Derick Rethans 078cdd8f76 Prepare for 7.4.15 2020-12-15 14:13:29 +00:00
Gabriel Caruso 9eea9aae10 Prepare for PHP 8.0.2
This was missing from f1f78ac875.
2020-12-15 11:03:21 -03:00
Gabriel Caruso f1f78ac875 Next is 8.0.2 2020-12-15 10:30:55 -03:00
Dmitry Stogov de78786566 Optimize out result value of ASSIGN, ASSIGN_OP and INC/DEC opcodes, if possible. 2020-12-15 14:30:58 +03:00
Christoph M. Becker c2fbab392c Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #77322: PharData::addEmptyDir('/') Possible integer overflow
2020-12-15 11:46:28 +01:00
Christoph M. Becker a53d67ceac Fix #77322: PharData::addEmptyDir('/') Possible integer overflow
`phar_path_check()` already strips a leading slash, so we must not
attempt to strip the trailing slash from an now empty directory name.

Closes GH-6508.
2020-12-15 11:44:53 +01:00
Christoph M. Becker 305500a3b1 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  7.3.27 is next
2020-12-15 11:32:10 +01:00
Christoph M. Becker c0a1c2c5ee Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  7.3.27 is next
2020-12-15 11:30:46 +01:00
Christoph M. Becker 40d9e3ab86 7.3.27 is next 2020-12-15 11:28:01 +01:00
Ayesh Karunaratne 724e241c9d JIT: Update invalid opcache.jit INI value message to include "tracing" and "function" values
`opcache.jit` accepts `tracing` and `function` as aliases, but they were not mentioned in the start-up INI warning message.
This updates the error message to include all possible values.

Closes GH-6490.
2020-12-15 10:18:33 +01:00
Nikita Popov b6d043aae2 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  IBM i PASE doesn't support ITIMER_PROF
2020-12-15 10:15:47 +01:00
Calvin Buckley 54248b18fe IBM i PASE doesn't support ITIMER_PROF
Like Cygwin, this platform needs to use a real-time timer.

This was based on a patch by @kadler, but it didn't handle unsetting
the timer, so the timeout would continue to be active, triggering
`hard_timeout` unexpectedly. The patch is fixed to handle unsetting.

Closes GH-6503.
2020-12-15 10:15:28 +01:00
David Carlier 1e6c7e776c JIT disabled build fix.
Closes GH-6514.
2020-12-15 09:51:16 +01:00
Christoph M. Becker 2e974c8c81 Add Windows support for OCI 19
As requested by Christopher Jones.
2020-12-14 23:11:04 +01:00
Christoph M. Becker 15d9c42070 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Drop pdo_mysql_prepare_load_data.phpt
2020-12-14 18:27:53 +01:00
Christoph M. Becker 10c9d615de Drop pdo_mysql_prepare_load_data.phpt
Like the test title and some comments in this test describe, this test
was supposed to have `::prepare()` failing because `LOAD DATA INFILE`
would not be supported as prepared statement, and then the test checks
whether follow-up queries would succeed.  However, `LOAD DATA INFILE`
is supported for prepared statements at least on Windows with mysqlnd,
so the test does no longer test what it is supposed to do.  Therefore,
we drop it.

Closes GH-6509.
2020-12-14 18:26:12 +01:00
Dmitry Stogov b3377028dc Remove unused flag 2020-12-14 15:29:21 +03:00
Dmitry Stogov 66e390707c Fixed bug #80506 (Immediate SIGSEGV upon ini_set("opcache.jit_debug", 1)) 2020-12-14 15:28:03 +03:00
Dmitry Stogov a12e7affd7 Fixed bug #80506 (Immediate SIGSEGV upon ini_set("opcache.jit_debug", 1)) 2020-12-14 15:26:11 +03:00
Jakub Zelenka d254078020 Merge branch 'PHP-7.4' into PHP-8.0 2020-12-13 18:42:11 +00:00
Jakub Zelenka a221e17b41 Fix bug #69625: FPM returns 200 status on request without SCRIPT_FILENAME 2020-12-13 18:39:48 +00:00
ekinhbayar b0e858da8b Remove bug41347.phpt as the error cases are already tested
Closes GH-6506.
2020-12-11 16:47:40 +01:00
Nikita Popov ccb7f1c7d8 Fixed bug #79132
Following cmb's suggestion and replacing the counter with a check
against the bound_params HT, which ensures that both cannot go
out of sync.
2020-12-11 16:35:03 +01:00
Nikita Popov 7a89157f8c PDO MySQL: Fix nextRowset() on libmysqlclient with native PS
The logic after next_result should match the one after execute.
This was the case for mysqlnd but not libmysqlclient, which used
the non-PS logic.
2020-12-11 14:48:44 +01:00
Nikita Popov 81f012a164 PDO MySQL: Don't skip two LOCAL_INFILE tests with libmysqlclient 2020-12-11 14:48:43 +01:00
Nikita Popov e4e88bd7e3 PDO MySQL: Unskip bug_41125.phpt
This test was always skipped (leftover debug statement?)

Contrary to the comments in the test and the test expectation,
this actually works fine.
2020-12-11 13:04:20 +01:00
Nikita Popov ad8eb116d8 Fixed bug #67004
Repeated execute() with native PS failed to release the previous
result set on libmysqlclient.

Move freeing the result set into a common location.
2020-12-11 12:52:59 +01:00
Nikita Popov d6b4b82a38 PDO MySQL: Use stmt_next_result with libmysqlclient as well
libmysqlclient added this function in version 5.5, which happens
to be the minimum we support. If we have a prepared statement,
we should use it on both mysqlnd and libmysqlclient, even if the
handling afterwards is different.

This fixes error handling with native prepared statements.
2020-12-11 12:20:04 +01:00
Nikita Popov 4e51059d52 PDO MySQL: Fix libmysql option test
The fact that getAttribute() fails for various libmysqlclient-only
options is a known issue, and the test was taking that into account.
However, the change of the default error mode broke the handling.
We need to handle the exceptions now.
2020-12-11 12:20:02 +01:00
Nikita Popov 43741a3f26 Fixed bug #62889
Our minimum libmysqlclient version requirement is high enough
that we don't need to check for MYSQL_OPT_LOCAL_INFILE support.

However, the mysql_get_option() function seems to only be available
since 5.7 (though it's really hard to find any definitie information
on when MySQL introduced certain functions or changes...) so we
need to store the value of the flag locally to make it available
through getAttribute().
2020-12-11 11:25:36 +01:00
Nikita Popov c927c831e6 PDO MySQL: Fix leak with libmysqlclient and multiple rowsets
stmt->column_count gets reset before the next_rowset handler is
invoked, so we need to fetch the value from the result set instead.

Arguably PDO should be separating the destruction of the previous
result set and the switch to the next result set more cleanly...
2020-12-11 10:51:14 +01:00
Dharman 54a63d91b8 Fix test cases for MariaDB
And remove unnecessary try-catch.

Closes GH-6505.
2020-12-11 09:53:20 +01:00
Nikita Popov 9e3ba775b7 Fixed bug #72368
Generate a param count mismatch error even if the query contains
no placeholders.

Additionally we shouldn't HANDLE errors from pdo_parse_params,
which are always reported via raise_impl_error. Doing so results
in duplicate error messages.
2020-12-10 16:53:08 +01:00
Nikita Popov a5527577e7 Allow drivers to omit error code
And thus generate error messages that match what PDO emulation
would generate.

This fixes the error message regression from the previous commit.
2020-12-10 16:04:33 +01:00
Nikita Popov 15b51a215a Fixed bug #79131
When a driver reports an error during EVT_ALLOC (and some over EVTs),
make sure we handle it as usual, i.e. warn or throw.

This requires some adjustments in PDO PgSQL to stop manually doing
this through an impl error.

Unfortunately the PDO PgSQL error messages regress because of this,
as they now include a completely arbitrary error code. There doesn't
seem to be an ability to skip it right now.
2020-12-10 15:53:23 +01:00
Dmitry Stogov dde5572937 Eliminate some repeatable IS_REFERENCE checks 2020-12-10 14:45:54 +03:00
Nikita Popov 288581fade Fixed bug #79872 by improving error message
The actual behavior here is correct, but the previous error
message was misleading, as neither fetchAll() nor buffered queries
would help in this situation. Instead it is necessary to consume
all rowsets, which can be done by either unsetting the statement
or calling closeCursor().
2020-12-10 11:46:29 +01:00
Nikita Popov d63aedd173 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #76815
2020-12-10 11:24:19 +01:00
Nikita Popov e450621f5e Fixed bug #76815
When we receive an error while reading a result set, we should
assume that no more result sets are available. libmysqlclient
implements the same behavior.
2020-12-10 11:23:41 +01:00
Nikita Popov 9b678bc4d5 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #71145
2020-12-10 10:31:36 +01:00
Nikita Popov 4922049213 Fixed bug #71145
Consume any additional result sets when running INIT_COMMAND.
2020-12-10 10:28:10 +01:00
twosee 26c7b9402d EXTERN_C wrapping for GC buffer APIs
Closes GH-6502.
2020-12-10 17:15:19 +08:00
Nikita Popov c95680d4b7 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Backport fix for bug #70066
2020-12-10 10:05:38 +01:00
Nikita Popov f3d5877845 Backport fix for bug #70066
Given the number of duplicates this bug report had, it seems
worthwhile to fix this on PHP-7.4 as well.

Cherry-pick of 106e7e4bca.
2020-12-10 09:58:47 +01:00
Dmitry Stogov e9f9e9f863 Perform early guard type check for result of FETCH_CONSTANT 2020-12-09 22:24:03 +03:00
Nikita Popov 106e7e4bca Fixed bug #70066
If we fall back to emulated prepared statements, destroy S->stmt,
so the code doesn't get confused about which mode we're in.
2020-12-09 17:24:30 +01:00
Nikita Popov fcfa7fd06b Fixed bug #66878
Keep track of whether we have fully consumed all result sets,
either using nextRowset() calls or closeCursor() and skip the
attempt to consume remaining results sets during destruction in
that case.

Especiall if closeCursor() has been used, we really shouldn't
have this sort of cross-statement inference.
2020-12-09 16:38:22 +01:00
Nikita Popov ef342b0730 Remove unnecessary more_results() checks
Just calling next_result() is sufficient.
2020-12-09 16:16:17 +01:00
Nikita Popov a073b0218c Add ifdef for mysqlnd only function 2020-12-09 16:16:17 +01:00
Nikita Popov b9ea8d6b96 PDO MySQL: Extract common code for handling PS results 2020-12-09 15:28:16 +01:00
Nikita Popov fb69c7752d PDO MySQL: Use set_row_count() helper 2020-12-09 15:21:12 +01:00
Dmitry Stogov 8d268e8443 Fixed IS_32BIT/IS_SIGNED_32BIT mess 2020-12-09 17:16:54 +03:00
Nikita Popov 186b766368 PDO MySQL: Make sure nextRowset() works with partially consumed result
This was already working in all cases apart from native prepared
statements with unbuffered queries. In that case invoking
stmt_free_result() addresses the issue.
2020-12-09 14:46:49 +01:00
Nikita Popov 23193e89e4 PDO MySQL: Handle error during closeCursor() 2020-12-09 14:04:30 +01:00
Nikita Popov 71b5f1446e Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #78154
2020-12-09 12:47:34 +01:00
Nikita Popov 44b234a9bc Fixed bug #78154
Handle errors during next_result in exec.
2020-12-09 12:46:47 +01:00
Nikita Popov 18517e7a63 Fix stmt_free_result implementation and usage
Two bugs both affecting the bug_pecl_7976.phpt test ("works with
mysqlnd" haha):

 * We should not change the connection state in stmt_free_result.
   This makes mysql_stmt_free_result usable under mysqlnd and
   not just libmysqlclient.
 * If we call mysql_stmt_free_result, we still need to consume
   any outstanding result sets.
2020-12-09 11:13:48 +01:00
Nikita Popov 9c0712d2cd Make XFAILED test less broken
At least allow it to print some output rather than throw right
away...
2020-12-09 10:42:44 +01:00
Nikita Popov 311a77d08e Handle changing column count in mysqlnd result binding
If the count changes from prepare to execute and result_bind is
alreadly allocated, reallocate it there.

This is something of a hack. It would be cleaner to require that
result bindings are registered only after execute, when the final
result set fields are known. But mysqli at least directly exposes
this to the user, so we have no guarantee.
2020-12-09 10:30:23 +01:00
Nikita Popov 2df09b9b64 PDO MySQL: Normalize handling of empty stored procedure result set
MySQL always returns a trailing empty result set for stored
procedure calls, which is used to convey status information.
The PDO MySQL implementation is presently confused about what to
do with it: If mysqlnd is used and native prepared statements are
used, this result set is skipped. In all other cases it is not
skipped. We also have quite a few XFAILed tests relating to this.

This patch normalizes (for PHP-8.0 only) the behavior towards
always retaining the empty result set. This is simply how MySQL
stored procedures work (some expletives omitted here) and we can't
distinguish this "useless" result set from an empty result of a
multi query. Multi queries are not a concern for native prepared
statements, as PDO does not allow them in that case, but they are
a concern for emulated prepared statements.

Closes GH-6497.
2020-12-08 17:01:56 +01:00
Nikita Popov bfa69d27bc Handle column count change in PDO MySQL
This has been fixed for PDO SQlite by GH-4313, however the same
issue also applied to PDO MySQL.

Move the column count setting function into the main PDO layer
(and export it) and then use it in both PDO SQLite and PDO MySQL.
2020-12-08 16:41:35 +01:00
Nikita Popov 713ef8511b Enable XFAILed test
This one had a rather scary XFAIL message, but seems to work just
fine...
2020-12-08 16:03:50 +01:00
Christoph M. Becker fb4bc0f9e5 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #48725: Support for flushing in zlib stream
2020-12-08 12:24:49 +01:00
Christoph M. Becker 20e75329f2 Fix #48725: Support for flushing in zlib stream
When `php_zlib_deflate_filter()` is called with `PSFS_FLAG_FLUSH_INC`
but without new buckets being available (e.g. because a user calls
`rewind()` after writing to the stream), we have to make sure that any
pending data are flushed.  This could basically be done like in the
attached patch[1], but that could cause unnessary flushes, which can be
harmful for compression, and adds unnecessary flush markers to the
stream.  Thus, we use the `php_zlib_filter_data.finished` field, which
has not been used for `zlib.deflate` filters, and properly keep track
of the need to flush.

[1] <https://bugs.php.net/patch-display.php?bug_id=48725&patch=zlib-filter-flush-fix.patch&revision=latest>

Closes GH-6019.
2020-12-08 12:23:24 +01:00
Christoph M. Becker d6ae0f010e Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #77069: stream filter loses final block of data
2020-12-08 11:49:28 +01:00
Christoph M. Becker 65f5573bc8 Fix #77069: stream filter loses final block of data
Reading from a stream may return greater than zero, but nonetheless the
stream's EOF flag may have been set.  We have to cater to this
condition by setting the close flag for filters.

We also have to cater to that change in the zlib.inflate filter:

If `inflate()` is called with flush mode `Z_FINISH`, but the output
buffer is not large enough to inflate all available data, it fails with
`Z_BUF_ERROR`.  However, `Z_BUF_ERROR` is not fatal; in fact, the zlib
manual states: "If deflate returns with Z_OK or Z_BUF_ERROR, this
function must be called again with Z_FINISH and more output space
(updated avail_out) but no more input data, until it returns with
Z_STREAM_END or an error."  Hence, we do so.

Closes GH-6001.
2020-12-08 11:47:49 +01:00
Christoph M. Becker c3734f9ae1 ldap_exop_whoami() does not return TRUE
Closes GH-6496.
2020-12-08 11:44:04 +01:00
Nikita Popov bd72e4aa44 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #63185
2020-12-08 11:35:57 +01:00
Nikita Popov bd093ad861 Fixed bug #63185 2020-12-08 11:30:54 +01:00
Dmitry Stogov db34491a62 Avoid unnecessary checks 2020-12-08 13:10:35 +03:00
Nikita Popov 2d467abc46 Fix another typed resource issue in unserialization
We also need to discard old entries in the ref_props HT when values
are overwritten.

We should really forbid these kinds of overwrites. I believe they
can only occur in manually crafted serialization strings, and
cause so many problems...

Fixes oss-fuzz #28257.
2020-12-07 12:36:09 +01:00
Dmitry Stogov 7971602574 Fixed bug #80480 (Segmentation fault with JIT enabled) 2020-12-07 13:28:37 +03:00
Nikita Popov 9dc42b4114 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #80458
2020-12-04 17:00:51 +01:00
Dharman a83cc03c13 Fixed bug #80458
If there is no result set (e.g. for upsert queries), still allow
fetching to occur without error, i.e. treat it the same way as
an empty result set.

This normalizes behavior between native and emulated prepared
statements and addresses a regression in PHP 7.4.13.
2020-12-04 16:59:47 +01:00
Christoph M. Becker b52db133df Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #75102: `PharData` says invalid checksum for valid tar
2020-12-04 13:04:33 +01:00
Christoph M. Becker 8588ae7215 Fix #75102: PharData says invalid checksum for valid tar
Apparently, there are broken tarballs out there which are actually in
ustar format, but did not write the `ustar` marker.  Since popular tar
tools like GNU tar and 7zip have no issues dealing with such tarballs,
Phar should also be more resilient.

Thus, when the first checksum check of a tarball in (presumed) in old-
style format fails, we check whether the checksum would be suitable for
ustar format; if so, we treat the tarball as being in ustar format.

Closes GH-6479.
2020-12-04 13:02:29 +01:00
Nikita Popov 77325c4448 Fix removal of type source during unserialization
Missed a check for info in this code. Add it, and add an assertion
in type source removal to make it easier to catch this issue.

Fixes oss-fuzz #28208 and #28257.
2020-12-04 12:56:05 +01:00
George Peter Banyard 426fe2f20c Standardize behaviour for int message number between functions 2020-12-03 17:43:08 +00:00
George Peter Banyard e45cc31c41 Add tests for passing a UID instead of a message number 2020-12-03 16:38:22 +00:00
Nikita Popov 724ee93ce6 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Upload coverage data to codecov.io
2020-12-03 12:05:14 +01:00
Paul Crovella 8f8e6f95af Upload coverage data to codecov.io
Closes GH-6486.
2020-12-03 12:04:50 +01:00
Nikita Popov 1a1eeee716 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix mysqli_expire_password test for mariadb
2020-12-03 11:02:11 +01:00
Nikita Popov 0f6c41c6f8 Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  Fix mysqli_expire_password test for mariadb
2020-12-03 11:01:57 +01:00
Daniel Black 0697a64f7e Fix mysqli_expire_password test for mariadb
In MariaDB-10.4.3 EXPIRE passwords where supported for
MariaDB. This only behaves like MySQL when the system
variable disconnect_on_expired_passwords=1.

MariaDB if there was no password it could not be considered
expired. So the test is adjusted to use actual passwords.
(MariaDB commit a94b20a8e0d9e64eeaabdaaa7a3e03fcdb8a686e)

The error codes produced my MariaDB are different
however still conforming to the SQL specification.

Closes GH-6480.
2020-12-03 10:56:00 +01:00
Nikita Popov 98cccd304a Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  fix mysqli_stmt_get_result_metadata_fetch_field test for mariadb
2020-12-03 10:45:27 +01:00
Daniel Black 5d5c1cea5f fix mysqli_stmt_get_result_metadata_fetch_field test for mariadb
MariaDB extended the default decimal field to 39 characters
instead of MySQL's 31 characters.

This small change allows the test to pass on MySQL and MariaDB.

Closes GH-6484.
2020-12-03 10:45:11 +01:00
Dharman 261faa62da Remove PHP 5 mysqli tests
These tests all require functions that no longer exist.
2020-12-03 10:42:46 +01:00
Dharman 53f7bddbeb Fix typos in mysql tests
%d because of line endings on Windows
2020-12-03 10:42:39 +01:00
Nikita Popov 8d2a1c8966 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Backport fix for bug #78750
2020-12-03 10:22:21 +01:00
Peter Kokot d386ed1e6b Backport fix for bug #78750
Cherry-picks
fe2afef36f
and
86e2b7bb70.
2020-12-03 10:07:09 +01:00
Christian Schneider 7bc7a80445 Make is_file() and friends return false when path contains 0-byte
These functions now return false silently:
is_writable, is_readable, is_executable, is_file, is_dir, is_link,
file_exists

These functions now throw a warning an return false (rather than
throwing a ValueError):
fileperms, fileinode, filesize, fileowner, filegroup, filetype,
fileatime, filemtime, filectime, lstat, stat

See also https://externals.io/message/112333.

Closes GH-6478.
2020-12-03 09:43:15 +01:00
Christoph M. Becker 72cd5793be Fix failing VirtualProtect() calls
Whenever JIT is disabled due to incompatibilities, we also need to set
`JIT_G(on)` to zero.

Closes GH-6470.
2020-12-02 16:51:50 +01:00
Nikita Popov 9dda22bd1e Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #80457
2020-12-02 11:29:41 +01:00
Nikita Popov f2833ca1be Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  Fixed bug #80457
2020-12-02 11:29:06 +01:00
Nikita Popov d6fcaf5da4 Fixed bug #80457
On x32 sizeof(size_t) != sizeof(zend_long), so we need to be
careful with sign extension here.

Patch by bruno dot premont at restena dot lu.
2020-12-02 11:26:10 +01:00
Nikita Popov a89aaf6c38 Don't throw from imagecreatefromstring() with too short string
If the string is too short, we should treat this the same way as
an unrecognized image type. This function should be usable to
determine whether something is a valid image without doing any
checks beforehand.
2020-12-02 10:51:55 +01:00
Nikita Popov 7a61984a2b Fixed bug #80462 2020-12-02 10:19:32 +01:00
George Peter Banyard 5aaffc8095 Backport IMAP test modernization to PHP-8.0 branch
Closes GH-6476
2020-12-01 16:38:08 +00:00
Christoph M. Becker 83cf4aa13a Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #73809: Phar Zip parse crash - mmap fail
2020-12-01 17:00:27 +01:00
Christoph M. Becker c283f53b24 Fix #73809: Phar Zip parse crash - mmap fail
Phar signatures practically are of limited size; for the MD5 and SHA
hashes the size is fixed (at most 64 bytes for SHA512); for OpenSSL
public keys there is no size limit in theory, but "64 KiB ought to be
good enough for anybody".  So we check for that limit, to avoid fatal
errors due to out of memory conditions.

Since it is neither possible to have the signature compressed in the
ZIP archive, nor is it possible to manually add a signature via Phar,
we use ZipArchive to create a suitable archive for the test on the fly.

Closes GH-6474.
2020-12-01 16:58:19 +01:00
Dmitry Stogov 44475e70e2 Fixed bug #80447 (Strange out of memory error when running with JIT) 2020-12-01 16:46:41 +03:00
Dmitry Stogov 1674c96c0b Bug #80447 (Strange out of memory error when running with JIT) 2020-12-01 16:43:05 +03:00
Dmitry Stogov 8ad2b59e12 Disable stack reuse optimization for x86 PIC code. It may clobber local variable used for Global Offset Table. 2020-12-01 15:20:06 +03:00
Nikita Popov f06afc434a Don't use scope when validating Attribute
This is not safe to do at this point. Even if we made it safe,
we'd see inconsistencies due to a partially compiled class.

Fixes oss-fuzz #28129.
2020-12-01 11:49:27 +01:00
Nikita Popov 5dfec886d6 Fix use after free with file cache and arena allocated strings 2020-12-01 11:31:23 +01:00
Nikita Popov 648cda6c9f Don't mark cpu_supports functions as always inline
The use of no-sanitize may result in an inlining failure, which
will be promoted into a compile error by always-inline. Use a
normal inlining hint without enforcing it.
2020-12-01 10:22:36 +01:00
Dmitry Stogov 4959c60524 Fixed incorrect "skipif.inc" include 2020-12-01 11:34:09 +03:00
Dmitry Stogov 31eafedf2e Skip test if JIT is not available 2020-12-01 09:58:33 +03:00
Christoph M. Becker f1d11c118d Fix #62004: SplFileObject: fgets after seek returns wrong line
As it is, `::seek(0)` sets the file pointer to the beginning of the
file, but `::seek($n)` where `$n > 0` sets the file pointer to the
beginning of the following line, having line `$n` already read into the
line buffer.  This is pretty inconsistent; we fix it by always seeking
to the beginning of the line.

We also add a test case for the duplicate bug #46569.

Closes GH-6434.
2020-11-30 16:03:37 +01:00
Dmitry Stogov 841b00f641 Preallocate stack space for JIT in execute_ex() to eliminate JIT prologue/epilogue. 2020-11-30 17:56:08 +03:00
Dmitry Stogov 5f36d0497f Fixed "may be used uninitialized" compilation warnings 2020-11-30 17:46:43 +03:00
Christoph M. Becker 57463cf78b Drop all JIT related XFAILS from phpdbg test suite
phpdbg now disables JIT, so these cause XFAIL warnings.
2020-11-30 15:24:15 +01:00
Nikita Popov 32cd5a1bc8 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Next attempt to fix bug #80368
2020-11-30 15:17:27 +01:00
Nikita Popov ecee3f1209 Next attempt to fix bug #80368
Apparently treating LibreSSL as OpenSSL 1.1 is not just something
we did in our code, it's something that upstream LibreSSL claims,
despite not actually being compatible. Duh.

Check for EVP_CIPH_OCB_MODE instead, which should reliably
determine support...
2020-11-30 15:15:59 +01:00
George Peter Banyard 0076b47326 Fix Bug #80438: imap_msgno() incorrectly warns and return false on valid UIDs in PHP 8.0.0
Checking for a valid Unique ID (UID) cannot use the convenience macro as they might
be larger than the message number which has for maximum value the total number of
current messages available in the mailbox.
2020-11-30 14:08:31 +00:00
George Peter Banyard a55402d07c Rename XmlParser to XMLParser for consistency with XMLWriter/XMLReader 2020-11-30 14:08:31 +00:00
Nikita Popov 24a19cc232 Suppress stream errors in mysqlnd
mysqlnd currently sets error_reporting=0 to suppress errors while
writing to streams. Unfortunately these errors are still visible
to userland error handlers, which is a source of confusion.
See for example https://bugs.php.net/bug.php?id=80412.

Instead add a stream flag that suppresses the emission of
read/write errors in the first place, and set it in mysqlnd.

I think it might be useful to have this option for userland as
well in the future, but for now this is just an internal
mechanism.

Closes GH-6458.
2020-11-30 15:06:28 +01:00
Dmitry Stogov a0baa09b99 Hide phpdbg/JIT incompatibility macro (JIT is disabled for phpdbg) 2020-11-30 16:42:17 +03:00
Nikita Popov 4643c0aac5 Add additional entries to unserialize corpus
These are useful to seed typed property fuzzing.
2020-11-30 14:32:07 +01:00
Nikita Popov ed9532cff0 Fix another ref source management bug in unserialize
When we overwrite an existing property during unserialization,
we also have to drop the ref source from it.
2020-11-30 14:23:54 +01:00
Christoph M. Becker 666833b238 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #76813: Access violation near NULL on source operand
2020-11-30 12:33:13 +01:00
Christoph M. Becker 5e15c9c41f Fix #76813: Access violation near NULL on source operand
We avoid `YYCURSOR` becoming `NULL` by initializing `YYMARKER`, and add
a default rule for `<NORMAL>` where we catch unexpected input.

We also fix the only superficially related issue regarding empty input
followed by `T_SEPARATOR` and command, which caused another segfault.

Closes GH-6464.
2020-11-30 12:29:24 +01:00
Dmitry Stogov d5a82e2c4e Disable JIT with incompatible third-party extensions 2020-11-30 13:58:34 +03:00
Nikita Popov 15073d8e1d Fixed bug #80437
Only chmod if the file has been created.
2020-11-30 11:40:46 +01:00
Nikita Popov fdb05b92bf Only replace IN_ARRAY result type for JMPZ/JMPNZ
Replacing the result type in the general case is dangerous,
because not all opcodes support both VAR and TMP. One common case
is the in_array() result being passed to SEND_VAR, which would
have to be changed to SEND_VAL.

Rather than complicating this logic, reduce the scope to only
doing the type replacement for JMPZ and JMPNZ. The only reason
we're doing this in the first place is to enable the smart branch
optimization, so we can limit it to the relevant opcodes. Replacing
the result type may be marginally useful in other cases as well
(as it may avoid reference checks), but not worth the bother.
2020-11-30 11:18:21 +01:00
Nikita Popov e77ac88a44 Use ephemeral ports in mcast_ipv*_recv.phpt 2020-11-30 09:49:39 +01:00
Christoph M. Becker 44ccccdfb8 tidy::repairFile() and ::repairString() return string|false 2020-11-30 00:29:10 +01:00
Nikita Popov 5b3809e942 Respect strict_types during sccp function call evaluation
Similar to what we do with attributes, add a dummy call frame
on which we can set the strict_types flag.
2020-11-27 20:24:00 +01:00
Nikita Popov 0ce9b5f755 Don't check for throwing calls in sccp function evaluation
We only need to reject functions that could warn (or have runtime
dependent behavior). If a function can throw in some cases, just
let it and discard the result.
2020-11-27 17:49:51 +01:00
Nikita Popov a505fc627e Fix handling of sccp exceptions
We should clear the exception *before* we destroy the execute_data.
Add a variation of the test that indirects through another file,
and would crash otherwise.
2020-11-27 17:44:30 +01:00
Jakub Zelenka a87d620543 Merge branch 'PHP-7.4' into PHP-8.0 2020-11-27 16:35:16 +00:00
Jakub Zelenka b855907f54 Merge branch 'PHP-7.3' into PHP-7.4 2020-11-27 16:33:47 +00:00
Jakub Zelenka 685708160e Fix test for bug62890 to not depend on system cert store 2020-11-27 16:32:43 +00:00
Nikita Popov 08919578ca Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix build for non-x86
2020-11-27 17:04:50 +01:00
Nikita Popov 3430d856ac Fix build for non-x86 2020-11-27 17:04:17 +01:00
Nikita Popov e5aae35855 Handle exceptions during SCCP function evaluation
Easier to handle them than to ensure they can't happen in the
first place.
2020-11-27 17:00:12 +01:00
Nikita Popov 4f3cf983dc Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix AVX detection
2020-11-27 14:49:45 +01:00
Nikita Popov 4e30ab33d8 Fix AVX detection
Our CPU detection code currently only checks whether hardware
support for AVX exists. However, we also need to check for operating
system support for XSAVE, as well as whether XCR0 has the SSE and
AVX bits set.

If this is not the case, unset the AVX and AVX2 bits in the cpuinfo
structure.

Hopefully this resolves our issues with CPU support detection.

Closes GH-6460.
2020-11-27 14:49:31 +01:00
Nikita Popov 8b281e5b6b Only use travis for cron jobs
Our primary CI has been Azure Pipelines for a while now already.
Travis was primarily retained as a) a fast feedback builder and
b) to test architectures not available elsewhere.

Due to Travis CI open source policy changes, Travis is no longer
useful as a fast feedback builder. As such, only use it for cron
job builds.
2020-11-27 14:15:34 +01:00
Nikita Popov 8e25cf26af Make sure zend_cpu_supports_pclmul() is always defined
If __builtin_cpu_supports() is available, but doesn't have support
for pclmul, the function would end up not being defined at all.
2020-11-27 12:22:03 +01:00
Christoph M. Becker bcefbf8602 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix mysqli_get_client_stats test
2020-11-27 11:51:30 +01:00
Christoph M. Becker 07c5efbd76 Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  Fix mysqli_get_client_stats test
2020-11-27 11:50:59 +01:00
Daniel Black 4a10037cb4 Fix mysqli_get_client_stats test
MySQL removed RENAME DATABASE in 18300001c1dbbfddf9a0adcbaeea68956102bdd0
(Sept 2007, 5.1.23). As this briefest existance is very insignificant lets remove it.

It also breaks when testing against MariaDB.

As the alternate path in this test covers all supported MySQL and MariaDB
versions and a signifant portion of unsupported versions lets keep it simple.

Closes GH-6459.
2020-11-27 11:43:34 +01:00
Nikita Popov 2772f7c3ad Avoid direct calls to zend_cpu_supports()
While the use of zend_cpu_supports_*() is only strictly necessary
inside ifunc resolvers, where the cpu state has not been initialized
yet, we should prefer the compiler builtins in all cases.
2020-11-27 11:18:10 +01:00
Nikita Popov f35b194029 Assert that cpuinfo is initialized before use
And fix some incorrect indentation.
2020-11-27 11:14:07 +01:00
Nikita Popov 4a7ebb6d83 Move avx check into a macro 2020-11-27 11:06:05 +01:00
Nikita Popov f4e1768e21 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #80368
2020-11-27 10:58:34 +01:00
Nikita Popov 0f579fd7c8 Fixed bug #80368
We assume that usually LibreSSL supports everything OpenSSL 1.1 does.
In this instance, this is not the case.
2020-11-27 10:57:19 +01:00
Nikita Popov 48ff654fb9 Fixed bug #80433
Use ZEND_STRTOL to allow leading zeros in opcache.jit option.
2020-11-27 10:51:57 +01:00
Nikita Popov c61390cfb4 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #80425
2020-11-27 10:03:21 +01:00
Nikita Popov 5240f8391f Fixed bug #80425
Rename the methods in MessageFormatAdapter to make sure they don't
clash with anything defined by icu itself, which may be a problem
if icu is linked statically.
2020-11-27 10:02:00 +01:00
Christopher Jones a9c44d1b5a Update PECL package release date 2020-11-27 10:17:37 +11:00
Christoph M. Becker 49e1ed1941 Fix bug number 2020-11-26 23:34:35 +01:00
Dmitry Stogov 3697648be5 Eliminate deafd stores 2020-11-26 21:05:07 +03:00
Nikita Popov 6132389d1c Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix bug #80402: Don't strip -lpthread
2020-11-26 11:56:00 +01:00
Nikita Popov ea372e7463 Fix bug #80402: Don't strip -lpthread
The current behavior has been introduced 20 years ago in
f9e375f493 as part of a larger change.
It's not clear to me why special treatement of -lpthread is necessary
here.
2020-11-26 11:54:20 +01:00
Sara Golemon c65f0c7aca Remove -dev from ZEND_VERSION 2020-11-26 02:19:51 +00:00
Nikita Popov 306555e11d Add UPGRADING note for PDO::inTransaction()
[ci skip]
2020-11-25 17:28:23 +01:00
Nikita Popov 217f247bb5 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #80411
2020-11-25 17:24:49 +01:00
Nikita Popov 2fb12be84c Fixed bug #80411
References to null-serializations are stored as null, and as such
are part of the reference count.

Reminds me that we really need to deprecate the mess that is
Serializable.
2020-11-25 17:23:42 +01:00
Nikita Popov f5b93626a6 Fix unserialization ref source management, again
Handle one case the previous patch did not account for: If
unserialization of data fails, we should still register a ref
source.

Also add an extra test for a reference between two typed properties,
as this used to be handled incorrectly earlier.
2020-11-25 17:04:07 +01:00
Nikita Popov 518eb0ca2b Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed error reporting in mysqli_stmt::__construct
2020-11-25 16:29:00 +01:00
Dharman 233f507fe6 Fixed error reporting in mysqli_stmt::__construct
For the sake of simplicity, I've synchronized the implementation
with PHP 8, which means null values are also accepted.

Closes GH-6454.
2020-11-25 16:27:41 +01:00
Nikita Popov e3e6e1e59b Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Reindent more mysqli tests
2020-11-25 16:08:28 +01:00
Nikita Popov 367f8452c4 Fix phpt reindentation in tidy script
This was missing adjacent SKIPIF/FILE/CLEAN sections.
2020-11-25 16:07:56 +01:00
Nikita Popov e3e67b721f Reindent more mysqli tests
Due to a bug in the tidy script, most tests did not actually get
reindented...
2020-11-25 16:07:16 +01:00
Nikita Popov 308050e94b Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Reindent ext/mysqli tests
2020-11-25 15:58:21 +01:00
Nikita Popov 97d192b444 Reindent ext/mysqli tests
Reindent ext/mysqli tests on PHP-7.4, so they match with the
indentation on PHP-8.0. Otherwise merging test changes across
branches is very unpleasant.
2020-11-25 15:57:11 +01:00
Nikita Popov 373fd61a51 Allow running tidy.php on specific directory 2020-11-25 15:54:26 +01:00
Nikita Popov 7a3f25e370 Fix ref source management during unserialization
Only register the slot for adding ref sources later if we didn't
immediately register one. Also avoids leaking a ref source if
it is added early and the assignment fails.

Fixes oss-fuzz #27628.
2020-11-25 12:25:07 +01:00
Calvin Buckley e074e029ee sockets: Fix variable/macro name collision on AIX
The name "rem_size" is used by a macro in a system header on AIX,
specifically `sys/xmem.h`. Without changing the name, you get the
name mangled like so:

```
In file included from /usr/include/sys/uio.h:92:0,
                 from /QOpenSys/pkgs/lib/gcc/powerpc-ibm-aix6.1.0.0/6.3.0/include-fixed-7.1/sys/socket.h:83,
                 from /usr/include/sys/syslog.h:151,
                 from /usr/include/syslog.h:29,
                 from /home/calvin/rpmbuild/BUILD/php-8.0.0RC5/main/php_syslog.h:27,
                 from /home/calvin/rpmbuild/BUILD/php-8.0.0RC5/main/php.h:318,
                 from /home/calvin/rpmbuild/BUILD/php-8.0.0RC5/ext/sockets/sendrecvmsg.c:17:
/home/calvin/rpmbuild/BUILD/php-8.0.0RC5/ext/sockets/sendrecvmsg.c: In function 'zif_socket_cmsg_space':
/home/calvin/rpmbuild/BUILD/php-8.0.0RC5/ext/sockets/sendrecvmsg.c:298:10: error: expected '=', ',', ';', 'asm' or '__attribute__' before '.' token
   size_t rem_size = ZEND_LONG_MAX - entry->size;
          ^
/home/calvin/rpmbuild/BUILD/php-8.0.0RC5/ext/sockets/sendrecvmsg.c:298:10: error: expected expression before '.' token
/home/calvin/rpmbuild/BUILD/php-8.0.0RC5/ext/sockets/sendrecvmsg.c:299:18: error: 'u2' undeclared (first use in this function)
   size_t n_max = rem_size / entry->var_el_size;
                  ^
/home/calvin/rpmbuild/BUILD/php-8.0.0RC5/ext/sockets/sendrecvmsg.c:299:18: note: each undeclared identifier is reported only once for each function it appears in
```

...because of the declaration in `sys/xmem.h`:

```
```

This just renames the variable so that it won't trip on this
definition. Tested to fix the build on IBM i PASE.

Closes GH-6453.
2020-11-25 11:54:40 +01:00
Nikita Popov 4633e70ab1 Fixed bug #80377
Make sure the $PHP_THREAD_SAFETY variable is always available
when configuring extensions. It was previously available for
phpized extensions, but for in-tree builds it was being set
too late.

Then, use $PHP_THREAD_SAFETY instead of $enable_zts to check for
ZTS in bundled extensions, which makes sure these checks also
work for phpize builds.
2020-11-25 11:47:05 +01:00
Christopher Jones 37f96d990c Fix test diff 2020-11-25 16:42:12 +11:00
Dmitry Stogov cb399d0410 Use diferent temporary register (%r0 may keep a method address) 2020-11-25 03:49:42 +03:00
Dmitry Stogov 7fc2a3e15e Revert "Fixed bug #80377"
This reverts commit fc26ad9b12.
2020-11-25 01:10:26 +03:00
Florian Engelhardt cdd5ec7a3c [ci skip] Fix misspelled method names
Closes GH-6452.
2020-11-24 18:18:40 +01:00
Nikita Popov 70f59b3416 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix usage of casted string in ReflectionParameter ctor
2020-11-24 16:42:52 +01:00
Nikita Popov 706241f82d Fix usage of casted string in ReflectionParameter ctor
Fixes oss-fuzz #27755.
2020-11-24 16:42:16 +01:00
Nikita Popov fc26ad9b12 Fixed bug #80377
Use $PHP_THREAD_SAFETY instead of $enable_zts to check for ZTS.
This variable is also available for phpize builds, while enable_zts
is only present for in-tree builds.
2020-11-24 15:52:41 +01:00
Nikita Popov ae6e56fb98 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #80393
2020-11-24 15:27:43 +01:00
Nikita Popov d016434ad3 Fixed bug #80393
Handle macos versions that don't start with 10.* in libtool.

Patch by kir dot morozov at gmail dot com.
2020-11-24 15:26:40 +01:00
Christoph M. Becker bf244757ee Allow PHP_CURL_APIs to be imported by DLLs
Closes GH-6438.
2020-11-24 14:12:39 +01:00
Christoph M. Becker e589609b4c Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #77961: finfo_open crafted magic parsing SIGABRT
2020-11-24 14:06:53 +01:00
Christoph M. Becker 39f95f5614 Fix #77961: finfo_open crafted magic parsing SIGABRT
libmagic may abort the running process, which is not desirable for PHP;
we raise a fatal error instead.

Closes GH-6437.
2020-11-24 14:01:15 +01:00
Christoph M. Becker 337031abbd [ci skip] Update generate_patch.sh
This has apparently been forgotten when updating to libmagic 5.39.
2020-11-24 13:38:31 +01:00
Christoph M. Becker deb8b8190e Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #80366: Return Value of zend_fstat() not Checked
2020-11-24 13:10:35 +01:00
Christoph M. Becker 5f9c82d514 Fix #80366: Return Value of zend_fstat() not Checked
In the somewhat unlikely case that `zend_fstat()` fails, we must not
proceed executing the function, but return `false` instead.

Patch based on the patch contributed by sagpant at microsoft dot com.

Closes GH-6432.
2020-11-24 13:09:16 +01:00
Nikita Popov b91bf22333 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fixed bug #80362: Running dtrace scripts can cause php to crash
2020-11-24 13:02:08 +01:00
Nikita Popov fa713ec17b Fixed bug #80362: Running dtrace scripts can cause php to crash
Patch by al at coralnet dot name.
2020-11-24 13:01:51 +01:00
Nikita Popov 03f8bccaf5 Fixed bug #80404
For a division like [1..1]/[2..2] produce [0..1] as a result, which
would be the integer envelope of the floating-point result.

The implementation is pretty ugly (we're now taking min/max across
eight values...) but I couldn't come up with a more elegant way
to handle this that doesn't make things a lot more complex (the
division sign handling is the annoying issue here).
2020-11-24 11:35:44 +01:00
Nikita Popov 912cb8b8b5 Fixed bug #80391
Iterable was not considered a subtype of array|object, and thus
also not a subtype of mixed.
2020-11-24 10:09:28 +01:00
Benjamin Morel 4bbb98c24f Fix PDOStatement::fetchObject() stub
Closes GH-6449.
2020-11-24 09:49:30 +01:00
Christopher Jones 68d5878097 Sync README with package.xml 2020-11-24 10:45:48 +11:00
Christoph M. Becker 807775b641 Fix COMPersistHelper::__construct() stub
`$variant` is optional.
2020-11-24 00:23:29 +01:00
Remi Collet ce18899b44 zip extension is 1.19.2 2020-11-23 15:59:15 +01:00
Dmitry Stogov 337d2af6ca zend_jit_trace_stack_frame.stack can't be NULL 2020-11-23 16:19:22 +03:00
Dmitry Stogov 586ccfdfd5 Fixed use-after-free in PHPUnit tests 2020-11-23 14:42:38 +03:00
Dmitry Stogov 4cf3da7383 Keep value of register before possible side exit 2020-11-23 12:07:05 +03:00
Christoph M. Becker 9b1c02c2df Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #77594: ob_tidyhandler is never reset
2020-11-22 14:04:59 +01:00
Christoph M. Becker 221345a013 Fix #77594: ob_tidyhandler is never reset
We reset to original INI value on request shutdown.

Closes GH-6425.
2020-11-22 14:02:29 +01:00
Máté Kocsis 40ebfd6730 Remove some incorrect mixed parameter types 2020-11-21 23:17:35 +01:00
Nikita Popov 0dac69c059 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix typos in php.ini files
2020-11-20 16:50:52 +01:00
Benjamin Morel ed949a1973 Fix typos in php.ini files
Closes GH-6441.

[ci skip]
2020-11-20 16:50:29 +01:00
jrfnl 860f46e2f5 UPGRADING: (real) cast has been removed
.. but the removal wasn't mentioned in the `UPGRADING` docs yet.

Ref:
* https://github.com/php/php-src/pull/5220
* https://github.com/php/php-src/commit/c9db32271a8083721582c5ec1dd09c4d4f562c74

Closes GH-6440.

[ci-skip]
2020-11-20 16:48:32 +01:00
Nikita Popov fa67864c13 Use MIN/MAX when dumping RANGE[]
It's very common that one of the bounds is LONG_MIN or LONG_MAX.
Dump them as MIN/MAX instead of the int representation in that
case, as it makes the dump less noisy.
2020-11-20 16:47:46 +01:00
Dmitry Stogov c0d1dbcb43 Fixed incorrect TRACE_FRAME_MASK_NESTED flag setting 2020-11-20 18:22:21 +03:00
Dmitry Stogov c8df28d276 Fixed 32-bit JIT 2020-11-20 15:12:30 +03:00
Christoph M. Becker c7343510e4 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #72964: White space not unfolded for CC/Bcc headers
2020-11-19 19:26:56 +01:00
Christoph M. Becker 881e43a03c Fix #72964: White space not unfolded for CC/Bcc headers
`\r\n` does only terminate a header, if not followed by `\t` or ` `.
We have to cater to that when determining the end position of the
respective headers.

Closes GH-6420.
2020-11-19 19:25:03 +01:00
Christoph M. Becker 2e27bb8682 Merge branch 'PHP-7.4' into PHP-8.0
* PHP-7.4:
  Fix #80345: PHPIZE configuration has outdated PHP_RELEASE_VERSION
2020-11-19 16:26:45 +01:00
Christoph M. Becker c2b1182879 Fix #80345: PHPIZE configuration has outdated PHP_RELEASE_VERSION
We must not redefine the version "constants" for phpize builds, because
these have already generated in phpize.js, from where we pass these
variables forward to configure.js.

We also add `PHP_EXTRA_VERSION` and `PHP_VERSION_STRING` to the files
for completeness.

Closes GH-6419.
2020-11-19 16:23:20 +01:00
Sara Golemon 3c44e9c080 8.0 branch should be prepping for 8.0.1 2020-11-19 14:37:44 +00:00
498 changed files with 31763 additions and 24391 deletions

No files matched your search

+2 -1
View File
@@ -340,7 +340,8 @@ define ____print_ht
end
printf "[%d] ", $i
if $p->key
printf "%s => ", $p->key->val
____print_str $p->key->val $p->key->len
printf " => "
else
printf "%d => ", $p->h
end
+2
View File
@@ -70,8 +70,10 @@ jobs:
include:
- env: ENABLE_ZTS=0 ENABLE_DEBUG=0
arch: amd64
if: type = cron
- env: ENABLE_ZTS=1 ENABLE_DEBUG=1
arch: amd64
if: type = cron
- env: ENABLE_ZTS=1 ENABLE_DEBUG=1 SKIP_IO_CAPTURE_TESTS=1 ARM64=1
arch: arm64
if: type = cron
+174 -2
View File
@@ -1,5 +1,178 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
04 Feb 2021, PHP 8.0.2
- Core:
. Fixed bug #80523 (bogus parse error on >4GB source code). (Nikita)
. Fixed bug #80384 (filter buffers entire read until file closed). (Adam
Seitz, cmb)
. Fixed bug #80596 (Invalid union type TypeError in anonymous classes).
(Daniil Gentili)
. Fixed bug #80617 (GCC throws warning about type narrowing in
ZEND_TYPE_INIT_CODE). (Nikita)
- BCMath:
. Fixed bug #80545 (bcadd('a', 'a') doesn't throw an exception).
(Jens de Nies)
- Curl:
. Fixed bug #80595 (Resetting POSTFIELDS to empty array breaks request). (cmb)
- Date:
. Fixed bug #80376 (last day of the month causes runway cpu usage). (Derick)
- DOM:
. Fixed bug #80537 (Wrong parameter type in DOMElement::removeAttributeNode
stub). (Nikita)
- Filter:
. Fixed bug #80584 (0x and 0X are considered valid hex numbers by
filter_var()). (girgias)
- GMP:
. Fixed bug #80560 (Strings containing only a base prefix return 0 object).
(girgias)
- Intl:
. Fixed bug #80644 (Missing resource causes subsequent get() calls to fail).
(Nikita)
- MySQLi:
. Fixed bug #67983 (mysqlnd with MYSQLI_OPT_INT_AND_FLOAT_NATIVE fails to
interpret bit columns). (Nikita)
. Fixed bug #64638 (Fetching resultsets from stored procedure with cursor
fails). (Nikita)
. Fixed bug #72862 (segfault using prepared statements on stored procedures
that use a cursor). (Nikita)
. Fixed bug #77935 (Crash in mysqlnd_fetch_stmt_row_cursor when calling an SP
with a cursor). (Nikita)
- ODBC:
. Fixed bug #80592 (all floats are the same in ODBC parameters). (cmb)
- Opcache:
. Fixed bug #80422 (php_opcache.dll crashes when using Apache 2.4 with JIT).
(Dmitry)
- PDO_Firebird:
. Fixed bug #80521 (Parameters with underscores no longer recognized). (cmb,
Simonov Denis)
- Phar:
. Fixed bug #76929 (zip-based phar does not respect phar.require_hash).
(david at bamsoftware, cmb)
. Fixed bug #77565 (Incorrect locator detection in ZIP-based phars). (cmb)
. Fixed bug #69279 (Compressed ZIP Phar extractTo() creates garbage files).
(cmb)
- Phpdbg:
. Reverted fix for bug #76813 (Access violation near NULL on source operand).
(cmb)
- SOAP:
. Fixed bug #80672 (Null Dereference in SoapClient). (CVE-2021-21702) (cmb, Stas)
07 Jan 2021, PHP 8.0.1
- Core:
. Fixed bug #80345 (PHPIZE configuration has outdated PHP_RELEASE_VERSION).
(cmb)
. Fixed bug #72964 (White space not unfolded for CC/Bcc headers). (cmb)
. Fixed bug #80391 (Iterable not covariant to mixed). (Nikita)
. Fixed bug #80393 (Build of PHP extension fails due to configuration gap
with libtool). (kir dot morozov at gmail dot com)
. Fixed bug #77069 (stream filter loses final block of data). (cmb)
- Fileinfo:
. Fixed bug #77961 (finfo_open crafted magic parsing SIGABRT). (cmb)
- FPM:
. Fixed bug #69625 (FPM returns 200 status on request without
SCRIPT_FILENAME env). (Jakub Zelenka)
- IMAP
. Fixed bug #80438 (imap_msgno() incorrectly warns and return false on valid UIDs in PHP 8.0.0). (girgias)
. Fix a regression with valid UIDs in imap_savebody() (girgias)
. Make warnings for invalid message numbers/UIDs between functions consistent (girgias)
- Intl:
. Fixed bug #80425 (MessageFormatAdapter::getArgTypeList redefined). (Nikita)
- OCI8
. Create Windows DLLs for Oracle Client 19c. (cmb)
- Opcache:
. Fixed bug #80404 (Incorrect range inference result when division results
in float). (Nikita)
. Fixed bug #80377 (Opcache misses executor_globals). (Nikita)
. Fixed bug #80433 (Unable to disable the use of the AVX command when using
JIT). (Nikita)
. Fixed bug #80447 (Strange out of memory error when running with JIT).
(Dmitry)
. Fixed bug #80480 (Segmentation fault with JIT enabled). (Dmitry)
. Fixed bug #80506 (Immediate SIGSEGV upon ini_set("opcache.jit_debug", 1)).
(Dmitry)
- OpenSSL:
. Fixed bug #80368 (OpenSSL extension fails to build against LibreSSL due to
lack of OCB support). (Nikita)
- PDO MySQL:
. Fixed bug #80458 (PDOStatement::fetchAll() throws for upsert queries).
(Kamil Tekiela)
. Fixed bug #63185 (nextRowset() ignores MySQL errors with native prepared
statements). (Nikita)
. Fixed bug #78152 (PDO::exec() - Bad error handling with multiple commands).
(Nikita)
. Fixed bug #66878 (Multiple rowsets not returned unless PDO statement object
is unset()). (Nikita)
. Fixed bug #70066 (Unexpected "Cannot execute queries while other unbuffered
queries"). (Nikita)
. Fixed bug #71145 (Multiple statements in init command triggers unbuffered
query error). (Nikita)
. Fixed bug #76815 (PDOStatement cannot be GCed/closeCursor-ed when a
PROCEDURE resultset SIGNAL). (Nikita)
. Fixed bug #79872 (Can't execute query with pending result sets). (Nikita)
. Fixed bug #79131 (PDO does not throw an exception when parameter values are
missing). (Nikita)
. Fixed bug #72368 (PdoStatement->execute() fails but does not throw an
exception). (Nikita)
. Fixed bug #62889 (LOAD DATA INFILE broken). (Nikita)
. Fixed bug #67004 (Executing PDOStatement::fetch() more than once prevents
releasing resultset). (Nikita)
. Fixed bug #79132 (PDO re-uses parameter values from earlier calls to
execute()). (Nikita)
- Phar:
. Fixed bug #73809 (Phar Zip parse crash - mmap fail). (cmb)
. Fixed bug #75102 (`PharData` says invalid checksum for valid tar). (cmb)
. Fixed bug #77322 (PharData::addEmptyDir('/') Possible integer overflow).
(cmb)
- Phpdbg:
. Fixed bug #76813 (Access violation near NULL on source operand). (cmb)
- SPL:
. Fixed #62004 (SplFileObject: fgets after seek returns wrong line). (cmb)
- Standard:
. Fixed bug #77423 (FILTER_VALIDATE_URL accepts URLs with invalid userinfo).
(CVE-2020-7071) (cmb)
. Fixed bug #80366 (Return Value of zend_fstat() not Checked). (sagpant, cmb)
- Tidy:
. Fixed bug #77594 (ob_tidyhandler is never reset). (cmb)
- Tokenizer:
. Fixed bug #80462 (Nullsafe operator tokenize with TOKEN_PARSE flag fails).
(Nikita)
- XML:
. XmlParser opaque object renamed to XMLParser for consistency with other XML objects. (girgias)
- Zlib:
. Fixed #48725 (Support for flushing in zlib stream). (cmb)
26 Nov 2020, PHP 8.0.0
- BZ2:
@@ -83,7 +256,7 @@ PHP NEWS
. Fixed bug #80280 (ADD_EXTENSION_DEP() fails for ext/standard and ext/date).
(cmb)
. Fixed bug #80334 (assert() vs named parameters - confusing error). (Nikita)
. Fixed bug #8055 (Abstract trait methods returning "self" cannot be
. Fixed bug #80055 (Abstract trait methods returning "self" cannot be
fulfilled by traits). (Nikita)
. Fixed faulty generator cleanup with yield from. (Bob)
. Implement #[Attr] Attribute syntax as per final vote in RFC
@@ -373,4 +546,3 @@ PHP NEWS
. Fixed bug #71417 (fread() does not report zlib.inflate errors). (cmb)
. Fixed bug #78792 (zlib.output_compression disabled by Content-Type: image/).
(cmb)
+15 -6
View File
@@ -29,6 +29,7 @@ PHP 8.0 UPGRADE NOTES
. Removed ability to call non-static methods statically.
Thus `is_callable` will fail when checking for a non-static method with a
classname (must check with an object instance).
. Removed (real) cast.
. Removed (unset) cast.
. Removed track_errors ini directive. This means that $php_errormsg is no
longer available. The error_get_last() function may be used instead.
@@ -442,6 +443,12 @@ PHP 8.0 UPGRADE NOTES
string $statement, ?int $fetch_mode = null, ...$fetch_mode_args)
PDOStatement::setFetchMode(int $mode, ...$params)
- PDO MySQL:
. PDO::inTransaction() now reports the actual transaction state of the
connection, rather than an approximation maintained by PDO. If a query that
is subject to "implicit commit" is executed, PDO::inTransaction() will
subsequently return false, as a transaction is no longer active.
- PDO_ODBC:
. The php.ini directive pdo_odbc.db2_instance_name has been removed
@@ -509,6 +516,8 @@ PHP 8.0 UPGRADE NOTES
- SPL:
. SplFileObject::fgetss() has been removed.
. SplFileObject::seek() now always seeks to the beginning of the line.
Previously, positions >=1 sought to the beginning of the next line.
. SplHeap::compare($a, $b) now specifies a method signature. Inheriting
classes implementing this method will now have to use a compatible
method signature.
@@ -656,10 +665,10 @@ PHP 8.0 UPGRADE NOTES
RFC: https://wiki.php.net/rfc/namespaced_names_as_token
- XML:
. xml_parser_create(_ns) will now return an XmlParser object rather than a
. xml_parser_create(_ns) will now return an XMLParser object rather than a
resource. Return value checks using is_resource() should be replaced with
checks for `false`. The xml_parser_free() function no longer has an effect,
instead the XmlParser instance is automatically destroyed if it is no longer
instead the XMLParser instance is automatically destroyed if it is no longer
referenced.
- XMLReader:
@@ -879,8 +888,8 @@ PHP 8.0 UPGRADE NOTES
and this function is no longer needed to protect against XXE attacks.
- PGSQL / PDO PGSQL:
. The constant PG_VERSION_STR has now the same value as PG_VERSION, and thus
is deprecated.
. The constant PGSQL_LIBPQ_VERSION_STR has now the same value as
PGSQL_LIBPQ_VERSION, and thus is deprecated.
. Function aliases in the pgsql extension have been deprecated.
- Zip:
@@ -981,8 +990,8 @@ PHP 8.0 UPGRADE NOTES
- Zip:
. ZipArchive::setMtimeName and ZipArchive::setMtimeIndex to set the
modification time of an entry.
. ZipArchive::setProgressCallback to provide updates during archive close.
. ZipArchive::setCancelCallback to allow cancellation during archive close.
. ZipArchive::registerProgressCallback to provide updates during archive close.
. ZipArchive::registerCancelCallback to allow cancellation during archive close.
. ZipArchive::replaceFile to replace an entry content.
. ZipArchive::isCompressionMethodSupported to check optional compression
features.
-6
View File
@@ -190,12 +190,6 @@ dnl LIBZEND_OTHER_CHECKS
dnl
AC_DEFUN([LIBZEND_OTHER_CHECKS],[
AC_ARG_ENABLE([zts],
[AS_HELP_STRING([--enable-zts],
[Enable thread safety])],
[ZEND_ZTS=$enableval],
[ZEND_ZTS=no])
AC_MSG_CHECKING(whether to enable thread-safety)
AC_MSG_RESULT($ZEND_ZTS)
@@ -0,0 +1,9 @@
--TEST--
Validation for "Attribute" does not use a scope when evaluating constant ASTs
--FILE--
<?php
#[Attribute(parent::x)]
class x extends y {}
?>
--EXPECTF--
Fatal error: Cannot access "parent" when no class scope is active in %s on line %d
+23
View File
@@ -0,0 +1,23 @@
--TEST--
Iterable not covariant to mixed
--FILE--
<?php
class A {
public function method1(): mixed {}
public function method2(): array|object {}
public function method3(iterable $x) {}
public function method4(iterable $x) {}
}
class B extends A {
public function method1(): iterable {}
public function method2(): iterable {}
public function method3(mixed $x) {}
public function method4(array|object $x) {}
}
?>
===DONE===
--EXPECT--
===DONE===
+11
View File
@@ -0,0 +1,11 @@
--TEST--
Bug #80404: Incorrect range inference result when division results in float
--FILE--
<?php
$n = 63;
var_dump((int) ($n / 120 * 100));
?>
--EXPECT--
int(52)
@@ -0,0 +1,30 @@
--TEST--
Union with anonymous class type
--FILE--
<?php
$a = new class {
public function testParam(self|string $a)
{
}
public function test(): self|string
{
return new \stdClass;
}
};
try {
$a->testParam(null);
} catch (\Throwable $e) {
echo $e->getMessage()."\n";
}
try {
$a->test();
} catch (\Throwable $e) {
echo $e->getMessage()."\n";
}
?>
--EXPECTF--
class@anonymous(): Argument #1 ($a) must be of type class@anonymous|string, null given, called in %s on line %d
class@anonymous::test(): Return value must be of type class@anonymous|string, stdClass returned
@@ -0,0 +1,17 @@
--TEST--
Infinite recursion in unlinked_instanceof()
--FILE--
<?php
interface I {}
spl_autoload_register(function() {
class X {
function test(): I {}
}
class Y extends X {
function test(): C {}
}
});
class C extends Z implements C {}
?>
--EXPECTF--
Fatal error: Declaration of Y::test(): C must be compatible with X::test(): I in %s on line %d
+1 -1
View File
@@ -20,7 +20,7 @@
#ifndef ZEND_H
#define ZEND_H
#define ZEND_VERSION "4.0.0-dev"
#define ZEND_VERSION "4.0.2"
#define ZEND_ENGINE_3
+33 -3
View File
@@ -2455,10 +2455,40 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend
for (i = 0; i < num_args; i++) {
if (ZEND_TYPE_HAS_CLASS(new_arg_info[i].type)) {
ZEND_ASSERT(ZEND_TYPE_HAS_NAME(new_arg_info[i].type)
&& "Only simple classes are currently supported");
&& "Should be stored as simple name");
const char *class_name = ZEND_TYPE_LITERAL_NAME(new_arg_info[i].type);
ZEND_TYPE_SET_PTR(new_arg_info[i].type,
zend_string_init_interned(class_name, strlen(class_name), 1));
size_t num_types = 1;
const char *p = class_name;
while ((p = strchr(p, '|'))) {
num_types++;
p++;
}
if (num_types == 1) {
/* Simple class type */
ZEND_TYPE_SET_PTR(new_arg_info[i].type,
zend_string_init_interned(class_name, strlen(class_name), 1));
} else {
/* Union type */
zend_type_list *list = malloc(ZEND_TYPE_LIST_SIZE(num_types));
list->num_types = num_types;
ZEND_TYPE_SET_LIST(new_arg_info[i].type, list);
const char *start = class_name;
uint32_t j = 0;
while (true) {
const char *end = strchr(start, '|');
zend_string *str =
zend_string_init(start, end ? end - start : strlen(start), 1);
list->types[j] = (zend_type) ZEND_TYPE_INIT_CLASS(str, 0, 0);
if (!end) {
break;
}
start = end + 1;
j++;
}
}
}
}
}
+4 -1
View File
@@ -33,7 +33,10 @@ void validate_attribute(zend_attribute *attr, uint32_t target, zend_class_entry
if (attr->argc > 0) {
zval flags;
if (FAILURE == zend_get_attribute_value(&flags, attr, 0, scope)) {
/* As this is run in the middle of compilation, fetch the attribute value without
* specifying a scope. The class is not fully linked yet, and we may seen an
* inconsistent state. */
if (FAILURE == zend_get_attribute_value(&flags, attr, 0, NULL)) {
return;
}
+2 -2
View File
@@ -48,10 +48,10 @@ function get_mangled_object_vars(object $object): array {}
function get_class_methods(object|string $object_or_class): array {}
/** @param object|string $object_or_class */
function method_exists(mixed $object_or_class, string $method): bool {}
function method_exists($object_or_class, string $method): bool {}
/** @param object|string $object_or_class */
function property_exists(mixed $object_or_class, string $property): bool {}
function property_exists($object_or_class, string $property): bool {}
function class_exists(string $class, bool $autoload = true): bool {}
+3 -3
View File
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 9a77101b93e8584315bf43305830e129d359b033 */
* Stub hash: b09e9199a21595a3b6f6c02db81c8e22c36c277f */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_zend_version, 0, 0, IS_STRING, 0)
ZEND_END_ARG_INFO()
@@ -84,12 +84,12 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_get_class_methods, 0, 1, IS_ARRA
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_method_exists, 0, 2, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, object_or_class, IS_MIXED, 0)
ZEND_ARG_INFO(0, object_or_class)
ZEND_ARG_TYPE_INFO(0, method, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_property_exists, 0, 2, _IS_BOOL, 0)
ZEND_ARG_TYPE_INFO(0, object_or_class, IS_MIXED, 0)
ZEND_ARG_INFO(0, object_or_class)
ZEND_ARG_TYPE_INFO(0, property, IS_STRING, 0)
ZEND_END_ARG_INFO()
+16 -4
View File
@@ -422,6 +422,9 @@ void init_compiler(void) /* {{{ */
void shutdown_compiler(void) /* {{{ */
{
/* Reset filename before destroying the arena, as file cache may use arena allocated strings. */
zend_restore_compiled_filename(NULL);
zend_stack_destroy(&CG(loop_var_stack));
zend_stack_destroy(&CG(delayed_oplines_stack));
zend_stack_destroy(&CG(short_circuiting_opnums));
@@ -437,7 +440,6 @@ void shutdown_compiler(void) /* {{{ */
FREE_HASHTABLE(CG(delayed_autoloads));
CG(delayed_autoloads) = NULL;
}
zend_restore_compiled_filename(NULL);
}
/* }}} */
@@ -1165,7 +1167,15 @@ static zend_string *resolve_class_name(zend_string *name, zend_class_entry *scop
name = scope->parent->name;
}
}
return name;
/* The resolved name for anonymous classes contains null bytes. Cut off everything after the
* null byte here, to avoid larger parts of the type being omitted by printing code later. */
size_t len = strlen(ZSTR_VAL(name));
if (len != ZSTR_LEN(name)) {
ZEND_ASSERT(scope && "This should only happen with resolved types");
return zend_string_init(ZSTR_VAL(name), len, 0);
}
return zend_string_copy(name);
}
zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scope) {
@@ -1177,11 +1187,13 @@ zend_string *zend_type_to_string_resolved(zend_type type, zend_class_entry *scop
if (ZEND_TYPE_HAS_CE(*list_type)) {
str = add_type_string(str, ZEND_TYPE_CE(*list_type)->name);
} else {
str = add_type_string(str, resolve_class_name(ZEND_TYPE_NAME(*list_type), scope));
zend_string *resolved = resolve_class_name(ZEND_TYPE_NAME(*list_type), scope);
str = add_type_string(str, resolved);
zend_string_release(resolved);
}
} ZEND_TYPE_LIST_FOREACH_END();
} else if (ZEND_TYPE_HAS_NAME(type)) {
str = zend_string_copy(resolve_class_name(ZEND_TYPE_NAME(type), scope));
str = resolve_class_name(ZEND_TYPE_NAME(type), scope);
} else if (ZEND_TYPE_HAS_CE(type)) {
str = zend_string_copy(ZEND_TYPE_CE(type)->name);
}
+44
View File
@@ -73,6 +73,44 @@ static void __zend_cpuid(uint32_t func, uint32_t subfunc, zend_cpu_info *cpuinfo
}
#endif
#if defined(__i386__) || defined(__x86_64__)
/* Function based on compiler-rt implementation. */
static unsigned get_xcr0_eax() {
# if defined(__GNUC__) || defined(__clang__)
// Check xgetbv; this uses a .byte sequence instead of the instruction
// directly because older assemblers do not include support for xgetbv and
// there is no easy way to conditionally compile based on the assembler used.
unsigned eax, edx;
__asm__(".byte 0x0f, 0x01, 0xd0" : "=a"(eax), "=d"(edx) : "c"(0));
return eax;
# elif defined(ZEND_WIN32) && defined(_XCR_XFEATURE_ENABLED_MASK)
return _xgetbv(_XCR_XFEATURE_ENABLED_MASK);
# else
return 0;
# endif
}
static zend_bool is_avx_supported() {
if (!(cpuinfo.ecx & ZEND_CPU_FEATURE_AVX)) {
/* No support for AVX */
return 0;
}
if (!(cpuinfo.ecx & ZEND_CPU_FEATURE_OSXSAVE)) {
/* The operating system does not support XSAVE. */
return 0;
}
if ((get_xcr0_eax() & 0x6) != 0x6) {
/* XCR0 SSE and AVX bits must be set. */
return 0;
}
return 1;
}
#else
static zend_bool is_avx_supported() {
return 0;
}
#endif
void zend_cpu_startup(void)
{
if (!cpuinfo.initialized) {
@@ -95,10 +133,16 @@ void zend_cpu_startup(void)
} else {
cpuinfo.ebx = 0;
}
if (!is_avx_supported()) {
cpuinfo.edx &= ~ZEND_CPU_FEATURE_AVX;
cpuinfo.ebx &= ~(ZEND_CPU_FEATURE_AVX2 & ~ZEND_CPU_EBX_MASK);
}
}
}
ZEND_API int zend_cpu_supports(zend_cpu_feature feature) {
ZEND_ASSERT(cpuinfo.initialized);
if (feature & ZEND_CPU_EDX_MASK) {
return (cpuinfo.edx & (feature & ~ZEND_CPU_EDX_MASK));
} else if (feature & ZEND_CPU_EBX_MASK) {
+28 -29
View File
@@ -120,7 +120,7 @@ ZEND_API int zend_cpu_supports(zend_cpu_feature feature);
* resolver functions should not depend on any external
* functions */
ZEND_NO_SANITIZE_ADDRESS
static zend_always_inline int zend_cpu_supports_sse2() {
static inline int zend_cpu_supports_sse2() {
#if PHP_HAVE_BUILTIN_CPU_INIT
__builtin_cpu_init();
#endif
@@ -128,7 +128,7 @@ static zend_always_inline int zend_cpu_supports_sse2() {
}
ZEND_NO_SANITIZE_ADDRESS
static zend_always_inline int zend_cpu_supports_sse3() {
static inline int zend_cpu_supports_sse3() {
#if PHP_HAVE_BUILTIN_CPU_INIT
__builtin_cpu_init();
#endif
@@ -136,7 +136,7 @@ static zend_always_inline int zend_cpu_supports_sse3() {
}
ZEND_NO_SANITIZE_ADDRESS
static zend_always_inline int zend_cpu_supports_ssse3() {
static inline int zend_cpu_supports_ssse3() {
#if PHP_HAVE_BUILTIN_CPU_INIT
__builtin_cpu_init();
#endif
@@ -144,7 +144,7 @@ static zend_always_inline int zend_cpu_supports_ssse3() {
}
ZEND_NO_SANITIZE_ADDRESS
static zend_always_inline int zend_cpu_supports_sse41() {
static inline int zend_cpu_supports_sse41() {
#if PHP_HAVE_BUILTIN_CPU_INIT
__builtin_cpu_init();
#endif
@@ -152,26 +152,15 @@ static zend_always_inline int zend_cpu_supports_sse41() {
}
ZEND_NO_SANITIZE_ADDRESS
static zend_always_inline int zend_cpu_supports_sse42() {
static inline int zend_cpu_supports_sse42() {
#if PHP_HAVE_BUILTIN_CPU_INIT
__builtin_cpu_init();
#endif
return __builtin_cpu_supports("sse4.2");
}
/* __builtin_cpu_supports has pclmul from gcc9 */
#if (!defined(__GNUC__) || (ZEND_GCC_VERSION >= 9000))
ZEND_NO_SANITIZE_ADDRESS
static zend_always_inline int zend_cpu_supports_pclmul() {
#if PHP_HAVE_BUILTIN_CPU_INIT
__builtin_cpu_init();
#endif
return __builtin_cpu_supports("pclmul");
}
#endif
ZEND_NO_SANITIZE_ADDRESS
static zend_always_inline int zend_cpu_supports_avx() {
static inline int zend_cpu_supports_avx() {
#if PHP_HAVE_BUILTIN_CPU_INIT
__builtin_cpu_init();
#endif
@@ -179,7 +168,7 @@ static zend_always_inline int zend_cpu_supports_avx() {
}
ZEND_NO_SANITIZE_ADDRESS
static zend_always_inline int zend_cpu_supports_avx2() {
static inline int zend_cpu_supports_avx2() {
#if PHP_HAVE_BUILTIN_CPU_INIT
__builtin_cpu_init();
#endif
@@ -187,38 +176,48 @@ static zend_always_inline int zend_cpu_supports_avx2() {
}
#else
static zend_always_inline int zend_cpu_supports_sse2() {
static inline int zend_cpu_supports_sse2() {
return zend_cpu_supports(ZEND_CPU_FEATURE_SSE2);
}
static zend_always_inline int zend_cpu_supports_sse3() {
static inline int zend_cpu_supports_sse3() {
return zend_cpu_supports(ZEND_CPU_FEATURE_SSE3);
}
static zend_always_inline int zend_cpu_supports_ssse3() {
static inline int zend_cpu_supports_ssse3() {
return zend_cpu_supports(ZEND_CPU_FEATURE_SSSE3);
}
static zend_always_inline int zend_cpu_supports_sse41() {
static inline int zend_cpu_supports_sse41() {
return zend_cpu_supports(ZEND_CPU_FEATURE_SSE41);
}
static zend_always_inline int zend_cpu_supports_sse42() {
static inline int zend_cpu_supports_sse42() {
return zend_cpu_supports(ZEND_CPU_FEATURE_SSE42);
}
static zend_always_inline int zend_cpu_supports_pclmul() {
return zend_cpu_supports(ZEND_CPU_FEATURE_PCLMULQDQ);
}
static zend_always_inline int zend_cpu_supports_avx() {
static inline int zend_cpu_supports_avx() {
return zend_cpu_supports(ZEND_CPU_FEATURE_AVX);
}
static zend_always_inline int zend_cpu_supports_avx2() {
static inline int zend_cpu_supports_avx2() {
return zend_cpu_supports(ZEND_CPU_FEATURE_AVX2);
}
#endif
/* __builtin_cpu_supports has pclmul from gcc9 */
#if PHP_HAVE_BUILTIN_CPU_SUPPORTS && (!defined(__GNUC__) || (ZEND_GCC_VERSION >= 9000))
ZEND_NO_SANITIZE_ADDRESS
static inline int zend_cpu_supports_pclmul() {
#if PHP_HAVE_BUILTIN_CPU_INIT
__builtin_cpu_init();
#endif
return __builtin_cpu_supports("pclmul");
}
#else
static inline int zend_cpu_supports_pclmul() {
return zend_cpu_supports(ZEND_CPU_FEATURE_PCLMULQDQ);
}
#endif
#endif
+41 -16
View File
@@ -763,6 +763,17 @@ static zend_bool zend_verify_weak_scalar_type_hint(uint32_t type_mask, zval *arg
}
#if ZEND_DEBUG
static bool can_convert_to_string(zval *zv) {
/* We don't call cast_object here, because this check must be side-effect free. As this
* is only used for a sanity check of arginfo/zpp consistency, it's okay if we accept
* more than actually allowed here. */
if (Z_TYPE_P(zv) == IS_OBJECT) {
return Z_OBJ_HT_P(zv)->cast_object != zend_std_cast_object_tostring
|| Z_OBJCE_P(zv)->__tostring;
}
return Z_TYPE_P(zv) <= IS_STRING;
}
/* Used to sanity-check internal arginfo types without performing any actual type conversions. */
static zend_bool zend_verify_weak_scalar_type_hint_no_sideeffect(uint32_t type_mask, zval *arg)
{
@@ -776,10 +787,7 @@ static zend_bool zend_verify_weak_scalar_type_hint_no_sideeffect(uint32_t type_m
if ((type_mask & MAY_BE_DOUBLE) && zend_parse_arg_double_weak(arg, &dval)) {
return 1;
}
/* We don't call cast_object here, because this check must be side-effect free. As this
* is only used for a sanity check of arginfo/zpp consistency, it's okay if we accept
* more than actually allowed here. */
if ((type_mask & MAY_BE_STRING) && (Z_TYPE_P(arg) < IS_STRING || Z_TYPE_P(arg) == IS_OBJECT)) {
if ((type_mask & MAY_BE_STRING) && can_convert_to_string(arg)) {
return 1;
}
if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL && zend_parse_arg_bool_weak(arg, &bval)) {
@@ -943,6 +951,13 @@ ZEND_API zend_bool zend_value_instanceof_static(zval *zv) {
return instanceof_function(Z_OBJCE_P(zv), called_scope);
}
/* The cache_slot may only be NULL in debug builds, where arginfo verification of
* internal functions is enabled. Avoid unnecessary checks in release builds. */
#if ZEND_DEBUG
# define HAVE_CACHE_SLOT (cache_slot != NULL)
#else
# define HAVE_CACHE_SLOT 1
#endif
static zend_always_inline zend_bool zend_check_type_slow(
zend_type type, zval *arg, zend_reference *ref, void **cache_slot, zend_class_entry *scope,
@@ -954,31 +969,39 @@ static zend_always_inline zend_bool zend_check_type_slow(
if (ZEND_TYPE_HAS_LIST(type)) {
zend_type *list_type;
ZEND_TYPE_LIST_FOREACH(ZEND_TYPE_LIST(type), list_type) {
if (*cache_slot) {
if (HAVE_CACHE_SLOT && *cache_slot) {
ce = *cache_slot;
} else {
ce = zend_fetch_class(ZEND_TYPE_NAME(*list_type),
(ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
if (!ce) {
cache_slot++;
if (HAVE_CACHE_SLOT) {
cache_slot++;
}
continue;
}
*cache_slot = ce;
if (HAVE_CACHE_SLOT) {
*cache_slot = ce;
}
}
if (instanceof_function(Z_OBJCE_P(arg), ce)) {
return 1;
}
cache_slot++;
if (HAVE_CACHE_SLOT) {
cache_slot++;
}
} ZEND_TYPE_LIST_FOREACH_END();
} else {
if (EXPECTED(*cache_slot)) {
if (EXPECTED(HAVE_CACHE_SLOT && *cache_slot)) {
ce = (zend_class_entry *) *cache_slot;
} else {
ce = zend_fetch_class(ZEND_TYPE_NAME(type), (ZEND_FETCH_CLASS_AUTO | ZEND_FETCH_CLASS_NO_AUTOLOAD));
if (UNEXPECTED(!ce)) {
goto builtin_types;
}
*cache_slot = (void *) ce;
if (HAVE_CACHE_SLOT) {
*cache_slot = (void *) ce;
}
}
if (instanceof_function(Z_OBJCE_P(arg), ce)) {
return 1;
@@ -1071,8 +1094,6 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ
for (i = 0; i < num_args; ++i) {
zend_arg_info *cur_arg_info;
void *dummy_cache_slot = NULL;
if (EXPECTED(i < fbc->common.num_args)) {
cur_arg_info = &fbc->common.arg_info[i];
} else if (UNEXPECTED(fbc->common.fn_flags & ZEND_ACC_VARIADIC)) {
@@ -1082,7 +1103,7 @@ static zend_never_inline ZEND_ATTRIBUTE_UNUSED bool zend_verify_internal_arg_typ
}
if (ZEND_TYPE_IS_SET(cur_arg_info->type)
&& UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, &dummy_cache_slot, fbc->common.scope, 0, /* is_internal */ 1))) {
&& UNEXPECTED(!zend_check_type(cur_arg_info->type, arg, /* cache_slot */ NULL, fbc->common.scope, 0, /* is_internal */ 1))) {
return 0;
}
arg++;
@@ -1207,8 +1228,6 @@ static ZEND_COLD void zend_verify_void_return_error(const zend_function *zf, con
static bool zend_verify_internal_return_type(zend_function *zf, zval *ret)
{
zend_internal_arg_info *ret_info = zf->internal_function.arg_info - 1;
void *dummy_cache_slot = NULL;
if (ZEND_TYPE_FULL_MASK(ret_info->type) & MAY_BE_VOID) {
if (UNEXPECTED(Z_TYPE_P(ret) != IS_NULL)) {
zend_verify_void_return_error(zf, zend_zval_type_name(ret), "");
@@ -1217,7 +1236,7 @@ static bool zend_verify_internal_return_type(zend_function *zf, zval *ret)
return 1;
}
if (UNEXPECTED(!zend_check_type(ret_info->type, ret, &dummy_cache_slot, NULL, 1, /* is_internal */ 1))) {
if (UNEXPECTED(!zend_check_type(ret_info->type, ret, /* cache_slot */ NULL, NULL, 1, /* is_internal */ 1))) {
zend_verify_internal_return_error(zf, ret);
return 0;
}
@@ -3262,6 +3281,7 @@ ZEND_API void ZEND_FASTCALL zend_ref_del_type_source(zend_property_info_source_l
zend_property_info_list *list = ZEND_PROPERTY_INFO_SOURCE_TO_LIST(source_list->list);
zend_property_info **ptr, **end;
ZEND_ASSERT(prop);
if (!ZEND_PROPERTY_INFO_SOURCE_IS_LIST(source_list->list)) {
ZEND_ASSERT(source_list->ptr == prop);
source_list->ptr = NULL;
@@ -4757,6 +4777,11 @@ static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame(uint
} \
} while (0)
#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE
/* This callback disables optimization of "vm_stack_data" variable in VM */
void (*zend_touch_vm_stack_data)(void *vm_stack_data) = NULL;
#endif
#include "zend_vm_execute.h"
ZEND_API zend_result zend_set_user_opcode_handler(zend_uchar opcode, user_opcode_handler_t handler)
+2 -2
View File
@@ -1382,7 +1382,7 @@ static void zend_set_timeout_ex(zend_long seconds, bool reset_signals) /* {{{ */
t_r.it_value.tv_sec = seconds;
t_r.it_value.tv_usec = t_r.it_interval.tv_sec = t_r.it_interval.tv_usec = 0;
# ifdef __CYGWIN__
# if defined(__CYGWIN__) || defined(__PASE__)
setitimer(ITIMER_REAL, &t_r, NULL);
}
signo = SIGALRM;
@@ -1444,7 +1444,7 @@ void zend_unset_timeout(void) /* {{{ */
no_timeout.it_value.tv_sec = no_timeout.it_value.tv_usec = no_timeout.it_interval.tv_sec = no_timeout.it_interval.tv_usec = 0;
# ifdef __CYGWIN__
# if defined(__CYGWIN__) || defined(__PASE__)
setitimer(ITIMER_REAL, &no_timeout, NULL);
# else
setitimer(ITIMER_PROF, &no_timeout, NULL);
+2 -2
View File
@@ -55,8 +55,6 @@ void gc_reset(void);
size_t zend_gc_globals_size(void);
#endif
END_EXTERN_C()
#define GC_REMOVE_FROM_BUFFER(p) do { \
zend_refcounted *_p = (zend_refcounted*)(p); \
if (GC_TYPE_INFO(_p) & GC_INFO_MASK) { \
@@ -122,4 +120,6 @@ static zend_always_inline void zend_get_gc_buffer_use(
*n = gc_buffer->cur - gc_buffer->start;
}
END_EXTERN_C()
#endif /* ZEND_GC_H */
+6 -1
View File
@@ -311,7 +311,8 @@ static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce
zend_class_entry *ce = zend_lookup_class_ex(
ce1->interface_names[i].name, ce1->interface_names[i].lc_name,
ZEND_FETCH_CLASS_ALLOW_UNLINKED | ZEND_FETCH_CLASS_NO_AUTOLOAD);
if (ce && unlinked_instanceof(ce, ce2)) {
/* Avoid recursing if class implements ifself. */
if (ce && ce != ce1 && unlinked_instanceof(ce, ce2)) {
return 1;
}
}
@@ -323,6 +324,10 @@ static zend_bool unlinked_instanceof(zend_class_entry *ce1, zend_class_entry *ce
static zend_bool zend_type_contains_traversable(zend_type type) {
zend_type *single_type;
if (ZEND_TYPE_FULL_MASK(type) & MAY_BE_OBJECT) {
return 1;
}
ZEND_TYPE_FOREACH(type, single_type) {
if (ZEND_TYPE_HAS_NAME(*single_type)
&& zend_string_equals_literal_ci(ZEND_TYPE_NAME(*single_type), "Traversable")) {
+4 -4
View File
@@ -177,7 +177,7 @@ static void yy_pop_state(void)
zend_stack_del_top(&SCNG(state_stack));
}
static void yy_scan_buffer(char *str, unsigned int len)
static void yy_scan_buffer(char *str, size_t len)
{
YYCURSOR = (YYCTYPE*)str;
YYLIMIT = YYCURSOR + len;
@@ -571,7 +571,7 @@ ZEND_API zend_result open_file_for_scanning(zend_file_handle *file_handle)
}
}
SCNG(yy_start) = (unsigned char *)buf;
yy_scan_buffer(buf, (unsigned int)size);
yy_scan_buffer(buf, size);
} else {
zend_error_noreturn(E_COMPILE_ERROR, "zend_stream_mmap() failed");
}
@@ -772,7 +772,7 @@ ZEND_API void zend_prepare_string_for_scanning(zval *str, const char *filename)
}
}
yy_scan_buffer(buf, (unsigned int)size);
yy_scan_buffer(buf, size);
new_compiled_filename = zend_string_init(filename, strlen(filename), 0);
zend_set_compiled_filename(new_compiled_filename);
@@ -1564,7 +1564,7 @@ NEWLINE ("\r"|"\n"|"\r\n")
<ST_IN_SCRIPTING>"?->" {
yy_push_state(ST_LOOKING_FOR_PROPERTY);
return T_NULLSAFE_OBJECT_OPERATOR;
RETURN_TOKEN(T_NULLSAFE_OBJECT_OPERATOR);
}
<ST_IN_SCRIPTING,ST_LOOKING_FOR_PROPERTY>{WHITESPACE}+ {
+2 -1
View File
@@ -62,7 +62,8 @@ ZEND_API zend_signal_globals_t zend_signal_globals;
static void zend_signal_handler(int signo, siginfo_t *siginfo, void *context);
static int zend_signal_register(int signo, void (*handler)(int, siginfo_t*, void*));
#ifdef __CYGWIN__
#if defined(__CYGWIN__) || defined(__PASE__)
/* Matches zend_excute_API.c; these platforms don't support ITIMER_PROF. */
#define TIMEOUT_SIG SIGALRM
#else
#define TIMEOUT_SIG SIGPROF
+13
View File
@@ -195,6 +195,19 @@ static zend_always_inline zend_string *zend_string_dup(zend_string *s, bool pers
}
}
static zend_always_inline zend_string *zend_string_separate(zend_string *s, bool persistent)
{
if (ZSTR_IS_INTERNED(s) || GC_REFCOUNT(s) > 1) {
if (!ZSTR_IS_INTERNED(s)) {
GC_DELREF(s);
}
return zend_string_init(ZSTR_VAL(s), ZSTR_LEN(s), persistent);
}
zend_string_forget_hash_val(s);
return s;
}
static zend_always_inline zend_string *zend_string_realloc(zend_string *s, size_t len, bool persistent)
{
zend_string *ret;
+1 -1
View File
@@ -150,7 +150,7 @@ typedef struct {
/* Type mask excluding the flags above. */
#define _ZEND_TYPE_MAY_BE_MASK ((1u << 20) - 1)
/* Must have same value as MAY_BE_NULL */
#define _ZEND_TYPE_NULLABLE_BIT 0x2
#define _ZEND_TYPE_NULLABLE_BIT 0x2u
#define ZEND_TYPE_IS_SET(t) \
(((t).type_mask & _ZEND_TYPE_MASK) != 0)
+26 -7
View File
@@ -50826,15 +50826,34 @@ ZEND_API void execute_ex(zend_execute_data *ex)
{
DCL_OPLINE
#if defined(ZEND_VM_IP_GLOBAL_REG) || defined(ZEND_VM_IP_GLOBAL_REG)
struct {
#ifdef ZEND_VM_IP_GLOBAL_REG
const zend_op *orig_opline = opline;
const zend_op *orig_opline;
#endif
#ifdef ZEND_VM_FP_GLOBAL_REG
zend_execute_data *orig_execute_data = execute_data;
zend_execute_data *orig_execute_data;
#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE
char hybrid_jit_red_zone[ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE];
#endif
#endif
} vm_stack_data;
#endif
#ifdef ZEND_VM_IP_GLOBAL_REG
vm_stack_data.orig_opline = opline;
#endif
#ifdef ZEND_VM_FP_GLOBAL_REG
vm_stack_data.orig_execute_data = execute_data;
execute_data = ex;
#else
zend_execute_data *execute_data = ex;
#endif
#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE
memset(vm_stack_data.hybrid_jit_red_zone, 0, ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE);
if (zend_touch_vm_stack_data) {
zend_touch_vm_stack_data(&vm_stack_data);
}
#endif
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID)
if (UNEXPECTED(execute_data == NULL)) {
@@ -58788,10 +58807,10 @@ zend_leave_helper_SPEC_LABEL:
HYBRID_BREAK();
HYBRID_CASE(HYBRID_HALT):
#ifdef ZEND_VM_FP_GLOBAL_REG
execute_data = orig_execute_data;
execute_data = vm_stack_data.orig_execute_data;
#endif
#ifdef ZEND_VM_IP_GLOBAL_REG
opline = orig_opline;
opline = vm_stack_data.orig_opline;
#endif
return;
HYBRID_DEFAULT:
@@ -58800,9 +58819,9 @@ zend_leave_helper_SPEC_LABEL:
HYBRID_BREAK(); /* Never reached */
#else
#ifdef ZEND_VM_FP_GLOBAL_REG
execute_data = orig_execute_data;
execute_data = vm_stack_data.orig_execute_data;
# ifdef ZEND_VM_IP_GLOBAL_REG
opline = orig_opline;
opline = vm_stack_data.orig_opline;
# endif
return;
#else
@@ -58811,7 +58830,7 @@ zend_leave_helper_SPEC_LABEL:
ZEND_VM_LOOP_INTERRUPT_CHECK();
} else {
# ifdef ZEND_VM_IP_GLOBAL_REG
opline = orig_opline;
opline = vm_stack_data.orig_opline;
# endif
return;
}
+32 -7
View File
@@ -1780,10 +1780,10 @@ function gen_executor_code($f, $spec, $kind, $prolog, &$switch_labels = array())
case ZEND_VM_KIND_HYBRID:
out($f,"\t\t\tHYBRID_CASE(HYBRID_HALT):\n");
out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
out($f,"\t\t\t\texecute_data = orig_execute_data;\n");
out($f,"\t\t\t\texecute_data = vm_stack_data.orig_execute_data;\n");
out($f,"#endif\n");
out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
out($f,"\t\t\t\topline = orig_opline;\n");
out($f,"\t\t\t\topline = vm_stack_data.orig_opline;\n");
out($f,"#endif\n");
out($f,"\t\t\t\treturn;\n");
out($f,"\t\t\tHYBRID_DEFAULT:\n");
@@ -2065,15 +2065,34 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
out($f,$m[1]."zend_execute_data *execute_data = ex;\n");
out($f,"#endif\n");
} else {
out($f,"#if defined(ZEND_VM_IP_GLOBAL_REG) || defined(ZEND_VM_IP_GLOBAL_REG)\n");
out($f,$m[1]."struct {\n");
out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
out($f,$m[1]."const zend_op *orig_opline = opline;\n");
out($f,$m[1]."\tconst zend_op *orig_opline;\n");
out($f,"#endif\n");
out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
out($f,$m[1]."zend_execute_data *orig_execute_data = execute_data;\n");
out($f,$m[1]."\tzend_execute_data *orig_execute_data;\n");
out($f,"#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE\n");
out($f,$m[1]."\tchar hybrid_jit_red_zone[ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE];\n");
out($f,"#endif\n");
out($f,"#endif\n");
out($f,$m[1]."} vm_stack_data;\n");
out($f,"#endif\n");
out($f,"#ifdef ZEND_VM_IP_GLOBAL_REG\n");
out($f,$m[1]."vm_stack_data.orig_opline = opline;\n");
out($f,"#endif\n");
out($f,"#ifdef ZEND_VM_FP_GLOBAL_REG\n");
out($f,$m[1]."vm_stack_data.orig_execute_data = execute_data;\n");
out($f,$m[1]."execute_data = ex;\n");
out($f,"#else\n");
out($f,$m[1]."zend_execute_data *execute_data = ex;\n");
out($f,"#endif\n");
out($f,"#ifdef ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE\n");
out($f,$m[1]."memset(vm_stack_data.hybrid_jit_red_zone, 0, ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE);\n");
out($f,$m[1]."if (zend_touch_vm_stack_data) {\n");
out($f,$m[1]."\tzend_touch_vm_stack_data(&vm_stack_data);\n");
out($f,$m[1]."}\n");
out($f,"#endif\n");
}
break;
case "INTERNAL_LABELS":
@@ -2159,9 +2178,9 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
}
out($f,
"#ifdef ZEND_VM_FP_GLOBAL_REG\n" .
$m[1]."execute_data = orig_execute_data;\n" .
$m[1]."execute_data = vm_stack_data.orig_execute_data;\n" .
"# ifdef ZEND_VM_IP_GLOBAL_REG\n" .
$m[1]."opline = orig_opline;\n" .
$m[1]."opline = vm_stack_data.orig_opline;\n" .
"# endif\n" .
$m[1]."return;\n" .
"#else\n" .
@@ -2170,7 +2189,7 @@ function gen_executor($f, $skl, $spec, $kind, $executor_name, $initializer_name)
$m[1]."\tZEND_VM_LOOP_INTERRUPT_CHECK();\n".
$m[1]."} else {\n" .
"# ifdef ZEND_VM_IP_GLOBAL_REG\n" .
$m[1]."\topline = orig_opline;\n" .
$m[1]."\topline = vm_stack_data.orig_opline;\n" .
"# endif\n".
$m[1]."\treturn;\n".
$m[1]."}\n".
@@ -2578,6 +2597,12 @@ function gen_vm($def, $skel) {
fputs($f, "#define ZEND_VM_KIND\t\t" . $GLOBALS["vm_kind_name"][ZEND_VM_KIND] . "\n");
}
fputs($f, "\n");
fputs($f, "#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) && !defined(__SANITIZE_ADDRESS__)\n");
fputs($f, "# if ((defined(i386) && !defined(__PIC__)) || defined(__x86_64__) || defined(_M_X64))\n");
fputs($f, "# define ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE 16\n");
fputs($f, "# endif\n");
fputs($f, "#endif\n");
fputs($f, "\n");
foreach($vm_op_flags as $name => $val) {
fprintf($f, "#define %-24s 0x%08x\n", $name, $val);
}
+6
View File
@@ -34,6 +34,12 @@
# define ZEND_VM_KIND ZEND_VM_KIND_CALL
#endif
#if (ZEND_VM_KIND == ZEND_VM_KIND_HYBRID) && !defined(__SANITIZE_ADDRESS__)
# if ((defined(i386) && !defined(__PIC__)) || defined(__x86_64__) || defined(_M_X64))
# define ZEND_VM_HYBRID_JIT_RED_ZONE_SIZE 16
# endif
#endif
#define ZEND_VM_OP_SPEC 0x00000001
#define ZEND_VM_OP_CONST 0x00000002
#define ZEND_VM_OP_TMPVAR 0x00000004
+4 -1
View File
@@ -32,10 +32,13 @@ jobs:
runTestsParameters: >-
${{ parameters.runTestsParameters }}
-d zend_extension=opcache.so
- script: bash <(curl -s https://codecov.io/bash)
displayName: 'Upload ${{ parameters.configurationName }} Test Coverage to Codecov.io'
condition: or(succeeded(), failed())
- script: |
make gcovr-xml
mv gcovr.xml coverage.xml
displayName: 'Generate ${{ parameters.configurationName }} Test Coverage'
displayName: 'Generate ${{ parameters.configurationName }} Test Coverage Cobertura XML Report'
condition: or(succeeded(), failed())
- task: PublishCodeCoverageResults@1
inputs:
+2 -2
View File
@@ -20,8 +20,8 @@ steps:
set -e
sudo groupadd -g 5000 vmail
sudo useradd -m -d /var/vmail -s /bin/false -u 5000 -g vmail vmail
sudo cp ext/imap/tests/dovecot.conf /etc/dovecot/dovecot.conf
sudo cp ext/imap/tests/dovecotpass /etc/dovecot/dovecotpass
sudo cp ext/imap/tests/setup/dovecot.conf /etc/dovecot/dovecot.conf
sudo cp ext/imap/tests/setup/dovecotpass /etc/dovecot/dovecotpass
sudo service dovecot restart
displayName: 'Configure IMAP'
+595 -72
View File
@@ -111,7 +111,7 @@ class SimpleType {
$this->isBuiltin = $isBuiltin;
}
public static function fromNode(Node $node) {
public static function fromNode(Node $node): SimpleType {
if ($node instanceof Node\Name) {
if ($node->toLowerString() === 'static') {
// PHP internally considers "static" a builtin type.
@@ -127,11 +127,48 @@ class SimpleType {
throw new Exception("Unexpected node type");
}
public function isNull() {
public static function fromPhpDoc(string $type): SimpleType
{
switch (strtolower($type)) {
case "void":
case "null":
case "false":
case "bool":
case "int":
case "float":
case "string":
case "array":
case "iterable":
case "object":
case "resource":
case "mixed":
case "self":
case "static":
return new SimpleType(strtolower($type), true);
}
if (strpos($type, "[]") !== false) {
return new SimpleType("array", true);
}
return new SimpleType($type, false);
}
public static function null(): SimpleType
{
return new SimpleType("null", true);
}
public static function void(): SimpleType
{
return new SimpleType("void", true);
}
public function isNull(): bool {
return $this->isBuiltin && $this->name === 'null';
}
public function toTypeCode() {
public function toTypeCode(): string {
assert($this->isBuiltin);
switch (strtolower($this->name)) {
case "bool":
@@ -209,19 +246,30 @@ class Type {
$this->types = $types;
}
public static function fromNode(Node $node) {
public static function fromNode(Node $node): Type {
if ($node instanceof Node\UnionType) {
return new Type(array_map(['SimpleType', 'fromNode'], $node->types));
}
if ($node instanceof Node\NullableType) {
return new Type([
SimpleType::fromNode($node->type),
new SimpleType('null', true),
SimpleType::null(),
]);
}
return new Type([SimpleType::fromNode($node)]);
}
public static function fromPhpDoc(string $phpDocType) {
$types = explode("|", $phpDocType);
$simpleTypes = [];
foreach ($types as $type) {
$simpleTypes[] = SimpleType::fromPhpDoc($type);
}
return new Type($simpleTypes);
}
public function isNullable(): bool {
foreach ($this->types as $type) {
if ($type->isNull()) {
@@ -245,20 +293,17 @@ class Type {
return null;
}
public function tryToRepresentableType(): ?RepresentableType {
$classType = null;
public function toArginfoType(): ?ArginfoType {
$classTypes = [];
$builtinTypes = [];
foreach ($this->types as $type) {
if ($type->isBuiltin) {
$builtinTypes[] = $type;
} else if ($classType === null) {
$classType = $type;
} else {
// We can only represent a single class type.
return null;
$classTypes[] = $type;
}
}
return new RepresentableType($classType, $builtinTypes);
return new ArginfoType($classTypes, $builtinTypes);
}
public static function equals(?Type $a, ?Type $b): bool {
@@ -278,20 +323,45 @@ class Type {
return true;
}
public function __toString() {
if ($this->types === null) {
return 'mixed';
}
return implode('|', array_map(
function ($type) { return $type->name; },
$this->types)
);
}
}
class RepresentableType {
/** @var ?SimpleType $classType */
public $classType;
/** @var SimpleType[] $builtinTypes */
public $builtinTypes;
class ArginfoType {
/** @var ClassType[] $classTypes */
public $classTypes;
public function __construct(?SimpleType $classType, array $builtinTypes) {
$this->classType = $classType;
/** @var SimpleType[] $builtinTypes */
private $builtinTypes;
public function __construct(array $classTypes, array $builtinTypes) {
$this->classTypes = $classTypes;
$this->builtinTypes = $builtinTypes;
}
public function hasClassType(): bool {
return !empty($this->classTypes);
}
public function toClassTypeString(): string {
return implode('|', array_map(function(SimpleType $type) {
return $type->toEscapedName();
}, $this->classTypes));
}
public function toTypeMask(): string {
if (empty($this->builtinTypes)) {
return '0';
}
return implode('|', array_map(function(SimpleType $type) {
return $type->toTypeMask();
}, $this->builtinTypes));
@@ -311,14 +381,17 @@ class ArgInfo {
public $isVariadic;
/** @var Type|null */
public $type;
/** @var Type|null */
public $phpDocType;
/** @var string|null */
public $defaultValue;
public function __construct(string $name, int $sendBy, bool $isVariadic, ?Type $type, ?string $defaultValue) {
public function __construct(string $name, int $sendBy, bool $isVariadic, ?Type $type, ?Type $phpDocType, ?string $defaultValue) {
$this->name = $name;
$this->sendBy = $sendBy;
$this->isVariadic = $isVariadic;
$this->type = $type;
$this->phpDocType = $phpDocType;
$this->defaultValue = $defaultValue;
}
@@ -342,22 +415,52 @@ class ArgInfo {
throw new Exception("Invalid sendBy value");
}
public function hasDefaultValue(): bool {
public function getMethodSynopsisType(): Type {
if ($this->type) {
return $this->type;
}
if ($this->phpDocType) {
return $this->phpDocType;
}
throw new Exception("A parameter must have a type");
}
public function hasProperDefaultValue(): bool {
return $this->defaultValue !== null && $this->defaultValue !== "UNKNOWN";
}
public function getDefaultValueString(): string {
if ($this->hasDefaultValue()) {
public function getDefaultValueAsArginfoString(): string {
if ($this->hasProperDefaultValue()) {
return '"' . addslashes($this->defaultValue) . '"';
}
return "NULL";
}
public function getDefaultValueAsMethodSynopsisString(): ?string {
if ($this->defaultValue === null) {
return null;
}
switch ($this->defaultValue) {
case 'UNKNOWN':
return null;
case 'false':
case 'true':
case 'null':
return "&{$this->defaultValue};";
}
return $this->defaultValue;
}
}
interface FunctionOrMethodName {
public function getDeclaration(): string;
public function getArgInfoName(): string;
public function getMethodSynopsisFilename(): string;
public function __toString(): string;
public function isMethod(): bool;
public function isConstructor(): bool;
@@ -399,6 +502,10 @@ class FunctionName implements FunctionOrMethodName {
return "arginfo_$underscoreName";
}
public function getMethodSynopsisFilename(): string {
return implode('_', $this->name->parts);
}
public function __toString(): string {
return $this->name->toString();
}
@@ -439,6 +546,10 @@ class MethodName implements FunctionOrMethodName {
return "arginfo_class_{$this->getDeclarationClassName()}_{$this->methodName}";
}
public function getMethodSynopsisFilename(): string {
return $this->getDeclarationClassName() . "_{$this->methodName}";
}
public function __toString(): string {
return "$this->className::$this->methodName";
}
@@ -461,16 +572,23 @@ class ReturnInfo {
public $byRef;
/** @var Type|null */
public $type;
/** @var Type|null */
public $phpDocType;
public function __construct(bool $byRef, ?Type $type) {
public function __construct(bool $byRef, ?Type $type, ?Type $phpDocType) {
$this->byRef = $byRef;
$this->type = $type;
$this->phpDocType = $phpDocType;
}
public function equals(ReturnInfo $other): bool {
return $this->byRef === $other->byRef
&& Type::equals($this->type, $other->type);
}
public function getMethodSynopsisType(): ?Type {
return $this->type ?? $this->phpDocType;
}
}
class FuncInfo {
@@ -538,6 +656,47 @@ class FuncInfo {
return !($this->flags & Class_::MODIFIER_STATIC) && $this->isMethod() && !$this->name->isConstructor();
}
/** @return string[] */
public function getModifierNames(): array
{
if (!$this->isMethod()) {
return [];
}
$result = [];
if ($this->flags & Class_::MODIFIER_FINAL) {
$result[] = "final";
} elseif ($this->flags & Class_::MODIFIER_ABSTRACT && $this->classFlags & ~Class_::MODIFIER_ABSTRACT) {
$result[] = "abstract";
}
if ($this->flags & Class_::MODIFIER_PROTECTED) {
$result[] = "protected";
} elseif ($this->flags & Class_::MODIFIER_PRIVATE) {
$result[] = "private";
} else {
$result[] = "public";
}
if ($this->flags & Class_::MODIFIER_STATIC) {
$result[] = "static";
}
return $result;
}
public function hasParamWithUnknownDefaultValue(): bool
{
foreach ($this->args as $arg) {
if ($arg->defaultValue && !$arg->hasProperDefaultValue()) {
return true;
}
}
return false;
}
public function equalsApartFromName(FuncInfo $other): bool {
if (count($this->args) !== count($other->args)) {
return false;
@@ -583,13 +742,13 @@ class FuncInfo {
return sprintf(
"\tZEND_MALIAS(%s, %s, %s, %s, %s)\n",
$this->alias->getDeclarationClassName(), $this->name->methodName,
$this->alias->methodName, $this->getArgInfoName(), $this->getFlagsAsString()
$this->alias->methodName, $this->getArgInfoName(), $this->getFlagsAsArginfoString()
);
} else if ($this->alias instanceof FunctionName) {
return sprintf(
"\tZEND_ME_MAPPING(%s, %s, %s, %s)\n",
$this->name->methodName, $this->alias->getNonNamespacedName(),
$this->getArgInfoName(), $this->getFlagsAsString()
$this->getArgInfoName(), $this->getFlagsAsArginfoString()
);
} else {
throw new Error("Cannot happen");
@@ -600,14 +759,14 @@ class FuncInfo {
return sprintf(
"\tZEND_ABSTRACT_ME_WITH_FLAGS(%s, %s, %s, %s)\n",
$declarationClassName, $this->name->methodName, $this->getArgInfoName(),
$this->getFlagsAsString()
$this->getFlagsAsArginfoString()
);
}
return sprintf(
"\tZEND_ME(%s, %s, %s, %s)\n",
$declarationClassName, $this->name->methodName, $this->getArgInfoName(),
$this->getFlagsAsString()
$this->getFlagsAsArginfoString()
);
}
} else if ($this->name instanceof FunctionName) {
@@ -645,7 +804,7 @@ class FuncInfo {
}
}
private function getFlagsAsString(): string
private function getFlagsAsArginfoString(): string
{
$flags = "ZEND_ACC_PUBLIC";
if ($this->flags & Class_::MODIFIER_PROTECTED) {
@@ -673,6 +832,114 @@ class FuncInfo {
return $flags;
}
/**
* @param FuncInfo[] $funcMap
* @param FuncInfo[] $aliasMap
* @throws Exception
*/
public function getMethodSynopsisDocument(array $funcMap, array $aliasMap): ?string {
$doc = new DOMDocument();
$doc->formatOutput = true;
$methodSynopsis = $this->getMethodSynopsisElement($funcMap, $aliasMap, $doc);
if (!$methodSynopsis) {
return null;
}
$doc->appendChild($methodSynopsis);
return $doc->saveXML();
}
/**
* @param FuncInfo[] $funcMap
* @param FuncInfo[] $aliasMap
* @throws Exception
*/
public function getMethodSynopsisElement(array $funcMap, array $aliasMap, DOMDocument $doc): ?DOMElement {
if ($this->hasParamWithUnknownDefaultValue()) {
return null;
}
if ($this->name->isConstructor()) {
$synopsisType = "constructorsynopsis";
} elseif ($this->name->isDestructor()) {
$synopsisType = "destructorsynopsis";
} else {
$synopsisType = "methodsynopsis";
}
$methodSynopsis = $doc->createElement($synopsisType);
$aliasedFunc = $this->aliasType === "alias" && isset($funcMap[$this->alias->__toString()]) ? $funcMap[$this->alias->__toString()] : null;
$aliasFunc = $aliasMap[$this->name->__toString()] ?? null;
if (($this->aliasType === "alias" && $aliasedFunc !== null && $aliasedFunc->isMethod() !== $this->isMethod()) ||
($aliasFunc !== null && $aliasFunc->isMethod() !== $this->isMethod())
) {
$role = $doc->createAttribute("role");
$role->value = $this->isMethod() ? "oop" : "procedural";
$methodSynopsis->appendChild($role);
}
$methodSynopsis->appendChild(new DOMText("\n "));
foreach ($this->getModifierNames() as $modifierString) {
$modifierElement = $doc->createElement('modifier', $modifierString);
$methodSynopsis->appendChild($modifierElement);
$methodSynopsis->appendChild(new DOMText(" "));
}
$returnType = $this->return->getMethodSynopsisType();
if ($returnType) {
$this->appendMethodSynopsisTypeToElement($doc, $methodSynopsis, $returnType);
}
$methodname = $doc->createElement('methodname', $this->name->__toString());
$methodSynopsis->appendChild($methodname);
if (empty($this->args)) {
$methodSynopsis->appendChild(new DOMText("\n "));
$void = $doc->createElement('void');
$methodSynopsis->appendChild($void);
} else {
foreach ($this->args as $arg) {
$methodSynopsis->appendChild(new DOMText("\n "));
$methodparam = $doc->createElement('methodparam');
if ($arg->defaultValue !== null) {
$methodparam->setAttribute("choice", "opt");
}
if ($arg->isVariadic) {
$methodparam->setAttribute("rep", "repeat");
}
$methodSynopsis->appendChild($methodparam);
$this->appendMethodSynopsisTypeToElement($doc, $methodparam, $arg->getMethodSynopsisType());
$parameter = $doc->createElement('parameter', $arg->name);
if ($arg->sendBy !== ArgInfo::SEND_BY_VAL) {
$parameter->setAttribute("role", "reference");
}
$methodparam->appendChild($parameter);
$defaultValue = $arg->getDefaultValueAsMethodSynopsisString();
if ($defaultValue !== null) {
$initializer = $doc->createElement('initializer');
if (preg_match('/^[a-zA-Z_][a-zA-Z_0-9]*$/', $defaultValue)) {
$constant = $doc->createElement('constant', $defaultValue);
$initializer->appendChild($constant);
} else {
$initializer->nodeValue = $defaultValue;
}
$methodparam->appendChild($initializer);
}
}
}
$methodSynopsis->appendChild(new DOMText("\n "));
return $methodSynopsis;
}
public function discardInfoForOldPhpVersions(): void {
$this->return->type = null;
foreach ($this->args as $arg) {
@@ -680,6 +947,22 @@ class FuncInfo {
$arg->defaultValue = null;
}
}
private function appendMethodSynopsisTypeToElement(DOMDocument $doc, DOMElement $elementToAppend, Type $type) {
if (count($type->types) > 1) {
$typeElement = $doc->createElement('type');
$typeElement->setAttribute("class", "union");
foreach ($type->types as $type) {
$unionTypeElement = $doc->createElement('type', $type->name);
$typeElement->appendChild($unionTypeElement);
}
} else {
$typeElement = $doc->createElement('type', $type->types[0]->name);
}
$elementToAppend->appendChild($typeElement);
}
}
class ClassInfo {
@@ -736,8 +1019,26 @@ class DocCommentTag {
return $this->value;
}
public function getVariableName(): string {
public function getType(): string {
$value = $this->getValue();
$matches = [];
if ($this->name === "param") {
preg_match('/^\s*([\w\|\\\\\[\]]+)\s*\$\w+.*$/', $value, $matches);
} elseif ($this->name === "return") {
preg_match('/^\s*([\w\|\\\\\[\]]+)\s*$/', $value, $matches);
}
if (isset($matches[1]) === false) {
throw new Exception("@$this->name doesn't contain a type or has an invalid format \"$value\"");
}
return $matches[1];
}
public function getVariableName(): string {
$value = $this->value;
if ($value === null || strlen($value) === 0) {
throw new Exception("@$this->name doesn't have any value");
}
@@ -745,13 +1046,13 @@ class DocCommentTag {
$matches = [];
if ($this->name === "param") {
preg_match('/^\s*[\w\|\\\\]+\s*\$(\w+).*$/', $value, $matches);
preg_match('/^\s*[\w\|\\\\\[\]]+\s*\$(\w+).*$/', $value, $matches);
} elseif ($this->name === "prefer-ref") {
preg_match('/^\s*\$(\w+).*$/', $value, $matches);
}
if (isset($matches[1]) === false) {
throw new Exception("@$this->name doesn't contain variable name or has an invalid format \"$value\"");
throw new Exception("@$this->name doesn't contain a variable name or has an invalid format \"$value\"");
}
return $matches[1];
@@ -786,7 +1087,7 @@ function parseFunctionLike(
$alias = null;
$isDeprecated = false;
$verify = true;
$haveDocReturnType = false;
$docReturnType = null;
$docParamTypes = [];
if ($comment) {
@@ -811,9 +1112,9 @@ function parseFunctionLike(
} else if ($tag->name === 'no-verify') {
$verify = false;
} else if ($tag->name === 'return') {
$haveDocReturnType = true;
$docReturnType = $tag->getType();
} else if ($tag->name === 'param') {
$docParamTypes[$tag->getVariableName()] = true;
$docParamTypes[$tag->getVariableName()] = $tag->getType();
}
}
}
@@ -867,6 +1168,7 @@ function parseFunctionLike(
$sendBy,
$param->variadic,
$type,
isset($docParamTypes[$varName]) ? Type::fromPhpDoc($docParamTypes[$varName]) : null,
$param->default ? $prettyPrinter->prettyPrintExpr($param->default) : null
);
if (!$param->default && !$param->variadic) {
@@ -879,13 +1181,14 @@ function parseFunctionLike(
}
$returnType = $func->getReturnType();
if ($returnType === null && !$haveDocReturnType && !$name->isConstructor() && !$name->isDestructor()) {
if ($returnType === null && $docReturnType === null && !$name->isConstructor() && !$name->isDestructor()) {
throw new Exception("Missing return type for function $name()");
}
$return = new ReturnInfo(
$func->returnsByRef(),
$returnType ? Type::fromNode($returnType) : null
$returnType ? Type::fromNode($returnType) : null,
$docReturnType ? Type::fromPhpDoc($docReturnType) : null
);
return new FuncInfo(
@@ -1070,24 +1373,23 @@ function funcInfoToCode(FuncInfo $funcInfo): string {
$simpleReturnType->toEscapedName(), $returnType->isNullable()
);
}
} else if (null !== $representableType = $returnType->tryToRepresentableType()) {
if ($representableType->classType !== null) {
} else {
$arginfoType = $returnType->toArginfoType();
if ($arginfoType->hasClassType()) {
$code .= sprintf(
"ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(%s, %d, %d, %s, %s)\n",
$funcInfo->getArgInfoName(), $funcInfo->return->byRef,
$funcInfo->numRequiredArgs,
$representableType->classType->toEscapedName(), $representableType->toTypeMask()
$arginfoType->toClassTypeString(), $arginfoType->toTypeMask()
);
} else {
$code .= sprintf(
"ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(%s, %d, %d, %s)\n",
$funcInfo->getArgInfoName(), $funcInfo->return->byRef,
$funcInfo->numRequiredArgs,
$representableType->toTypeMask()
$arginfoType->toTypeMask()
);
}
} else {
throw new Exception('Unimplemented');
}
} else {
$code .= sprintf(
@@ -1098,7 +1400,7 @@ function funcInfoToCode(FuncInfo $funcInfo): string {
foreach ($funcInfo->args as $argInfo) {
$argKind = $argInfo->isVariadic ? "ARG_VARIADIC" : "ARG";
$argDefaultKind = $argInfo->hasDefaultValue() ? "_WITH_DEFAULT_VALUE" : "";
$argDefaultKind = $argInfo->hasProperDefaultValue() ? "_WITH_DEFAULT_VALUE" : "";
$argType = $argInfo->type;
if ($argType !== null) {
if (null !== $simpleArgType = $argType->tryToSimpleType()) {
@@ -1107,41 +1409,39 @@ function funcInfoToCode(FuncInfo $funcInfo): string {
"\tZEND_%s_TYPE_INFO%s(%s, %s, %s, %d%s)\n",
$argKind, $argDefaultKind, $argInfo->getSendByString(), $argInfo->name,
$simpleArgType->toTypeCode(), $argType->isNullable(),
$argInfo->hasDefaultValue() ? ", " . $argInfo->getDefaultValueString() : ""
$argInfo->hasProperDefaultValue() ? ", " . $argInfo->getDefaultValueAsArginfoString() : ""
);
} else {
$code .= sprintf(
"\tZEND_%s_OBJ_INFO%s(%s, %s, %s, %d%s)\n",
$argKind,$argDefaultKind, $argInfo->getSendByString(), $argInfo->name,
$simpleArgType->toEscapedName(), $argType->isNullable(),
$argInfo->hasDefaultValue() ? ", " . $argInfo->getDefaultValueString() : ""
$argInfo->hasProperDefaultValue() ? ", " . $argInfo->getDefaultValueAsArginfoString() : ""
);
}
} else if (null !== $representableType = $argType->tryToRepresentableType()) {
if ($representableType->classType !== null) {
} else {
$arginfoType = $argType->toArginfoType();
if ($arginfoType->hasClassType()) {
$code .= sprintf(
"\tZEND_%s_OBJ_TYPE_MASK(%s, %s, %s, %s, %s)\n",
$argKind, $argInfo->getSendByString(), $argInfo->name,
$representableType->classType->toEscapedName(),
$representableType->toTypeMask(),
$argInfo->getDefaultValueString()
$arginfoType->toClassTypeString(), $arginfoType->toTypeMask(),
$argInfo->getDefaultValueAsArginfoString()
);
} else {
$code .= sprintf(
"\tZEND_%s_TYPE_MASK(%s, %s, %s, %s)\n",
$argKind, $argInfo->getSendByString(), $argInfo->name,
$representableType->toTypeMask(),
$argInfo->getDefaultValueString()
$arginfoType->toTypeMask(),
$argInfo->getDefaultValueAsArginfoString()
);
}
} else {
throw new Exception('Unimplemented');
}
} else {
$code .= sprintf(
"\tZEND_%s_INFO%s(%s, %s%s)\n",
$argKind, $argDefaultKind, $argInfo->getSendByString(), $argInfo->name,
$argInfo->hasDefaultValue() ? ", " . $argInfo->getDefaultValueString() : ""
$argInfo->hasProperDefaultValue() ? ", " . $argInfo->getDefaultValueAsArginfoString() : ""
);
}
}
@@ -1253,6 +1553,194 @@ function generateFunctionEntries(?Name $className, array $funcInfos): string {
return $code;
}
/**
* @param FuncInfo[] $funcMap
* @param FuncInfo[] $aliasMap
* @return array<string, string>
*/
function generateMethodSynopses(array $funcMap, array $aliasMap): array {
$result = [];
foreach ($funcMap as $funcInfo) {
$methodSynopsis = $funcInfo->getMethodSynopsisDocument($funcMap, $aliasMap);
if ($methodSynopsis !== null) {
$result[$funcInfo->name->getMethodSynopsisFilename() . ".xml"] = $methodSynopsis;
}
}
return $result;
}
/**
* @param FuncInfo[] $funcMap
* @param FuncInfo[] $aliasMap
* @return array<string, string>
*/
function replaceMethodSynopses(string $targetDirectory, array $funcMap, array $aliasMap): array {
$methodSynopses = [];
$it = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($targetDirectory),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($it as $file) {
$pathName = $file->getPathName();
if (!preg_match('/\.xml$/i', $pathName)) {
continue;
}
$xml = file_get_contents($pathName);
if ($xml === false) {
continue;
}
if (stripos($xml, "<methodsynopsis") === false && stripos($xml, "<constructorsynopsis") === false && stripos($xml, "<destructorsynopsis") === false) {
continue;
}
$replacedXml = preg_replace("/&([A-Za-z0-9._{}%-]+?;)/", "REPLACED-ENTITY-$1", $xml);
$doc = new DOMDocument();
$doc->formatOutput = false;
$doc->preserveWhiteSpace = true;
$doc->validateOnParse = true;
$success = $doc->loadXML($replacedXml);
if (!$success) {
echo "Failed opening $pathName\n";
continue;
}
$docComparator = new DOMDocument();
$docComparator->preserveWhiteSpace = false;
$docComparator->formatOutput = true;
$methodSynopsisElements = [];
foreach ($doc->getElementsByTagName("constructorsynopsis") as $element) {
$methodSynopsisElements[] = $element;
}
foreach ($doc->getElementsByTagName("destructorsynopsis") as $element) {
$methodSynopsisElements[] = $element;
}
foreach ($doc->getElementsByTagName("methodsynopsis") as $element) {
$methodSynopsisElements[] = $element;
}
foreach ($methodSynopsisElements as $methodSynopsis) {
if (!$methodSynopsis instanceof DOMElement) {
continue;
}
$list = $methodSynopsis->getElementsByTagName("methodname");
$item = $list->item(0);
if (!$item instanceof DOMElement) {
continue;
}
$funcName = $item->textContent;
if (!isset($funcMap[$funcName])) {
continue;
}
$funcInfo = $funcMap[$funcName];
$newMethodSynopsis = $funcInfo->getMethodSynopsisElement($funcMap, $aliasMap, $doc);
if ($newMethodSynopsis === null) {
continue;
}
// Retrieve current signature
$params = [];
$list = $methodSynopsis->getElementsByTagName("methodparam");
foreach ($list as $i => $item) {
if (!$item instanceof DOMElement) {
continue;
}
$paramList = $item->getElementsByTagName("parameter");
if ($paramList->count() !== 1) {
continue;
}
$paramName = $paramList->item(0)->textContent;
$paramTypes = [];
$paramList = $item->getElementsByTagName("type");
foreach ($paramList as $type) {
if (!$type instanceof DOMElement) {
continue;
}
$paramTypes[] = $type->textContent;
}
$params[$paramName] = ["index" => $i, "type" => $paramTypes];
}
// Check if there is any change - short circuit if there is not any.
$xml1 = $doc->saveXML($methodSynopsis);
$xml1 = preg_replace("/&([A-Za-z0-9._{}%-]+?;)/", "REPLACED-ENTITY-$1", $xml1);
$docComparator->loadXML($xml1);
$xml1 = $docComparator->saveXML();
$methodSynopsis->parentNode->replaceChild($newMethodSynopsis, $methodSynopsis);
$xml2 = $doc->saveXML($newMethodSynopsis);
$xml2 = preg_replace("/&([A-Za-z0-9._{}%-]+?;)/", "REPLACED-ENTITY-$1", $xml2);
$docComparator->loadXML($xml2);
$xml2 = $docComparator->saveXML();
if ($xml1 === $xml2) {
continue;
}
// Update parameter references
$paramList = $doc->getElementsByTagName("parameter");
/** @var DOMElement $paramElement */
foreach ($paramList as $paramElement) {
if ($paramElement->parentNode && $paramElement->parentNode->nodeName === "methodparam") {
continue;
}
$name = $paramElement->textContent;
if (!isset($params[$name])) {
continue;
}
$index = $params[$name]["index"];
if (!isset($funcInfo->args[$index])) {
continue;
}
$paramElement->textContent = $funcInfo->args[$index]->name;
}
// Return the updated XML
$replacedXml = $doc->saveXML();
$replacedXml = preg_replace(
[
"/REPLACED-ENTITY-([A-Za-z0-9._{}%-]+?;)/",
"/<refentry\s+xmlns=\"([a-z0-9.:\/]+)\"\s+xml:id=\"([a-z0-9._-]+)\"\s*>/i",
"/<refentry\s+xmlns=\"([a-z0-9.:\/]+)\"\s+xmlns:xlink=\"([a-z0-9.:\/]+)\"\s+xml:id=\"([a-z0-9._-]+)\"\s*>/i",
],
[
"&$1",
"<refentry xml:id=\"$2\" xmlns=\"$1\">",
"<refentry xml:id=\"$3\" xmlns=\"$1\" xmlns:xlink=\"$2\">",
],
$replacedXml
);
$methodSynopses[$pathName] = $replacedXml;
}
}
return $methodSynopses;
}
function installPhpParser(string $version, string $phpParserDir) {
$lockFile = __DIR__ . "/PHP-Parser-install-lock";
$lockFd = fopen($lockFile, 'w+');
@@ -1318,16 +1806,22 @@ function initPhpParser() {
}
$optind = null;
$options = getopt("fh", ["force-regeneration", "parameter-stats", "help", "verify"], $optind);
$options = getopt("fh", ["force-regeneration", "parameter-stats", "help", "verify", "generate-methodsynopses", "replace-methodsynopses"], $optind);
$context = new Context;
$printParameterStats = isset($options["parameter-stats"]);
$verify = isset($options["verify"]);
$generateMethodSynopses = isset($options["generate-methodsynopses"]);
$replaceMethodSynopses = isset($options["replace-methodsynopses"]);
$context->forceRegeneration = isset($options["f"]) || isset($options["force-regeneration"]);
$context->forceParse = $context->forceRegeneration || $printParameterStats || $verify;
$context->forceParse = $context->forceRegeneration || $printParameterStats || $verify || $generateMethodSynopses || $replaceMethodSynopses;
$targetMethodSynopses = $argv[$optind + 1] ?? null;
if ($replaceMethodSynopses && $targetMethodSynopses === null) {
die("A target directory must be provided.\n");
}
if (isset($options["h"]) || isset($options["help"])) {
die("\nusage: gen-stub.php [ -f | --force-regeneration ] [ --parameter-stats ] [ --verify ] [ -h | --help ] [ name.stub.php | directory ]\n\n");
die("\nusage: gen-stub.php [ -f | --force-regeneration ] [ --generate-methodsynopses ] [ --replace-methodsynopses ] [ --parameter-stats ] [ --verify ] [ -h | --help ] [ name.stub.php | directory ] [ directory ]\n\n");
}
$fileInfos = [];
@@ -1363,23 +1857,26 @@ if ($printParameterStats) {
echo json_encode($parameterStats, JSON_PRETTY_PRINT), "\n";
}
if ($verify) {
$errors = [];
$funcMap = [];
$aliases = [];
/** @var FuncInfo[] $funcMap */
$funcMap = [];
/** @var FuncInfo[] $aliasMap */
$aliasMap = [];
foreach ($fileInfos as $fileInfo) {
foreach ($fileInfo->getAllFuncInfos() as $funcInfo) {
/** @var FuncInfo $funcInfo */
$funcMap[$funcInfo->name->__toString()] = $funcInfo;
foreach ($fileInfos as $fileInfo) {
foreach ($fileInfo->getAllFuncInfos() as $funcInfo) {
/** @var FuncInfo $funcInfo */
$funcMap[$funcInfo->name->__toString()] = $funcInfo;
if ($funcInfo->aliasType === "alias") {
$aliases[] = $funcInfo;
}
if ($funcInfo->aliasType === "alias") {
$aliasMap[$funcInfo->alias->__toString()] = $funcInfo;
}
}
}
foreach ($aliases as $aliasFunc) {
if ($verify) {
$errors = [];
foreach ($aliasMap as $aliasFunc) {
if (!isset($funcMap[$aliasFunc->alias->__toString()])) {
$errors[] = "Aliased function {$aliasFunc->alias}() cannot be found";
continue;
@@ -1412,7 +1909,6 @@ if ($verify) {
}
if ($aliasedArg === null) {
assert($aliasArg !== null);
$errors[] = "{$aliasedFunc->name}(): Argument \$$aliasArg->name of alias function {$aliasFunc->name}() is missing";
return null;
}
@@ -1447,3 +1943,30 @@ if ($verify) {
exit(1);
}
}
if ($generateMethodSynopses) {
$methodSynopsesDirectory = getcwd() . "/methodsynopses";
$methodSynopses = generateMethodSynopses($funcMap, $aliasMap);
if (!empty($methodSynopses)) {
if (!file_exists($methodSynopsesDirectory)) {
mkdir($methodSynopsesDirectory);
}
foreach ($methodSynopses as $filename => $content) {
if (file_put_contents("$methodSynopsesDirectory/$filename", $content)) {
echo "Saved $filename\n";
}
}
}
}
if ($replaceMethodSynopses) {
$methodSynopses = replaceMethodSynopses($targetMethodSynopses, $funcMap, $aliasMap);
foreach ($methodSynopses as $filename => $content) {
if (file_put_contents($filename, $content)) {
echo "Saved $filename\n";
}
}
}
+3 -3
View File
@@ -340,7 +340,7 @@ AC_DEFUN([_LT_REQUIRED_DARWIN_CHECKS],[
_lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
10.[[012]]*)
_lt_dar_allow_undefined='${wl}-flat_namespace ${wl}-undefined ${wl}suppress' ;;
10.*)
*)
_lt_dar_allow_undefined='${wl}-undefined ${wl}dynamic_lookup' ;;
esac
;;
@@ -1522,7 +1522,7 @@ darwin* | rhapsody*)
shlibpath_var=DYLD_LIBRARY_PATH
shrext_cmds='`test .$module = .yes && echo .so || echo .dylib`'
ifelse([$1], [],[
sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
sys_lib_search_path_spec="$sys_lib_search_path_spec /usr/local/lib"])
sys_lib_dlsearch_path_spec='/usr/local/lib /lib /usr/lib'
;;
@@ -5800,7 +5800,7 @@ _LT_EOF
10.[[012]])
_LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-flat_namespace ${wl}-undefined ${wl}suppress'
;;
10.*)
*)
_LT_AC_TAGVAR(allow_undefined_flag, $1)='${wl}-undefined ${wl}dynamic_lookup'
;;
esac
+1 -1
View File
@@ -478,7 +478,7 @@ dnl Internal, don't use.
dnl
AC_DEFUN([_PHP_ADD_LIBRARY_SKELETON],[
case $1 in
c|c_r|pthread*[)] ;;
c|c_r[)] ;;
*[)] ifelse($3,,[
_PHP_X_ADD_LIBRARY($1,$2,$5)
],[
+14 -8
View File
@@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice.
dnl ----------------------------------------------------------------------------
AC_PREREQ([2.68])
AC_INIT([PHP],[8.0.0],[https://bugs.php.net],[php],[https://www.php.net])
AC_INIT([PHP],[8.0.2],[https://bugs.php.net],[php],[https://www.php.net])
AC_CONFIG_SRCDIR([main/php_version.h])
AC_CONFIG_AUX_DIR([build])
AC_PRESERVE_HELP_ORDER
@@ -797,6 +797,19 @@ if test "$PHP_DEBUG_ASSERTIONS" = "yes"; then
ZEND_DEBUG=yes
fi
AC_ARG_ENABLE([zts],
[AS_HELP_STRING([--enable-zts],
[Enable thread safety])],
[ZEND_ZTS=$enableval],
[ZEND_ZTS=no])
if test "$ZEND_ZTS" = "yes"; then
AC_DEFINE(ZTS, 1,[ ])
PHP_THREAD_SAFETY=yes
else
PHP_THREAD_SAFETY=no
fi
PHP_ARG_ENABLE([rtld-now],
[whether to dlopen extensions with RTLD_NOW instead of RTLD_LAZY],
[AS_HELP_STRING([--enable-rtld-now],
@@ -1136,13 +1149,6 @@ LIBZEND_BASIC_CHECKS
LIBZEND_DLSYM_CHECK
LIBZEND_OTHER_CHECKS
if test "$ZEND_ZTS" = "yes"; then
AC_DEFINE(ZTS,1,[ ])
PHP_THREAD_SAFETY=yes
else
PHP_THREAD_SAFETY=no
fi
INCLUDES="$INCLUDES -I\$(top_builddir)/TSRM"
INCLUDES="$INCLUDES -I\$(top_builddir)/Zend"
+144 -53
View File
@@ -129,20 +129,23 @@ PHP_MINFO_FUNCTION(bcmath)
/* {{{ php_str2num
Convert to bc_num detecting scale */
static void php_str2num(bc_num *num, char *str)
static zend_result php_str2num(bc_num *num, char *str)
{
char *p;
if (!(p = strchr(str, '.'))) {
if (!bc_str2num(num, str, 0)) {
php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
return FAILURE;
}
return;
return SUCCESS;
}
if (!bc_str2num(num, str, strlen(p+1))) {
php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
return FAILURE;
}
return SUCCESS;
}
/* }}} */
@@ -174,15 +177,26 @@ PHP_FUNCTION(bcadd)
bc_init_num(&first);
bc_init_num(&second);
bc_init_num(&result);
php_str2num(&first, ZSTR_VAL(left));
php_str2num(&second, ZSTR_VAL(right));
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
zend_argument_value_error(1, "is not well-formed");
goto cleanup;
}
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
zend_argument_value_error(2, "is not well-formed");
goto cleanup;
}
bc_add (first, second, &result, scale);
RETVAL_STR(bc_num2str_ex(result, scale));
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
return;
cleanup: {
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
};
}
/* }}} */
@@ -214,15 +228,26 @@ PHP_FUNCTION(bcsub)
bc_init_num(&first);
bc_init_num(&second);
bc_init_num(&result);
php_str2num(&first, ZSTR_VAL(left));
php_str2num(&second, ZSTR_VAL(right));
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
zend_argument_value_error(1, "is not well-formed");
goto cleanup;
}
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
zend_argument_value_error(2, "is not well-formed");
goto cleanup;
}
bc_sub (first, second, &result, scale);
RETVAL_STR(bc_num2str_ex(result, scale));
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
return;
cleanup: {
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
};
}
/* }}} */
@@ -254,15 +279,26 @@ PHP_FUNCTION(bcmul)
bc_init_num(&first);
bc_init_num(&second);
bc_init_num(&result);
php_str2num(&first, ZSTR_VAL(left));
php_str2num(&second, ZSTR_VAL(right));
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
zend_argument_value_error(1, "is not well-formed");
goto cleanup;
}
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
zend_argument_value_error(2, "is not well-formed");
goto cleanup;
}
bc_multiply (first, second, &result, scale);
RETVAL_STR(bc_num2str_ex(result, scale));
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
return;
cleanup: {
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
};
}
/* }}} */
@@ -294,8 +330,16 @@ PHP_FUNCTION(bcdiv)
bc_init_num(&first);
bc_init_num(&second);
bc_init_num(&result);
php_str2num(&first, ZSTR_VAL(left));
php_str2num(&second, ZSTR_VAL(right));
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
zend_argument_value_error(1, "is not well-formed");
goto cleanup;
}
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
zend_argument_value_error(2, "is not well-formed");
goto cleanup;
}
switch (bc_divide(first, second, &result, scale)) {
case 0: /* OK */
@@ -306,10 +350,11 @@ PHP_FUNCTION(bcdiv)
break;
}
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
return;
cleanup: {
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
};
}
/* }}} */
@@ -341,8 +386,16 @@ PHP_FUNCTION(bcmod)
bc_init_num(&first);
bc_init_num(&second);
bc_init_num(&result);
php_str2num(&first, ZSTR_VAL(left));
php_str2num(&second, ZSTR_VAL(right));
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
zend_argument_value_error(1, "is not well-formed");
goto cleanup;
}
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
zend_argument_value_error(2, "is not well-formed");
goto cleanup;
}
switch (bc_modulo(first, second, &result, scale)) {
case 0:
@@ -353,9 +406,11 @@ PHP_FUNCTION(bcmod)
break;
}
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
cleanup: {
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
};
}
/* }}} */
@@ -389,18 +444,32 @@ PHP_FUNCTION(bcpowmod)
bc_init_num(&second);
bc_init_num(&mod);
bc_init_num(&result);
php_str2num(&first, ZSTR_VAL(left));
php_str2num(&second, ZSTR_VAL(right));
php_str2num(&mod, ZSTR_VAL(modulus));
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
zend_argument_value_error(1, "is not well-formed");
goto cleanup;
}
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
zend_argument_value_error(2, "is not well-formed");
goto cleanup;
}
if (php_str2num(&mod, ZSTR_VAL(modulus)) == FAILURE) {
zend_argument_value_error(3, "is not well-formed");
goto cleanup;
}
if (bc_raisemod(first, second, mod, &result, scale) == SUCCESS) {
RETVAL_STR(bc_num2str_ex(result, scale));
}
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&mod);
bc_free_num(&result);
cleanup: {
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&mod);
bc_free_num(&result);
};
}
/* }}} */
@@ -432,14 +501,26 @@ PHP_FUNCTION(bcpow)
bc_init_num(&first);
bc_init_num(&second);
bc_init_num(&result);
php_str2num(&first, ZSTR_VAL(left));
php_str2num(&second, ZSTR_VAL(right));
if (php_str2num(&first, ZSTR_VAL(left)) == FAILURE) {
zend_argument_value_error(1, "is not well-formed");
goto cleanup;
}
if (php_str2num(&second, ZSTR_VAL(right)) == FAILURE) {
zend_argument_value_error(2, "is not well-formed");
goto cleanup;
}
bc_raise (first, second, &result, scale);
RETVAL_STR(bc_num2str_ex(result, scale));
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
cleanup: {
bc_free_num(&first);
bc_free_num(&second);
bc_free_num(&result);
};
}
/* }}} */
@@ -468,7 +549,11 @@ PHP_FUNCTION(bcsqrt)
}
bc_init_num(&result);
php_str2num(&result, ZSTR_VAL(left));
if (php_str2num(&result, ZSTR_VAL(left)) == FAILURE) {
zend_argument_value_error(1, "is not well-formed");
goto cleanup;
}
if (bc_sqrt (&result, scale) != 0) {
RETVAL_STR(bc_num2str_ex(result, scale));
@@ -476,8 +561,9 @@ PHP_FUNCTION(bcsqrt)
zend_argument_value_error(1, "must be greater than or equal to 0");
}
bc_free_num(&result);
return;
cleanup: {
bc_free_num(&result);
};
}
/* }}} */
@@ -510,16 +596,21 @@ PHP_FUNCTION(bccomp)
bc_init_num(&second);
if (!bc_str2num(&first, ZSTR_VAL(left), scale)) {
php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
zend_argument_value_error(1, "is not well-formed");
goto cleanup;
}
if (!bc_str2num(&second, ZSTR_VAL(right), scale)) {
php_error_docref(NULL, E_WARNING, "bcmath function argument is not well-formed");
zend_argument_value_error(2, "is not well-formed");
goto cleanup;
}
RETVAL_LONG(bc_compare(first, second));
bc_free_num(&first);
bc_free_num(&second);
return;
cleanup: {
bc_free_num(&first);
bc_free_num(&second);
};
}
/* }}} */
+25
View File
@@ -0,0 +1,25 @@
--TEST--
Bug #80545 (bcadd('a', 'a') and bcadd('1', 'a') doesn't throw an exception)
--SKIPIF--
<?php
if (!extension_loaded('bcmath')) die('skip bcmath extension not available');
?>
--FILE--
<?php
try {
bcadd('a', 'a');
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
bcadd('1', 'a');
} catch (\ValueError $e) {
echo $e->getMessage();
}
?>
--EXPECT--
bcadd(): Argument #1 ($num1) is not well-formed
bcadd(): Argument #2 ($num2) is not well-formed
+75 -31
View File
@@ -14,12 +14,39 @@ echo bcadd("", "2", 2),"\n";
echo bcadd("+0", "2"), "\n";
echo bcadd("-0", "2"), "\n";
echo bcadd(" 0", "2");
echo bcadd("1e1", "2");
echo bcadd("1,1", "2");
echo bcadd("Hello", "2");
echo bcadd("1 1", "2");
echo "\n", "\n";
echo "\n";
try {
echo bcadd(" 0", "2");
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
echo bcadd("1e1", "2");
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
echo bcadd("1,1", "2");
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
echo bcadd("Hello", "2");
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
echo bcadd("1 1", "2");
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
echo "\n";
echo bccomp("1", "2"),"\n";
echo bccomp("1.1", "2", 2),"\n";
@@ -27,11 +54,38 @@ echo bccomp("", "2"),"\n";
echo bccomp("+0", "2"), "\n";
echo bccomp("-0", "2"), "\n";
echo bccomp(" 0", "2");
echo bccomp("1e1", "2");
echo bccomp("1,1", "2");
echo bccomp("Hello", "2");
echo bccomp("1 1", "2");
echo "\n";
try {
echo bccomp(" 0", "2");
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
echo bccomp("1e1", "2");
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
echo bccomp("1,1", "2");
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
echo bccomp("Hello", "2");
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
try {
echo bccomp("1 1", "2");
} catch (\ValueError $e) {
echo $e->getMessage() . PHP_EOL;
}
?>
--EXPECTF--
3
@@ -40,16 +94,11 @@ echo bccomp("1 1", "2");
2
2
Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
2
Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
2
Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
2
Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
2
Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
2
bcadd(): Argument #1 ($num1) is not well-formed
bcadd(): Argument #1 ($num1) is not well-formed
bcadd(): Argument #1 ($num1) is not well-formed
bcadd(): Argument #1 ($num1) is not well-formed
bcadd(): Argument #1 ($num1) is not well-formed
-1
-1
@@ -57,13 +106,8 @@ Warning: bcadd(): bcmath function argument is not well-formed in %s on line %d
-1
-1
Warning: bccomp(): bcmath function argument is not well-formed in %s on line %d
-1
Warning: bccomp(): bcmath function argument is not well-formed in %s on line %d
-1
Warning: bccomp(): bcmath function argument is not well-formed in %s on line %d
-1
Warning: bccomp(): bcmath function argument is not well-formed in %s on line %d
-1
Warning: bccomp(): bcmath function argument is not well-formed in %s on line %d
-1
bccomp(): Argument #1 ($num1) is not well-formed
bccomp(): Argument #1 ($num1) is not well-formed
bccomp(): Argument #1 ($num1) is not well-formed
bccomp(): Argument #1 ($num1) is not well-formed
bccomp(): Argument #1 ($num1) is not well-formed
+1 -1
View File
@@ -4,7 +4,7 @@
final class COMPersistHelper
{
public function __construct(?variant $variant) {}
public function __construct(?variant $variant = null) {}
public function GetCurFileName(): string|false {}
+3 -3
View File
@@ -1,8 +1,8 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: d04d007cac328014c6cc76a00cc291237965d56d */
* Stub hash: 2c2759e6c1894713439e3ee8da7f56810d00d8cf */
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_COMPersistHelper___construct, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, variant, variant, 1)
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_COMPersistHelper___construct, 0, 0, 0)
ZEND_ARG_OBJ_INFO_WITH_DEFAULT_VALUE(0, variant, variant, 1, "null")
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_class_COMPersistHelper_GetCurFileName, 0, 0, MAY_BE_STRING|MAY_BE_FALSE)
+1 -1
View File
@@ -28,7 +28,7 @@ if (PHP_CURL != "no") {
) {
EXTENSION("curl", "interface.c multi.c share.c curl_file.c");
AC_DEFINE('HAVE_CURL', 1, 'Have cURL library');
ADD_FLAG("CFLAGS_CURL", "/D CURL_STATICLIB");
ADD_FLAG("CFLAGS_CURL", "/D CURL_STATICLIB /D PHP_CURL_EXPORTS=1");
PHP_INSTALL_HEADERS("ext/curl", "php_curl.h");
// TODO: check for curl_version_info
} else {
+8 -1
View File
@@ -2722,7 +2722,14 @@ static int _php_curl_setopt(php_curl *ch, zend_long option, zval *zvalue, bool i
case CURLOPT_POSTFIELDS:
if (Z_TYPE_P(zvalue) == IS_ARRAY) {
return build_mime_structure_from_hash(ch, zvalue);
if (zend_hash_num_elements(HASH_OF(zvalue)) == 0) {
/* no need to build the mime structure for empty hashtables;
also works around https://github.com/curl/curl/issues/6455 */
curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDS, "");
error = curl_easy_setopt(ch->cp, CURLOPT_POSTFIELDSIZE, 0);
} else {
return build_mime_structure_from_hash(ch, zvalue);
}
} else {
zend_string *tmp_str;
zend_string *str = zval_get_tmp_string(zvalue, &tmp_str);
+5 -1
View File
@@ -21,7 +21,11 @@
#include "php.h"
#ifdef PHP_WIN32
# define PHP_CURL_API __declspec(dllexport)
# ifdef PHP_CURL_EXPORTS
# define PHP_CURL_API __declspec(dllexport)
# else
# define PHP_CURL_API __declspec(dllimport)
# endif
#elif defined(__GNUC__) && __GNUC__ >= 4
# define PHP_CURL_API __attribute__ ((visibility("default")))
#else
+1
View File
@@ -25,5 +25,6 @@ string(%d) "POST /get.inc?test=post HTTP/1.1
Host: localhost:%d
Accept: */*
Content-Length: 0
Content-Type: application/x-www-form-urlencoded
"
+30
View File
@@ -0,0 +1,30 @@
--TEST--
Bug #80595 (Resetting POSTFIELDS to empty array breaks request)
--SKIPIF--
<?php include 'skipif.inc'; ?>
--FILE--
<?php
include 'server.inc';
$host = curl_cli_server_start();
$ch = curl_init();
curl_setopt_array($ch, [
CURLOPT_RETURNTRANSFER => true,
CURLOPT_POST => true,
CURLOPT_URL => "{$host}/get.inc?test=post",
]);
curl_setopt($ch, CURLOPT_POSTFIELDS, ['foo' => 'bar']);
var_dump(curl_exec($ch));
curl_setopt($ch, CURLOPT_POSTFIELDS, []);
var_dump(curl_exec($ch));
?>
--EXPECT--
string(43) "array(1) {
["foo"]=>
string(3) "bar"
}
"
string(13) "array(0) {
}
"
+23303 -20532
View File
File diff suppressed because it is too large. Load diff
File diff suppressed because it is too large. Load diff
+10 -10
View File
@@ -57,7 +57,7 @@ function date_sub(DateTime $object, DateInterval $interval): DateTime {}
function date_timezone_get(DateTimeInterface $object): DateTimeZone|false {}
function date_timezone_set(DateTimeInterface $object, DateTimeZone $timezone): DateTime {}
function date_timezone_set(DateTime $object, DateTimeZone $timezone): DateTime {}
function date_offset_get(DateTimeInterface $object): int {}
@@ -105,12 +105,12 @@ function date_default_timezone_get(): string {}
function date_sunrise(
int $timestamp, int $returnFormat = SUNFUNCS_RET_STRING,
?float $latitude = null, ?float $longitude = null, ?float $zenith = null,
float $utcOffset = 0): string|int|float|false {}
?float $utcOffset = null): string|int|float|false {}
function date_sunset(
int $timestamp, int $returnFormat = SUNFUNCS_RET_STRING,
?float $latitude = null, ?float $longitude = null, ?float $zenith = null,
float $utcOffset = 0): string|int|float|false {}
?float $utcOffset = null): string|int|float|false {}
function date_sun_info(int $timestamp, float $latitude, float $longitude): array {}
@@ -125,7 +125,7 @@ interface DateTimeInterface
/** @return DateTimeZone|false */
public function getTimezone();
/** @return int|false */
/** @return int */
public function getOffset();
/** @return int|false */
@@ -202,7 +202,7 @@ class DateTime implements DateTimeInterface
public function setTimezone(DateTimeZone $timezone) {}
/**
* @return int|false
* @return int
* @alias date_offset_get
*/
public function getOffset() {}
@@ -238,7 +238,7 @@ class DateTime implements DateTimeInterface
public function getTimestamp() {}
/**
* @return DateInterval|false
* @return DateInterval
* @alias date_diff
*/
public function diff(DateTimeInterface $targetObject, bool $absolute = false) {}
@@ -251,7 +251,7 @@ class DateTimeImmutable implements DateTimeInterface
/** @return void */
public function __wakeup() {}
/** @return DateTimeZone */
/** @return DateTimeImmutable */
public static function __set_state(array $array) {}
/**
@@ -279,7 +279,7 @@ class DateTimeImmutable implements DateTimeInterface
public function getTimezone() {}
/**
* @return int|false
* @return int
* @alias date_offset_get
*/
public function getOffset() {}
@@ -291,7 +291,7 @@ class DateTimeImmutable implements DateTimeInterface
public function getTimestamp() {}
/**
* @return DateInterval|false
* @return DateInterval
* @alias date_diff
*/
public function diff(DateTimeInterface $targetObject, bool $absolute = false) {}
@@ -361,7 +361,7 @@ class DateTimeZone
public static function listAbbreviations() {}
/**
* @return array|false
* @return array
* @alias timezone_identifiers_list
*/
public static function listIdentifiers(int $timezoneGroup = DateTimeZone::ALL, ?string $countryCode = null) {}
+3 -3
View File
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 07d0e6179d838847d4a5d454f8b56438f8df19c0 */
* Stub hash: 880a93d8a3461635447318317869fa7d3d7762dd */
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_strtotime, 0, 1, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_ARG_TYPE_INFO(0, datetime, IS_STRING, 0)
@@ -110,7 +110,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_TYPE_MASK_EX(arginfo_date_timezone_get, 0, 1, Dat
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_date_timezone_set, 0, 2, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTimeInterface, 0)
ZEND_ARG_OBJ_INFO(0, object, DateTime, 0)
ZEND_ARG_OBJ_INFO(0, timezone, DateTimeZone, 0)
ZEND_END_ARG_INFO()
@@ -214,7 +214,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_date_sunrise, 0, 1, MAY_BE_STRIN
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, latitude, IS_DOUBLE, 1, "null")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, longitude, IS_DOUBLE, 1, "null")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, zenith, IS_DOUBLE, 1, "null")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, utcOffset, IS_DOUBLE, 0, "0")
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, utcOffset, IS_DOUBLE, 1, "null")
ZEND_END_ARG_INFO()
#define arginfo_date_sunset arginfo_date_sunrise
+8
View File
@@ -0,0 +1,8 @@
--TEST--
Bug #76770 'U' modifier in 'datetime::createFromFormat' adds seconds to other specifiers
--FILE--
<?php
var_dump(datetime::createFromFormat('U H', '3600 01')->getTimestamp());
?>
--EXPECT--
int(3600)
+2 -2
View File
@@ -129,7 +129,7 @@ class DOMNodeList implements IteratorAggregate, Countable
public function getIterator(): Iterator {}
/** @return ?DOMNode */
/** @return DOMNode|null */
public function item(int $index) {}
}
@@ -205,7 +205,7 @@ class DOMElement implements DOMParentNode, DOMChildNode
public function removeAttributeNS(?string $namespace, string $localName) {}
/** @return DOMAttr|false */
public function removeAttributeNode(string $qualifiedName) {}
public function removeAttributeNode(DOMAttr $attr) {}
/** @return DOMAttr|bool */
public function setAttribute(string $qualifiedName, string $value) {}
+6 -6
View File
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 128108b08807ce0b125fc7b963bf3c5b77e6987a */
* Stub hash: 7cba1a7a34cc4789871faf44fc4794a48db26e61 */
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_dom_import_simplexml, 0, 1, DOMElement, 1)
ZEND_ARG_TYPE_INFO(0, node, IS_OBJECT, 0)
@@ -197,7 +197,9 @@ ZEND_END_ARG_INFO()
#define arginfo_class_DOMElement_removeAttributeNS arginfo_class_DOMElement_getAttributeNS
#define arginfo_class_DOMElement_removeAttributeNode arginfo_class_DOMElement_getAttribute
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DOMElement_removeAttributeNode, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, attr, DOMAttr, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DOMElement_setAttribute, 0, 0, 2)
ZEND_ARG_TYPE_INFO(0, qualifiedName, IS_STRING, 0)
@@ -210,11 +212,9 @@ ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DOMElement_setAttributeNS, 0, 0, 3)
ZEND_ARG_TYPE_INFO(0, value, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DOMElement_setAttributeNode, 0, 0, 1)
ZEND_ARG_OBJ_INFO(0, attr, DOMAttr, 0)
ZEND_END_ARG_INFO()
#define arginfo_class_DOMElement_setAttributeNode arginfo_class_DOMElement_removeAttributeNode
#define arginfo_class_DOMElement_setAttributeNodeNS arginfo_class_DOMElement_setAttributeNode
#define arginfo_class_DOMElement_setAttributeNodeNS arginfo_class_DOMElement_removeAttributeNode
ZEND_BEGIN_ARG_INFO_EX(arginfo_class_DOMElement_setIdAttribute, 0, 0, 2)
ZEND_ARG_TYPE_INFO(0, qualifiedName, IS_STRING, 0)
+9 -9
View File
@@ -3865,7 +3865,7 @@ ZEND_METHOD(FFI, cast) /* {{{ */
RETURN_OBJ(&cdata->std);
} else {
zend_wrong_parameter_class_error(2, "FFI\\CData", zv);
return;
RETURN_THROWS();
}
}
@@ -4006,7 +4006,7 @@ ZEND_METHOD(FFI, typeof) /* {{{ */
}
} else {
zend_wrong_parameter_class_error(1, "FFI\\CData", zv);
return;
RETURN_THROWS();
}
ctype = (zend_ffi_ctype*)zend_ffi_ctype_new(zend_ffi_ctype_ce);
@@ -4110,7 +4110,7 @@ ZEND_METHOD(FFI, addr) /* {{{ */
ZVAL_DEREF(zv);
if (Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != zend_ffi_cdata_ce) {
zend_wrong_parameter_class_error(1, "FFI\\CData", zv);
return;
RETURN_THROWS();
}
cdata = (zend_ffi_cdata*)Z_OBJ_P(zv);
@@ -4165,7 +4165,7 @@ ZEND_METHOD(FFI, sizeof) /* {{{ */
type = ZEND_FFI_TYPE(ctype->type);
} else {
zend_wrong_parameter_class_error(1, "FFI\\CData or FFI\\CType", zv);
return;
RETURN_THROWS();
}
RETURN_LONG(type->size);
@@ -4191,7 +4191,7 @@ ZEND_METHOD(FFI, alignof) /* {{{ */
type = ZEND_FFI_TYPE(ctype->type);
} else {
zend_wrong_parameter_class_error(1, "FFI\\CData or FFI\\CType", zv);
return;
RETURN_THROWS();
}
RETURN_LONG(type->align);
@@ -4246,7 +4246,7 @@ ZEND_METHOD(FFI, memcpy) /* {{{ */
}
} else {
zend_wrong_parameter_class_error(2, "FFI\\CData or string", zv2);
return;
RETURN_THROWS();
}
memcpy(ptr1, ptr2, size);
@@ -4290,7 +4290,7 @@ ZEND_METHOD(FFI, memcmp) /* {{{ */
}
} else {
zend_wrong_parameter_class_error(1, "FFI\\CData or string", zv1);
return;
RETURN_THROWS();
}
ZVAL_DEREF(zv2);
@@ -4314,7 +4314,7 @@ ZEND_METHOD(FFI, memcmp) /* {{{ */
}
} else {
zend_wrong_parameter_class_error(2, "FFI\\CData or string", zv2);
return;
RETURN_THROWS();
}
ret = memcmp(ptr1, ptr2, size);
@@ -4416,7 +4416,7 @@ ZEND_METHOD(FFI, isNull) /* {{{ */
ZVAL_DEREF(zv);
if (Z_TYPE_P(zv) != IS_OBJECT || Z_OBJCE_P(zv) != zend_ffi_cdata_ce) {
zend_wrong_parameter_class_error(1, "FFI\\CData", zv);
return;
RETURN_THROWS();
}
cdata = (zend_ffi_cdata*)Z_OBJ_P(zv);
+8 -8
View File
@@ -10,7 +10,7 @@ final class FFI
public static function load(string $filename): ?FFI {}
public static function scope(string $name): ?FFI {}
public static function scope(string $name): FFI {}
public static function new(FFI\CType|string $type, bool $owned = true, bool $persistent = false): ?FFI\CData {}
@@ -18,7 +18,7 @@ final class FFI
public static function free(FFI\CData $ptr): void {}
/**
* @param FFI\CData|string|int|null $ptr
* @param FFI\CData|int|float|bool|null $ptr
* @prefer-ref $ptr
*/
public static function cast(FFI\CType|string $type, $ptr): ?FFI\CData {}
@@ -26,18 +26,18 @@ final class FFI
public static function type(string $type): ?FFI\CType {}
/** @prefer-ref $ptr */
public static function typeof(FFI\CData $ptr): ?FFI\CType {}
public static function typeof(FFI\CData $ptr): FFI\CType {}
public static function arrayType(FFI\CType $type, array $dimensions): ?FFI\CType {}
public static function arrayType(FFI\CType $type, array $dimensions): FFI\CType {}
/** @prefer-ref $ptr */
public static function addr(FFI\CData $ptr): FFI\CData {}
/** @prefer-ref $ptr */
public static function sizeof(object $ptr): ?int {}
public static function sizeof(FFI\CData|FFI\CType $ptr): int {}
/** @prefer-ref $ptr */
public static function alignof(object $ptr): ?int {}
public static function alignof(FFI\CData|FFI\CType $ptr): int {}
/**
* @param FFI\CData|string $from
@@ -52,13 +52,13 @@ final class FFI
* @prefer-ref $ptr2
* @param string|FFI\CData $ptr2
*/
public static function memcmp($ptr1, $ptr2, int $size): ?int {}
public static function memcmp($ptr1, $ptr2, int $size): int {}
/** @prefer-ref $ptr */
public static function memset(FFI\CData $ptr, int $value, int $size): void {}
/** @prefer-ref $ptr */
public static function string(FFI\CData $ptr, ?int $size = null): ?string {}
public static function string(FFI\CData $ptr, ?int $size = null): string {}
/** @prefer-ref $ptr */
public static function isNull(FFI\CData $ptr): bool {}
+8 -8
View File
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: abd3bc186ae3f71f2b7eb1d47f3b6bab84fb2bda */
* Stub hash: 5aeec68fea7a94cd643464acfb10bf4cfcc863da */
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_cdef, 0, 0, FFI, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, code, IS_STRING, 0, "\"\"")
@@ -10,7 +10,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_load, 0, 1, FFI, 1)
ZEND_ARG_TYPE_INFO(0, filename, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_scope, 0, 1, FFI, 1)
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_scope, 0, 1, FFI, 0)
ZEND_ARG_TYPE_INFO(0, name, IS_STRING, 0)
ZEND_END_ARG_INFO()
@@ -33,11 +33,11 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_type, 0, 1, FFI\\CType,
ZEND_ARG_TYPE_INFO(0, type, IS_STRING, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_typeof, 0, 1, FFI\\CType, 1)
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_typeof, 0, 1, FFI\\CType, 0)
ZEND_ARG_OBJ_INFO(ZEND_SEND_PREFER_REF, ptr, FFI\\CData, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_arrayType, 0, 2, FFI\\CType, 1)
ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_arrayType, 0, 2, FFI\\CType, 0)
ZEND_ARG_OBJ_INFO(0, type, FFI\\CType, 0)
ZEND_ARG_TYPE_INFO(0, dimensions, IS_ARRAY, 0)
ZEND_END_ARG_INFO()
@@ -46,8 +46,8 @@ ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_FFI_addr, 0, 1, FFI\\CData,
ZEND_ARG_OBJ_INFO(ZEND_SEND_PREFER_REF, ptr, FFI\\CData, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_sizeof, 0, 1, IS_LONG, 1)
ZEND_ARG_TYPE_INFO(ZEND_SEND_PREFER_REF, ptr, IS_OBJECT, 0)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_sizeof, 0, 1, IS_LONG, 0)
ZEND_ARG_OBJ_TYPE_MASK(ZEND_SEND_PREFER_REF, ptr, FFI\\CData|FFI\\CType, 0, NULL)
ZEND_END_ARG_INFO()
#define arginfo_class_FFI_alignof arginfo_class_FFI_sizeof
@@ -58,7 +58,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_memcpy, 0, 3, IS_VOID,
ZEND_ARG_TYPE_INFO(0, size, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_memcmp, 0, 3, IS_LONG, 1)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_memcmp, 0, 3, IS_LONG, 0)
ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, ptr1)
ZEND_ARG_INFO(ZEND_SEND_PREFER_REF, ptr2)
ZEND_ARG_TYPE_INFO(0, size, IS_LONG, 0)
@@ -70,7 +70,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_memset, 0, 3, IS_VOID,
ZEND_ARG_TYPE_INFO(0, size, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_string, 0, 1, IS_STRING, 1)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_FFI_string, 0, 1, IS_STRING, 0)
ZEND_ARG_OBJ_INFO(ZEND_SEND_PREFER_REF, ptr, FFI\\CData, 0)
ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, size, IS_LONG, 1, "null")
ZEND_END_ARG_INFO()
+1 -1
View File
@@ -1,4 +1,4 @@
VERSION=5.37
VERSION=5.39
if [[ ! -d libmagic.orig ]]; then
mkdir libmagic.orig
wget -O - ftp://ftp.astron.com/pub/file/file-$VERSION.tar.gz \
+57 -50
View File
@@ -1,6 +1,6 @@
diff -ur libmagic.orig/apprentice.c libmagic/apprentice.c
diff -u libmagic.orig/apprentice.c libmagic/apprentice.c
--- libmagic.orig/apprentice.c 2020-05-09 20:57:15.000000000 +0200
+++ libmagic/apprentice.c 2020-08-29 19:56:29.638061530 +0200
+++ libmagic/apprentice.c 2020-11-07 14:41:13.543842900 +0100
@@ -29,6 +29,8 @@
* apprentice - make one pass through /etc/magic, learning its secrets.
*/
@@ -927,9 +927,9 @@ diff -ur libmagic.orig/apprentice.c libmagic/apprentice.c
m->str_range = swap4(m->str_range);
m->str_flags = swap4(m->str_flags);
}
diff -ur libmagic.orig/ascmagic.c libmagic/ascmagic.c
diff -u libmagic.orig/ascmagic.c libmagic/ascmagic.c
--- libmagic.orig/ascmagic.c 2020-06-15 02:01:01.000000000 +0200
+++ libmagic/ascmagic.c 2020-08-29 02:05:56.212049441 +0200
+++ libmagic/ascmagic.c 2020-11-07 14:41:13.543842900 +0100
@@ -50,7 +50,7 @@
#define ISSPC(x) ((x) == ' ' || (x) == '\t' || (x) == '\r' || (x) == '\n' \
|| (x) == 0x85 || (x) == '\f')
@@ -993,9 +993,9 @@ diff -ur libmagic.orig/ascmagic.c libmagic/ascmagic.c
{
size_t i;
unsigned char *end = buf + len;
diff -ur libmagic.orig/buffer.c libmagic/buffer.c
diff -u libmagic.orig/buffer.c libmagic/buffer.c
--- libmagic.orig/buffer.c 2020-02-16 16:52:49.000000000 +0100
+++ libmagic/buffer.c 2020-08-29 02:05:56.212049441 +0200
+++ libmagic/buffer.c 2020-11-07 14:41:13.543842900 +0100
@@ -31,19 +31,23 @@
#endif /* lint */
@@ -1049,9 +1049,9 @@ diff -ur libmagic.orig/buffer.c libmagic/buffer.c
b->ebuf = NULL;
goto out;
}
diff -ur libmagic.orig/cdf.c libmagic/cdf.c
diff -u libmagic.orig/cdf.c libmagic/cdf.c
--- libmagic.orig/cdf.c 2019-09-30 17:42:50.000000000 +0200
+++ libmagic/cdf.c 2020-08-29 02:05:56.212049441 +0200
+++ libmagic/cdf.c 2020-11-07 14:41:13.559464400 +0100
@@ -43,7 +43,17 @@
#include <err.h>
#endif
@@ -1284,9 +1284,9 @@ diff -ur libmagic.orig/cdf.c libmagic/cdf.c
}
#endif
diff -ur libmagic.orig/cdf.h libmagic/cdf.h
diff -u libmagic.orig/cdf.h libmagic/cdf.h
--- libmagic.orig/cdf.h 2019-09-30 17:42:50.000000000 +0200
+++ libmagic/cdf.h 2020-07-04 12:40:36.663619335 +0200
+++ libmagic/cdf.h 2020-10-09 14:15:33.483358900 +0200
@@ -35,10 +35,10 @@
#ifndef _H_CDF_
#define _H_CDF_
@@ -1301,9 +1301,9 @@ diff -ur libmagic.orig/cdf.h libmagic/cdf.h
#endif
#ifdef __DJGPP__
#define timespec timeval
diff -ur libmagic.orig/cdf_time.c libmagic/cdf_time.c
diff -u libmagic.orig/cdf_time.c libmagic/cdf_time.c
--- libmagic.orig/cdf_time.c 2019-03-12 21:43:05.000000000 +0100
+++ libmagic/cdf_time.c 2020-07-04 12:40:36.667619309 +0200
+++ libmagic/cdf_time.c 2020-10-09 14:15:33.484360000 +0200
@@ -23,6 +23,7 @@
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
@@ -1330,9 +1330,9 @@ diff -ur libmagic.orig/cdf_time.c libmagic/cdf_time.c
if (ptr != NULL)
return buf;
(void)snprintf(buf, 26, "*Bad* %#16.16" INT64_T_FORMAT "x\n",
diff -ur libmagic.orig/compress.c libmagic/compress.c
diff -u libmagic.orig/compress.c libmagic/compress.c
--- libmagic.orig/compress.c 2020-05-31 02:11:06.000000000 +0200
+++ libmagic/compress.c 2020-08-29 02:05:56.212049441 +0200
+++ libmagic/compress.c 2020-11-07 14:41:13.559464400 +0100
@@ -51,7 +51,7 @@
#ifndef HAVE_SIG_T
typedef void (*sig_t)(int);
@@ -1467,9 +1467,9 @@ diff -ur libmagic.orig/compress.c libmagic/compress.c
}
#endif
+#endif
diff -ur libmagic.orig/der.c libmagic/der.c
diff -u libmagic.orig/der.c libmagic/der.c
--- libmagic.orig/der.c 2020-06-15 02:01:01.000000000 +0200
+++ libmagic/der.c 2020-08-29 11:56:12.303522747 +0200
+++ libmagic/der.c 2020-11-07 14:41:13.559464400 +0100
@@ -54,7 +54,9 @@
#include "magic.h"
#include "der.h"
@@ -1480,9 +1480,9 @@ diff -ur libmagic.orig/der.c libmagic/der.c
#include <sys/stat.h>
#include <err.h>
#endif
diff -ur libmagic.orig/elfclass.h libmagic/elfclass.h
diff -u libmagic.orig/elfclass.h libmagic/elfclass.h
--- libmagic.orig/elfclass.h 2019-02-20 02:30:19.000000000 +0100
+++ libmagic/elfclass.h 2020-07-04 12:40:36.667619309 +0200
+++ libmagic/elfclass.h 2020-10-09 14:15:33.488358700 +0200
@@ -41,7 +41,7 @@
return toomany(ms, "program headers", phnum);
flags |= FLAGS_IS_CORE;
@@ -1510,9 +1510,9 @@ diff -ur libmagic.orig/elfclass.h libmagic/elfclass.h
CAST(size_t, elf_getu16(swap, elfhdr.e_shentsize)),
fsize, elf_getu16(swap, elfhdr.e_machine),
CAST(int, elf_getu16(swap, elfhdr.e_shstrndx)),
diff -ur libmagic.orig/encoding.c libmagic/encoding.c
diff -u libmagic.orig/encoding.c libmagic/encoding.c
--- libmagic.orig/encoding.c 2019-06-10 23:34:41.000000000 +0200
+++ libmagic/encoding.c 2020-08-29 02:05:56.212049441 +0200
+++ libmagic/encoding.c 2020-11-07 14:41:13.559464400 +0100
@@ -43,14 +43,14 @@
#include <stdlib.h>
@@ -1700,9 +1700,9 @@ diff -ur libmagic.orig/encoding.c libmagic/encoding.c
if (ubf[*ulen - 1] == 0xfffe)
return 0;
diff -ur libmagic.orig/file.h libmagic/file.h
diff -u libmagic.orig/file.h libmagic/file.h
--- libmagic.orig/file.h 2020-06-15 02:01:01.000000000 +0200
+++ libmagic/file.h 2020-09-02 17:35:51.709611515 +0200
+++ libmagic/file.h 2020-11-24 13:44:41.506472900 +0100
@@ -33,17 +33,13 @@
#ifndef __file_h__
#define __file_h__
@@ -1725,7 +1725,7 @@ diff -ur libmagic.orig/file.h libmagic/file.h
#ifndef __STDC_LIMIT_MACROS
#define __STDC_LIMIT_MACROS
@@ -79,10 +75,11 @@
@@ -79,23 +75,26 @@
#include <stdio.h> /* Include that here, to make sure __P gets defined */
#include <errno.h>
#include <fcntl.h> /* For open and flags */
@@ -1740,7 +1740,14 @@ diff -ur libmagic.orig/file.h libmagic/file.h
#include <sys/param.h>
#endif
/* Do this here and now, because struct stat gets re-defined on solaris */
@@ -95,7 +92,7 @@
#include <sys/stat.h>
#include <stdarg.h>
+#define abort() zend_error_noreturn(E_ERROR, "fatal libmagic error")
+
#define ENABLE_CONDITIONALS
#ifndef MAGIC
#define MAGIC "/etc/magic"
#endif
@@ -1749,7 +1756,7 @@ diff -ur libmagic.orig/file.h libmagic/file.h
#define PATHSEP ';'
#else
#define PATHSEP ':'
@@ -129,12 +126,6 @@
@@ -129,12 +128,6 @@
#endif
#endif
@@ -1762,7 +1769,7 @@ diff -ur libmagic.orig/file.h libmagic/file.h
#ifndef MIN
#define MIN(a,b) (((a) < (b)) ? (a) : (b))
#endif
@@ -161,10 +152,10 @@
@@ -161,10 +154,10 @@
struct buffer {
int fd;
@@ -1775,7 +1782,7 @@ diff -ur libmagic.orig/file.h libmagic/file.h
void *ebuf;
size_t elen;
};
@@ -258,7 +249,7 @@
@@ -258,7 +251,7 @@
#define FILE_OFFSET 50
#define FILE_NAMES_SIZE 51 /* size of array to contain all names */
@@ -1784,7 +1791,7 @@ diff -ur libmagic.orig/file.h libmagic/file.h
((t) == FILE_STRING || \
(t) == FILE_PSTRING || \
(t) == FILE_BESTRING16 || \
@@ -464,21 +455,17 @@
@@ -464,21 +457,17 @@
};
/* Type for Unicode characters */
@@ -1810,7 +1817,7 @@ diff -ur libmagic.orig/file.h libmagic/file.h
protected int file_separator(struct magic_set *);
protected char *file_copystr(char *, size_t, size_t, const char *);
protected int file_checkfmt(char *, size_t, const char *);
@@ -486,48 +473,42 @@
@@ -486,48 +475,42 @@
protected int file_print_guid(char *, size_t, const uint64_t *);
protected int file_parse_guid(const char *, uint64_t *);
protected int file_replace(struct magic_set *, const char *, const char *);
@@ -1867,7 +1874,7 @@ diff -ur libmagic.orig/file.h libmagic/file.h
size_t *);
protected size_t file_pstring_length_size(struct magic_set *,
const struct magic *);
@@ -539,34 +520,12 @@
@@ -539,34 +522,12 @@
size_t);
#endif /* __EMX__ */
@@ -1904,7 +1911,7 @@ diff -ur libmagic.orig/file.h libmagic/file.h
typedef struct {
char *buf;
@@ -582,23 +541,10 @@
@@ -582,23 +543,10 @@
extern const size_t file_nnames;
#endif
@@ -1930,7 +1937,7 @@ diff -ur libmagic.orig/file.h libmagic/file.h
size_t strlcat(char *, const char *, size_t);
#endif
#ifndef HAVE_STRCASESTR
@@ -614,39 +560,6 @@
@@ -614,39 +562,6 @@
#ifndef HAVE_ASCTIME_R
char *asctime_r(const struct tm *, char *);
#endif
@@ -1970,7 +1977,7 @@ diff -ur libmagic.orig/file.h libmagic/file.h
#if defined(HAVE_MMAP) && defined(HAVE_SYS_MMAN_H) && !defined(QUICK)
#define QUICK
@@ -676,4 +589,16 @@
@@ -676,4 +591,16 @@
#define __RCSID(a)
#endif
@@ -1987,9 +1994,9 @@ diff -ur libmagic.orig/file.h libmagic/file.h
+#endif
+
#endif /* __file_h__ */
diff -ur libmagic.orig/fsmagic.c libmagic/fsmagic.c
diff -u libmagic.orig/fsmagic.c libmagic/fsmagic.c
--- libmagic.orig/fsmagic.c 2019-07-16 15:30:32.000000000 +0200
+++ libmagic/fsmagic.c 2020-08-29 02:05:56.212049441 +0200
+++ libmagic/fsmagic.c 2020-11-07 14:41:13.559464400 +0100
@@ -66,26 +66,10 @@
# define minor(dev) ((dev) & 0xff)
#endif
@@ -2280,9 +2287,9 @@ diff -ur libmagic.orig/fsmagic.c libmagic/fsmagic.c
#ifdef S_IFSOCK
#ifndef __COHERENT__
case S_IFSOCK:
diff -ur libmagic.orig/funcs.c libmagic/funcs.c
diff -u libmagic.orig/funcs.c libmagic/funcs.c
--- libmagic.orig/funcs.c 2020-02-20 16:50:20.000000000 +0100
+++ libmagic/funcs.c 2020-08-29 11:56:12.303522747 +0200
+++ libmagic/funcs.c 2020-11-07 14:41:13.559464400 +0100
@@ -48,6 +48,13 @@
#define SIZE_MAX ((size_t)~0)
#endif
@@ -2655,9 +2662,9 @@ diff -ur libmagic.orig/funcs.c libmagic/funcs.c
return rbuf;
}
diff -ur libmagic.orig/magic.c libmagic/magic.c
diff -u libmagic.orig/magic.c libmagic/magic.c
--- libmagic.orig/magic.c 2020-06-15 02:01:01.000000000 +0200
+++ libmagic/magic.c 2020-08-29 11:56:12.303522747 +0200
+++ libmagic/magic.c 2020-11-07 14:41:13.559464400 +0100
@@ -25,11 +25,6 @@
* SUCH DAMAGE.
*/
@@ -3131,9 +3138,9 @@ diff -ur libmagic.orig/magic.c libmagic/magic.c
return NULL;
}
return file_getbuffer(ms);
diff -ur libmagic.orig/magic.h libmagic/magic.h
--- libmagic.orig/magic.h 2020-06-29 01:13:35.424557511 +0200
+++ libmagic/magic.h 2020-08-29 02:05:56.212049441 +0200
diff -u libmagic.orig/magic.h libmagic/magic.h
--- libmagic.orig/magic.h 2020-11-24 13:45:15.355600300 +0100
+++ libmagic/magic.h 2020-11-07 14:41:13.559464400 +0100
@@ -126,6 +126,7 @@
const char *magic_getpath(const char *, int);
@@ -3142,9 +3149,9 @@ diff -ur libmagic.orig/magic.h libmagic/magic.h
const char *magic_descriptor(magic_t, int);
const char *magic_buffer(magic_t, const void *, size_t);
diff -ur libmagic.orig/print.c libmagic/print.c
diff -u libmagic.orig/print.c libmagic/print.c
--- libmagic.orig/print.c 2020-05-09 20:57:15.000000000 +0200
+++ libmagic/print.c 2020-08-29 11:56:12.303522747 +0200
+++ libmagic/print.c 2020-11-07 14:41:13.559464400 +0100
@@ -28,6 +28,7 @@
/*
* print.c - debugging printout routines
@@ -3207,9 +3214,9 @@ diff -ur libmagic.orig/print.c libmagic/print.c
if (pp == NULL)
goto out;
diff -ur libmagic.orig/readcdf.c libmagic/readcdf.c
diff -u libmagic.orig/readcdf.c libmagic/readcdf.c
--- libmagic.orig/readcdf.c 2019-09-30 17:42:50.000000000 +0200
+++ libmagic/readcdf.c 2020-08-29 02:05:56.212049441 +0200
+++ libmagic/readcdf.c 2020-11-07 14:41:13.559464400 +0100
@@ -31,7 +31,11 @@
#include <assert.h>
@@ -3331,9 +3338,9 @@ diff -ur libmagic.orig/readcdf.c libmagic/readcdf.c
out0:
/* If we handled it already, return */
if (i != -1)
diff -ur libmagic.orig/softmagic.c libmagic/softmagic.c
diff -u libmagic.orig/softmagic.c libmagic/softmagic.c
--- libmagic.orig/softmagic.c 2020-06-15 02:01:01.000000000 +0200
+++ libmagic/softmagic.c 2020-09-02 20:04:00.794667114 +0200
+++ libmagic/softmagic.c 2020-11-07 14:41:13.559464400 +0100
@@ -43,6 +43,10 @@
#include <time.h>
#include "der.h"
@@ -3682,9 +3689,9 @@ diff -ur libmagic.orig/softmagic.c libmagic/softmagic.c
break;
}
case FILE_INDIRECT:
diff -ur libmagic.orig/strcasestr.c libmagic/strcasestr.c
diff -u libmagic.orig/strcasestr.c libmagic/strcasestr.c
--- libmagic.orig/strcasestr.c 2014-09-11 17:05:33.000000000 +0200
+++ libmagic/strcasestr.c 2020-07-04 12:40:36.675619260 +0200
+++ libmagic/strcasestr.c 2020-10-09 14:15:33.499288400 +0200
@@ -39,6 +39,8 @@
#include "file.h"
+2
View File
@@ -86,6 +86,8 @@
#include <sys/stat.h>
#include <stdarg.h>
#define abort() zend_error_noreturn(E_ERROR, "fatal libmagic error")
#define ENABLE_CONDITIONALS
#ifndef MAGIC
+50
View File
@@ -0,0 +1,50 @@
0 string 1
>1 regex \^[0-9:,\ ]*-->[0-9:,\ ]* SubRip File
!:mime text/x-srt
0 lelong 0xc3cbc6c5 RISC OS Chunk data
>12 string OBJ_ \b, AOF object
>12 string LIB_ \b, ALF library
0 name mach-o \b [
>0 use mach-o-cpu \b
>(8.L) indirect 8 \b:
>0 belong x \b]
0 belong 0xcafed00d JAR compressed with pack200,
>5 byte x version %d.
>4 byte x \b%d
!:mime application/x-java-pack200
# Objective-C
0 regex \^#import Objective-C source text
!:strength + 25
!:mime text/x-objective-c
0 string \x20\x20\x20\x20\x20\x20\x20\x20-:\x20\x20\x20\ 0:Source:
>&0 search/128 \x20\x20\x20\x20\x20\x20\x20\x20-:\x20\x20\x20\ 0:Graph:
>>&0 search/128 \x20\x20\x20\x20\x20\x20\x20\x20-:\x20\x20\x20\ 0:Data: GCOV coverage report
0 name certinfo
>0 der seq
>>&0 der set
>>>&0 der seq
>>>>&0 der obj_id3=550406
>>>>&0 der prt_str=x \b, countryName=%s
>>&0 der set
>>>&0 der seq
>>>>&0 der obj_id3=550408
>>>>&0 der utf8_str=x \b, stateOrProvinceName=%s
>>&0 der set
>>>&0 der seq
>>>>&0 der obj_id3=55040a
>>>>&0 der utf8_str=x \b, organizationName=%s
>>&0 der set
>>>&0 der seq
>>>>&0 der obj_id3=550403
>>>>&0 der utf8_str=x \b, commonName=%s
>>&0 der seq
0 search/1 FONT ASCII vfont text
0 short 0436 Berkeley vfont data
0 short 017001 byte-swapped Berkeley vfont data
+14
View File
@@ -0,0 +1,14 @@
--TEST--
Bug #77961 (finfo_open crafted magic parsing SIGABRT)
--SKIPIF--
<?php
if (!extension_loaded('fileinfo')) die('skip fileinfo extension not available');
?>
--FILE--
<?php
finfo_open(FILEINFO_NONE, __DIR__ . '/bug77961.magic');
?>
--EXPECTF--
Warning: finfo_open(): Expected numeric type got `indirect' in %s on line %d
Fatal error: fatal libmagic error in %s on line %d
+26
View File
@@ -233,6 +233,9 @@ void php_filter_int(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
p++; len--;
if (allow_hex && (*p == 'x' || *p == 'X')) {
p++; len--;
if (len == 0) {
RETURN_VALIDATION_FAILED
}
if (php_filter_parse_hex(p, len, &ctx_value) < 0) {
error = 1;
}
@@ -553,6 +556,22 @@ void php_filter_validate_domain(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
}
/* }}} */
static int is_userinfo_valid(zend_string *str)
{
const char *valid = "-._~!$&'()*+,;=:";
const char *p = ZSTR_VAL(str);
while (p - ZSTR_VAL(str) < ZSTR_LEN(str)) {
if (isalpha(*p) || isdigit(*p) || strchr(valid, *p)) {
p++;
} else if (*p == '%' && p - ZSTR_VAL(str) <= ZSTR_LEN(str) - 3 && isdigit(*(p+1)) && isxdigit(*(p+2))) {
p += 3;
} else {
return 0;
}
}
return 1;
}
void php_filter_validate_url(PHP_INPUT_FILTER_PARAM_DECL) /* {{{ */
{
php_url *url;
@@ -608,6 +627,13 @@ bad_url:
php_url_free(url);
RETURN_VALIDATION_FAILED
}
if (url->user != NULL && !is_userinfo_valid(url->user)) {
php_url_free(url);
RETURN_VALIDATION_FAILED
}
php_url_free(url);
}
/* }}} */
+15
View File
@@ -0,0 +1,15 @@
--TEST--
Bug #77423 (parse_url() will deliver a wrong host to user)
--FILE--
<?php
$urls = array(
"http://php.net\@aliyun.com/aaa.do",
"https://example.com\uFF03@bing.com",
);
foreach ($urls as $url) {
var_dump(filter_var($url, FILTER_VALIDATE_URL));
}
?>
--EXPECT--
bool(false)
bool(false)
+18
View File
@@ -0,0 +1,18 @@
--TEST--
Bug #80584: "0x" and "0X" are considered valid hex numbers by filter_var()
--SKIPIF--
<?php
if (!extension_loaded('filter')) die('skip filter extension not available');
?>
--FILE--
<?php
var_dump(filter_var('0x', FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX));
var_dump(filter_var('0X', FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX));
var_dump(filter_var('', FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX));
var_dump(filter_var('0', FILTER_VALIDATE_INT, FILTER_FLAG_ALLOW_HEX));
?>
--EXPECT--
bool(false)
bool(false)
bool(false)
int(0)
+3 -2
View File
@@ -1483,8 +1483,9 @@ PHP_FUNCTION(imagecreatefromstring)
}
if (ZSTR_LEN(data) < sizeof(sig)) {
zend_argument_value_error(1, "cannot be empty");
RETURN_THROWS();
/* Handle this the same way as an unknown image type. */
php_error_docref(NULL, E_WARNING, "Data is not in a recognized format");
RETURN_FALSE;
}
memcpy(sig, ZSTR_VAL(data), sizeof(sig));
+3 -2
View File
@@ -62,6 +62,7 @@ $im = imagecreatefromstring(' asdf jklp foo');
--EXPECTF--
createfromstring truecolor png: ok
createfromstring palette png: ok
imagecreatefromstring(): Argument #1 ($data) cannot be empty
Warning: imagecreatefromstring(): Data is not in a recognized format in %screatefromstring.php on line %d
Warning: imagecreatefromstring(): Data is not in a recognized format in %s on line %d
Warning: imagecreatefromstring(): Data is not in a recognized format in %s on line %d
+10 -5
View File
@@ -174,7 +174,7 @@ if (IS_GMP(zval)) { \
gmp_create(return_value, &gmpnumber)
static void gmp_strval(zval *result, mpz_t gmpnum, int base);
static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos);
static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos);
static void gmp_cmp(zval *return_value, zval *a_arg, zval *b_arg);
/*
@@ -429,9 +429,14 @@ static int gmp_compare(zval *op1, zval *op2) /* {{{ */
zval result;
gmp_cmp(&result, op1, op2);
if (Z_TYPE(result) == IS_FALSE) {
/* An error/exception occurs if one of the operands is not a numeric string
* or an object which is different from GMP */
if (EG(exception)) {
return 1;
}
/* result can only be a zend_long if gmp_cmp hasn't thrown an Error */
ZEND_ASSERT(Z_TYPE(result) == IS_LONG);
return Z_LVAL(result);
}
/* }}} */
@@ -585,7 +590,7 @@ ZEND_MODULE_INFO_D(gmp)
/* {{{ convert_to_gmp
* Convert zval to be gmp number */
static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos)
static zend_result convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t arg_pos)
{
switch (Z_TYPE_P(val)) {
case IS_LONG:
@@ -596,7 +601,7 @@ static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t a
zend_bool skip_lead = 0;
int ret;
if (Z_STRLEN_P(val) > 2 && numstr[0] == '0') {
if (Z_STRLEN_P(val) >= 2 && numstr[0] == '0') {
if ((base == 0 || base == 16) && (numstr[1] == 'x' || numstr[1] == 'X')) {
base = 16;
skip_lead = 1;
@@ -614,7 +619,7 @@ static int convert_to_gmp(mpz_t gmpnumber, zval *val, zend_long base, uint32_t a
"Cannot convert variable to GMP, it is not an integer string");
return FAILURE;
}
zend_argument_type_error(arg_pos, "is not an integer string");
zend_argument_value_error(arg_pos, "is not an integer string");
return FAILURE;
}
+1 -1
View File
@@ -25,7 +25,7 @@ Check for number base recognition
$test[] = gmp_init("0x4d2", 16);
try {
$test[] = gmp_init("4d2");
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
$test[] = gmp_init("4d2", 16);
+1 -1
View File
@@ -7,7 +7,7 @@ Bug #66872: Crash when passing string to gmp_testbit
try {
var_dump(gmp_testbit("abc", 1));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
+222
View File
@@ -0,0 +1,222 @@
--TEST--
Bug #80560: Strings containing only a base prefix return 0 object
--SKIPIF--
<?php if (!extension_loaded("gmp")) print "skip"; ?>
--FILE--
<?php
$functions1 = [
'gmp_init',
'gmp_export',
'gmp_intval',
'gmp_strval',
'gmp_neg',
'gmp_abs',
'gmp_fact',
'gmp_sqrt',
'gmp_sqrtrem',
'gmp_perfect_square',
'gmp_perfect_power',
'gmp_prob_prime',
'gmp_sign',
'gmp_random_seed',
'gmp_popcount',
'gmp_com',
'gmp_nextprime',
];
$functions1_need_int_2 = [
'gmp_testbit',
'gmp_scan0',
'gmp_scan1',
'gmp_binomial',
'gmp_root',
'gmp_rootrem',
'gmp_pow',
];
$functions2 = [
'gmp_add',
'gmp_sub',
'gmp_mul',
'gmp_div',
'gmp_div_q',
'gmp_div_r',
'gmp_div_qr',
'gmp_divexact',
'gmp_mod',
'gmp_gcd',
'gmp_gcdext',
'gmp_lcm',
'gmp_invert',
'gmp_jacobi',
'gmp_legendre',
'gmp_kronecker',
'gmp_cmp',
'gmp_random_range',
'gmp_and',
'gmp_or',
'gmp_xor',
'gmp_hamdist',
];
$functions3 = [
'gmp_powm',
];
echo 'Explicit base with gmp_init:', \PHP_EOL;
echo 'Hexadecimal', \PHP_EOL;
try {
var_dump(gmp_init('0X', 16));
} catch (\ValueError $e) {
echo $e->getMessage(), \PHP_EOL;
}
try {
var_dump(gmp_init('0x', 16));
} catch (\ValueError $e) {
echo $e->getMessage(), \PHP_EOL;
}
echo 'Binary', \PHP_EOL;
try {
var_dump(gmp_init('0B', 2));
} catch (\ValueError $e) {
echo $e->getMessage(), \PHP_EOL;
}
try {
var_dump(gmp_init('0b', 2));
} catch (\ValueError $e) {
echo $e->getMessage(), \PHP_EOL;
}
echo 'Fuzzing gmp functions:', \PHP_EOL;
foreach ($functions1 as $function) {
try {
$function('0B');
echo $function, ' failed with 0B', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0b');
echo $function, ' failed with 0b', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0X');
echo $function, ' failed with 0X', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0x');
echo $function, ' failed with 0x', \PHP_EOL;
} catch (\ValueError) { }
}
foreach ($functions1_need_int_2 as $function) {
try {
$function('0B', 1);
echo $function, ' failed with 0B', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0b', 1);
echo $function, ' failed with 0b', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0X', 1);
echo $function, ' failed with 0X', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0x', 1);
echo $function, ' failed with 0x', \PHP_EOL;
} catch (\ValueError) { }
}
foreach ($functions2 as $function) {
try {
$function('0B', 1);
echo $function, ' arg 1 failed with 0B', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0b', 1);
echo $function, ' arg 1 failed with 0b', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0X', 1);
echo $function, ' arg 1 failed with 0X', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0x', 1);
echo $function, ' arg 1 failed with 0x', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, '0B');
echo $function, ' arg 2 failed with 0B', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, '0b');
echo $function, ' arg 2 failed with 0b', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, '0X');
echo $function, ' arg 2 failed with 0X', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, '0x');
echo $function, ' arg 2 failed with 0x', \PHP_EOL;
} catch (\ValueError) { }
}
foreach ($functions3 as $function) {
try {
$function('0B', 1, 1);
echo $function, ' arg 1 failed with 0B', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0b', 1, 1);
echo $function, ' arg 1 failed with 0b', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0X', 1, 1);
echo $function, ' arg 1 failed with 0X', \PHP_EOL;
} catch (\ValueError) { }
try {
$function('0x', 1, 1);
echo $function, ' arg 1 failed with 0x', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, '0B', 1);
echo $function, ' arg 2 failed with 0B', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, '0b', 1);
echo $function, ' arg 2 failed with 0b', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, '0X', 1);
echo $function, ' arg 2 failed with 0X', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, '0x', 1);
echo $function, ' arg 2 failed with 0x', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, 1, '0B');
echo $function, ' arg 3 failed with 0B', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, 1, '0b');
echo $function, ' arg 3 failed with 0b', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, 1, '0X');
echo $function, ' arg 3 failed with 0X', \PHP_EOL;
} catch (\ValueError) { }
try {
$function(1, 1, '0x');
echo $function, ' arg 3 failed with 0x', \PHP_EOL;
} catch (\ValueError) { }
}
echo "Done\n";
?>
--EXPECT--
Explicit base with gmp_init:
Hexadecimal
gmp_init(): Argument #1 ($num) is not an integer string
gmp_init(): Argument #1 ($num) is not an integer string
Binary
gmp_init(): Argument #1 ($num) is not an integer string
gmp_init(): Argument #1 ($num) is not an integer string
Fuzzing gmp functions:
Done
+23
View File
@@ -0,0 +1,23 @@
--TEST--
Invalid comparison with a GMP object
--SKIPIF--
<?php if (!extension_loaded("gmp")) print "skip"; ?>
--FILE--
<?php
try {
var_dump("hapfegfbu" > gmp_init(0));
} catch (\Error $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
try {
var_dump((new DateTime()) > gmp_init(0));
} catch (\Error $e) {
echo $e::class, ': ', $e->getMessage(), \PHP_EOL;
}
?>
--EXPECT--
ValueError: main(): Argument #2 is not an integer string
TypeError: main(): Argument #2 must be of type GMP|string|int, DateTime given
+3 -3
View File
@@ -7,7 +7,7 @@ gmp_abs() basic tests
try {
var_dump(gmp_strval(gmp_abs("")));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
var_dump(gmp_strval(gmp_abs("0")));
@@ -24,13 +24,13 @@ var_dump(gmp_strval(gmp_abs("0000")));
try {
// Base 8
var_dump(gmp_strval(gmp_abs("09876543")));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
try {
// Base 8
var_dump(gmp_strval(gmp_abs("-099987654")));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
+1 -1
View File
@@ -13,7 +13,7 @@ var_dump(gmp_strval(gmp_and(4545, -20)));
try {
var_dump(gmp_strval(gmp_and("test", "no test")));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
+1 -1
View File
@@ -9,7 +9,7 @@ var_dump(gmp_strval(gmp_com(0)));
var_dump(gmp_strval(gmp_com("0")));
try {
var_dump(gmp_strval(gmp_com("test")));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
var_dump(gmp_strval(gmp_com("2394876545678")));
+1 -1
View File
@@ -8,7 +8,7 @@ gmp_fact() basic tests
var_dump(gmp_strval(gmp_fact(0)));
try {
var_dump(gmp_strval(gmp_fact("")));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
var_dump(gmp_strval(gmp_fact("0")));
+3 -3
View File
@@ -15,17 +15,17 @@ try {
try {
var_dump(gmp_init("",36));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
try {
var_dump(gmp_init("foo",3));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
try {
var_dump(gmp_strval(gmp_init("993247326237679187178",3)));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
+2 -2
View File
@@ -16,7 +16,7 @@ var_dump(gmp_intval($g));
try {
var_dump(gmp_intval(""));
} catch (TypeError $e) {
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
try {
@@ -31,7 +31,7 @@ try {
}
try {
var_dump(gmp_intval("1.0001"));
} catch (TypeError $e) {
} catch (ValueError $e) {
echo $e->getMessage(), "\n";
}
+1 -1
View File
@@ -7,7 +7,7 @@ gmp_mod tests()
try {
var_dump(gmp_mod("",""));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
var_dump(gmp_mod(0,1));
+1 -1
View File
@@ -12,7 +12,7 @@ var_dump(gmp_intval(gmp_neg("-1")));
try {
var_dump(gmp_intval(gmp_neg("")));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
+1 -1
View File
@@ -25,7 +25,7 @@ try {
try {
$n = gmp_nextprime("");
var_dump(gmp_strval($n));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
try {
+1 -1
View File
@@ -13,7 +13,7 @@ var_dump(gmp_strval(gmp_or(4545, -20)));
try {
var_dump(gmp_strval(gmp_or("test", "no test")));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
+1 -1
View File
@@ -108,7 +108,7 @@ var_dump(gmp_strval(gmp_random_range(-10000, 0)));
// standard non conversion error
try {
var_dump(gmp_random_seed('not a number'));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
+2 -2
View File
@@ -13,13 +13,13 @@ var_dump(gmp_sign("-34535345345"));
try {
var_dump(gmp_sign("+34534573457345"));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
try {
$n = gmp_init("098909878976786545");
var_dump(gmp_sign($n));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
try {
+1 -1
View File
@@ -7,7 +7,7 @@ gmp_strval() tests
try {
var_dump(gmp_strval(""));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
try {
+1 -1
View File
@@ -7,7 +7,7 @@ gmp_sub() tests
try {
var_dump(gmp_sub("", ""));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
try {
+1 -1
View File
@@ -13,7 +13,7 @@ var_dump(gmp_strval(gmp_xor(4545, -20)));
try {
var_dump(gmp_strval(gmp_xor("test", "no test")));
} catch (\TypeError $e) {
} catch (\ValueError $e) {
echo $e->getMessage() . \PHP_EOL;
}
+53 -88
View File
@@ -152,6 +152,28 @@ static int le_imap;
RETURN_FALSE; \
} \
#define PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgindex, arg_pos) \
if (msgindex < 1) { \
zend_argument_value_error(arg_pos, "must be greater than 0"); \
RETURN_THROWS(); \
} \
#define PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgindex, arg_pos, func_flags, uid_flag) \
if (func_flags & uid_flag) { \
/* This should be cached; if it causes an extra RTT to the IMAP server, */ \
/* then that's the price we pay for making sure we don't crash. */ \
unsigned int msg_no_from_uid = mail_msgno(imap_le_struct->imap_stream, msgindex); \
if (msg_no_from_uid == 0) { \
php_error_docref(NULL, E_WARNING, "UID does not exist"); \
RETURN_FALSE; \
} \
} else { \
if (((unsigned) msgindex) > imap_le_struct->imap_stream->nmsgs) { \
php_error_docref(NULL, E_WARNING, "Bad message number"); \
RETURN_FALSE; \
} \
} \
/* {{{ mail_close_it */
static void mail_close_it(zend_resource *rsrc)
{
@@ -1258,7 +1280,6 @@ PHP_FUNCTION(imap_body)
zval *streamind;
zend_long msgno, flags = 0;
pils *imap_le_struct;
unsigned long msgindex;
char *body;
unsigned long body_len = 0;
@@ -1270,32 +1291,15 @@ PHP_FUNCTION(imap_body)
RETURN_THROWS();
}
if (msgno < 1) {
zend_argument_value_error(2, "must be greater than 0");
RETURN_THROWS();
}
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
zend_argument_value_error(3, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
RETURN_THROWS();
}
if (flags && (flags & FT_UID)) {
/* This should be cached; if it causes an extra RTT to the
IMAP server, then that's the price we pay for making
sure we don't crash. */
msgindex = mail_msgno(imap_le_struct->imap_stream, msgno);
if (msgindex == 0) {
php_error_docref(NULL, E_WARNING, "UID does not exist");
RETURN_FALSE;
}
} else {
msgindex = (unsigned long) msgno;
}
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
PHP_IMAP_CHECK_MSGNO(msgindex, 2);
/* TODO Shouldn't this pass msgindex??? */
body = mail_fetchtext_full (imap_le_struct->imap_stream, msgno, &body_len, flags);
if (body_len == 0) {
RETVAL_EMPTY_STRING();
@@ -1305,6 +1309,7 @@ PHP_FUNCTION(imap_body)
}
/* }}} */
/* TODO UID Tests */
/* {{{ Copy specified message to a mailbox */
PHP_FUNCTION(imap_mail_copy)
{
@@ -1334,6 +1339,7 @@ PHP_FUNCTION(imap_mail_copy)
}
/* }}} */
/* TODO UID Tests */
/* {{{ Move specified message to a mailbox */
PHP_FUNCTION(imap_mail_move)
{
@@ -1605,13 +1611,15 @@ PHP_FUNCTION(imap_delete)
RETURN_THROWS();
}
// TODO Check sequence validity?
if (flags && ((flags & ~FT_UID) != 0)) {
zend_argument_value_error(3, "must be FT_UID or 0");
RETURN_THROWS();
}
mail_setflag_full(imap_le_struct->imap_stream, ZSTR_VAL(sequence), "\\DELETED", flags);
RETVAL_TRUE;
RETURN_TRUE;
}
/* }}} */
@@ -1882,7 +1890,6 @@ PHP_FUNCTION(imap_fetchstructure)
zend_long msgno, flags = 0;
pils *imap_le_struct;
BODY *body;
int msgindex;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|l", &streamind, &msgno, &flags) == FAILURE) {
RETURN_THROWS();
@@ -1892,34 +1899,18 @@ PHP_FUNCTION(imap_fetchstructure)
RETURN_THROWS();
}
if (msgno < 1) {
zend_argument_value_error(2, "must be greater than 0");
RETURN_THROWS();
}
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
if (flags && ((flags & ~FT_UID) != 0)) {
zend_argument_value_error(3, "must be FT_UID or 0");
RETURN_THROWS();
}
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
object_init(return_value);
if (flags & FT_UID) {
/* This should be cached; if it causes an extra RTT to the
IMAP server, then that's the price we pay for making
sure we don't crash. */
msgindex = mail_msgno(imap_le_struct->imap_stream, msgno);
if (msgindex == 0) {
php_error_docref(NULL, E_WARNING, "UID does not exist");
RETURN_FALSE;
}
} else {
msgindex = msgno;
}
PHP_IMAP_CHECK_MSGNO(msgindex, 2);
/* TODO Shouldn't this pass msgindex??? */
mail_fetchstructure_full(imap_le_struct->imap_stream, msgno, &body , (ZEND_NUM_ARGS() == 3 ? flags : NIL));
mail_fetchstructure_full(imap_le_struct->imap_stream, msgno, &body , flags);
if (!body) {
php_error_docref(NULL, E_WARNING, "No body information available");
@@ -1948,20 +1939,14 @@ PHP_FUNCTION(imap_fetchbody)
RETURN_THROWS();
}
if (msgno < 1) {
zend_argument_value_error(2, "must be greater than 0");
RETURN_THROWS();
}
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
zend_argument_value_error(4, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
RETURN_THROWS();
}
if (!(flags & FT_UID)) {
/* only perform the check if the msgno is a message number and not a UID */
PHP_IMAP_CHECK_MSGNO(msgno, 2);
}
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
body = mail_fetchbody_full(imap_le_struct->imap_stream, msgno, ZSTR_VAL(sec), &len, flags);
@@ -1989,24 +1974,18 @@ PHP_FUNCTION(imap_fetchmime)
RETURN_THROWS();
}
if (msgno < 1) {
zend_argument_value_error(2, "must be greater than 0");
if ((imap_le_struct = (pils *)zend_fetch_resource(Z_RES_P(streamind), "imap", le_imap)) == NULL) {
RETURN_THROWS();
}
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
zend_argument_value_error(4, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
RETURN_THROWS();
}
if ((imap_le_struct = (pils *)zend_fetch_resource(Z_RES_P(streamind), "imap", le_imap)) == NULL) {
RETURN_THROWS();
}
if (!(flags & FT_UID)) {
/* only perform the check if the msgno is a message number and not a UID */
PHP_IMAP_CHECK_MSGNO(msgno, 2);
}
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
body = mail_fetch_mime(imap_le_struct->imap_stream, msgno, ZSTR_VAL(sec), &len, flags);
@@ -2037,17 +2016,14 @@ PHP_FUNCTION(imap_savebody)
RETURN_THROWS();
}
PHP_IMAP_CHECK_MSGNO(msgno, 3);
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 3)
if (flags && ((flags & ~(FT_UID|FT_PEEK|FT_INTERNAL)) != 0)) {
zend_argument_value_error(5, "must be a bitmask of FT_UID, FT_PEEK, and FT_INTERNAL");
RETURN_THROWS();
}
// TODO Drop this?
if (!imap_le_struct) {
RETURN_FALSE;
}
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 3, flags, FT_UID);
switch (Z_TYPE_P(out))
{
@@ -2771,9 +2747,8 @@ PHP_FUNCTION(imap_sort)
PHP_FUNCTION(imap_fetchheader)
{
zval *streamind;
zend_long msgno, flags = 0L;
zend_long msgno, flags = 0;
pils *imap_le_struct;
int msgindex;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl|l", &streamind, &msgno, &flags) == FAILURE) {
RETURN_THROWS();
@@ -2783,30 +2758,16 @@ PHP_FUNCTION(imap_fetchheader)
RETURN_THROWS();
}
// TODO Check for msgno < 1 now or wait later for PHP_IMAP_CHECK_MSGNO check?
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_PRE_FLAG_CHECKS(msgno, 2);
if (flags && ((flags & ~(FT_UID|FT_INTERNAL|FT_PREFETCHTEXT)) != 0)) {
zend_argument_value_error(3, "must be a bitmask of FT_UID, FT_PREFETCHTEXT, and FT_INTERNAL");
RETURN_THROWS();
}
if (flags & FT_UID) {
/* This should be cached; if it causes an extra RTT to the
IMAP server, then that's the price we pay for making sure
we don't crash. */
msgindex = mail_msgno(imap_le_struct->imap_stream, msgno);
if (msgindex == 0) {
php_error_docref(NULL, E_WARNING, "UID does not exist");
RETURN_FALSE;
}
} else {
msgindex = msgno;
}
PHP_IMAP_CHECK_MSGNO_MAYBE_UID_POST_FLAG_CHECKS(msgno, 2, flags, FT_UID);
PHP_IMAP_CHECK_MSGNO(msgindex, 2);
/* TODO Check shouldn't this pass msgindex???? */
RETVAL_STRING(mail_fetchheader_full(imap_le_struct->imap_stream, msgno, NIL, NIL, (ZEND_NUM_ARGS() == 3 ? flags : NIL)));
RETVAL_STRING(mail_fetchheader_full(imap_le_struct->imap_stream, msgno, NIL, NIL, flags));
}
/* }}} */
@@ -2835,10 +2796,10 @@ PHP_FUNCTION(imap_uid)
PHP_FUNCTION(imap_msgno)
{
zval *streamind;
zend_long msgno;
zend_long msg_uid;
pils *imap_le_struct;
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &streamind, &msgno) == FAILURE) {
if (zend_parse_parameters(ZEND_NUM_ARGS(), "rl", &streamind, &msg_uid) == FAILURE) {
RETURN_THROWS();
}
@@ -2846,9 +2807,13 @@ PHP_FUNCTION(imap_msgno)
RETURN_THROWS();
}
PHP_IMAP_CHECK_MSGNO(msgno, 2);
/* Do NOT use the PHP_IMAP_CHECK_MSGNO() macro as UID cannot be checked for their upper bound. */
if (msg_uid < 1) {
zend_argument_value_error(2, "must be greater than 0");
RETURN_THROWS();
}
RETURN_LONG(mail_msgno(imap_le_struct->imap_stream, msgno));
RETURN_LONG(mail_msgno(imap_le_struct->imap_stream, msg_uid));
}
/* }}} */
+2 -2
View File
@@ -21,7 +21,7 @@ function imap_close($imap, int $flags = 0): bool {}
function imap_num_msg($imap): int|false {}
/** @param resource $imap */
function imap_num_recent($imap): int|false {}
function imap_num_recent($imap): int {}
/** @param resource $imap */
function imap_headers($imap): array|false {}
@@ -179,7 +179,7 @@ function imap_sort($imap, int $criteria, bool $reverse, int $flags = 0, ?string
function imap_uid($imap, int $message_num): int|false {}
/** @param resource $imap */
function imap_msgno($imap, int $message_uid): int|false {}
function imap_msgno($imap, int $message_uid): int {}
/** @param resource $imap */
function imap_list($imap, string $reference, string $pattern): array|false {}
+5 -3
View File
@@ -1,5 +1,5 @@
/* This is a generated file, edit the .stub.php file instead.
* Stub hash: 326cb0410034aecc702e9397cd88ef91adaa254c */
* Stub hash: d6d158112a802d867646b8f85402b8762599180b */
ZEND_BEGIN_ARG_INFO_EX(arginfo_imap_open, 0, 0, 3)
ZEND_ARG_TYPE_INFO(0, mailbox, IS_STRING, 0)
@@ -26,7 +26,9 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imap_num_msg, 0, 1, MAY_BE_LONG|
ZEND_ARG_INFO(0, imap)
ZEND_END_ARG_INFO()
#define arginfo_imap_num_recent arginfo_imap_num_msg
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imap_num_recent, 0, 1, IS_LONG, 0)
ZEND_ARG_INFO(0, imap)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imap_headers, 0, 1, MAY_BE_ARRAY|MAY_BE_FALSE)
ZEND_ARG_INFO(0, imap)
@@ -218,7 +220,7 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imap_uid, 0, 2, MAY_BE_LONG|MAY_
ZEND_ARG_TYPE_INFO(0, message_num, IS_LONG, 0)
ZEND_END_ARG_INFO()
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_imap_msgno, 0, 2, MAY_BE_LONG|MAY_BE_FALSE)
ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_imap_msgno, 0, 2, IS_LONG, 0)
ZEND_ARG_INFO(0, imap)
ZEND_ARG_TYPE_INFO(0, message_uid, IS_LONG, 0)
ZEND_END_ARG_INFO()
-1
View File
@@ -1 +0,0 @@
imap
+3 -3
View File
@@ -11,14 +11,14 @@ hMailServer on Windows. The tests are intended to be mailserver agnostic.
## Set-up tests on Ubuntu (checked on Ubuntu 18.04 (Bionic))
The necessary packages can be installed using the following command;
`apt-get install libc-client-dev libkrb5-dev dovecot-core dovecot-pop3d dovecot-imapd`
`apt-get install libc-client-dev libkrb5-dev dovecot-core dovecot-pop3d dovecot-imapd sendmail`
The build of PHP will need to be compiled with the following flags:
```
--with-imap --with-kerberos --with-imap-ssl
```
Then run the set-up script `ext/imap/tests/setup.sh` which will add the `vmail`
Then run the set-up script `ext/imap/tests/setup/setup.sh` which will add the `vmail`
group and user which is used by Dovecot for the mailbox. It will also copy the
`ext/imap/tests/dovecot.conf` and `ext/imap/tests/dovecotpass` to the correct
`ext/imap/tests/setup/dovecot.conf` and `ext/imap/tests/setup/dovecotpass` to the correct
location for Dovecot and restarts it for the new configuration to be enabled.
+1 -3
View File
@@ -2,9 +2,7 @@
Bug #31142 test #2 (imap_mail_compose() generates incorrect output)
--SKIPIF--
<?php
if (!extension_loaded("imap")) {
die("skip imap extension not available");
}
extension_loaded('imap') or die('skip imap extension not available in this build');
?>
--FILE--
<?php
+1 -3
View File
@@ -2,9 +2,7 @@
Bug #32589 (crash inside imap_mail_compose() function)
--SKIPIF--
<?php
if (!extension_loaded("imap")) {
die("skip imap extension not available");
}
extension_loaded('imap') or die('skip imap extension not available in this build');
?>
--FILE--
<?php
+27 -29
View File
@@ -2,45 +2,43 @@
Bug #35669 (imap_mail_compose() crashes with multipart-multiboundary-email)
--SKIPIF--
<?php
if (!extension_loaded("imap")) {
die("skip imap extension not available");
}
extension_loaded('imap') or die('skip imap extension not available in this build');
?>
--FILE--
<?php
$envelope["from"] = 'Santa <somewhere@northpole.gov>';
$envelope["to"] = 'The bad smurf <bad@smurf.com>';
$envelope['date'] = 'Wed, 04 Jan 2006 19:24:43 -0500';
$envelope["from"] = 'Santa <somewhere@northpole.gov>';
$envelope["to"] = 'The bad smurf <bad@smurf.com>';
$envelope['date'] = 'Wed, 04 Jan 2006 19:24:43 -0500';
$multipart["type"] = TYPEMULTIPART;
$multipart["subtype"] = "MIXED";
$body[] = $multipart; //add multipart stuff
$multipart["type"] = TYPEMULTIPART;
$multipart["subtype"] = "MIXED";
$body[] = $multipart; //add multipart stuff
$textpart["type"] = TYPEMULTIPART;
$textpart["subtype"] = "ALTERNATIVE";
$body[] = $textpart; //add body part
$textpart["type"] = TYPEMULTIPART;
$textpart["subtype"] = "ALTERNATIVE";
$body[] = $textpart; //add body part
$plain["type"] = TYPETEXT;
$plain["subtype"] = "PLAIN";
$plain["charset"] = "iso-8859-1";
$plain["encoding"] = ENCQUOTEDPRINTABLE;
$plain["description"] = "Plaintype part of message";
$plain['disposition'] = "inline";
$plain["contents.data"] = 'See mom, it will crash';
$plain["type"] = TYPETEXT;
$plain["subtype"] = "PLAIN";
$plain["charset"] = "iso-8859-1";
$plain["encoding"] = ENCQUOTEDPRINTABLE;
$plain["description"] = "Plaintype part of message";
$plain['disposition'] = "inline";
$plain["contents.data"] = 'See mom, it will crash';
$body[] = $plain; //next add plain text part
$body[] = $plain; //next add plain text part
$html["type"] = TYPETEXT;
$html["subtype"] = "HTML";
$html["charset"] = "iso-8859-1";
$html["encoding"] = ENCQUOTEDPRINTABLE;
$html["description"] = "HTML part of message";
$html['disposition'] = "inline";
$html["contents.data"] = 'See mom, it will <b>crash</b>';
$html["type"] = TYPETEXT;
$html["subtype"] = "HTML";
$html["charset"] = "iso-8859-1";
$html["encoding"] = ENCQUOTEDPRINTABLE;
$html["description"] = "HTML part of message";
$html['disposition'] = "inline";
$html["contents.data"] = 'See mom, it will <b>crash</b>';
$body[] = $html;
$body[] = $html;
echo imap_mail_compose($envelope, $body);
echo imap_mail_compose($envelope, $body);
?>
--EXPECTF--
Date: Wed, 04 Jan 2006 19:24:43 -0500
+4 -9
View File
@@ -2,19 +2,14 @@
Bug #44098 (imap_utf8() returns only capital letters)
--SKIPIF--
<?php
if (!extension_loaded("imap")) {
die("skip imap extension not available");
}
extension_loaded('imap') or die('skip imap extension not available in this build');
?>
--FILE--
<?php
$exp = 'Luzon®14 dot CoM';
$res = imap_utf8('=?iso-8859-1?b?THV6b26uMTQ=?= dot CoM');
if ($res != $exp) {
echo "failed: got <$res>, expected <exp>\n";
} else {
echo "ok";
}
var_dump($res);
?>
--EXPECT--
ok
string(17) "Luzon®14 dot CoM"
+1 -3
View File
@@ -2,9 +2,7 @@
Bug #45705 test #1 (imap rfc822_parse_adrlist() modifies passed address parameter)
--SKIPIF--
<?php
if (!extension_loaded("imap")) {
die("skip imap extension not available");
}
extension_loaded('imap') or die('skip imap extension not available in this build');
?>
--FILE--
<?php
+1 -3
View File
@@ -2,9 +2,7 @@
Bug #45705 test #2 (imap rfc822_parse_adrlist() modifies passed address parameter)
--SKIPIF--
<?php
if (!extension_loaded("imap")) {
die("skip imap extension not available");
}
extension_loaded('imap') or die('skip imap extension not available in this build');
?>
--FILE--
<?php
+1 -3
View File
@@ -2,9 +2,7 @@
Bug #53377 (imap_mime_header_decode() doesn't ignore \t during long MIME header unfolding)
--SKIPIF--
<?php
if (!extension_loaded("imap")) {
die("skip imap extension not available");
}
extension_loaded('imap') or die('skip imap extension not available in this build');
?>
--FILE--
<?php
+8 -5
View File
@@ -4,11 +4,11 @@ imap_open() DISABLE_AUTHENTICATOR ignores array param
<?php
extension_loaded('imap') or die('skip imap extension not available in this build');
require_once(__DIR__.'/imap_include.inc');
require_once(__DIR__. '/setup/imap_include.inc');
$in = @imap_open($default_mailbox, $username, $password, OP_HALFOPEN, 1);
$in = @imap_open(IMAP_SERVER_DEBUG, IMAP_MAILBOX_USERNAME, IMAP_MAILBOX_PASSWORD, OP_HALFOPEN, 1);
if (!$in) {
die("skip could not connect to mailbox $default_mailbox");
die("skip could not connect to mailbox " . IMAP_SERVER_DEBUG);
}
$kerberos = false;
if (is_array($errors = imap_errors())) {
@@ -22,16 +22,19 @@ if (!$kerberos) {
die("skip need a GSSAPI/Kerberos aware server");
}
?>
--CONFLICTS--
defaultmailbox
--FILE--
<?php
// TODO Test Kerberos on CI
$tests = array(
'Array' => array('DISABLE_AUTHENTICATOR' => array('GSSAPI','NTLM')),
'String' => array('DISABLE_AUTHENTICATOR' => 'GSSAPI'),
);
require_once(__DIR__.'/imap_include.inc');
require_once(__DIR__. '/setup/imap_include.inc');
foreach ($tests as $name => $testparams) {
echo "Test for $name\n";
$in = imap_open($default_mailbox, $username, $password, OP_HALFOPEN, 1, $testparams);
$in = imap_open(IMAP_SERVER_DEBUG, IMAP_MAILBOX_USERNAME, IMAP_MAILBOX_PASSWORD, OP_HALFOPEN, 1, $testparams);
if ($in) {
if (is_array($errors = imap_errors())) {
foreach ($errors as $err) {
+6 -5
View File
@@ -2,22 +2,23 @@
Bug #64076 (imap_sort() does not return FALSE on failure)
--SKIPIF--
<?php
require_once __DIR__ . '/skipif.inc';
require_once __DIR__ . '/setup/skipif.inc';
?>
--FILE--
<?php
require_once __DIR__ . '/imap_include.inc';
$stream = setup_test_mailbox('', 2);
require_once __DIR__ . '/setup/imap_include.inc';
$stream = setup_test_mailbox('bug64076', 2);
imap_errors(); // clear error stack
var_dump(imap_sort($stream, SORTFROM, 0, 0, 'UNSUPPORTED SEARCH CRITERIUM'));
var_dump(imap_errors() !== false);
?>
--CLEAN--
<?php
require_once __DIR__ . '/clean.inc';
$mailbox_suffix = 'bug64076';
require_once(__DIR__ . '/setup/clean.inc');
?>
--EXPECT--
Create a temporary mailbox and add 2 msgs
.. mailbox '{127.0.0.1:143/norsh}INBOX.phpttest' created
New mailbox created
bool(false)
bool(true)
+3 -3
View File
@@ -6,8 +6,8 @@ if (!extension_loaded('imap')) die('skip imap extension not available');
?>
--FILE--
<?php
imap_mail('1', 1, NULL);
@imap_mail('1', 1, NULL);
echo 'done'
?>
--EXPECTF--
Warning: imap_mail(): No message string in mail command in %s on line %d
%S
%Adone
Loaded 100 of 498 files, more files were not shown because too many files have changed in this diff. Show more