Compare commits

..
113 Commits
Author SHA1 Message Date
Derick Rethans 197a7083df Update versions for PHP 7.4.18 2021-04-27 14:35:40 +00:00
Derick Rethans 13389613fa Update NEWS for PHP 7.4.18 2021-04-27 14:35:40 +00:00
Derick Rethans f98f4875df Prepare for 7.4.18 2021-04-27 15:33:01 +01:00
Christoph M. Becker b1680c5fe3 Fix #80710: imap_mail_compose() header injection
Like `mail()` and `mb_send_mail()`, `imap_mail_compose()` must prevent
header injection.  For maximum backward compatibility, we still allow
header folding for general headers, and still accept trailing line
breaks for address lists.
2021-04-27 15:29:59 +01:00
Derick Rethans 8cb114413f Put back inadvertedly removed NEWS entries 2021-04-13 11:49:36 +01:00
Derick Rethans 1e0f53278d Update NEWS for PHP 7.4.18RC1 2021-04-13 10:24:25 +00:00
Derick Rethans d4f7e8cedc Prepare NEWS for 7.4.18RC1 2021-04-13 10:00:45 +01:00
Nikita Popov a1fdfa700b Fixed bug #80950
Function info for curl_exec() incorrect specified that the
function cannot return true. This is already fixed in PHP 8,
as the func info entry was removed there.
2021-04-12 16:05:37 +02:00
Christoph M. Becker 0a36d417e8 Fix #79812: Potential integer overflow in pcntl_exec()
We use the proper type, and make sure that no overflow can occur by
using `safe_emalloc()` (we can assume that neither string length is
`SIZE_MAX`).

Closes GH-6845.
2021-04-12 12:12:40 +02:00
David Carlier a04fac84e7 Disable ifunc support on openbsd
Enabling it leads to segfault when resolvers are used e.g.
php_stripslashes.

Closes GH-6851.
2021-04-12 11:27:50 +02:00
fishmore 600402d986 Update zend_alloc.c
Don't free main thunk.  It will crash.
2021-04-12 09:28:24 +03:00
Matteo Beccati 340a06778c Fix #80892: PDO::PARAM_INT is treated the same as PDO::PARAM_STR 2021-04-12 08:03:07 +02:00
Matteo Beccati da3a807f22 Increased test compatibility
The test expects no masked signals at the beginning, but when run as part
of a Bamboo build, SIGQUIT is already masked and the test fails.
2021-04-11 17:19:58 +02:00
Nikita Popov 454d297564 Fix gidlist allocation leak on error 2021-04-11 10:37:40 +02:00
Dmitry Stogov 7a8ffcec7d Fixed type inference for OP_DATA 2021-04-09 14:52:55 +03:00
Nikita Popov 29fa4d203a Don't mark non-refcounted phi as live
If the value is not refcounted, then it doesn't matter if the
FREE gets dropped.
2021-04-08 18:20:09 +02:00
Nikita Popov 0826a54836 Fix DCE of FREE of COALESCE
When encountering the following SSA graph:

    BB1:
    #2.T1 [string] = COALESCE #1.CV0($str) [null, string] BB2

    BB2:
    #5.T1 [string] = QM_ASSIGN string("")

    BB3:
    #7.X1 [string] = Phi(#2.X1 [string], #5.X1 [string])
    FREE #7.T1 [string]

We would currently determine that #7, #5 are dead, and eliminate
the FREE and QM_ASSIGN. However, we cannot eliminate #2, as
COALESCE is also responsible for control flow.

Fix this my marking all non-CV phis as live to start with. This
can be relaxed to check the kind of the source instruction, but
I couldn't immediately come up with a case where it would be
useful.
2021-04-08 17:01:13 +02:00
Remi Collet 25f5a1b2e1 Improve fix for #80783 2021-04-08 15:28:03 +02:00
Nikita Popov eebcfeb68e Support more than NGROUPS_MAX groups on macos
I suspect this is the cause for our recent CI failures. Apparently,
on macos it is possible for getgroups() to return more than
NGROUPS_MAX groups. We avoid an EINVAL in that case by fetching
the exact number of groups in advance. This should work on both
macos and posix systems.
2021-04-08 12:23:39 +02:00
Christoph M. Becker 0a181ca27a Update version in main/php_version.h as well
Otherwise the file is modified by each new build, what is confusing.
2021-04-07 12:45:21 +02:00
Christoph M. Becker 9688071679 Fix #80880: SSL_read on shutdown, ftp/proc_open
When `SSL_read()` after `SSL_shutdown()` fails with `SSL_ERROR_SYSCALL`,
we should not warn about this, because it is likely caused by the peer
having closed the connection without having sent a close_notify
shutdown alert.

Signed-off-by: Christoph M. Becker <cmbecker69@gmx.de>

Closes GH-6803.
2021-04-06 14:03:19 +02:00
Dylan K. Taylor 50f476591f .gdbinit: make zbacktrace show the correct stack when switching threads
I found this mainly to be a problem when working with threading
extensions. zbacktrace doesn't show the correct stack when switching
threads.

Closes GH-6814.
2021-04-05 21:10:52 +02:00
Dmitry Stogov 39d8fc1edc Changed PowerPC CPU registers used by Zend VM to work around GCC bug.
Old registers (r28/r29) might be clobbered by _restgpr routine used for return from C function compiled with -Os.
2021-03-31 13:10:21 +03:00
Rowan Tommins 206fd35a98 Handle reference zvals when outputting superglobals in phpinfo()
Fixes <https://bugs.php.net/80915>.

Closes GH-80915.

Signed-off-by: Christoph M. Becker <cmbecker69@gmx.de>
2021-03-30 13:49:22 +02:00
Christoph M. Becker 75cb678206 Fix #69668: SOAP special XML characters in namespace URIs not encoded
`xmlNewNs()` does not XML encode the passed `href`, so we need to do
that manually.

Closes GH-6804.

Signed-off-by: Christoph M. Becker <cmbecker69@gmx.de>
2021-03-29 14:17:55 +02:00
Christoph M. Becker 498eb8e052 Fix #73533: Invalid memory access in php_libxml_xmlCheckUTF8
A string passed to `php_libxml_xmlCheckUTF8()` may be longer than
1<<31-1 bytes, so we're better using a `size_t`.

Closes GH-6802.
2021-03-24 11:50:50 +01:00
Christoph M. Becker 688e56d0ac Properly initialize PS(mod) on RINIT
We need to do that in case a user handler has been set.  However, we
can't do that in `php_rinit_session_globals()` since that function is
called by PHP function `session_destroy()` too, but in that case we
don't want to reset PS(mod).

Closes GH-6795.
2021-03-23 13:12:19 +01:00
Christoph M. Becker 838951c2d6 Fix #80889: amendment
`session_set_save_handler()` may be called with callables instead of an
object; we need to cater to that as well.

We also extract a set_user_save_handler_ini() function to avoid code
duplication.

Closes GH-6796.
2021-03-22 22:17:35 +01:00
Jakub Zelenka bc7ea73da5 Use ServerClientTestCase in a test for default_socket_timeout=-1 2021-03-21 21:19:40 +00:00
Jakub Zelenka 538f95b1b7 Fix NEWS entry position for the latest FPM fix 2021-03-21 18:58:57 +00:00
Jakub Zelenka c483b59124 Fix bug #80024: Duplication of info about inherited socket after pool removing 2021-03-21 18:52:07 +00:00
Christoph M. Becker 06bfada99b Fix #80889: Cannot set save handler when save_handler is invalid
There is no need to require a (valid) save_handler to be set, when a
user handler is supposed to be set.  We just have to make sure, that
no user handler is already set in this case.

Closes GH-6788.
2021-03-19 16:59:54 +01:00
Christoph M. Becker bccca0b53a Fix #80783: PDO ODBC truncates BLOB records at every 256th byte
It is not guaranteed, that the driver inserts only a single NUL byte at
the end of the buffer.  Apparently, there is no way to find out the
actual data length in the buffer after calling `SQLGetData()`, so we
adjust after the next `SQLGetData()` call.

We also prevent PDO::ODBC_ATTR_ASSUME_UTF8 from fetching garbage, by
fetching all chunks with the same C type.

Closes GH-6716.
2021-03-18 15:13:27 +01:00
Nikita Popov 4be867e910 Fix locale switch back to C in pcre
The compile context is shared between patterns, so we need to set
the character tables unconditionally in case we switched from
a non-C locale to the C locale.
2021-03-18 10:48:43 +01:00
Christoph M. Becker a08847ab39 Fix #66783: UAF when appending DOMDocument to element
According to the DOM standard, elements may only contain element, text,
processing instruction and comment nodes[1].  It is also specified that
a HierarchyRequestError should be thrown if a document is to be
inserted[2].  We follow that standard, and prevent the use-after-free
this way.

[1] <https://dom.spec.whatwg.org/#node-trees>
[2] <https://dom.spec.whatwg.org/#mutation-algorithms>

Closes GH-6765.
2021-03-17 12:37:18 +01:00
Derick Rethans 4adc08a403 Fix build version too 2021-03-16 09:41:21 +00:00
Derick Rethans 5e4ee3d0bd NEWS for 7.4.18 2021-03-16 09:40:05 +00:00
Derick Rethans eb1d1fe373 Prepare for 7.4.17RC1 2021-03-16 09:33:33 +00:00
Christoph M. Becker f448b0e6dd Fix #80817: dba_popen() may cause segfault during RSHUTDOWN
We need to close persistent streams with the proper flag.
2021-03-15 18:37:44 +01:00
Dharman 282355efd5 Fix bug #80866
Closes GH-6774.
2021-03-15 14:47:45 +01:00
Dharman c93b461ad7 Fix bug #80837
The error needs to be reported on the statement, not the connection.
2021-03-15 14:38:09 +01:00
Nikita Popov fc4cd598a2 Update ubuntu on i386 job
There is a failure with apt on PHP-7.4 that's not present on
PHP-8.0/master. Switching to a newer ubuntu version on PHP-7.4
avoids the issue.
2021-03-15 14:11:19 +01:00
Nikita Popov 703bbf5210 Downgrade security level in tests using TLS < 1.2
A few additional tests have been added on master that require
lower security level.

(cherry picked from commit c2a6395dcb)
2021-03-15 14:11:12 +01:00
Christoph M. BeckerandMichael Wallner f901bec494 Fix #51903: simplexml_load_file() doesn't use HTTP headers
The `encoding` attribute of the XML declaration is optional; it is good
practice to use external encoding information where available if it is
missing.  Thus, we check for `charset` info of `Content-Type` headers,
and see whether the encoding is supported.

We cater to trailing parameters and quoted-strings, but not to escaped
backslashes and quotes in quoted-strings, since no known character
encoding contains these anyway.

Co-authored-by: Michael Wallner <mike@php.net>

Closes GH-6747.
2021-03-08 15:07:01 +01:00
manuel 5787f91c55 Fix #80838: HTTP wrapper waits for HTTP 1 response after HTTP 101
Don't wait for further responses after a HTTP 101 (Switching Protocols) response

Closes GH-6730.
2021-03-08 14:36:31 +01:00
George Wang 8fc0bdfb0a Merge branch 'PHP-7.4' of git.php.net:php-src into PHP-7.4 2021-03-05 10:57:46 -05:00
George Wang 797edd6211 LiteSpeed SAPI v7.9: Process manager keeps forked child process alive for longer time based on load. Reduces PM overhead for busy setup. 2021-03-05 10:46:12 -05:00
Christoph M. Becker e0e167e581 Print error code if CreateMutex() fails
This issue came up recently in a bug report[1]; without the error code,
users can barely guess why the function failed.

[1] <https://bugs.php.net/80812>

Closes GH-6745.
2021-03-05 15:06:18 +01:00
Christoph M. Becker 51e2015af3 Fix #78719: http wrapper silently ignores long Location headers
When opening HTTP streams, and reading the headers, we currently
discard header lines longer than `HTTP_HEADER_BLOCK_SIZE` (1024 bytes).
While this is not generally forbidden by RFC 7230, section 3.2.5, it
is not generally allowed either, since that may change the "message
framing or response semantics".

We thus fix this by allowing arbitrarily long header lines.

Closes GH-6720.
2021-03-03 10:45:25 +01:00
Christoph M. BeckerandNikita Popov 71297a254b Fix #80751: Comma in recipient name breaks email delivery
So far, `SendText()` simply separates potential email address lists at
any comma, disregarding that commas inside a quoted-string do not
delimit addresses.  We fix that by introducing an own variant of
`strtok_r()` which caters to quoted-strings.

We also make `FormatEmailAddress()` aware of quoted strings.

We do not cater to email address comments, and potentially other quirks
of RFC 5322 email addresses, but catering to quoted-strings is supposed
to solve almost all practical use cases.

Co-authored-by: Nikita Popov <nikita.ppv@gmail.com>

Closes GH-6735.
2021-03-01 18:46:21 +01:00
Nikita Popov 2c508c4d40 Always remove HT iterators, even for uninit HT
Fixes oss-fuzz #31423.
2021-03-01 16:22:11 +01:00
Nikita Popov e857936518 Fixed bug #80805
Handle missing result_var in binary_op_result_type.

(cherry picked from commit 8446e28275)
2021-03-01 15:13:15 +01:00
Felipe Pena 988c3f9659 Fix memleak on ReflectionFunction and ReflectionGenerator classes when calling __construct after instantiation 2021-02-25 20:53:14 +00:00
Remi Collet ae0585c98e skip test with openssl < 1.1.0
The test fails, but without any crash
(this test is designed to catch a crash)
2021-02-25 13:52:35 +01:00
Dylan K. Taylor a480bf8093 Capture Microsoft-defined HRESULT exit codes exit codes
The lack of such a check leads to false-passes of tests on Windows
which expect no output, but produce a segfault or similar issue. I
discovered this a while ago due to bad tests in an extension I maintain.

Closes GH-6722.
2021-02-25 12:01:04 +01:00
Daniel Black 8309c04464 mysqlnd pam fix test error message
Closes GH-6727.
2021-02-25 09:51:51 +01:00
Nikita Popov 766f827e26 Fix potential file collision in dom tests 2021-02-24 21:30:20 +01:00
Felipe Pena 3ec37a74a2 Fix bug #80757 (Exit code is 0 when could not open file) 2021-02-24 18:50:27 +00:00
Felipe Pena 78b0a85de6 Update NEWS 2021-02-24 18:40:32 +00:00
Christoph M. Becker 67bb06cc9b Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  run-tests: fixed exit code not being set on BORKED tests
2021-02-23 13:15:30 +01:00
Dylan K. Taylor 729cd8bacd run-tests: fixed exit code not being set on BORKED tests
When no test paths are specified this shows up when 'make test' is used on a PECL extension without specifying tests to run (or in php-src too, I guess...)

Closes GH-6717.
2021-02-23 12:50:03 +01:00
Christoph M. Becker 81396ea890 Update php_version.h to proper version number 2021-02-23 12:09:06 +01:00
Christoph M. Becker 963e50c8c4 Fix #75776: Flushing streams with compression filter is broken
First, the `bzip2.compress` filter has the same issue as `zlib.deflate`
so we port the respective fix[1] to ext/bz2.

Second, there is still an issue, if a stream with an attached
compression filter is flushed before it is closed, without any writes
in between.  In that case, the compression is never finalized.  We fix
this by enforcing a `_php_stream_flush()` with the `closing` flag set
in `_php_stream_free()`, whenever a write filter is attached.  This
call is superfluous for most write filters, but does not hurt, even
when it is unnecessary.

[1] <http://git.php.net/?p=php-src.git;a=commit;h=20e75329f2adb11dd231852c061926d0e4080929>

Closes GH-6703.
2021-02-22 15:28:46 +01:00
Christoph M. Becker 073b6ea818 Fix #80771: phpinfo(INFO_CREDITS) displays nothing in CLI
There is no good reason not to show the credits in text based SAPIs,
except for brevity.  Thus, we suppress the credits from `php -i`.

Closes GH-6710.
2021-02-22 14:31:51 +01:00
Christoph M. Becker d7c98ca1ac Fix #80774: session_name() problem with backslash
Since we do no longer URL decode cookie names[1], we must not URL
encode the session name.  We need to prevent broken Set-Cookie headers,
by rejecting names which contain invalid characters.

[1] <http://git.php.net/?p=php-src.git;a=commit;h=6559fe912661ca5ce5f0eeeb591d928451428ed0>

Closes GH-6711.
2021-02-22 12:32:56 +01:00
Nikita Popov 6dd85f83f7 Fixed bug #80781
zend_find_array_dim_slow() may throw, make sure to handle this.
This backports the code we already use for this on PHP-8.0,
and also backports an exception check that makes this easier to
catch.
2021-02-22 09:36:43 +01:00
Christoph M. Becker 84b6152842 Fix #80763: msgfmt_format() does not accept DateTime references
`intl_zval_to_millis()` needs to cater to references.

Closes GH-6707.
2021-02-17 17:26:48 +01:00
Nikita Popov 9552cf6b84 Handle incomplete result set metadata more gracefully
Rather than segfaulting because sname is missing lateron, report
a FAIL here. As this indicates a server bug, the errors is reported
as an out of band warning, rather than a client error.

This fixes the PHP side of bug #80713.
2021-02-16 15:34:14 +01:00
Derick Rethans 2d858fbfb1 Fixed dates 2021-02-16 11:31:34 +00:00
Derick Rethans 6d3d9104e6 PHP-7.4 is now 7.4.17-dev 2021-02-16 11:26:47 +00:00
Nikita Popov 7566742754 Suppress OpenSSL error on missing optional config
openssl_pkey_new() fetches various options from the config file --
most of these are optional, and not specifying them is not an error
condition from the perspective of the user. Unfortunately, the
CONF_get_string() API pushes an error when accessing a key that
doesn't exist (_CONF_get_string does not, but that is presumably a
private API). This commit adds a helper php_openssl_conf_get_string()
that automatically clears the error in this case. I've found that
OpenSSL occasionally does the same thing internally:
https://github.com/openssl/openssl/blob/22040fb790c854cefb04bed98ed38ea6357daf83/apps/req.c#L515-L517

Closes GH-6699.
2021-02-16 10:11:00 +01:00
Nikita Popov 64b1085464 Fixed bug #80747
If RSA key generation fails, actually report that failure.
2021-02-15 15:34:01 +01:00
Nikita Popov 7b7d99839c Fix symtable cache being used while cleaning symtable
We need to first clean the symtable and then check whether a cache
slot is available for it. Otherwise, it may happen that a destructor
runs while cleaning the table and uses up all the remaining slots
in the cache.

This is particularly insidious because once we overflow the cache,
the first pointer we modify is symtable_cache_ptr, making it hard
to understand what happened after the fact.

Fixes oss-fuzz #30815.
2021-02-15 14:58:38 +01:00
Daniel Black 3646604203 Fix #78680: mysqlnd pam plugin missing terminating null
The PAM service requires the terminating null to be part
of the communication.

Tested with MariaDB-10.4(pam) and Percona Server 5.7.32(auth_pam_compat).

Also changed MySQL Enterprise test to the server side plugin, authentication_pam
as opposed to the client plugin mysql_clear_password.

Add additional check for pamtest user and pam service file as
all are required for the test.

More importantly, test result should actually succeed.

Thanks Geoff Montee for bug report.

Closes GH-78680.
2021-02-15 11:32:07 +01:00
Nikita Popov 44a80b64b9 Fix leak when breaking out of FilesystemIterator
We need to always destroy current, not just when iter.data is not
set.

Take this opportunity to clean up the iterator destructor code a
bit, to remove redundant checks and incorrect comments.
2021-02-15 10:37:59 +01:00
Nikita Popov c34c523467 Fixed bug #80719 2021-02-11 16:12:06 +01:00
Christoph M. Becker 4f508003a9 Avoid C4090 level 1 warning
This breaks the build for PHP 8 by default.
2021-02-08 23:11:37 +01:00
Christoph M. Becker 03713ace23 Fix locale dependent parsing of PostgreSQL version number
Version numbers are not supposed to be localized, so we must not apply
locale dependent parsing with `atof()`.

Using `php_version_compare()` might even be better.

Closes GH-6668.
2021-02-08 18:57:08 +01:00
Christoph M. Becker ca7547c9e2 Fix #80706: mail(): Headers after Bcc headers may be ignored
We need to handle the case where a CRLF after a Bcc header is not the
beginning of a folding marker, because in that case the Bcc header was
not the last "thing".

Closes GH-6666.
2021-02-08 18:42:31 +01:00
Christoph M. Becker 4ff2665509 Use ST_Y() instead of the deprecated/removed Y() in test 2021-02-05 14:53:19 +01:00
Christoph M. Becker 3f8d21b922 Fix #74779: x() and y() truncating floats to integers
We must not use the locale dependent `atof()`, but instead use the
(hopefully) locale independent `zend_strtod()`, when converting string
representations of floating point numbers which are sent by the server.

Closes GH-6665.
2021-02-05 13:09:59 +01:00
Nikita Popov 8b7aaad7d6 Try SIGTERM before SIGKILL in opcache restart
SIGTERM is subject to HANDLE_BLOCK_INTERRUPTIONS(), which will
allow code to exit critical sections before it gets terminated.

Closes GH-6493.
2021-02-04 17:07:18 +01:00
Christoph M. Becker 958e3b93c3 [ci skip] Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  Fix newly introduced compiler warning
2021-02-03 12:43:40 +01:00
Nikita Popov 06c9633b43 Fix newly introduced compiler warning
(cherry picked from commit ab8177de2c)
2021-02-03 12:42:28 +01:00
Christoph M. Becker 1bb2a4f91c Fix #53467: Phar cannot compress large archives
When Phars are flushed, a new temporary file is created for each entry
which should be compressed, and the `compressed_filesize` is retrieved.
Afterwards, the Phar manifest is written, and only after that the files
are copied to the actual Phar.  So for each such entry there is an open
temp file, what easily exceeds the limit.

Therefore, we use a single temporary file for all entries, and store
the start offset in the otherwise unused `header_offset` member.  We
ensure that the `cfp` members are properly set to NULL even if flushing
fails, to avoid use after free scenarios.

This solution is based on a suggestion by @lserni[1].

Closes GH-6643.

[1] <https://github.com/box-project/box2/issues/80#issuecomment-77147371>
2021-02-03 11:22:37 +01:00
Christoph M. Becker 3d09626f0d [ci skip] Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  7.3.28 is next
2021-02-02 17:07:16 +01:00
Christoph M. Becker 039ca4e219 7.3.28 is next 2021-02-02 17:01:55 +01:00
Peter Kokot 8c04944b66 Update year to 2021
Closes GH-6636.
2021-02-02 16:46:16 +01:00
Nikita Popov 54fa0a69f8 Add missing derefs in CurlFile
As pointed out on GH-6456.
2021-02-02 10:31:16 +01:00
Nikita Popov 51d76c346e Fix persistent leak on load_wsdl_ex failure
Move the load_wsdl_ex call into the zend_try that destroys the
docs hash table. The wsdl will be inserted into docs early on,
and will thus be released on subsequent bailout.
2021-02-02 10:05:35 +01:00
Christoph M. Becker 675a9b2831 Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  Revert "Updated to version 2021.1 (2021a)"
2021-02-01 13:42:43 +01:00
Christoph M. Becker 57257a4335 Revert "Updated to version 2021.1 (2021a)"
This reverts commit 491488d217, since
PHP-7.3 is in security mode, and this does not look security related.
2021-02-01 13:41:32 +01:00
Christoph M. Becker 7e9479083d Fix #80654: file_get_contents() maxlen fails above (2**31)-1 bytes
We remove the arbitrary restriction to `INT_MAX`; it is superfluous on
32bit systems where `ZEND_LONG_MAX == INT_MAX` anyway, and not useful
on 64bit systems, where larger files should be readable, if the
`memory_limit` is large enough.

Closes GH-6648.
2021-02-01 12:57:40 +01:00
Nikita Popov 217b9e7b41 Fix Laravel build on community job
Now requires PHP 7.4, so use php7.4 to run composer everywhere.
2021-02-01 09:48:14 +01:00
Nikita Popov ab8177de2c Fix build 2021-02-01 09:46:17 +01:00
Stanislav Malyshev 86de4d7af6 Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  Fix bug #80672 - Null Dereference in SoapClient
2021-01-31 21:42:41 -08:00
Stanislav Malyshev 3c939e3f69 Fix bug #80672 - Null Dereference in SoapClient 2021-01-31 21:15:23 -08:00
Remi Collet aeb4f21549 NEWS 2021-01-28 16:25:35 +01:00
Remi Collet 067f7e4150 Fix #80682 opcache doesn't honour pcre.jit option 2021-01-28 16:24:39 +01:00
Stanislav Malyshev 21f861225a Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  Rm unneeded function
2021-01-27 00:15:13 -08:00
Stanislav Malyshev 9c673083cd Rm unneeded function 2021-01-27 00:13:43 -08:00
Stanislav Malyshev fbf8c758fe Merge branch 'PHP-7.3' into PHP-7.4
* PHP-7.3:
  Alternative fix for bug 77423
2021-01-26 22:55:10 -08:00
Christoph M. Becker 4a89e726bd 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-01-26 22:54:58 -08:00
Christoph M. Becker 6a0b889f57 Fix #70091: Phar does not mark UTF-8 filenames in ZIP archives
The default encoding of filenames in a ZIP archive is IBM Code Page
437.  Phar, however, only supports UTF-8 filenames.  Therefore we have
to mark filenames as being stored in UTF-8 by setting the general
purpose bit 11 (the language encoding flag).

The effect of not setting this bit for non ASCII filenames can be seen
in popular tools like 7-Zip and UnZip, but not when extracting the
archives via ext/phar (which is agnostic to the filename encoding), or
via ext/zip (which guesses the encoding).  Thus we add a somewhat
brittle low-level test case.

Closes GH-6630.
2021-01-26 19:14:25 +01:00
Christoph M. Becker 94af11d5e1 Update version
That appears to have been forgotten for a while.
2021-01-26 19:08:23 +01:00
Christoph M. Becker 61ed904cec Fix #75850: Unclear error message wrt. __halt_compiler() w/o semicolon
We add the failure reason to the error message.

Closes GH-6638.
2021-01-25 18:47:15 +01:00
Derick Rethans 3f183bbcf8 Updated to version 2021.1 (2021a) 2021-01-25 10:44:05 +00:00
Derick Rethans 072cfef1d5 Empty merge 2021-01-25 10:44:05 +00:00
Derick Rethans 491488d217 Updated to version 2021.1 (2021a) 2021-01-25 10:44:04 +00:00
Christoph M. Becker edb389730d Add missing SKIPIF clause for recently introduced test case 2021-01-21 17:27:09 +01:00
Christoph M. Becker 6adfb8c962 Fix #80648: Fix for bug 79296 should be based on runtime version
Instead of checking for actually affected libzip versions, we now always
`ZIP_TRUNCATE` empty files unless `ZIP_RDONLY` is set.

Closes GH-6625.
2021-01-20 16:20:13 +01:00
Christoph M. Becker 4c1b3e3036 Add missing SKIPIF clauses to new test cases 2021-01-20 11:02:52 +01:00
Derick Rethans a33d0c3aae Update NEWS and version 2021-01-19 14:58:38 +00:00
120 changed files with 4846 additions and 2811 deletions

No files matched your search

+1 -3
View File
@@ -11,9 +11,7 @@ end
define ____executor_globals
if basic_functions_module.zts
if !$tsrm_ls
set $tsrm_ls = ts_resource_ex(0, 0)
end
set $tsrm_ls = _tsrm_ls_cache
set $eg = ((zend_executor_globals*) (*((void ***) $tsrm_ls))[executor_globals_id-1])
set $cg = ((zend_compiler_globals*) (*((void ***) $tsrm_ls))[compiler_globals_id-1])
set $eg_ptr = $eg
+1 -1
View File
@@ -1,6 +1,6 @@
--------------------------------------------------------------------
The PHP License, version 3.01
Copyright (c) 1999 - 2019 The PHP Group. All rights reserved.
Copyright (c) 1999 - 2021 The PHP Group. All rights reserved.
--------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
+115 -4
View File
@@ -1,5 +1,120 @@
PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
29 Apr 2021, PHP 7.4.18
- Core:
. Fixed bug #80781 (Error handler that throws ErrorException infinite loop).
(Nikita)
. Fixed bug #75776 (Flushing streams with compression filter is broken). (cmb)
- Dba:
. Fixed bug #80817 (dba_popen() may cause segfault during RSHUTDOWN). (cmb)
- DOM:
. Fixed bug #66783 (UAF when appending DOMDocument to element). (cmb)
- FPM:
. Fixed bug #80024 (Duplication of info about inherited socket after pool
removing). (Jakub Zelenka)
- FTP:
. Fixed bug #80880 (SSL_read on shutdown, ftp/proc_open). (cmb, Jakub
Zelenka)
- Imap:
. Fixed bug #80710 (imap_mail_compose() header injection). (cmb, Stas)
- Intl:
. Fixed bug #80763 (msgfmt_format() does not accept DateTime references).
(cmb)
- LibXML:
. Fixed bug #51903 (simplexml_load_file() doesn't use HTTP headers). (cmb)
. Fixed bug #73533 (Invalid memory access in php_libxml_xmlCheckUTF8). (cmb)
- MySQLnd:
. Fixed bug #80713 (SegFault when disabling ATTR_EMULATE_PREPARES and
MySQL 8.0). (Nikita)
. Fixed bug #80837 (Calling stmt_store_result after fetch doesn't throw an
error). (Kamil Tekiela)
- Opcache:
. Fixed bug #80805 (create simple class and get error in opcache.so). (Nikita)
. Fixed bug #80950 (Variables become null in if statements). (Nikita)
- Pcntl:
. Fixed bug #79812 (Potential integer overflow in pcntl_exec()). (cmb)
- PCRE:
. Fixed bug #80866 (preg_split ignores limit flag when pattern with \K has
0-width fullstring match). (Kamil Tekiela)
- PDO_ODBC:
. Fixed bug #80783 (PDO ODBC truncates BLOB records at every 256th byte).
(cmb)
- PDO_pgsql:
. Fixed bug #80892 (PDO::PARAM_INT is treated the same as PDO::PARAM_STR).
(Matteo)
- phpdbg:
. Fixed bug #80757 (Exit code is 0 when could not open file). (Felipe)
- Session:
. Fixed bug #80774 (session_name() problem with backslash). (cmb)
. Fixed bug #80889 (Cannot set save handler when save_handler is invalid).
(cmb)
- SOAP:
. Fixed bug #69668 (SOAP special XML characters in namespace URIs not
encoded). (cmb)
- Standard:
. Fixed bug #78719 (http wrapper silently ignores long Location headers).
(cmb)
. Fixed bug #80771 (phpinfo(INFO_CREDITS) displays nothing in CLI). (cmb)
. Fixed bug #80838 (HTTP wrapper waits for HTTP 1 response after HTTP 101).
(manuelm)
. Fixed bug #80915 (Taking a reference to $_SERVER hides its values from
phpinfo()). (Rowan Tommins)
04 Mar 2021, php 7.4.16
- Core:
. Fixed #80706 (mail(): Headers after Bcc headers may be ignored). (cmb)
- MySQLnd:
. Fixed bug #78680 (mysqlnd's mysql_clear_password does not transmit
null-terminated password). (Daniel Black)
- MySQLi:
. Fixed bug #74779 (x() and y() truncating floats to integers). (cmb)
- OPcache:
. Fixed bug #80682 (opcache doesn't honour pcre.jit option). (Remi)
- OpenSSL:
. Fixed bug #80747 (Providing RSA key size < 512 generates key that crash
PHP). (Nikita)
- Phar:
. Fixed bug #75850 (Unclear error message wrt. __halt_compiler() w/o
semicolon) (cmb)
. Fixed bug #70091 (Phar does not mark UTF-8 filenames in ZIP archives). (cmb)
. Fixed bug #53467 (Phar cannot compress large archives). (cmb, lserni)
- SPL:
. Fixed bug#80719 (Iterating after failed ArrayObject::setIteratorClass()
causes Segmentation fault). (Nikita)
- Standard:
. Fixed bug #80654 (file_get_contents() maxlen fails above (2**31)-1 bytes).
(cmb)
- Zip:
. Fixed bug #80648 (Fix for bug 79296 should be based on runtime version).
(cmb, Remi)
04 Feb 2021, PHP 7.4.15
- Core:
@@ -28,10 +143,6 @@ PHP NEWS
. Fixed bug #69279 (Compressed ZIP Phar extractTo() creates garbage files).
(cmb)
- SOAP:
. Fixed bug #80672 (Null Dereference in SoapClient). (CVE-2021-21702) (cmb,
Stas)
07 Jan 2021, PHP 7.4.14
- Core:
@@ -0,0 +1,15 @@
--TEST--
HT iterator should be destroyed if array becomes empty during array_splice
--FILE--
<?php
$a=[4];
$i = 0;
foreach ($a as &$r) {
var_dump($r);
$a = array_splice($a, 0);
if (++$i == 2) break;
}
?>
--EXPECT--
int(4)
int(4)
+32
View File
@@ -0,0 +1,32 @@
--TEST--
Bug #80781: Error handler that throws ErrorException infinite loop
--FILE--
<?php
function handle(int $severity, string $message, string $file, int $line): bool {
if((error_reporting() & $severity) !== 0) {
throw new \ErrorException($message, 0, $severity, $file, $line);
}
return true; // stfu operator
}
set_error_handler('handle');
function getPlugin(string $plugin) : bool{
return false;
}
$data = [];
$array = [];
if (isset($array[$data]) or getPlugin($data)) {
}
?>
--EXPECTF--
Fatal error: Uncaught ErrorException: Illegal offset type in isset or empty in %s:%d
Stack trace:
#0 %s(%d): handle(2, 'Illegal offset ...', %s, %d, Array)
#1 {main}
thrown in %s on line %d
@@ -0,0 +1,19 @@
--TEST--
Symtable cache slots may be acquired while cleaning symtable
--FILE--
<?php
class A {
// Must be larger than the symtable cache.
static $max = 40;
function __destruct() {
if (self::$max-- < 0) return;
$x = 'y';
$$x = new a;
}
}
new A;
?>
===DONE===
--EXPECT--
===DONE===
+1 -1
View File
@@ -1099,7 +1099,7 @@ static zend_always_inline void zend_mm_free_pages_ex(zend_mm_heap *heap, zend_mm
/* this setting may be not accurate */
chunk->free_tail = page_num;
}
if (free_chunk && chunk->free_pages == ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE) {
if (free_chunk && chunk != heap->main_chunk && chunk->free_pages == ZEND_MM_PAGES - ZEND_MM_FIRST_PAGE) {
zend_mm_delete_chunk(heap, chunk);
}
}
+9 -7
View File
@@ -51,11 +51,11 @@
# define ZEND_VM_FP_GLOBAL_REG "%r14"
# define ZEND_VM_IP_GLOBAL_REG "%r15"
# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__powerpc64__)
# define ZEND_VM_FP_GLOBAL_REG "r28"
# define ZEND_VM_IP_GLOBAL_REG "r29"
# define ZEND_VM_FP_GLOBAL_REG "r14"
# define ZEND_VM_IP_GLOBAL_REG "r15"
# elif defined(__IBMC__) && ZEND_GCC_VERSION >= 4002 && defined(__powerpc64__)
# define ZEND_VM_FP_GLOBAL_REG "r28"
# define ZEND_VM_IP_GLOBAL_REG "r29"
# define ZEND_VM_FP_GLOBAL_REG "r14"
# define ZEND_VM_IP_GLOBAL_REG "r15"
# elif defined(__GNUC__) && ZEND_GCC_VERSION >= 4008 && defined(__aarch64__)
# define ZEND_VM_FP_GLOBAL_REG "x27"
# define ZEND_VM_IP_GLOBAL_REG "x28"
@@ -3437,12 +3437,13 @@ ZEND_API void execute_internal(zend_execute_data *execute_data, zval *return_val
ZEND_API void zend_clean_and_cache_symbol_table(zend_array *symbol_table) /* {{{ */
{
/* Clean before putting into the cache, since clean could call dtors,
* which could use the cached hash. Also do this before the check for
* available cache slots, as those may be used by a dtor as well. */
zend_symtable_clean(symbol_table);
if (EG(symtable_cache_ptr) >= EG(symtable_cache_limit)) {
zend_array_destroy(symbol_table);
} else {
/* clean before putting into the cache, since clean
could call dtors, which could use cached hash */
zend_symtable_clean(symbol_table);
*(EG(symtable_cache_ptr)++) = symbol_table;
}
}
@@ -4554,6 +4555,7 @@ static zend_always_inline zend_execute_data *_zend_vm_stack_push_call_frame(uint
if (check_exception) { \
OPLINE = EX(opline) + (skip); \
} else { \
ZEND_ASSERT(!EG(exception)); \
OPLINE = opline + (skip); \
} \
ZEND_VM_CONTINUE()
+1 -1
View File
@@ -1630,10 +1630,10 @@ ZEND_API void ZEND_FASTCALL zend_array_destroy(HashTable *ht)
} else if (EXPECTED(HT_FLAGS(ht) & HASH_FLAG_UNINITIALIZED)) {
goto free_ht;
}
zend_hash_iterators_remove(ht);
SET_INCONSISTENT(HT_DESTROYED);
efree(HT_GET_DATA_ADDR(ht));
free_ht:
zend_hash_iterators_remove(ht);
FREE_HASHTABLE(ht);
}
+4
View File
@@ -6937,6 +6937,10 @@ ZEND_VM_C_LABEL(num_index_prop):
ZEND_VM_C_GOTO(isset_again);
} else {
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
if (UNEXPECTED(EG(exception))) {
result = 0;
ZEND_VM_C_GOTO(isset_dim_obj_exit);
}
}
if (!(opline->extended_value & ZEND_ISEMPTY)) {
+36
View File
@@ -6302,6 +6302,10 @@ num_index_prop:
goto isset_again;
} else {
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
if (UNEXPECTED(EG(exception))) {
result = 0;
goto isset_dim_obj_exit;
}
}
if (!(opline->extended_value & ZEND_ISEMPTY)) {
@@ -8496,6 +8500,10 @@ num_index_prop:
goto isset_again;
} else {
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
if (UNEXPECTED(EG(exception))) {
result = 0;
goto isset_dim_obj_exit;
}
}
if (!(opline->extended_value & ZEND_ISEMPTY)) {
@@ -10949,6 +10957,10 @@ num_index_prop:
goto isset_again;
} else {
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
if (UNEXPECTED(EG(exception))) {
result = 0;
goto isset_dim_obj_exit;
}
}
if (!(opline->extended_value & ZEND_ISEMPTY)) {
@@ -14985,6 +14997,10 @@ num_index_prop:
goto isset_again;
} else {
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
if (UNEXPECTED(EG(exception))) {
result = 0;
goto isset_dim_obj_exit;
}
}
if (!(opline->extended_value & ZEND_ISEMPTY)) {
@@ -16402,6 +16418,10 @@ num_index_prop:
goto isset_again;
} else {
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
if (UNEXPECTED(EG(exception))) {
result = 0;
goto isset_dim_obj_exit;
}
}
if (!(opline->extended_value & ZEND_ISEMPTY)) {
@@ -17689,6 +17709,10 @@ num_index_prop:
goto isset_again;
} else {
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
if (UNEXPECTED(EG(exception))) {
result = 0;
goto isset_dim_obj_exit;
}
}
if (!(opline->extended_value & ZEND_ISEMPTY)) {
@@ -41505,6 +41529,10 @@ num_index_prop:
goto isset_again;
} else {
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
if (UNEXPECTED(EG(exception))) {
result = 0;
goto isset_dim_obj_exit;
}
}
if (!(opline->extended_value & ZEND_ISEMPTY)) {
@@ -44950,6 +44978,10 @@ num_index_prop:
goto isset_again;
} else {
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
if (UNEXPECTED(EG(exception))) {
result = 0;
goto isset_dim_obj_exit;
}
}
if (!(opline->extended_value & ZEND_ISEMPTY)) {
@@ -50123,6 +50155,10 @@ num_index_prop:
goto isset_again;
} else {
value = zend_find_array_dim_slow(ht, offset EXECUTE_DATA_CC);
if (UNEXPECTED(EG(exception))) {
result = 0;
goto isset_dim_obj_exit;
}
}
if (!(opline->extended_value & ZEND_ISEMPTY)) {
+4 -4
View File
@@ -50,7 +50,7 @@ jobs:
- script: |
git clone https://github.com/laravel/framework.git --branch=master --depth=1
cd framework
php7.3 /usr/bin/composer install --no-progress
php7.4 /usr/bin/composer install --no-progress
export USE_ZEND_ALLOC=0
sed -i 's/$exit = true/$exit = false/g' vendor/phpunit/phpunit/src/TextUI/Command.php
# Avoid test using exit(), which thus leaks.
@@ -61,8 +61,8 @@ jobs:
- script: |
git clone https://github.com/symfony/symfony.git --depth=1
cd symfony
php7.3 /usr/bin/composer install --no-progress
php7.3 ./phpunit install
php7.4 /usr/bin/composer install --no-progress
php7.4 ./phpunit install
export USE_ZEND_ALLOC=0
export USE_TRACKED_ALLOC=1
export ASAN_OPTIONS=exitcode=139
@@ -82,7 +82,7 @@ jobs:
displayName: 'Test Amphp'
condition: or(succeeded(), failed())
- script: |
php7.3 /usr/bin/composer create-project symfony/symfony-demo symfony_demo --no-progress
php7.4 /usr/bin/composer create-project symfony/symfony-demo symfony_demo --no-progress
cd symfony_demo
export USE_ZEND_ALLOC=0
export USE_TRACKED_ALLOC=1
+1 -1
View File
@@ -5,7 +5,7 @@ parameters:
jobs:
- job: ${{ parameters.configurationName }}
pool:
vmImage: 'ubuntu-18.04'
vmImage: 'ubuntu-20.04'
steps:
- template: apt.yml
- script: |
+2 -2
View File
@@ -17,7 +17,7 @@ dnl Basic autoconf initialization, generation of config.nice.
dnl ----------------------------------------------------------------------------
AC_PREREQ([2.68])
AC_INIT([PHP],[7.4.15],[https://bugs.php.net],[php],[https://www.php.net])
AC_INIT([PHP],[7.4.18],[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
@@ -568,7 +568,7 @@ dnl Fix for these systems is already included in GCC 7, but not on GCC 6.
dnl
dnl At least some versions of FreeBSD seem to have buggy ifunc support, see
dnl bug #77284. Conservatively don't use ifuncs on FreeBSD.
AS_CASE([$host_alias], [*-*-*android*|*-*-*uclibc*|*-*-*musl*|*freebsd*], [true], [
AS_CASE([$host_alias], [*-*-*android*|*-*-*uclibc*|*-*-*musl*|*freebsd*|*openbsd*], [true], [
AX_GCC_FUNC_ATTRIBUTE([ifunc])
AX_GCC_FUNC_ATTRIBUTE([target])
])
+10 -3
View File
@@ -41,6 +41,7 @@ typedef struct _php_bz2_filter_data {
enum strm_status status; /* Decompress option */
unsigned int small_footprint : 1; /* Decompress option */
unsigned int expect_concatenated : 1; /* Decompress option */
unsigned int is_flushed : 1; /* only for compression */
int persistent;
} php_bz2_filter_data;
@@ -228,6 +229,8 @@ static php_stream_filter_status_t php_bz2_compress_filter(
bucket = php_stream_bucket_make_writeable(buckets_in->head);
while (bin < bucket->buflen) {
int flush_mode;
desired = bucket->buflen - bin;
if (desired > data->inbuf_len) {
desired = data->inbuf_len;
@@ -235,7 +238,9 @@ static php_stream_filter_status_t php_bz2_compress_filter(
memcpy(data->strm.next_in, bucket->buf + bin, desired);
data->strm.avail_in = desired;
status = BZ2_bzCompress(&(data->strm), flags & PSFS_FLAG_FLUSH_CLOSE ? BZ_FINISH : (flags & PSFS_FLAG_FLUSH_INC ? BZ_FLUSH : BZ_RUN));
flush_mode = flags & PSFS_FLAG_FLUSH_CLOSE ? BZ_FINISH : (flags & PSFS_FLAG_FLUSH_INC ? BZ_FLUSH : BZ_RUN);
data->is_flushed = flush_mode != BZ_RUN;
status = BZ2_bzCompress(&(data->strm), flush_mode);
if (status != BZ_RUN_OK && status != BZ_FLUSH_OK && status != BZ_FINISH_OK) {
/* Something bad happened */
php_stream_bucket_delref(bucket);
@@ -261,11 +266,12 @@ static php_stream_filter_status_t php_bz2_compress_filter(
php_stream_bucket_delref(bucket);
}
if (flags & PSFS_FLAG_FLUSH_CLOSE) {
if (flags & PSFS_FLAG_FLUSH_CLOSE || ((flags & PSFS_FLAG_FLUSH_INC) && !data->is_flushed)) {
/* Spit it out! */
status = BZ_FINISH_OK;
while (status == BZ_FINISH_OK) {
status = BZ2_bzCompress(&(data->strm), BZ_FINISH);
status = BZ2_bzCompress(&(data->strm), (flags & PSFS_FLAG_FLUSH_CLOSE ? BZ_FINISH : BZ_FLUSH));
data->is_flushed = 1;
if (data->strm.avail_out < data->outbuf_len) {
size_t bucketlen = data->outbuf_len - data->strm.avail_out;
@@ -381,6 +387,7 @@ static php_stream_filter *php_bz2_filter_create(const char *filtername, zval *fi
}
status = BZ2_bzCompressInit(&(data->strm), blockSize100k, 0, workFactor);
data->is_flushed = 1;
fops = &php_bz2_compress_ops;
} else {
status = BZ_DATA_ERROR;
+24
View File
@@ -0,0 +1,24 @@
--TEST--
Bug #75776 (Flushing streams with compression filter is broken)
--SKIPIF--
<?php
if (!extension_loaded('bz2')) die('skip bz2 extension not available');
?>
--FILE--
<?php
$text = str_repeat('0123456789abcdef', 1000);
$temp = fopen('php://temp', 'r+');
stream_filter_append($temp, 'bzip2.compress', STREAM_FILTER_WRITE);
fwrite($temp, $text);
rewind($temp);
var_dump(bin2hex(stream_get_contents($temp)));
var_dump(ftell($temp));
fclose($temp);
?>
--EXPECT--
string(144) "425a68343141592653599fe7bbbf0001f389007fe03f002000902980026826aa80003ea9061520c6a41954833a9069520d6a41b54837a9071520e6a41d5483ba9079520f6a41f548"
int(72)
+3
View File
@@ -2207,6 +2207,7 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
#endif
prop = zend_read_property(curl_CURLFile_class, current, "name", sizeof("name")-1, 0, &rv);
ZVAL_DEREF(prop);
if (Z_TYPE_P(prop) != IS_STRING) {
php_error_docref(NULL, E_WARNING, "Invalid filename for key %s", ZSTR_VAL(string_key));
} else {
@@ -2217,10 +2218,12 @@ static inline int build_mime_structure_from_hash(php_curl *ch, zval *zpostfields
}
prop = zend_read_property(curl_CURLFile_class, current, "mime", sizeof("mime")-1, 0, &rv);
ZVAL_DEREF(prop);
if (Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) {
type = Z_STRVAL_P(prop);
}
prop = zend_read_property(curl_CURLFile_class, current, "postname", sizeof("postname")-1, 0, &rv);
ZVAL_DEREF(prop);
if (Z_TYPE_P(prop) == IS_STRING && Z_STRLEN_P(prop) > 0) {
filename = Z_STRVAL_P(prop);
}
+2681 -2482
View File
File diff suppressed because it is too large. Load diff
+2 -2
View File
@@ -972,9 +972,9 @@ restart:
zend_bool close_both;
close_both = (info->fp != info->lock.fp);
php_stream_close(info->lock.fp);
php_stream_free(info->lock.fp, persistent ? PHP_STREAM_FREE_CLOSE_PERSISTENT : PHP_STREAM_FREE_CLOSE);
if (close_both) {
php_stream_close(info->fp);
php_stream_free(info->fp, persistent ? PHP_STREAM_FREE_CLOSE_PERSISTENT : PHP_STREAM_FREE_CLOSE);
}
info->fp = NULL;
info->lock.fp = NULL;
+7 -3
View File
@@ -1302,9 +1302,13 @@ int dom_hierarchy(xmlNodePtr parent, xmlNodePtr child)
{
xmlNodePtr nodep;
if (parent == NULL || child == NULL || child->doc != parent->doc) {
return SUCCESS;
}
if (parent == NULL || child == NULL || child->doc != parent->doc) {
return SUCCESS;
}
if (child->type == XML_DOCUMENT_NODE) {
return FAILURE;
}
nodep = parent;
@@ -9,7 +9,7 @@ require_once __DIR__ .'/skipif.inc';
?>
--FILE--
<?php
$filename = __DIR__."/tmp_savehtmlfile".time().".html";
$filename = __DIR__."/DOMDocument_saveHTMLFile_basic.html";
$doc = new DOMDocument('1.0');
$root = $doc->createElement('html');
$root = $doc->appendChild($root);
@@ -9,7 +9,7 @@ require_once __DIR__ .'/skipif.inc';
?>
--FILE--
<?php
$filename = __DIR__."/tmp_savehtmlfile".time().".html";
$filename = __DIR__."/DOMDocument_saveHTMLFile_formatOutput.html";
$doc = new DOMDocument('1.0');
$doc->formatOutput = true;
$root = $doc->createElement('html');
+19
View File
@@ -0,0 +1,19 @@
--TEST--
Bug #66783 (UAF when appending DOMDocument to element)
--SKIPIF--
<?php
if (!extension_loaded('dom')) die('skip dom extension not available');
?>
--FILE--
<?php
$doc = new DomDocument;
$doc->loadXML('<root></root>');
$e = $doc->createElement('e');
try {
$e->appendChild($doc);
} catch (DOMException $ex) {
echo $ex->getMessage(), PHP_EOL;
}
?>
--EXPECTF--
Hierarchy Request Error
+6
View File
@@ -1931,6 +1931,12 @@ static void ftp_ssl_shutdown(ftpbuf_t *ftp, php_socket_t fd, SSL *ssl_handle) {
/* SSL wants a write. Really odd. Let's bail out. */
done = 1;
break;
case SSL_ERROR_SYSCALL:
/* most likely the peer closed the connection without
sending a close_notify shutdown alert;
bail out to avoid raising a spurious warning */
done = 1;
break;
default:
if ((sslerror = ERR_get_error())) {
ERR_error_string_n(sslerror, buf, sizeof(buf));
+56
View File
@@ -3551,6 +3551,23 @@ PHP_FUNCTION(imap_fetch_overview)
}
/* }}} */
static zend_bool header_injection(zend_string *str, zend_bool adrlist)
{
char *p = ZSTR_VAL(str);
while ((p = strpbrk(p, "\r\n")) != NULL) {
if (!(p[0] == '\r' && p[1] == '\n')
/* adrlists do not support folding, but swallow trailing line breaks */
&& !((adrlist && p[1] == '\0')
/* other headers support folding */
|| !adrlist && (p[1] == ' ' || p[1] == '\t'))) {
return 1;
}
p++;
}
return 0;
}
/* {{{ proto string imap_mail_compose(array envelope, array body)
Create a MIME message based on given envelope and body sections */
PHP_FUNCTION(imap_mail_compose)
@@ -3571,6 +3588,13 @@ PHP_FUNCTION(imap_mail_compose)
return;
}
#define CHECK_HEADER_INJECTION(zstr, adrlist, header) \
if (header_injection(zstr, adrlist)) { \
php_error_docref(NULL, E_WARNING, "header injection attempt in " header); \
RETVAL_FALSE; \
goto done; \
}
#define PHP_RFC822_PARSE_ADRLIST(target, value) \
str_copy = estrndup(Z_STRVAL_P(value), Z_STRLEN_P(value)); \
rfc822_parse_adrlist(target, str_copy, "NO HOST"); \
@@ -3579,46 +3603,57 @@ PHP_FUNCTION(imap_mail_compose)
env = mail_newenvelope();
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "remail", sizeof("remail") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "remail");
env->remail = cpystr(Z_STRVAL_P(pvalue));
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "return_path", sizeof("return_path") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "return_path");
PHP_RFC822_PARSE_ADRLIST(&env->return_path, pvalue);
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "date", sizeof("date") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "date");
env->date = (unsigned char*)cpystr(Z_STRVAL_P(pvalue));
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "from", sizeof("from") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "from");
PHP_RFC822_PARSE_ADRLIST(&env->from, pvalue);
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "reply_to", sizeof("reply_to") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "reply_to");
PHP_RFC822_PARSE_ADRLIST(&env->reply_to, pvalue);
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "in_reply_to", sizeof("in_reply_to") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "in_reply_to");
env->in_reply_to = cpystr(Z_STRVAL_P(pvalue));
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "subject", sizeof("subject") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "subject");
env->subject = cpystr(Z_STRVAL_P(pvalue));
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "to", sizeof("to") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "to");
PHP_RFC822_PARSE_ADRLIST(&env->to, pvalue);
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "cc", sizeof("cc") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "cc");
PHP_RFC822_PARSE_ADRLIST(&env->cc, pvalue);
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "bcc", sizeof("bcc") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 1, "bcc");
PHP_RFC822_PARSE_ADRLIST(&env->bcc, pvalue);
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(envelope), "message_id", sizeof("message_id") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "message_id");
env->message_id=cpystr(Z_STRVAL_P(pvalue));
}
@@ -3629,6 +3664,7 @@ PHP_FUNCTION(imap_mail_compose)
ZEND_HASH_FOREACH_VAL(Z_ARRVAL_P(pvalue), env_data) {
custom_headers_param = mail_newbody_parameter();
convert_to_string_ex(env_data);
CHECK_HEADER_INJECTION(Z_STR_P(env_data), 0, "custom_headers");
custom_headers_param->value = (char *) fs_get(Z_STRLEN_P(env_data) + 1);
custom_headers_param->attribute = NULL;
memcpy(custom_headers_param->value, Z_STRVAL_P(env_data), Z_STRLEN_P(env_data) + 1);
@@ -3667,6 +3703,7 @@ PHP_FUNCTION(imap_mail_compose)
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
tmp_param = mail_newbody_parameter();
tmp_param->value = cpystr(Z_STRVAL_P(pvalue));
tmp_param->attribute = cpystr("CHARSET");
@@ -3679,9 +3716,11 @@ PHP_FUNCTION(imap_mail_compose)
SEPARATE_ARRAY(pvalue);
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
if (key == NULL) continue;
CHECK_HEADER_INJECTION(key, 0, "body disposition key");
disp_param = mail_newbody_parameter();
disp_param->attribute = cpystr(ZSTR_VAL(key));
convert_to_string_ex(disp_data);
CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
disp_param->next = tmp_param;
@@ -3692,18 +3731,22 @@ PHP_FUNCTION(imap_mail_compose)
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
bod->subtype = cpystr(Z_STRVAL_P(pvalue));
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
bod->id = cpystr(Z_STRVAL_P(pvalue));
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
bod->description = cpystr(Z_STRVAL_P(pvalue));
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
}
@@ -3713,9 +3756,11 @@ PHP_FUNCTION(imap_mail_compose)
SEPARATE_ARRAY(pvalue);
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
if (key == NULL) continue;
CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
disp_param = mail_newbody_parameter();
disp_param->attribute = cpystr(ZSTR_VAL(key));
convert_to_string_ex(disp_data);
CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
disp_param->next = tmp_param;
@@ -3746,6 +3791,7 @@ PHP_FUNCTION(imap_mail_compose)
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
bod->md5 = cpystr(Z_STRVAL_P(pvalue));
}
} else if (Z_TYPE_P(data) == IS_ARRAY && topbod->type == TYPEMULTIPART) {
@@ -3778,6 +3824,7 @@ PHP_FUNCTION(imap_mail_compose)
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "charset", sizeof("charset") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body charset");
tmp_param = mail_newbody_parameter();
tmp_param->value = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
memcpy(tmp_param->value, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue) + 1);
@@ -3791,9 +3838,11 @@ PHP_FUNCTION(imap_mail_compose)
SEPARATE_ARRAY(pvalue);
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
if (key == NULL) continue;
CHECK_HEADER_INJECTION(key, 0, "body type.parameters key");
disp_param = mail_newbody_parameter();
disp_param->attribute = cpystr(ZSTR_VAL(key));
convert_to_string_ex(disp_data);
CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body type.parameters value");
disp_param->value = (char *)fs_get(Z_STRLEN_P(disp_data) + 1);
memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
disp_param->next = tmp_param;
@@ -3804,18 +3853,22 @@ PHP_FUNCTION(imap_mail_compose)
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "subtype", sizeof("subtype") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body subtype");
bod->subtype = cpystr(Z_STRVAL_P(pvalue));
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "id", sizeof("id") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body id");
bod->id = cpystr(Z_STRVAL_P(pvalue));
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "description", sizeof("description") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body description");
bod->description = cpystr(Z_STRVAL_P(pvalue));
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "disposition.type", sizeof("disposition.type") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body disposition.type");
bod->disposition.type = (char *) fs_get(Z_STRLEN_P(pvalue) + 1);
memcpy(bod->disposition.type, Z_STRVAL_P(pvalue), Z_STRLEN_P(pvalue)+1);
}
@@ -3825,9 +3878,11 @@ PHP_FUNCTION(imap_mail_compose)
SEPARATE_ARRAY(pvalue);
ZEND_HASH_FOREACH_STR_KEY_VAL(Z_ARRVAL_P(pvalue), key, disp_data) {
if (key == NULL) continue;
CHECK_HEADER_INJECTION(key, 0, "body disposition key");
disp_param = mail_newbody_parameter();
disp_param->attribute = cpystr(ZSTR_VAL(key));
convert_to_string_ex(disp_data);
CHECK_HEADER_INJECTION(Z_STR_P(disp_data), 0, "body disposition value");
disp_param->value = (char *) fs_get(Z_STRLEN_P(disp_data) + 1);
memcpy(disp_param->value, Z_STRVAL_P(disp_data), Z_STRLEN_P(disp_data) + 1);
disp_param->next = tmp_param;
@@ -3858,6 +3913,7 @@ PHP_FUNCTION(imap_mail_compose)
}
if ((pvalue = zend_hash_str_find(Z_ARRVAL_P(data), "md5", sizeof("md5") - 1)) != NULL) {
convert_to_string_ex(pvalue);
CHECK_HEADER_INJECTION(Z_STR_P(pvalue), 0, "body md5");
bod->md5 = cpystr(Z_STRVAL_P(pvalue));
}
}
+37
View File
@@ -0,0 +1,37 @@
--TEST--
Bug #80710 (imap_mail_compose() header injection) - MIME Splitting Attack
--SKIPIF--
<?php
if (!extension_loaded("imap")) die("skip imap extension not available");
?>
--FILE--
<?php
$envelope["from"]= "joe@example.com\n From : X-INJECTED";
$envelope["to"] = "foo@example.com\nFrom: X-INJECTED";
$envelope["cc"] = "bar@example.com\nFrom: X-INJECTED";
$envelope["subject"] = "bar@example.com\n\n From : X-INJECTED";
$envelope["x-remail"] = "bar@example.com\nFrom: X-INJECTED";
$envelope["something"] = "bar@example.com\nFrom: X-INJECTED";
$part1["type"] = TYPEMULTIPART;
$part1["subtype"] = "mixed";
$part2["type"] = TYPEAPPLICATION;
$part2["encoding"] = ENCBINARY;
$part2["subtype"] = "octet-stream\nContent-Type: X-INJECTED";
$part2["description"] = "some file\nContent-Type: X-INJECTED";
$part2["contents.data"] = "ABC\nContent-Type: X-INJECTED";
$part3["type"] = TYPETEXT;
$part3["subtype"] = "plain";
$part3["description"] = "description3";
$part3["contents.data"] = "contents.data3\n\n\n\t";
$body[1] = $part1;
$body[2] = $part2;
$body[3] = $part3;
echo imap_mail_compose($envelope, $body);
?>
--EXPECTF--
Warning: imap_mail_compose(): header injection attempt in from in %s on line %d
+37
View File
@@ -0,0 +1,37 @@
--TEST--
Bug #80710 (imap_mail_compose() header injection) - Remail
--SKIPIF--
<?php
if (!extension_loaded("imap")) die("skip imap extension not available");
?>
--FILE--
<?php
$envelope["from"]= "joe@example.com\n From : X-INJECTED";
$envelope["to"] = "foo@example.com\nFrom: X-INJECTED";
$envelope["cc"] = "bar@example.com\nFrom: X-INJECTED";
$envelope["subject"] = "bar@example.com\n\n From : X-INJECTED";
$envelope["remail"] = "X-INJECTED-REMAIL: X-INJECTED\nFrom: X-INJECTED-REMAIL-FROM"; //<--- Injected as first hdr
$envelope["something"] = "bar@example.com\nFrom: X-INJECTED";
$part1["type"] = TYPEMULTIPART;
$part1["subtype"] = "mixed";
$part2["type"] = TYPEAPPLICATION;
$part2["encoding"] = ENCBINARY;
$part2["subtype"] = "octet-stream\nContent-Type: X-INJECTED";
$part2["description"] = "some file\nContent-Type: X-INJECTED";
$part2["contents.data"] = "ABC\nContent-Type: X-INJECTED";
$part3["type"] = TYPETEXT;
$part3["subtype"] = "plain";
$part3["description"] = "description3";
$part3["contents.data"] = "contents.data3\n\n\n\t";
$body[1] = $part1;
$body[2] = $part2;
$body[3] = $part3;
echo imap_mail_compose($envelope, $body);
?>
--EXPECTF--
Warning: imap_mail_compose(): header injection attempt in remail in %s on line %d
+4
View File
@@ -175,6 +175,7 @@ U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func)
return ZEND_NAN;
}
try_again:
switch (Z_TYPE_P(z)) {
case IS_STRING:
type = is_numeric_string(Z_STRVAL_P(z), Z_STRLEN_P(z), &lv, &rv, 0);
@@ -227,6 +228,9 @@ U_CFUNC double intl_zval_to_millis(zval *z, intl_error *err, const char *func)
efree(message);
}
break;
case IS_REFERENCE:
z = Z_REFVAL_P(z);
goto try_again;
default:
spprintf(&message, 0, "%s: invalid PHP type for date", func);
intl_errors_set(err, U_ILLEGAL_ARGUMENT_ERROR,
+16
View File
@@ -0,0 +1,16 @@
--TEST--
Bug #80763 (msgfmt_format() does not accept DateTime references)
--SKIPIF--
<?php
if (!extension_loaded('intl')) die('skip intl extension not available');
?>
--FILE--
<?php
$today = new DateTime('2021-02-17 12:00:00');
$formatter = new \MessageFormatter('en_US', 'Today is {today, date, full}.');
$params = ['today' => $today];
array_walk($params, fn() => 1);
var_dump($formatter->format($params));
?>
--EXPECT--
string(38) "Today is Wednesday, February 17, 2021."
+49 -1
View File
@@ -409,6 +409,54 @@ php_libxml_input_buffer_create_filename(const char *URI, xmlCharEncoding enc)
return(NULL);
}
/* Check if there's been an external transport protocol with an encoding information */
if (enc == XML_CHAR_ENCODING_NONE) {
php_stream *s = (php_stream *) context;
if (Z_TYPE(s->wrapperdata) == IS_ARRAY) {
zval *header;
ZEND_HASH_FOREACH_VAL_IND(Z_ARRVAL(s->wrapperdata), header) {
const char buf[] = "Content-Type:";
if (Z_TYPE_P(header) == IS_STRING &&
!zend_binary_strncasecmp(Z_STRVAL_P(header), Z_STRLEN_P(header), buf, sizeof(buf)-1, sizeof(buf)-1)) {
char *needle = estrdup("charset=");
char *haystack = estrndup(Z_STRVAL_P(header), Z_STRLEN_P(header));
char *encoding = php_stristr(haystack, needle, Z_STRLEN_P(header), sizeof("charset=")-1);
if (encoding) {
char *end;
encoding += sizeof("charset=")-1;
if (*encoding == '"') {
encoding++;
}
end = strchr(encoding, ';');
if (end == NULL) {
end = encoding + strlen(encoding);
}
end--; /* end == encoding-1 isn't a buffer underrun */
while (*end == ' ' || *end == '\t') {
end--;
}
if (*end == '"') {
end--;
}
if (encoding >= end) continue;
*(end+1) = '\0';
enc = xmlParseCharEncoding(encoding);
if (enc <= XML_CHAR_ENCODING_NONE) {
enc = XML_CHAR_ENCODING_NONE;
}
}
efree(haystack);
efree(needle);
break; /* found content-type */
}
} ZEND_HASH_FOREACH_END();
}
}
/* Allocate the Input buffer front-end. */
ret = xmlAllocParserInputBuffer(enc);
if (ret != NULL) {
@@ -1134,7 +1182,7 @@ static PHP_FUNCTION(libxml_set_external_entity_loader)
/* {{{ Common functions shared by extensions */
int php_libxml_xmlCheckUTF8(const unsigned char *s)
{
int i;
size_t i;
unsigned char c;
for (i = 0; (c = s[i++]);) {
+38
View File
@@ -0,0 +1,38 @@
--TEST--
Bug #51903 (simplexml_load_file() doesn't use HTTP headers)
--SKIPIF--
<?php
if (!extension_loaded('simplexml')) die('skip simplexml extension not available');
if (@!include "./ext/standard/tests/http/server.inc") die('skip server.inc not available');
http_server_skipif('tcp://127.0.0.1:12342');
?>
--FILE--
<?php
require "./ext/standard/tests/http/server.inc";
$responses = [
"data://text/plain,HTTP/1.1 200 OK\r\n"
. "Content-Type: text/xml; charset=ISO-8859-1\r\n\r\n"
. "<?xml version=\"1.0\"?>\n"
. "<root>\xE4\xF6\xFC</root>\n",
"data://text/plain,HTTP/1.1 200 OK\r\n"
. "Content-Type: text/xml; charset=ISO-8859-1; foo=bar\r\n\r\n"
. "<?xml version=\"1.0\"?>\n"
. "<root>\xE4\xF6\xFC</root>\n",
"data://text/plain,HTTP/1.1 200 OK\r\n"
. "Content-Type: text/xml; charset=\"ISO-8859-1\" ; foo=bar\r\n\r\n"
. "<?xml version=\"1.0\"?>\n"
. "<root>\xE4\xF6\xFC</root>\n",
];
$pid = http_server('tcp://127.0.0.1:12342', $responses);
for ($i = 0; $i < count($responses); $i++) {
$sxe = simplexml_load_file('http://127.0.0.1:12342/');
echo "$sxe\n";
}
http_server_kill($pid);
?>
--EXPECT--
äöü
äöü
äöü
+42
View File
@@ -0,0 +1,42 @@
--TEST--
Bug #74779 (x() and y() truncating floats to integers)
--SKIPIF--
<?php
require_once('skipif.inc');
require_once('skipifconnectfailure.inc');
if (!setlocale(LC_NUMERIC, "de_DE", "de_DE.UTF-8", "de-DE")) die('skip locale not available');
?>
--FILE--
<?php
require_once("connect.inc");
if (!$link = my_mysqli_connect($host, $user, $passwd, $db, $port, $socket)) {
printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
}
if (!setlocale(LC_NUMERIC, "de_DE", "de_DE.UTF-8", "de-DE")) {
echo "[002] Cannot set locale\n";
}
if (!$link->options(MYSQLI_OPT_INT_AND_FLOAT_NATIVE, true)) {
printf("[003] [%d] %s\n", $link->errno, $link->error);
}
if (!$result = $link->query("SELECT ST_Y(Point(56.7, 53.34))")) {
printf("[004] [%d] %s\n", $link->errno, $link->error);
}
if (!$array = $result->fetch_array(MYSQLI_ASSOC)) {
printf("[005] [%d] %s\n", $link->errno, $link->error);
}
var_dump($array);
mysqli_close($link);
?>
--EXPECT--
array(1) {
["ST_Y(Point(56.7, 53.34))"]=>
float(53,34)
}
+38
View File
@@ -0,0 +1,38 @@
--TEST--
Bug #80837 Calling stmt_store_result after fetch doesn't throw an error
--SKIPIF--
<?php
require_once 'skipif.inc';
require_once 'skipifconnectfailure.inc';
if (!defined('MYSQLI_STORE_RESULT_COPY_DATA')) die('skip requires mysqlnd');
?>
--FILE--
<?php
require_once "connect.inc";
mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
$mysqli = new my_mysqli($host, $user, $passwd, $db, $port, $socket);
$mysqli->query('DROP TABLE IF EXISTS test');
$mysqli->query('CREATE TABLE test (b int)');
$mysqli->query('INSERT INTO test VALUES (1),(2),(3)');
$statement = $mysqli->prepare("SELECT b FROM test");
$statement->execute();
$statement->bind_result($name);
$statement->fetch();
try {
$statement->store_result();
} catch (mysqli_sql_exception $e) {
echo $e->getMessage();
}
$mysqli->close();
?>
--CLEAN--
<?php
require_once "clean_table.inc";
?>
--EXPECTF--
Commands out of sync; you can't run this command now
+48 -8
View File
@@ -19,8 +19,8 @@ if (!$res = $link->query("SHOW PLUGINS"))
$have_pam = false;
while ($row = $res->fetch_assoc()) {
if (isset($row['Name']) && ('mysql_clear_password' == $row['Name'])) {
$have_pam = true;
if (isset($row['Name']) && in_array($row['Name'], array('pam', 'authentication_pam', 'auth_pam_compat'))) {
$have_pam = $row['Name'];
break;
}
}
@@ -29,12 +29,54 @@ $res->close();
if (!$have_pam)
die("SKIP Server PAM plugin not installed");
if ($have_pam == 'pam') {
/* MariaDB - needs system variable pam_use_cleartext_plugin=ON to be set */
if (!$res = mysqli_query($link, 'SHOW GLOBAL VARIABLES LIKE "pam_use_cleartext_plugin"'))
die(sprintf("SKIP MariaDB probe of GLOBAL VARIABLES failed [%d] %s\n",
mysqli_errno($link), mysqli_error($link)));
$pam_use_cleartext_plugin = mysqli_fetch_row($res);
mysqli_free_result($res);
if (!$pam_use_cleartext_plugin or $pam_use_cleartext_plugin[1]!='ON')
die("SKIP Server setting pam_use_cleartext_plugin!=ON");
$pam_service = file_get_contents('/etc/pam.d/mysql');
} elseif ($have_pam == 'authentication_pam') {
/*
required MySQL syntax:
https://dev.mysql.com/doc/refman/8.0/en/pam-pluggable-authentication.html#pam-pluggable-authentication-usage
*/
$have_pam .= " AS 'mysql-unix'";
$pam_service = file_get_contents('/etc/pam.d/mysql-unix');
} else {
$pam_service = file_get_contents('/etc/pam.d/mysql');
}
$auth = 0;
$account = 0;
foreach (explode("\n", $pam_service) as $line)
{
if (preg_match('/^auth/', $line)) {
$auth = 1;
} elseif (preg_match('/^account/', $line)) {
$account = 1;
}
}
if (!$auth) {
die("SKIP pam service file missing 'auth' directive");
}
if (!$account) {
die("SKIP pam service file missing 'account' directive");
}
if (!posix_getpwnam('pamtest')) {
die("SKIP no pamtest user");
}
/* Password of user 'pamtest' should be set to 'pamtest' */
mysqli_query($link, 'DROP USER pamtest');
mysqli_query($link, 'DROP USER pamtest@localhost');
if (!mysqli_query($link, 'CREATE USER pamtest@"%" IDENTIFIED WITH mysql_clear_password') ||
!mysqli_query($link, 'CREATE USER pamtest@"localhost" IDENTIFIED WITH mysql_clear_password')) {
if (!mysqli_query($link, "CREATE USER pamtest@'%' IDENTIFIED WITH $have_pam") ||
!mysqli_query($link, "CREATE USER pamtest@'localhost' IDENTIFIED WITH $have_pam")) {
printf("skip Cannot create second DB user [%d] %s", mysqli_errno($link), mysqli_error($link));
mysqli_close($link);
die("skip CREATE USER failed");
@@ -60,8 +102,8 @@ max_execution_time=240
require_once('table.inc');
if (!$link = my_mysqli_connect($host, 'pamtest', 'pamtest', $db, $port, $socket)) {
printf("[001] Cannot connect to the server using host=%s, user=%s, passwd=***, dbname=%s, port=%s, socket=%s\n",
$host, $user, $db, $port, $socket);
printf("[001] Cannot connect to the server using host=%s, user=pamtest, passwd=pamtest dbname=%s, port=%s, socket=%s\n",
$host, $db, $port, $socket);
} else {
if (!$res = $link->query("SELECT id FROM test WHERE id = 1"))
@@ -88,6 +130,4 @@ max_execution_time=240
mysqli_query($link, 'DROP USER pamtest@localhost');
?>
--EXPECTF--
Warning: mysqli_real_connect(): (28000/1045): Access denied for user %s
[001] Cannot connect to the server using host=%s
done!
+5 -1
View File
@@ -652,7 +652,11 @@ mysqlnd_pam_auth_get_auth_data(struct st_mysqlnd_authentication_plugin * self,
if (passwd && passwd_len) {
ret = (zend_uchar*) zend_strndup(passwd, passwd_len);
}
*auth_data_len = passwd_len;
/*
Trailing null required. bug#78680
https://dev.mysql.com/doc/dev/mysql-server/latest/page_protocol_connection_phase_authentication_methods_clear_text_password.html
*/
*auth_data_len = passwd_len + 1;
return ret;
}
+1 -1
View File
@@ -92,7 +92,7 @@ MYSQLND_METHOD(mysqlnd_stmt, store_result)(MYSQLND_STMT * const s)
/* Nothing to store for UPSERT/LOAD DATA*/
if (!mysqlnd_stmt_check_state(stmt)) {
SET_CLIENT_ERROR(conn->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
SET_CLIENT_ERROR(stmt->error_info, CR_COMMANDS_OUT_OF_SYNC, UNKNOWN_SQLSTATE, mysqlnd_out_of_sync);
DBG_RETURN(NULL);
}
+4 -3
View File
@@ -1216,8 +1216,9 @@ php_mysqlnd_rset_field_read(MYSQLND_CONN_DATA * conn, void * _packet)
DBG_RETURN(PASS);
} else if (EODATA_MARKER == *p && packet->header.size < 8) {
/* Premature EOF. That should be COM_FIELD_LIST. But we don't support COM_FIELD_LIST anymore, thus this should not happen */
DBG_INF("Premature EOF. That should be COM_FIELD_LIST");
DBG_RETURN(PASS);
DBG_ERR("Premature EOF. That should be COM_FIELD_LIST");
php_error_docref(NULL, E_WARNING, "Premature EOF in result field metadata");
DBG_RETURN(FAIL);
}
meta = packet->metadata;
@@ -1679,7 +1680,7 @@ php_mysqlnd_rowp_read_text_protocol_aux(MYSQLND_ROW_BUFFER * row_buffer, zval *
zend_uchar save = *(p + len);
/* We have to make it ASCIIZ temporarily */
*(p + len) = '\0';
ZVAL_DOUBLE(current_field, atof((char *) p));
ZVAL_DOUBLE(current_field, zend_strtod((char *) p, NULL));
*(p + len) = save;
}
#endif /* MYSQLND_STRING_TO_INT_CONVERSION */
+1 -1
View File
@@ -1,6 +1,6 @@
--------------------------------------------------------------------
The PHP License, version 3.01
Copyright (c) 1999 - 2019 The PHP Group. All rights reserved.
Copyright (c) 1999 - 2021 The PHP Group. All rights reserved.
--------------------------------------------------------------------
Redistribution and use in source and binary forms, with or without
+19 -5
View File
@@ -368,6 +368,10 @@ static zend_bool try_remove_var_def(context *ctx, int free_var, int use_chain, z
return 0;
}
static zend_always_inline zend_bool may_be_refcounted(uint32_t type) {
return (type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) != 0;
}
/* Returns whether the instruction has been DCEd */
static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
zend_ssa *ssa = ctx->ssa;
@@ -379,16 +383,15 @@ static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
}
/* We mark FREEs as dead, but they're only really dead if the destroyed var is dead */
if (opline->opcode == ZEND_FREE
&& (ssa->var_info[ssa_op->op1_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF))
if (opline->opcode == ZEND_FREE && may_be_refcounted(ssa->var_info[ssa_op->op1_use].type)
&& !is_var_dead(ctx, ssa_op->op1_use)) {
return 0;
}
if ((opline->op1_type & (IS_VAR|IS_TMP_VAR))&& !is_var_dead(ctx, ssa_op->op1_use)) {
if (!try_remove_var_def(ctx, ssa_op->op1_use, ssa_op->op1_use_chain, opline)) {
if (ssa->var_info[ssa_op->op1_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)
&& opline->opcode != ZEND_CASE) {
if (may_be_refcounted(ssa->var_info[ssa_op->op1_use].type)
&& opline->opcode != ZEND_CASE) {
free_var = ssa_op->op1_use;
free_var_type = opline->op1_type;
}
@@ -396,7 +399,7 @@ static zend_bool dce_instr(context *ctx, zend_op *opline, zend_ssa_op *ssa_op) {
}
if ((opline->op2_type & (IS_VAR|IS_TMP_VAR)) && !is_var_dead(ctx, ssa_op->op2_use)) {
if (!try_remove_var_def(ctx, ssa_op->op2_use, ssa_op->op2_use_chain, opline)) {
if (ssa->var_info[ssa_op->op2_use].type & (MAY_BE_STRING|MAY_BE_ARRAY|MAY_BE_OBJECT|MAY_BE_RESOURCE|MAY_BE_REF)) {
if (may_be_refcounted(ssa->var_info[ssa_op->op2_use].type)) {
if (free_var >= 0) {
// TODO: We can't free two vars. Keep instruction alive.
zend_bitset_excl(ctx->instr_dead, opline - ctx->op_array->opcodes);
@@ -503,6 +506,17 @@ int dce_optimize_op_array(zend_op_array *op_array, zend_ssa *ssa, zend_bool reor
ctx.phi_dead = alloca(sizeof(zend_ulong) * ctx.phi_worklist_len);
memset(ctx.phi_dead, 0xff, sizeof(zend_ulong) * ctx.phi_worklist_len);
/* Mark non-CV phis as live. Even if the result is unused, we generally cannot remove one
* of the producing instructions, as it combines producing the result with control flow.
* This can be made more precise if there are any cases where this is not the case. */
FOREACH_PHI(phi) {
if (phi->var >= op_array->last_var
&& may_be_refcounted(ssa->var_info[phi->ssa_var].type)) {
zend_bitset_excl(ctx.phi_dead, phi->ssa_var);
add_phi_sources_to_worklists(&ctx, phi, 0);
}
} FOREACH_PHI_END();
/* Mark reacable instruction without side effects as dead */
int b = ssa->cfg.blocks_count;
while (b > 0) {
+1 -1
View File
@@ -1040,7 +1040,7 @@ static const func_info_t func_infos[] = {
F1("curl_version", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_STRING | MAY_BE_ARRAY_OF_LONG | MAY_BE_ARRAY_OF_STRING | MAY_BE_ARRAY_OF_ARRAY),
F0("curl_setopt", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_TRUE),
F0("curl_setopt_array", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_TRUE),
FN("curl_exec", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING),
FN("curl_exec", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_TRUE | MAY_BE_STRING),
F1("curl_getinfo", MAY_BE_NULL | MAY_BE_FALSE | MAY_BE_STRING | MAY_BE_LONG | MAY_BE_DOUBLE | MAY_BE_ARRAY | MAY_BE_ARRAY_KEY_ANY | MAY_BE_ARRAY_OF_ANY),
F1("curl_error", MAY_BE_NULL | MAY_BE_STRING),
F0("curl_errno", MAY_BE_NULL | MAY_BE_LONG),
+19 -4
View File
@@ -1947,6 +1947,18 @@ static void add_usages(const zend_op_array *op_array, zend_ssa *ssa, zend_bitset
if (op->op2_def >= 0) {
zend_bitset_incl(worklist, op->op2_def);
}
} else if (use + 1 < op_array->last
&& op_array->opcodes[use + 1].opcode == ZEND_OP_DATA) {
op++;
if (op->result_def >= 0) {
zend_bitset_incl(worklist, op->result_def);
}
if (op->op1_def >= 0) {
zend_bitset_incl(worklist, op->op1_def);
}
if (op->op2_def >= 0) {
zend_bitset_incl(worklist, op->op2_def);
}
}
use = zend_ssa_next_use(ssa->ops, var, use);
} while (use >= 0);
@@ -2141,7 +2153,7 @@ static uint32_t assign_dim_result_type(
/* For binary ops that have compound assignment operators */
static uint32_t binary_op_result_type(
zend_ssa *ssa, zend_uchar opcode, uint32_t t1, uint32_t t2, uint32_t result_var,
zend_ssa *ssa, zend_uchar opcode, uint32_t t1, uint32_t t2, int result_var,
zend_long optimization_level) {
uint32_t tmp = 0;
uint32_t t1_type = (t1 & MAY_BE_ANY) | (t1 & MAY_BE_UNDEF ? MAY_BE_NULL : 0);
@@ -2159,7 +2171,8 @@ static uint32_t binary_op_result_type(
switch (opcode) {
case ZEND_ADD:
if (t1_type == MAY_BE_LONG && t2_type == MAY_BE_LONG) {
if (!ssa->var_info[result_var].has_range ||
if (result_var < 0 ||
!ssa->var_info[result_var].has_range ||
ssa->var_info[result_var].range.underflow ||
ssa->var_info[result_var].range.overflow) {
/* may overflow */
@@ -2185,7 +2198,8 @@ static uint32_t binary_op_result_type(
case ZEND_SUB:
case ZEND_MUL:
if (t1_type == MAY_BE_LONG && t2_type == MAY_BE_LONG) {
if (!ssa->var_info[result_var].has_range ||
if (result_var < 0 ||
!ssa->var_info[result_var].has_range ||
ssa->var_info[result_var].range.underflow ||
ssa->var_info[result_var].range.overflow) {
/* may overflow */
@@ -2627,7 +2641,8 @@ static int zend_update_type_info(const zend_op_array *op_array,
}
tmp |= binary_op_result_type(
ssa, opline->extended_value, t1, t2, ssa_ops[i].op1_def, optimization_level);
ssa, opline->extended_value, t1, t2,
opline->opcode == ZEND_ASSIGN_OP ? ssa_ops[i].op1_def : -1, optimization_level);
if (tmp & (MAY_BE_STRING|MAY_BE_ARRAY)) {
tmp |= MAY_BE_RC1;
}
+5 -2
View File
@@ -774,14 +774,15 @@ static inline void kill_all_lockers(struct flock *mem_usage_check)
/* so that other process won't try to force while we are busy cleaning up */
ZCSG(force_restart_time) = 0;
while (mem_usage_check->l_pid > 0) {
/* Clear previous errno, reset success and tries */
/* Try SIGTERM first, switch to SIGKILL if not successful. */
int signal = SIGTERM;
errno = 0;
success = 0;
tries = 10;
while (tries--) {
zend_accel_error(ACCEL_LOG_WARNING, "Attempting to kill locker %d", mem_usage_check->l_pid);
if (kill(mem_usage_check->l_pid, SIGKILL)) {
if (kill(mem_usage_check->l_pid, signal)) {
if (errno == ESRCH) {
/* Process died before the signal was sent */
success = 1;
@@ -800,6 +801,8 @@ static inline void kill_all_lockers(struct flock *mem_usage_check)
break;
}
usleep(10000);
/* If SIGTERM was not sufficient, use SIGKILL. */
signal = SIGKILL;
}
if (!success) {
/* errno is not ESRCH or we ran out of tries to kill the locker */
+1 -1
View File
@@ -80,7 +80,7 @@ void zend_shared_alloc_create_lock(void)
{
memory_mutex = CreateMutex(NULL, FALSE, create_name_with_username(ACCEL_MUTEX_NAME));
if (!memory_mutex) {
zend_accel_error(ACCEL_LOG_FATAL, "Cannot create mutex");
zend_accel_error(ACCEL_LOG_FATAL, "Cannot create mutex (error %u)", GetLastError());
return;
}
ReleaseMutex(memory_mutex);
+26
View File
@@ -0,0 +1,26 @@
--TEST--
Bug #80805: create simple class and get error in opcache.so
--FILE--
<?php
class Test {
public int $foo;
public function __construct()
{
$this->foo = 2;
}
public function inc(): int
{
return $this->foo += 2;
}
}
$test = new Test();
var_dump($test->foo);
$test->inc();
var_dump($test->foo);
?>
--EXPECT--
int(2)
int(4)
+17
View File
@@ -0,0 +1,17 @@
--TEST--
Incorrect DCE of FREE of COALESCE
--FILE--
<?php
function test(?string $str) {
$str ?? $str = '';
return strlen($str);
}
$foo = 'foo';
$foo .= 'bar';
var_dump(test($foo));
?>
--EXPECT--
int(6)
+6 -4
View File
@@ -185,10 +185,12 @@ static void zend_accel_blacklist_update_regexp(zend_blacklist *blacklist)
return;
}
#ifdef HAVE_PCRE_JIT_SUPPORT
if (0 > pcre2_jit_compile(it->re, PCRE2_JIT_COMPLETE)) {
/* Don't return here, even JIT could fail to compile, the pattern is still usable. */
pcre2_get_error_message(errnumber, pcre_error, sizeof(pcre_error));
zend_accel_error(ACCEL_LOG_WARNING, "Blacklist JIT compilation failed, %s\n", pcre_error);
if (PCRE_G(jit)) {
if (0 > pcre2_jit_compile(it->re, PCRE2_JIT_COMPLETE)) {
/* Don't return here, even JIT could fail to compile, the pattern is still usable. */
pcre2_get_error_message(errnumber, pcre_error, sizeof(pcre_error));
zend_accel_error(ACCEL_LOG_WARNING, "Blacklist JIT compilation failed, %s\n", pcre_error);
}
}
#endif
/* prepare for the next iteration */
+26 -26
View File
@@ -1064,6 +1064,17 @@ static inline int php_openssl_config_check_syntax(const char * section_label, co
}
/* }}} */
static char *php_openssl_conf_get_string(
LHASH_OF(CONF_VALUE) *conf, const char *group, const char *name) {
char *str = CONF_get_string(conf, group, name);
if (str == NULL) {
/* OpenSSL reports an error if a configuration value is not found.
* However, we don't want to generate errors for optional configuration. */
ERR_clear_error();
}
return str;
}
static int php_openssl_add_oid_section(struct php_x509_request * req) /* {{{ */
{
char * str;
@@ -1071,9 +1082,8 @@ static int php_openssl_add_oid_section(struct php_x509_request * req) /* {{{ */
CONF_VALUE * cnf;
int i;
str = CONF_get_string(req->req_config, NULL, "oid_section");
str = php_openssl_conf_get_string(req->req_config, NULL, "oid_section");
if (str == NULL) {
php_openssl_store_errors();
return SUCCESS;
}
sktmp = CONF_get_section(req->req_config, str);
@@ -1158,10 +1168,8 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
}
/* read in the oids */
str = CONF_get_string(req->req_config, NULL, "oid_file");
if (str == NULL) {
php_openssl_store_errors();
} else if (!php_openssl_open_base_dir_chk(str)) {
str = php_openssl_conf_get_string(req->req_config, NULL, "oid_file");
if (str != NULL && !php_openssl_open_base_dir_chk(str)) {
BIO *oid_bio = BIO_new_file(str, PHP_OPENSSL_BIO_MODE_R(PKCS7_BINARY));
if (oid_bio) {
OBJ_create_objects(oid_bio);
@@ -1173,11 +1181,11 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
return FAILURE;
}
SET_OPTIONAL_STRING_ARG("digest_alg", req->digest_name,
CONF_get_string(req->req_config, req->section_name, "default_md"));
php_openssl_conf_get_string(req->req_config, req->section_name, "default_md"));
SET_OPTIONAL_STRING_ARG("x509_extensions", req->extensions_section,
CONF_get_string(req->req_config, req->section_name, "x509_extensions"));
php_openssl_conf_get_string(req->req_config, req->section_name, "x509_extensions"));
SET_OPTIONAL_STRING_ARG("req_extensions", req->request_extensions_section,
CONF_get_string(req->req_config, req->section_name, "req_extensions"));
php_openssl_conf_get_string(req->req_config, req->section_name, "req_extensions"));
SET_OPTIONAL_LONG_ARG("private_key_bits", req->priv_key_bits,
CONF_get_number(req->req_config, req->section_name, "default_bits"));
@@ -1186,11 +1194,9 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
if (optional_args && (item = zend_hash_str_find(Z_ARRVAL_P(optional_args), "encrypt_key", sizeof("encrypt_key")-1)) != NULL) {
req->priv_key_encrypt = Z_TYPE_P(item) == IS_TRUE ? 1 : 0;
} else {
str = CONF_get_string(req->req_config, req->section_name, "encrypt_rsa_key");
str = php_openssl_conf_get_string(req->req_config, req->section_name, "encrypt_rsa_key");
if (str == NULL) {
str = CONF_get_string(req->req_config, req->section_name, "encrypt_key");
/* it is sure that there are some errrors as str was NULL for encrypt_rsa_key */
php_openssl_store_errors();
str = php_openssl_conf_get_string(req->req_config, req->section_name, "encrypt_key");
}
if (str != NULL && strcmp(str, "no") == 0) {
req->priv_key_encrypt = 0;
@@ -1218,12 +1224,10 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
/* digest alg */
if (req->digest_name == NULL) {
req->digest_name = CONF_get_string(req->req_config, req->section_name, "default_md");
req->digest_name = php_openssl_conf_get_string(req->req_config, req->section_name, "default_md");
}
if (req->digest_name != NULL) {
req->digest = req->md_alg = EVP_get_digestbyname(req->digest_name);
} else {
php_openssl_store_errors();
}
if (req->md_alg == NULL) {
req->md_alg = req->digest = EVP_sha1();
@@ -1245,10 +1249,8 @@ static int php_openssl_parse_config(struct php_x509_request * req, zval * option
#endif
/* set the string mask */
str = CONF_get_string(req->req_config, req->section_name, "string_mask");
if (str == NULL) {
php_openssl_store_errors();
} else if (!ASN1_STRING_set_default_mask_asc(str)) {
str = php_openssl_conf_get_string(req->req_config, req->section_name, "string_mask");
if (str != NULL && !ASN1_STRING_set_default_mask_asc(str)) {
php_error_docref(NULL, E_WARNING, "Invalid global string mask setting %s", str);
return FAILURE;
}
@@ -3138,9 +3140,8 @@ static int php_openssl_make_REQ(struct php_x509_request * req, X509_REQ * csr, z
php_openssl_store_errors();
return FAILURE;
}
attr_sect = CONF_get_string(req->req_config, req->section_name, "attributes");
attr_sect = php_openssl_conf_get_string(req->req_config, req->section_name, "attributes");
if (attr_sect == NULL) {
php_openssl_store_errors();
attr_sk = NULL;
} else {
attr_sk = CONF_get_section(req->req_config, attr_sect);
@@ -3994,10 +3995,7 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req
return NULL;
}
randfile = CONF_get_string(req->req_config, req->section_name, "RANDFILE");
if (randfile == NULL) {
php_openssl_store_errors();
}
randfile = php_openssl_conf_get_string(req->req_config, req->section_name, "RANDFILE");
php_openssl_load_rand_file(randfile, &egdsocket, &seeded);
if ((req->priv_key = EVP_PKEY_new()) != NULL) {
@@ -4021,6 +4019,8 @@ static EVP_PKEY * php_openssl_generate_private_key(struct php_x509_request * req
PHP_OPENSSL_RAND_ADD_TIME();
if (rsaparam == NULL || !RSA_generate_key_ex(rsaparam, req->priv_key_bits, bne, NULL)) {
php_openssl_store_errors();
RSA_free(rsaparam);
rsaparam = NULL;
}
BN_free(bne);
}
+42 -5
View File
@@ -3,14 +3,51 @@ Bug #62890 (default_socket_timeout=-1 causes connection to timeout)
--SKIPIF--
<?php
if (!extension_loaded('openssl')) die('skip openssl extension not available');
if (getenv('SKIP_ONLINE_TESTS')) die('skip online test');
if (!function_exists("proc_open")) die("skip no proc_open");
?>
--INI--
default_socket_timeout=-1
--FILE--
<?php
$clientCtx = stream_context_create(['ssl' => ['verify_peer' => false]]);
var_dump((bool) file_get_contents('https://www.php.net', false, $clientCtx));
$certFile = __DIR__ . DIRECTORY_SEPARATOR . 'bug62890.pem.tmp';
$serverCode = <<<'CODE'
$flags = STREAM_SERVER_BIND|STREAM_SERVER_LISTEN;
$ctx = stream_context_create(['ssl' => [
'local_cert' => '%s',
'security_level' => 1,
]]);
$server = stream_socket_server('tls://127.0.0.1:64321', $errno, $errstr, $flags, $ctx);
phpt_notify();
@stream_socket_accept($server, 3);
CODE;
$serverCode = sprintf($serverCode, $certFile);
$clientCode = <<<'CODE'
$flags = STREAM_CLIENT_CONNECT;
$ctx = stream_context_create(['ssl' => [
'verify_peer' => false,
'verify_peer_name' => false,
'security_level' => 1,
]]);
phpt_wait();
$client = stream_socket_client("tls://127.0.0.1:64321", $errno, $errstr, 3, $flags, $ctx);
var_dump($client);
CODE;
include 'CertificateGenerator.inc';
$certificateGenerator = new CertificateGenerator();
$certificateGenerator->saveNewCertAsFileWithKey('bug62890', $certFile);
include 'ServerClientTestCase.inc';
ServerClientTestCase::getInstance()->run($clientCode, $serverCode);
?>
--EXPECT--
bool(true)
--CLEAN--
<?php
@unlink(__DIR__ . DIRECTORY_SEPARATOR . 'bug62890.pem.tmp');
?>
--EXPECTF--
resource(%d) of type (stream)
+24
View File
@@ -0,0 +1,24 @@
--TEST--
Bug #80747: Providing RSA key size < 512 generates key that crash PHP
--FILE--
--SKIPIF--
<?php
if (!extension_loaded("openssl")) die("skip openssl not loaded");
if (OPENSSL_VERSION_NUMBER < 0x10100000) die("skip OpenSSL >= v1.1.0 required");
?>
--FILE--
<?php
$conf = array(
'config' => __DIR__ . DIRECTORY_SEPARATOR . 'openssl.cnf',
'private_key_bits' => 511,
);
var_dump(openssl_pkey_new($conf));
while ($e = openssl_error_string()) {
echo $e, "\n";
}
?>
--EXPECTF--
bool(false)
error:%s:key size too small
+3 -1
View File
@@ -14,7 +14,8 @@ $serverCode = <<<'CODE'
$serverUri = "ssl://127.0.0.1:64321";
$serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
$serverCtx = stream_context_create(['ssl' => [
'local_cert' => '%s'
'local_cert' => '%s',
'security_level' => 1,
]]);
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
@@ -36,6 +37,7 @@ $clientCode = <<<'CODE'
'cafile' => '%s',
'peer_name' => '%s',
'capture_session_meta' => true,
'security_level' => 1,
]]);
phpt_wait();
@@ -14,7 +14,8 @@ $serverCode = <<<'CODE'
$serverUri = "ssl://127.0.0.1:64321";
$serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
$serverCtx = stream_context_create(['ssl' => [
'local_cert' => '%s'
'local_cert' => '%s',
'security_level' => 1,
]]);
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
@@ -34,6 +35,7 @@ $clientCode = <<<'CODE'
'verify_peer' => true,
'cafile' => '%s',
'peer_name' => '%s',
'security_level' => 1,
]]);
phpt_wait();
@@ -14,7 +14,8 @@ $serverCode = <<<'CODE'
$serverUri = "ssl://127.0.0.1:64321";
$serverFlags = STREAM_SERVER_BIND | STREAM_SERVER_LISTEN;
$serverCtx = stream_context_create(['ssl' => [
'local_cert' => '%s'
'local_cert' => '%s',
'security_level' => 1,
]]);
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
@@ -35,6 +36,7 @@ $clientCode = <<<'CODE'
'verify_peer' => true,
'cafile' => '%s',
'peer_name' => '%s',
'security_level' => 1,
]]);
phpt_wait();
@@ -17,8 +17,9 @@ $serverCode = <<<'CODE'
$serverCtx = stream_context_create(['ssl' => [
'local_cert' => '%s',
// Only accept TLSv1.2 connections
// Only accept TLSv1.0 and TLSv1.2 connections
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_0_SERVER | STREAM_CRYPTO_METHOD_TLSv1_2_SERVER,
'security_level' => 1,
]]);
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
@@ -39,6 +40,7 @@ $clientCode = <<<'CODE'
'verify_peer' => true,
'cafile' => '%s',
'peer_name' => '%s',
'security_level' => 1,
]]);
phpt_wait();
@@ -16,6 +16,7 @@ $serverCode = <<<'CODE'
$serverCtx = stream_context_create(['ssl' => [
'local_cert' => '%s',
'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_0_SERVER,
'security_level' => 1,
]]);
$server = stream_socket_server($serverUri, $errno, $errstr, $serverFlags, $serverCtx);
@@ -36,6 +37,7 @@ $clientCode = <<<'CODE'
'verify_peer' => true,
'cafile' => '%s',
'peer_name' => '%s',
'security_level' => 1,
]]);
phpt_wait();
+3 -2
View File
@@ -955,7 +955,7 @@ PHP_FUNCTION(pcntl_exec)
int envc = 0, envi = 0;
char **argv = NULL, **envp = NULL;
char **current_arg, **pair;
int pair_length;
size_t pair_length;
zend_string *key;
char *path;
size_t path_len;
@@ -1015,8 +1015,9 @@ PHP_FUNCTION(pcntl_exec)
}
/* Length of element + equal sign + length of key + null */
ZEND_ASSERT(Z_STRLEN_P(element) < SIZE_MAX && ZSTR_LEN(key) < SIZE_MAX);
*pair = safe_emalloc(Z_STRLEN_P(element) + 1, sizeof(char), ZSTR_LEN(key) + 1);
pair_length = Z_STRLEN_P(element) + ZSTR_LEN(key) + 2;
*pair = emalloc(pair_length);
strlcpy(*pair, ZSTR_VAL(key), ZSTR_LEN(key) + 1);
strlcat(*pair, "=", pair_length);
strlcat(*pair, Z_STRVAL_P(element), pair_length);
+6 -1
View File
@@ -9,6 +9,9 @@ pcntl: SIG_BLOCK, SIG_UNBLOCK, SIG_SETMASK
--FILE--
<?php
// Clear mask
pcntl_sigprocmask(SIG_SETMASK, array(), $prev);
pcntl_sigprocmask(SIG_BLOCK, array(SIGCHLD,SIGTERM), $old);
var_dump(count($old));
pcntl_sigprocmask(SIG_BLOCK, array(SIGINT), $old);
@@ -19,7 +22,9 @@ pcntl_sigprocmask(SIG_SETMASK, array(SIGINT), $old);
var_dump(count($old));
pcntl_sigprocmask(SIG_SETMASK, array(), $old);
var_dump(count($old));
pcntl_sigprocmask(SIG_SETMASK, array(), $old);
// Restore previous mask
pcntl_sigprocmask(SIG_SETMASK, $prev, $old);
var_dump(count($old));
?>
+5 -1
View File
@@ -767,8 +767,8 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in
zend_hash_add_ptr(&char_tables, _k, (void *)tables);
zend_string_release(_k);
}
pcre2_set_character_tables(cctx, tables);
}
pcre2_set_character_tables(cctx, tables);
/* Set extra options for the compile context. */
if (PHP_PCRE_DEFAULT_EXTRA_COPTIONS != extra_coptions) {
@@ -2644,6 +2644,10 @@ matched:
the match again at the same point. If this fails (picked up above) we
advance to the next character. */
if (start_offset == offsets[0]) {
/* Get next piece if no limit or limit not yet reached and something matched*/
if (limit_val != -1 && limit_val <= 1) {
break;
}
count = pcre2_match(pce->re, (PCRE2_SPTR)subject, ZSTR_LEN(subject_str), start_offset,
PCRE2_NO_UTF_CHECK | PCRE2_NOTEMPTY_ATSTART | PCRE2_ANCHORED, match_data, mctx);
if (count >= 0) {
+12
View File
@@ -0,0 +1,12 @@
--TEST--
Bug #80866 preg_split ignores limit flag when pattern with \K has 0-width fullstring match
--FILE--
<?php
var_export(preg_split('~.{3}\K~', 'abcdefghijklm', 3));
?>
--EXPECT--
array (
0 => 'abc',
1 => 'def',
2 => 'ghijklm',
)
+18
View File
@@ -0,0 +1,18 @@
--TEST--
Changing LC_CTYPE back to C
--SKIPIF--
<?php
if (!setlocale(LC_CTYPE, "de_DE", "de-DE")) die("skip requires de_DE locale");
?>
--FILE--
<?php
var_dump(setlocale(LC_CTYPE, "de_DE", "de-DE") !== false);
var_dump(preg_match('/\w/', "\xe4"));
var_dump(setlocale(LC_CTYPE, "C") !== false);
var_dump(preg_match('/\w/', "\xe4"));
?>
--EXPECT--
bool(true)
int(1)
bool(true)
int(0)
+15 -5
View File
@@ -652,6 +652,7 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
/* if it is a column containing "long" data, perform late binding now */
if (C->is_long) {
SQLLEN orig_fetched_len = SQL_NULL_DATA;
zend_ulong used = 0;
char *buf;
RETCODE rc;
@@ -662,18 +663,20 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, C->data,
256, &C->fetched_len);
orig_fetched_len = C->fetched_len;
if (rc == SQL_SUCCESS) {
if (rc == SQL_SUCCESS && C->fetched_len < 256) {
/* all the data fit into our little buffer;
* jump down to the generic bound data case */
goto in_data;
}
if (rc == SQL_SUCCESS_WITH_INFO) {
if (rc == SQL_SUCCESS_WITH_INFO || rc == SQL_SUCCESS) {
/* this is a 'long column'
read the column in 255 byte blocks until the end of the column is reached, reassembling those blocks
in order into the output buffer
in order into the output buffer; 255 bytes are an optimistic assumption, since the driver may assert
more or less NUL bytes at the end; we cater to that later, if actual length information is available
this loop has to work whether or not SQLGetData() provides the total column length.
calling SQLDescribeCol() or other, specifically to get the column length, then doing a single read
@@ -687,10 +690,17 @@ static int odbc_stmt_get_col(pdo_stmt_t *stmt, int colno, char **ptr, zend_ulong
do {
C->fetched_len = 0;
/* read block. 256 bytes => 255 bytes are actually read, the last 1 is NULL */
rc = SQLGetData(S->stmt, colno+1, SQL_C_CHAR, buf2, 256, &C->fetched_len);
rc = SQLGetData(S->stmt, colno+1, C->is_unicode ? SQL_C_BINARY : SQL_C_CHAR, buf2, 256, &C->fetched_len);
/* adjust `used` in case we have length info from the driver */
if (orig_fetched_len >= 0 && C->fetched_len >= 0) {
SQLLEN fixed_used = orig_fetched_len - C->fetched_len;
ZEND_ASSERT(fixed_used <= used + 1);
used = fixed_used;
}
/* resize output buffer and reassemble block */
if (rc==SQL_SUCCESS_WITH_INFO) {
if (rc==SQL_SUCCESS_WITH_INFO || (rc==SQL_SUCCESS && C->fetched_len > 255)) {
/* point 5, in section "Retrieving Data with SQLGetData" in http://msdn.microsoft.com/en-us/library/windows/desktop/ms715441(v=vs.85).aspx
states that if SQL_SUCCESS_WITH_INFO, fetched_len will be > 255 (greater than buf2's size)
(if a driver fails to follow that and wrote less than 255 bytes to buf2, this will AV or read garbage into buf) */
+32
View File
@@ -0,0 +1,32 @@
--TEST--
Bug #80783 (PDO ODBC truncates BLOB records at every 256th byte)
--SKIPIF--
<?php
if (!extension_loaded('pdo_odbc')) die('skip pdo_odbc extension not available');
require 'ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->exec("CREATE TABLE bug80783 (name IMAGE)");
$string = str_repeat("0123456789", 50);
$db->exec("INSERT INTO bug80783 VALUES('$string')");
$stmt = $db->prepare("SELECT name FROM bug80783");
$stmt->bindColumn(1, $data, PDO::PARAM_LOB);
$stmt->execute();
$stmt->fetch(PDO::FETCH_BOUND);
var_dump($data === bin2hex($string));
?>
--CLEAN--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->exec("DROP TABLE bug80783");
?>
--EXPECT--
bool(true)
+33
View File
@@ -0,0 +1,33 @@
--TEST--
Bug #80783 (PDO ODBC truncates BLOB records at every 256th byte)
--SKIPIF--
<?php
if (!extension_loaded('pdo_odbc')) die('skip pdo_odbc extension not available');
require 'ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->exec("CREATE TABLE bug80783a (name NVARCHAR(MAX))");
$string = str_repeat("0123456789", 50);
$db->exec("INSERT INTO bug80783a VALUES('$string')");
$stmt = $db->prepare("SELECT name FROM bug80783a");
$stmt->setAttribute(PDO::ODBC_ATTR_ASSUME_UTF8, true);
$stmt->bindColumn(1, $data, PDO::PARAM_STR);
$stmt->execute();
$stmt->fetch(PDO::FETCH_BOUND);
var_dump($data === $string);
?>
--CLEAN--
<?php
require 'ext/pdo/tests/pdo_test.inc';
$db = PDOTest::test_factory(dirname(__FILE__) . '/common.phpt');
$db->exec("DROP TABLE bug80783a");
?>
--EXPECT--
bool(true)
+23 -1
View File
@@ -54,6 +54,19 @@
#define VARCHARLABEL "varchar"
#define VARCHAROID 1043
#define PG_INT32_MIN (-0x7FFFFFFF-1)
#define PG_INT32_MAX (0x7FFFFFFF)
#if defined(_MSC_VER)
# define strtoll(s, f, b) _atoi64(s)
#elif !defined(HAVE_STRTOLL)
# if defined(HAVE_ATOLL)
# define strtoll(s, f, b) atoll(s)
# else
# define strtoll(s, f, b) strtol(s, f, b)
# endif
#endif
static int pgsql_stmt_dtor(pdo_stmt_t *stmt)
@@ -390,7 +403,16 @@ static int pgsql_stmt_param_hook(pdo_stmt_t *stmt, struct pdo_bound_param_data *
S->param_formats[param->paramno] = 0;
}
if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_INT) {
/* we need to check if the number requires bigints */
long long val = strtoll(Z_STRVAL_P(parameter), NULL, 10);
if (val > PG_INT32_MAX || val < PG_INT32_MIN) {
S->param_types[param->paramno] = INT8OID;
} else {
S->param_types[param->paramno] = INT4OID;
}
} else if (PDO_PARAM_TYPE(param->param_type) == PDO_PARAM_LOB) {
S->param_types[param->paramno] = 0;
S->param_formats[param->paramno] = 1;
} else {
+77
View File
@@ -0,0 +1,77 @@
--TEST--
Bug #80892 PDO::PARAM_INT is treated the same as PDO::PARAM_STR
--SKIPIF--
<?php
if (!extension_loaded('pdo') || !extension_loaded('pdo_pgsql')) die('skip not loaded');
require __DIR__ . '/config.inc';
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
PDOTest::skip();
?>
--FILE--
<?php
require __DIR__ . '/../../../ext/pdo/tests/pdo_test.inc';
/** @var PDO $db */
$db = PDOTest::test_factory(__DIR__ . '/common.phpt');
$db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$db->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
$db->exec("CREATE OR REPLACE FUNCTION bug80892 (x bigint) RETURNS varchar AS $$ SELECT 'bigint' $$ LANGUAGE sql");
$db->exec("CREATE OR REPLACE FUNCTION bug80892 (x int) RETURNS varchar AS $$ SELECT 'int' $$ LANGUAGE sql");
$db->exec("CREATE OR REPLACE FUNCTION bug80892 (x text) RETURNS varchar AS $$ SELECT 'text' $$ LANGUAGE sql");
// Sanity check
var_dump($db->query("SELECT bug80892(2147483648)")->fetchColumn());
var_dump($db->query("SELECT bug80892(1)")->fetchColumn());
var_dump($db->query("SELECT bug80892('1')")->fetchColumn());
// No binding
$stmt = $db->prepare("SELECT bug80892(?)");
$stmt->execute([1]);
var_dump($stmt->fetchColumn());
// Bind int value as string
$stmt = $db->prepare("SELECT bug80892(?)");
$stmt->bindValue(1, 1, PDO::PARAM_STR);
$stmt->execute();
var_dump($stmt->fetchColumn());
// Bind int value as int
$stmt = $db->prepare("SELECT bug80892(?)");
$stmt->bindValue(1, 1, PDO::PARAM_INT);
$stmt->execute();
var_dump($stmt->fetchColumn());
// Bind string value as int
$stmt = $db->prepare("SELECT bug80892(?)");
$stmt->bindValue(1, '1', PDO::PARAM_INT);
$stmt->execute();
var_dump($stmt->fetchColumn());
// Bind bigint string value as int
$stmt = $db->prepare("SELECT bug80892(?)");
$stmt->bindValue(1, '2147483648', PDO::PARAM_INT);
$stmt->execute();
var_dump($stmt->fetchColumn());
// Bind negative bigint (string on 32bit) as int
$stmt = $db->prepare("SELECT bug80892(?)");
$stmt->bindValue(1, PHP_INT_SIZE == 4 ? '-33333333333' : -33333333333, PDO::PARAM_INT);
$stmt->execute();
var_dump($stmt->fetchColumn());
$db->exec("DROP FUNCTION bug80892 (bigint)");
$db->exec("DROP FUNCTION bug80892 (int)");
$db->exec("DROP FUNCTION bug80892 (text)");
?>
--EXPECT--
string(6) "bigint"
string(3) "int"
string(4) "text"
string(4) "text"
string(4) "text"
string(3) "int"
string(3) "int"
string(6) "bigint"
string(6) "bigint"
+9 -6
View File
@@ -1424,9 +1424,10 @@ static void php_pgsql_do_connect(INTERNAL_FUNCTION_PARAMETERS, int persistent)
}
pgsql = (PGconn *) le->ptr;
#if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS
if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 7.2) {
/* consider to use php_version_compare() here */
if (PQprotocolVersion(pgsql) >= 3 && zend_strtod(PQparameterStatus(pgsql, "server_version"), NULL) >= 7.2) {
#else
if (atof(PG_VERSION) >= 7.2) {
if (zend_strtod(PG_VERSION, NULL) >= 7.2) {
#endif
pg_result = PQexec(pgsql, "RESET ALL;");
PQclear(pg_result);
@@ -5326,9 +5327,10 @@ PHP_FUNCTION(pg_get_notify)
add_index_string(return_value, 0, pgsql_notify->relname);
add_index_long(return_value, 1, pgsql_notify->be_pid);
#if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS
if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 9.0) {
/* consider to use php_version_compare() here */
if (PQprotocolVersion(pgsql) >= 3 && zend_strtod(PQparameterStatus(pgsql, "server_version"), NULL) >= 9.0) {
#else
if (atof(PG_VERSION) >= 9.0) {
if (zend_strtod(PG_VERSION) >= 9.0, NULL) {
#endif
#if HAVE_PQPARAMETERSTATUS
add_index_string(return_value, 2, pgsql_notify->extra);
@@ -5339,9 +5341,10 @@ PHP_FUNCTION(pg_get_notify)
add_assoc_string(return_value, "message", pgsql_notify->relname);
add_assoc_long(return_value, "pid", pgsql_notify->be_pid);
#if HAVE_PQPROTOCOLVERSION && HAVE_PQPARAMETERSTATUS
if (PQprotocolVersion(pgsql) >= 3 && atof(PQparameterStatus(pgsql, "server_version")) >= 9.0) {
/* consider to use php_version_compare() here */
if (PQprotocolVersion(pgsql) >= 3 && zend_strtod(PQparameterStatus(pgsql, "server_version"), NULL) >= 9.0) {
#else
if (atof(PG_VERSION) >= 9.0) {
if (zend_strtod(PG_VERSION, NULL) >= 9.0) {
#endif
#if HAVE_PQPARAMETERSTATUS
add_assoc_string(return_value, "payload", pgsql_notify->extra);
+1 -1
View File
@@ -1,4 +1,4 @@
.TH PHAR 1 "2019" "The PHP Group" "User Commands"
.TH PHAR 1 "2021" "The PHP Group" "User Commands"
.SH NAME
phar, phar.phar \- PHAR (PHP archive) command line tool
.SH SYNOPSIS
+42 -18
View File
@@ -2508,6 +2508,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
smart_str main_metadata_str = {0};
int free_user_stub, free_fp = 1, free_ufp = 1;
int manifest_hack = 0;
php_stream *shared_cfp = NULL;
if (phar->is_persistent) {
if (error) {
@@ -2602,7 +2603,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
}
php_stream_close(newfile);
if (error) {
spprintf(error, 0, "illegal stub for phar \"%s\"", phar->fname);
spprintf(error, 0, "illegal stub for phar \"%s\" (__HALT_COMPILER(); is missing)", phar->fname);
}
if (free_user_stub) {
zend_string_free(suser_stub);
@@ -2788,10 +2789,13 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
return EOF;
}
/* create new file that holds the compressed version */
/* create new file that holds the compressed versions */
/* work around inability to specify freedom in write and strictness
in read count */
entry->cfp = php_stream_fopen_tmpfile();
if (shared_cfp == NULL) {
shared_cfp = php_stream_fopen_tmpfile();
}
entry->cfp = shared_cfp;
if (!entry->cfp) {
if (error) {
spprintf(error, 0, "unable to create temporary file");
@@ -2800,8 +2804,11 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
php_stream_close(oldfile);
}
php_stream_close(newfile);
return EOF;
goto cleanup;
}
/* for real phars, header_offset is unused; we misuse it here to store the offset in the temp file */
ZEND_ASSERT(entry->header_offset == 0);
entry->header_offset = php_stream_tell(entry->cfp);
php_stream_flush(file);
if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) {
if (closeoldfile) {
@@ -2811,7 +2818,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
if (error) {
spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
}
return EOF;
goto cleanup;
}
php_stream_filter_append((&entry->cfp->writefilters), filter);
if (SUCCESS != php_stream_copy_to_stream_ex(file, entry->cfp, entry->uncompressed_filesize, NULL)) {
@@ -2822,15 +2829,14 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
if (error) {
spprintf(error, 0, "unable to copy compressed file contents of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
}
return EOF;
goto cleanup;
}
php_stream_filter_flush(filter, 1);
php_stream_flush(entry->cfp);
php_stream_filter_remove(filter, 1);
php_stream_seek(entry->cfp, 0, SEEK_END);
entry->compressed_filesize = (uint32_t) php_stream_tell(entry->cfp);
entry->compressed_filesize = ((uint32_t) php_stream_tell(entry->cfp)) - entry->header_offset;
/* generate crc on compressed file */
php_stream_rewind(entry->cfp);
entry->old_flags = entry->flags;
entry->is_modified = 1;
global_flags |= (entry->flags & PHAR_ENT_COMPRESSION_MASK);
@@ -2886,7 +2892,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
spprintf(error, 0, "unable to write manifest header of new phar \"%s\"", phar->fname);
}
return EOF;
goto cleanup;
}
phar->alias_len = restore_alias_len;
@@ -2907,7 +2913,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
spprintf(error, 0, "unable to write manifest meta-data of new phar \"%s\"", phar->fname);
}
return EOF;
goto cleanup;
}
smart_str_free(&main_metadata_str);
@@ -2942,7 +2948,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
spprintf(error, 0, "unable to write filename of file \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname);
}
}
return EOF;
goto cleanup;
}
/* set the manifest meta-data:
@@ -2975,7 +2981,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
spprintf(error, 0, "unable to write temporary manifest of file \"%s\" to manifest of new phar \"%s\"", entry->filename, phar->fname);
}
return EOF;
goto cleanup;
}
} ZEND_HASH_FOREACH_END();
/* Hack - see bug #65028, add padding byte to the end of the manifest */
@@ -2991,7 +2997,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
spprintf(error, 0, "unable to write manifest padding byte");
}
return EOF;
goto cleanup;
}
}
@@ -3004,7 +3010,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
if (entry->cfp) {
file = entry->cfp;
php_stream_rewind(file);
php_stream_seek(file, entry->header_offset, SEEK_SET);
} else {
file = phar_get_efp(entry, 0);
if (-1 == phar_seek_efp(entry, 0, SEEK_SET, 0, 0)) {
@@ -3015,7 +3021,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
if (error) {
spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
}
return EOF;
goto cleanup;
}
}
@@ -3027,7 +3033,7 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
if (error) {
spprintf(error, 0, "unable to seek to start of file \"%s\" while creating new phar \"%s\"", entry->filename, phar->fname);
}
return EOF;
goto cleanup;
}
/* this will have changed for all files that have either changed compression or been modified */
@@ -3044,14 +3050,14 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
spprintf(error, 0, "unable to write contents of file \"%s\" to new phar \"%s\"", entry->filename, phar->fname);
}
return EOF;
goto cleanup;
}
entry->is_modified = 0;
if (entry->cfp) {
php_stream_close(entry->cfp);
entry->cfp = NULL;
entry->header_offset = 0;
}
if (entry->fp_type == PHAR_MOD) {
@@ -3067,6 +3073,11 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
}
} ZEND_HASH_FOREACH_END();
if (shared_cfp != NULL) {
php_stream_close(shared_cfp);
shared_cfp = NULL;
}
/* append signature */
if (global_flags & PHAR_HDR_SIGNATURE) {
char sig_buf[4];
@@ -3196,6 +3207,19 @@ int phar_flush(phar_archive_data *phar, char *user_stub, zend_long len, int conv
return EOF;
}
return EOF;
cleanup:
if (shared_cfp != NULL) {
php_stream_close(shared_cfp);
}
ZEND_HASH_FOREACH_PTR(&phar->manifest, entry) {
if (entry->cfp) {
entry->cfp = NULL;
entry->header_offset = 0;
}
} ZEND_HASH_FOREACH_END();
return EOF;
}
/* }}} */
+1
View File
@@ -3,6 +3,7 @@ Bug #69279 (Compressed ZIP Phar extractTo() creates garbage files)
--SKIPIF--
<?php
if (!extension_loaded('phar')) die('skip phar extension not available');
if (!extension_loaded('zlib')) die('skip zlib extension not available');
?>
--INI--
phar.readonly=0
+1
View File
@@ -3,6 +3,7 @@ Bug #69279 (Compressed ZIP Phar extractTo() creates garbage files)
--SKIPIF--
<?php
if (!extension_loaded('phar')) die('skip phar extension not available');
if (!extension_loaded('zlib')) die('skip zlib extension not available');
?>
--FILE--
<?php
+60
View File
@@ -0,0 +1,60 @@
--TEST--
Bug #70091 (Phar does not mark UTF-8 filenames in ZIP archives)
--SKIPIF--
<?php
if (!extension_loaded('phar')) die('skip phar extension not available');
if (!extension_loaded('zlib')) die('skip zlib extension not available');
?>
--FILE--
<?php
$phar = new PharData(__DIR__ . '/bug70091.zip');
$phar->addFromString('föö', '');
$phar->addFromString('foo', '');
unset($phar);
$stream = fopen(__DIR__ . '/bug70091.zip', 'r');
$data = fread($stream, 8);
var_dump(unpack('H8sig/@6/nflags', $data));
fseek($stream, 53);
$data = fread($stream, 8);
var_dump(unpack('H8sig/@6/nflags', $data));
fseek($stream, 104);
$data = fread($stream, 10);
var_dump(unpack('H8sig/@8/nflags', $data));
fseek($stream, 173);
$data = fread($stream, 10);
var_dump(unpack('H8sig/@8/nflags', $data));
?>
--EXPECT--
array(2) {
["sig"]=>
string(8) "504b0304"
["flags"]=>
int(8)
}
array(2) {
["sig"]=>
string(8) "504b0304"
["flags"]=>
int(8)
}
array(2) {
["sig"]=>
string(8) "504b0102"
["flags"]=>
int(8)
}
array(2) {
["sig"]=>
string(8) "504b0102"
["flags"]=>
int(8)
}
--CLEAN--
<?php
@unlink(__DIR__ . '/bug70091.zip');
?>
+1
View File
@@ -3,6 +3,7 @@ Bug #79912 (Phar::decompressFiles not working)
--SKIPIF--
<?php
if (!extension_loaded('phar')) die('skip phar extension is not available');
if (!extension_loaded('zlib')) die('skip zlib extension not available');
?>
--INI--
phar.readonly=0
+1 -1
View File
@@ -48,7 +48,7 @@ __HALT_COMPILER();
string(48) "<?php echo "first stub\n"; __HALT_COMPILER(); ?>"
string(48) "<?php echo "first stub\n"; __HALT_COMPILER(); ?>"
bool(true)
Exception: illegal stub for phar "%sphar_stub_error.phar.php"
Exception: illegal stub for phar "%sphar_stub_error.phar.php" (__HALT_COMPILER(); is missing)
string(48) "<?php echo "first stub\n"; __HALT_COMPILER(); ?>"
bool(true)
string(48) "<?php echo "first stub\n"; __HALT_COMPILER(); ?>"
+6
View File
@@ -829,6 +829,7 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{
zend_off_t offset;
int not_really_modified = 0;
p = (struct _phar_zip_pass*) arg;
uint16_t general_purpose_flags;
if (entry->is_mounted) {
return ZEND_HASH_APPLY_KEEP;
@@ -878,6 +879,11 @@ static int phar_zip_changed_apply_int(phar_entry_info *entry, void *arg) /* {{{
memcpy(central.datestamp, local.datestamp, sizeof(local.datestamp));
PHAR_SET_16(central.filename_len, entry->filename_len + (entry->is_dir ? 1 : 0));
PHAR_SET_16(local.filename_len, entry->filename_len + (entry->is_dir ? 1 : 0));
// set language encoding flag (all filenames have to be UTF-8 anyway)
general_purpose_flags = PHAR_GET_16(central.flags);
PHAR_SET_16(central.flags, general_purpose_flags | (1 << 11));
general_purpose_flags = PHAR_GET_16(local.flags);
PHAR_SET_16(local.flags, general_purpose_flags | (1 << 11));
PHAR_SET_32(central.offset, php_stream_tell(p->filefp));
/* do extra field for perms later */
+12 -2
View File
@@ -563,22 +563,32 @@ PHP_FUNCTION(posix_setegid)
#ifdef HAVE_GETGROUPS
PHP_FUNCTION(posix_getgroups)
{
gid_t gidlist[NGROUPS_MAX];
gid_t *gidlist;
int result;
int i;
PHP_POSIX_NO_ARGS;
if ((result = getgroups(NGROUPS_MAX, gidlist)) < 0) {
/* MacOS may return more than NGROUPS_MAX groups.
* Fetch the actual number of groups and create an appropriate allocation. */
if ((result = getgroups(0, NULL)) < 0) {
POSIX_G(last_error) = errno;
RETURN_FALSE;
}
gidlist = emalloc(sizeof(gid_t) * result);
if ((result = getgroups(result, gidlist)) < 0) {
POSIX_G(last_error) = errno;
efree(gidlist);
RETURN_FALSE;
}
array_init(return_value);
for (i=0; i<result; i++) {
add_next_index_long(return_value, gidlist[i]);
}
efree(gidlist);
}
#endif
/* }}} */
+9
View File
@@ -1534,6 +1534,11 @@ ZEND_METHOD(reflection_function, __construct)
}
}
if (intern->ptr) {
zval_ptr_dtor(&intern->obj);
zval_ptr_dtor(reflection_prop_name(object));
}
ZVAL_STR_COPY(reflection_prop_name(object), fptr->common.function_name);
intern->ptr = fptr;
intern->ref_type = REF_TYPE_FUNCTION;
@@ -2073,6 +2078,10 @@ ZEND_METHOD(reflection_generator, __construct)
return;
}
if (intern->ce) {
zval_ptr_dtor(&intern->obj);
}
intern->ref_type = REF_TYPE_GENERATOR;
Z_ADDREF_P(generator);
ZVAL_OBJ(&intern->obj, Z_OBJ_P(generator));
+29 -27
View File
@@ -1261,13 +1261,11 @@ static void php_session_remove_cookie(void) {
zend_llist_element *next;
zend_llist_element *current;
char *session_cookie;
zend_string *e_session_name;
size_t session_cookie_len;
size_t len = sizeof("Set-Cookie")-1;
e_session_name = php_url_encode(PS(session_name), strlen(PS(session_name)));
spprintf(&session_cookie, 0, "Set-Cookie: %s=", ZSTR_VAL(e_session_name));
zend_string_free(e_session_name);
ZEND_ASSERT(strpbrk(PS(session_name), "=,; \t\r\n\013\014") == NULL);
spprintf(&session_cookie, 0, "Set-Cookie: %s=", PS(session_name));
session_cookie_len = strlen(session_cookie);
current = l->head;
@@ -1299,7 +1297,7 @@ static int php_session_send_cookie(void) /* {{{ */
{
smart_str ncookie = {0};
zend_string *date_fmt = NULL;
zend_string *e_session_name, *e_id;
zend_string *e_id;
if (SG(headers_sent)) {
const char *output_start_filename = php_output_get_start_filename();
@@ -1313,16 +1311,20 @@ static int php_session_send_cookie(void) /* {{{ */
return FAILURE;
}
/* URL encode session_name and id because they might be user supplied */
e_session_name = php_url_encode(PS(session_name), strlen(PS(session_name)));
/* Prevent broken Set-Cookie header, because the session_name might be user supplied */
if (strpbrk(PS(session_name), "=,; \t\r\n\013\014") != NULL) { /* man isspace for \013 and \014 */
php_error_docref(NULL, E_WARNING, "session.name cannot contain any of the following '=,; \\t\\r\\n\\013\\014'");
return FAILURE;
}
/* URL encode id because it might be user supplied */
e_id = php_url_encode(ZSTR_VAL(PS(id)), ZSTR_LEN(PS(id)));
smart_str_appendl(&ncookie, "Set-Cookie: ", sizeof("Set-Cookie: ")-1);
smart_str_appendl(&ncookie, ZSTR_VAL(e_session_name), ZSTR_LEN(e_session_name));
smart_str_appendl(&ncookie, PS(session_name), strlen(PS(session_name)));
smart_str_appendc(&ncookie, '=');
smart_str_appendl(&ncookie, ZSTR_VAL(e_id), ZSTR_LEN(e_id));
zend_string_release_ex(e_session_name, 0);
zend_string_release_ex(e_id, 0);
if (PS(cookie_lifetime) > 0) {
@@ -1921,13 +1923,24 @@ static PHP_FUNCTION(session_module_name)
}
/* }}} */
static inline void set_user_save_handler_ini(void) {
zend_string *ini_name, *ini_val;
ini_name = zend_string_init("session.save_handler", sizeof("session.save_handler") - 1, 0);
ini_val = zend_string_init("user", sizeof("user") - 1, 0);
PS(set_handler) = 1;
zend_alter_ini_entry(ini_name, ini_val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
PS(set_handler) = 0;
zend_string_release_ex(ini_val, 0);
zend_string_release_ex(ini_name, 0);
}
/* {{{ proto bool session_set_save_handler(string open, string close, string read, string write, string destroy, string gc, string create_sid)
Sets user-level functions */
static PHP_FUNCTION(session_set_save_handler)
{
zval *args = NULL;
int i, num_args, argc = ZEND_NUM_ARGS();
zend_string *ini_name, *ini_val;
if (PS(session_status) == php_session_active) {
php_error_docref(NULL, E_WARNING, "Cannot change save handler when session is active");
@@ -2029,14 +2042,8 @@ static PHP_FUNCTION(session_set_save_handler)
remove_user_shutdown_function("session_shutdown", sizeof("session_shutdown") - 1);
}
if (PS(mod) && PS(session_status) != php_session_active && PS(mod) != &ps_mod_user) {
ini_name = zend_string_init("session.save_handler", sizeof("session.save_handler") - 1, 0);
ini_val = zend_string_init("user", sizeof("user") - 1, 0);
PS(set_handler) = 1;
zend_alter_ini_entry(ini_name, ini_val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
PS(set_handler) = 0;
zend_string_release_ex(ini_val, 0);
zend_string_release_ex(ini_name, 0);
if (PS(session_status) != php_session_active && (!PS(mod) || PS(mod) != &ps_mod_user)) {
set_user_save_handler_ini();
}
RETURN_TRUE;
@@ -2064,14 +2071,8 @@ static PHP_FUNCTION(session_set_save_handler)
}
}
if (PS(mod) && PS(mod) != &ps_mod_user) {
ini_name = zend_string_init("session.save_handler", sizeof("session.save_handler") - 1, 0);
ini_val = zend_string_init("user", sizeof("user") - 1, 0);
PS(set_handler) = 1;
zend_alter_ini_entry(ini_name, ini_val, PHP_INI_USER, PHP_INI_STAGE_RUNTIME);
PS(set_handler) = 0;
zend_string_release_ex(ini_val, 0);
zend_string_release_ex(ini_name, 0);
if (!PS(mod) || PS(mod) != &ps_mod_user) {
set_user_save_handler_ini();
}
for (i = 0; i < argc; i++) {
@@ -2854,7 +2855,8 @@ static int php_rinit_session(zend_bool auto_start) /* {{{ */
{
php_rinit_session_globals();
if (PS(mod) == NULL) {
PS(mod) = NULL;
{
char *value;
value = zend_ini_string("session.save_handler", sizeof("session.save_handler") - 1, 0);
+15
View File
@@ -0,0 +1,15 @@
--TEST--
Bug #80774 (session_name() problem with backslash)
--SKIPIF--
<?php
if (!extension_loaded('session')) die("skip session extension not available");
?>
--FILE--
<?php
session_name("foo\\bar");
session_id('12345');
session_start();
?>
--EXPECTHEADERS--
Set-Cookie: foo\bar=12345; path=/
--EXPECT--
+37
View File
@@ -0,0 +1,37 @@
--TEST--
Bug #80889 (Cannot set save handler when save_handler is invalid)
--SKIPIF--
<?php include('skipif.inc'); ?>
--INI--
session.save_handler=whatever
--FILE--
<?php
class DummyHandler implements SessionHandlerInterface {
public function open($savePath, $sessionName) {
return true;
}
public function close() {
return true;
}
public function read($id) {
return '';
}
public function write($id, $data) {
return true;
}
public function destroy($id) {
return true;
}
public function gc($maxlifetime) {
return true;
}
}
$initHandler = ini_get('session.save_handler');
session_set_save_handler(new DummyHandler());
$setHandler = ini_get('session.save_handler');
var_dump($initHandler, $setHandler);
?>
--EXPECT--
string(8) "whatever"
string(4) "user"
+35
View File
@@ -0,0 +1,35 @@
--TEST--
Bug #80889 (Cannot set save handler when save_handler is invalid)
--SKIPIF--
<?php include('skipif.inc'); ?>
--INI--
session.save_handler=whatever
--FILE--
<?php
$initHandler = ini_get('session.save_handler');
session_set_save_handler(
function ($savePath, $sessionName) {
return true;
},
function () {
return true;
},
function ($id) {
return '';
},
function ($id, $data) {
return true;
},
function ($id) {
return true;
},
function ($maxlifetime) {
return true;
}
);
$setHandler = ini_get('session.save_handler');
var_dump($initHandler, $setHandler);
?>
--EXPECT--
string(8) "whatever"
string(4) "user"
@@ -48,6 +48,8 @@ string(9) "PHPSESSID"
bool(true)
string(9) "PHPSESSID"
string(9) "PHPSESSID"
Warning: session_start(): session.name cannot contain any of the following '=,; \t\r\n\013\014' in %s on line %d
bool(true)
string(1) " "
bool(true)
@@ -55,6 +57,8 @@ string(1) " "
Warning: session_name(): session.name cannot be a numeric or empty '' in %s on line %d
string(1) " "
Warning: session_start(): session.name cannot contain any of the following '=,; \t\r\n\013\014' in %s on line %d
bool(true)
string(1) " "
bool(true)
+4 -1
View File
@@ -3381,6 +3381,7 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
} else {
smart_str prefix = {0};
int num = ++SOAP_GLOBAL(cur_uniq_ns);
xmlChar *enc_ns;
while (1) {
smart_str_appendl(&prefix, "ns", 2);
@@ -3394,7 +3395,9 @@ xmlNsPtr encode_add_ns(xmlNodePtr node, const char* ns)
num = ++SOAP_GLOBAL(cur_uniq_ns);
}
xmlns = xmlNewNs(node->doc->children, BAD_CAST(ns), BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : ""));
enc_ns = xmlEncodeSpecialChars(node->doc, BAD_CAST(ns));
xmlns = xmlNewNs(node->doc->children, enc_ns, BAD_CAST(prefix.s ? ZSTR_VAL(prefix.s) : ""));
xmlFree(enc_ns);
smart_str_free(&prefix);
}
}
+1 -2
View File
@@ -741,9 +741,8 @@ static sdlPtr load_wsdl(zval *this_ptr, char *struri)
zend_hash_init(&ctx.portTypes, 0, NULL, NULL, 0);
zend_hash_init(&ctx.services, 0, NULL, NULL, 0);
load_wsdl_ex(this_ptr, struri, &ctx, 0);
zend_try {
load_wsdl_ex(this_ptr, struri, &ctx, 0);
schema_pass2(&ctx);
n = zend_hash_num_elements(&ctx.services);
+26
View File
@@ -0,0 +1,26 @@
--TEST--
Bug #69668 (SOAP: special XML characters in namespace URIs not encoded)
--SKIPIF--
<?php
require_once('skipif.inc');
?>
--FILE--
<?php
class MySoapClient extends SoapClient {
public function __doRequest($request, $location, $action, $version, $one_way = 0) {
echo $request, PHP_EOL;
return '';
}
}
$client = new MySoapClient(__DIR__ . '/bug69668.wsdl', [
'trace' => true,
'exceptions' => true,
'cache_wsdl' => WSDL_CACHE_NONE,
]);
$client->test();
?>
--EXPECT--
<?xml version="1.0" encoding="UTF-8"?>
<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="http://localhost/69668.php?a=a&amp;b=b" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:test/></SOAP-ENV:Body></SOAP-ENV:Envelope>
+35
View File
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="UTF-8"?>
<definitions xmlns="http://schemas.xmlsoap.org/wsdl/" xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" xmlns:tns="http://localhost/69668.php?a=a&amp;b=b" xmlns:soap="http://schemas.xmlsoap.org/wsdl/soap/" xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:soap-enc="http://schemas.xmlsoap.org/soap/encoding/" xmlns:soap12="http://schemas.xmlsoap.org/wsdl/soap12/" name="TestService" targetNamespace="http://localhost/69668.php?a=a&amp;b=b">
<types>
<xsd:schema targetNamespace="http://localhost/69668.php?a=a&amp;b=b" />
</types>
<portType name="TestServicePort">
<operation name="test">
<documentation>test</documentation>
<input message="tns:testIn" />
<output message="tns:testOut" />
</operation>
</portType>
<binding name="TestServiceBinding" type="tns:TestServicePort">
<soap:binding style="rpc" transport="http://schemas.xmlsoap.org/soap/http" />
<operation name="test">
<soap:operation soapAction="http://localhost/69668.php?a=a&amp;b=b#test" />
<input>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/69668.php?a=a&amp;b=b" />
</input>
<output>
<soap:body use="encoded" encodingStyle="http://schemas.xmlsoap.org/soap/encoding/" namespace="http://localhost/69668.php?a=a&amp;b=b" />
</output>
</operation>
</binding>
<service name="TestServiceService">
<port name="TestServicePort" binding="tns:TestServiceBinding">
<soap:address location="http://localhost/69668.php?a=a&amp;b=b" />
</port>
</service>
<message name="testIn" />
<message name="testOut">
<part name="return" type="xsd:string" />
</message>
</definitions>
+2 -2
View File
@@ -1179,7 +1179,7 @@ SPL_METHOD(Array, __construct)
spl_array_object *intern;
zval *array;
zend_long ar_flags = 0;
zend_class_entry *ce_get_iterator = spl_ce_Iterator;
zend_class_entry *ce_get_iterator = spl_ce_ArrayIterator;
if (ZEND_NUM_ARGS() == 0) {
return; /* nothing to do */
@@ -1232,7 +1232,7 @@ SPL_METHOD(Array, setIteratorClass)
{
zval *object = ZEND_THIS;
spl_array_object *intern = Z_SPLARRAY_P(object);
zend_class_entry * ce_get_iterator = spl_ce_Iterator;
zend_class_entry *ce_get_iterator = spl_ce_ArrayIterator;
ZEND_PARSE_PARAMETERS_START(1, 1)
Z_PARAM_CLASS(ce_get_iterator)
+3 -19
View File
@@ -1677,15 +1677,7 @@ zend_object_iterator *spl_filesystem_dir_get_iterator(zend_class_entry *ce, zval
static void spl_filesystem_dir_it_dtor(zend_object_iterator *iter)
{
spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
if (!Z_ISUNDEF(iterator->intern.data)) {
zval *object = &iterator->intern.data;
zval_ptr_dtor(object);
}
/* Otherwise we were called from the owning object free storage handler as
* it sets iterator->intern.data to IS_UNDEF.
* We don't even need to destroy iterator->current as we didn't add a
* reference to it in move_forward or get_iterator */
zval_ptr_dtor(&iterator->intern.data);
}
/* }}} */
@@ -1747,16 +1739,8 @@ static void spl_filesystem_dir_it_rewind(zend_object_iterator *iter)
static void spl_filesystem_tree_it_dtor(zend_object_iterator *iter)
{
spl_filesystem_iterator *iterator = (spl_filesystem_iterator *)iter;
if (!Z_ISUNDEF(iterator->intern.data)) {
zval *object = &iterator->intern.data;
zval_ptr_dtor(object);
} else {
if (!Z_ISUNDEF(iterator->current)) {
zval_ptr_dtor(&iterator->current);
ZVAL_UNDEF(&iterator->current);
}
}
zval_ptr_dtor(&iterator->intern.data);
zval_ptr_dtor(&iterator->current);
}
/* }}} */
@@ -20,6 +20,6 @@ try {
?>
--EXPECT--
Bad iterator type:
ArrayObject::__construct() expects parameter 3 to be a class name derived from Iterator, 'Exception' given(6)
ArrayObject::__construct() expects parameter 3 to be a class name derived from ArrayIterator, 'Exception' given(6)
Non-existent class:
ArrayObject::__construct() expects parameter 3 to be a class name derived from Iterator, 'nonExistentClassName' given(13)
ArrayObject::__construct() expects parameter 3 to be a class name derived from ArrayIterator, 'nonExistentClassName' given(13)
@@ -43,14 +43,14 @@ try {
?>
--EXPECTF--
Warning: ArrayObject::setIteratorClass() expects parameter 1 to be a class name derived from Iterator, 'nonExistentClass' given in %s on line 4
Warning: ArrayObject::setIteratorClass() expects parameter 1 to be a class name derived from ArrayIterator, 'nonExistentClass' given in %s on line %d
a=>1
b=>2
c=>3
Warning: ArrayObject::setIteratorClass() expects parameter 1 to be a class name derived from Iterator, 'stdClass' given in %s on line 14
Warning: ArrayObject::setIteratorClass() expects parameter 1 to be a class name derived from ArrayIterator, 'stdClass' given in %s on line %d
a=>1
b=>2
c=>3
string(113) "ArrayObject::__construct() expects parameter 3 to be a class name derived from Iterator, 'nonExistentClass' given"
string(105) "ArrayObject::__construct() expects parameter 3 to be a class name derived from Iterator, 'stdClass' given"
string(118) "ArrayObject::__construct() expects parameter 3 to be a class name derived from ArrayIterator, 'nonExistentClass' given"
string(110) "ArrayObject::__construct() expects parameter 3 to be a class name derived from ArrayIterator, 'stdClass' given"
+15
View File
@@ -0,0 +1,15 @@
--TEST--
Bug #80719: Iterating after failed ArrayObject::setIteratorClass() causes Segmentation fault
--FILE--
<?php
$array = new ArrayObject([42]);
$array->setIteratorClass(FilterIterator::class);
foreach ($array as $v) {
var_dump($v);
}
?>
--EXPECTF--
Warning: ArrayObject::setIteratorClass() expects parameter 1 to be a class name derived from ArrayIterator, 'FilterIterator' given in %s on line %d
int(42)
@@ -0,0 +1,12 @@
--TEST--
Don't leak when breaking from FilesystemIterator
--FILE--
<?php
$iterator = new FilesystemIterator(__DIR__);
foreach ($iterator as $value) {
break;
}
?>
===DONE===
--EXPECT--
===DONE===
-4
View File
@@ -564,10 +564,6 @@ PHP_FUNCTION(file_get_contents)
RETURN_FALSE;
}
if (maxlen > INT_MAX) {
php_error_docref(NULL, E_WARNING, "maxlen truncated from " ZEND_LONG_FMT " to %d bytes", maxlen, INT_MAX);
maxlen = INT_MAX;
}
if ((contents = php_stream_copy_to_mem(stream, maxlen, 0)) != NULL) {
RETVAL_STR(contents);
} else {
+6 -14
View File
@@ -680,7 +680,7 @@ finish:
/* status codes of 1xx are "informational", and will be followed by a real response
* e.g "100 Continue". RFC 7231 states that unexpected 1xx status MUST be parsed,
* and MAY be ignored. As such, we need to skip ahead to the "real" status*/
if (response_code >= 100 && response_code < 200) {
if (response_code >= 100 && response_code < 200 && response_code != 101) {
/* consume lines until we find a line starting 'HTTP/1' */
while (
!php_stream_eof(stream)
@@ -732,24 +732,16 @@ finish:
/* read past HTTP headers */
http_header_line = emalloc(HTTP_HEADER_BLOCK_SIZE);
while (!php_stream_eof(stream)) {
size_t http_header_line_length;
if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) && *http_header_line != '\n' && *http_header_line != '\r') {
if (http_header_line != NULL) {
efree(http_header_line);
}
if ((http_header_line = php_stream_get_line(stream, NULL, 0, &http_header_line_length)) && *http_header_line != '\n' && *http_header_line != '\r') {
char *e = http_header_line + http_header_line_length - 1;
char *http_header_value;
if (*e != '\n') {
do { /* partial header */
if (php_stream_get_line(stream, http_header_line, HTTP_HEADER_BLOCK_SIZE, &http_header_line_length) == NULL) {
php_stream_wrapper_log_error(wrapper, options, "Failed to read HTTP headers");
goto out;
}
e = http_header_line + http_header_line_length - 1;
} while (*e != '\n');
continue;
}
while (e >= http_header_line && (*e == '\n' || *e == '\r')) {
e--;
}
+2 -2
View File
@@ -176,7 +176,7 @@ static ZEND_COLD void php_print_gpcse_array(char *name, uint32_t name_length)
key = zend_string_init(name, name_length, 0);
zend_is_auto_global(key);
if ((data = zend_hash_find(&EG(symbol_table), key)) != NULL && (Z_TYPE_P(data) == IS_ARRAY)) {
if ((data = zend_hash_find_deref(&EG(symbol_table), key)) != NULL && (Z_TYPE_P(data) == IS_ARRAY)) {
ZEND_HASH_FOREACH_KEY_VAL(Z_ARRVAL_P(data), num_key, string_key, tmp) {
if (!sapi_module.phpinfo_as_text) {
php_info_print("<tr>");
@@ -1000,7 +1000,7 @@ PHPAPI ZEND_COLD void php_print_info(int flag)
}
if ((flag & PHP_INFO_CREDITS) && !sapi_module.phpinfo_as_text) {
if (flag & PHP_INFO_CREDITS) {
php_info_print_hr();
php_print_credits(PHP_CREDITS_ALL & ~PHP_CREDITS_FULLPAGE);
}
-4
View File
@@ -456,10 +456,6 @@ PHP_FUNCTION(stream_get_contents)
}
}
if (maxlen > INT_MAX) {
php_error_docref(NULL, E_WARNING, "maxlen truncated from " ZEND_LONG_FMT " to %d bytes", maxlen, INT_MAX);
maxlen = INT_MAX;
}
if ((contents = php_stream_copy_to_mem(stream, maxlen, 0))) {
RETURN_STR(contents);
} else {
+20
View File
@@ -0,0 +1,20 @@
--TEST--
Bug #80915: Taking a reference to $_SERVER hides its values from phpinfo()
--FILE--
<?php
$_ENV = [];
$_SERVER = [ 'test' => 'test' ];
$reference =& $_SERVER;
phpinfo(INFO_VARIABLES);
?>
--EXPECT--
phpinfo()
PHP Variables
Variable => Value
$_SERVER['test'] => test
@@ -0,0 +1,16 @@
--TEST--
Bug #80771 (phpinfo(INFO_CREDITS) displays nothing in CLI)
--FILE--
<?php
ob_start();
phpinfo(INFO_CREDITS);
$info = ob_get_clean();
ob_start();
phpcredits();
$credits = ob_get_clean();
var_dump(strpos($info, $credits) !== false);
?>
--EXPECT--
bool(true)
+26
View File
@@ -0,0 +1,26 @@
--TEST--
Bug #78719 (http wrapper silently ignores long Location headers)
--SKIPIF--
<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:12342'); ?>
--INI--
allow_url_fopen=1
--FILE--
<?php
require 'server.inc';
$url = str_repeat('*', 2000);
$responses = array(
"data://text/plain,HTTP/1.0 302 Ok\r\nLocation: $url\r\n\r\nBody",
);
$pid = http_server("tcp://127.0.0.1:12342", $responses, $output);
$context = stream_context_create(['http' => ['follow_location' => 0]]);
$stream = fopen('http://127.0.0.1:12342/', 'r', false, $context);
var_dump(stream_get_contents($stream));
var_dump(stream_get_meta_data($stream)['wrapper_data'][1] === "Location: $url");
http_server_kill($pid);
?>
--EXPECTF--
string(4) "Body"
bool(true)
+41
View File
@@ -0,0 +1,41 @@
--TEST--
Bug #80838 (HTTP wrapper waits for HTTP 1 response after HTTP 101)
--INI--
allow_url_fopen=1
--SKIPIF--
<?php require 'server.inc'; http_server_skipif('tcp://127.0.0.1:12342'); ?>
--FILE--
<?php
require 'server.inc';
$responses = [
"data://text/plain,HTTP/1.1 101 Switching Protocols\r\nHeader1: Value1\r\nHeader2: Value2\r\n\r\n"
. "Hello from another protocol"
];
$pid = http_server('tcp://127.0.0.1:12342', $responses);
$options = [
'http' => [
'ignore_errors' => true
],
];
$ctx = stream_context_create($options);
$fd = fopen('http://127.0.0.1:12342/', 'rb', false, $ctx);
fclose($fd);
var_dump($http_response_header);
http_server_kill($pid);
?>
--EXPECT--
array(3) {
[0]=>
string(32) "HTTP/1.1 101 Switching Protocols"
[1]=>
string(15) "Header1: Value1"
[2]=>
string(15) "Header2: Value2"
}
+76
View File
@@ -0,0 +1,76 @@
--TEST--
Bug #72964 (White space not unfolded for CC/Bcc headers)
--SKIPIF--
<?php
if (PHP_OS_FAMILY !== 'Windows') die('skip Windows only test');
if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
require_once __DIR__ . '/mail_skipif.inc';
?>
--INI--
SMTP=localhost
smtp_port=25
--FILE--
<?php
require_once __DIR__ . '/mail_include.inc';
function find_and_delete_message($username, $subject) {
global $default_mailbox, $password;
$imap_stream = imap_open($default_mailbox, $username, $password);
if ($imap_stream === false) {
die("Cannot connect to IMAP server $server: " . imap_last_error() . "\n");
}
$found = false;
$repeat_count = 20; // we will repeat a max of 20 times
while (!$found && $repeat_count > 0) {
// sleep for a while to allow msg to be delivered
sleep(1);
$num_messages = imap_check($imap_stream)->Nmsgs;
for ($i = $num_messages; $i > 0; $i--) {
$info = imap_headerinfo($imap_stream, $i);
if ($info->subject === $subject) {
$header = imap_fetchheader($imap_stream, $i);
echo "X-Mailer header found: ";
var_dump(strpos($header, 'X-Mailer: bug80706') !== false);
imap_delete($imap_stream, $i);
$found = true;
break;
}
}
$repeat_count--;
}
imap_close($imap_stream, CL_EXPUNGE);
return $found;
}
$to = "{$users[1]}@$domain";
$subject = bin2hex(random_bytes(16));
$message = 'hello';
$headers = "From: webmaster@example.com\r\n"
. "Bcc: {$users[2]}@$domain\r\n"
. "X-Mailer: bug80706";
$res = mail($to, $subject, $message, $headers);
if ($res !== true) {
die("TEST FAILED : Unable to send test email\n");
} else {
echo "Message sent OK\n";
}
foreach ([$users[1], $users[2]] as $user) {
if (!find_and_delete_message("$user@$domain", $subject)) {
echo "TEST FAILED: email not delivered\n";
} else {
echo "TEST PASSED: Message sent and deleted OK\n";
}
}
?>
--EXPECT--
Message sent OK
X-Mailer header found: bool(true)
TEST PASSED: Message sent and deleted OK
X-Mailer header found: bool(true)
TEST PASSED: Message sent and deleted OK
+93
View File
@@ -0,0 +1,93 @@
--TEST--
Bug #80751 (Comma in recipient name breaks email delivery)
--SKIPIF--
<?php
if (PHP_OS_FAMILY !== 'Windows') die('skip Windows only test');
if (getenv("SKIP_SLOW_TESTS")) die('skip slow test');
require_once __DIR__ . '/mail_skipif.inc';
?>
--INI--
SMTP=localhost
smtp_port=25
--FILE--
<?php
require_once __DIR__ . '/mail_include.inc';
function find_and_delete_message($username, $subject) {
global $default_mailbox, $password;
$imap_stream = imap_open($default_mailbox, $username, $password);
if ($imap_stream === false) {
die("Cannot connect to IMAP server $server: " . imap_last_error() . "\n");
}
$found = false;
$repeat_count = 20; // we will repeat a max of 20 times
while (!$found && $repeat_count > 0) {
// sleep for a while to allow msg to be delivered
sleep(1);
$num_messages = imap_check($imap_stream)->Nmsgs;
for ($i = $num_messages; $i > 0; $i--) {
$info = imap_headerinfo($imap_stream, $i);
if ($info->subject === $subject) {
$header = imap_fetchheader($imap_stream, $i);
echo "Return-Path header found: ";
var_dump(strpos($header, 'Return-Path: joe@example.com') !== false);
echo "To header found: ";
var_dump(strpos($header, 'To: "<bob@example.com>" <info@mail.local>') !== false);
echo "From header found: ";
var_dump(strpos($header, 'From: "<bob@example.com>" <joe@example.com>') !== false);
echo "Cc header found: ";
var_dump(strpos($header, 'Cc: "Lastname, Firstname\\\\" <admin@mail.local>') !== false);
imap_delete($imap_stream, $i);
$found = true;
break;
}
}
$repeat_count--;
}
imap_close($imap_stream, CL_EXPUNGE);
return $found;
}
$to = "\"<bob@example.com>\" <{$users[1]}@$domain>";
$subject = bin2hex(random_bytes(16));
$message = 'hello';
$headers = "From: \"<bob@example.com>\" <joe@example.com>\r\n"
. "Cc: \"Lastname, Firstname\\\\\" <{$users[2]}@$domain>\r\n"
. "Bcc: \"Firstname \\\"Ni,ck\\\" Lastname\" <{$users[3]}@$domain>\r\n";
$res = mail($to, $subject, $message, $headers);
if ($res !== true) {
die("TEST FAILED : Unable to send test email\n");
} else {
echo "Message sent OK\n";
}
foreach ([$users[1], $users[2], $users[3]] as $user) {
if (!find_and_delete_message("$user@$domain", $subject)) {
echo "TEST FAILED: email not delivered\n";
} else {
echo "TEST PASSED: Message sent and deleted OK\n";
}
}
?>
--EXPECT--
Message sent OK
Return-Path header found: bool(true)
To header found: bool(true)
From header found: bool(true)
Cc header found: bool(true)
TEST PASSED: Message sent and deleted OK
Return-Path header found: bool(true)
To header found: bool(true)
From header found: bool(true)
Cc header found: bool(true)
TEST PASSED: Message sent and deleted OK
Return-Path header found: bool(true)
To header found: bool(true)
From header found: bool(true)
Cc header found: bool(true)
TEST PASSED: Message sent and deleted OK
Loaded 100 of 120 files, more files were not shown because too many files have changed in this diff. Show more