When a class (or enum) has no methods, rather than using an array that only
contains `ZEND_FE_END`, use `NULL` for the functions. The implementation of
class registration for internal classes, `do_register_internal_class()` in
zend_API.c, already skips classes where the functions are `NULL`. By removing
these unneeded arrays, we can reduce the size of the header files, while also
removing an unneeded call to zend_register_functions() for each internal class
with no extra methods.
Currently, internal classes are registered with the following code:
INIT_CLASS_ENTRY(ce, "InternalClass", class_InternalClass_methods);
class_entry = zend_register_internal_class_ex(&ce, NULL);
class_entry->ce_flags |= ...;
This has worked well so far, except if InternalClass is readonly. It is because some inheritance checks are run by zend_register_internal_class_ex before ZEND_ACC_READONLY_CLASS is added to ce_flags.
The issue is fixed by adding a zend_register_internal_class_with_flags() zend API function that stubs can use from now on. This function makes sure to add the flags before running any checks. Since the new API is not available in lower PHP versions, gen_stub.php has to keep support for the existing API for PHP 8.3 and below.
PR #13498 bumped the required OpenSSL version to 1.1.1, but apparently
only for non Windows system. We catch up somewhat by dropping support
for OpenSSL < 1.1.0 on Windows; besides completely removing detection
of old OpenSSL versions in `SETUP_OPENSSL`, we also ensure that all
bundled extension using this function do no longer accept OpenSSL <
1.1.0, to avoid to still be able to build these extensions with older
`phpize` scripts.
We do not cater to `--phar-native-ssl` yet; that might better be
addressed by #14578.
Closes GH-14973.
* Include from build dir first
This fixes out of tree builds by ensuring that configure artifacts are included
from the build dir.
Before, out of tree builds would preferably include files from the src dir, as
the include path was defined as follows (ignoring includes from ext/ and sapi/) :
-I$(top_builddir)/main
-I$(top_srcdir)
-I$(top_builddir)/TSRM
-I$(top_builddir)/Zend
-I$(top_srcdir)/main
-I$(top_srcdir)/Zend
-I$(top_srcdir)/TSRM
-I$(top_builddir)/
As a result, an out of tree build would include configure artifacts such as
`main/php_config.h` from the src dir.
After this change, the include path is defined as follows:
-I$(top_builddir)/main
-I$(top_builddir)
-I$(top_srcdir)/main
-I$(top_srcdir)
-I$(top_builddir)/TSRM
-I$(top_builddir)/Zend
-I$(top_srcdir)/Zend
-I$(top_srcdir)/TSRM
* Fix extension include path for out of tree builds
* Include config.h with the brackets form
`#include "config.h"` searches in the directory containing the including-file
before any other include path. This can include the wrong config.h when building
out of tree and a config.h exists in the source tree.
Using `#include <config.h>` uses exclusively the include path, and gives
priority to the build dir.
This is a leftover from the refactoring of the --with-openssl-dir option
that once accepted the path to OpenSSL but wasn't renamed back then.
Instead of --with-openssl-dir, SSL support in ext/ftp and ext/mysqlnd
can be enabled implicitly when building with ext/openssl enabled
(--with-openssl) or explicitly by using new separate configure options
--with-ftp-ssl and --with-mysqlnd-ssl.
There are two slow parts in the upload logic:
- Reading from the input stream character by character
- Checking each character one by one to normalize line endings
First of all, the line normalization isn't necessary for binary
transfers, so we can use a simple read while loop to read bytes into the
transfer buffer.
Second, for the ASCII transfer where we do have to normalize line
endings, we can be smarter than reading one character at a time. There's
a php_stream_get_line() function that we can repurpose if the flags for
the stream are set up properly.
This patch implements these fixes.
Results: I tested this on an 850 MiB file, transferring this to an FTP
server running locally.
Results before patch:
Binary/ASCII transfer (same code path): 8.21s
Results after patch:
Binary transfer: 0.65s
ASCII transfer: 0.74s
Further improvement is probably possible by having a larger send buffer.
Bumps the minimum required OpenSSL version from 1.0.2 to 1.1.1.
OpenSSL 1.1.1 is an LTS release, but has reached[^1] EOL from upstream. However, Linux distro/OS vendors
continue to ship OpenSSL 1.1.1, so 1.1.1 was picked as the minimum. The current minimum 1.0.2 reached
EOL in 2018.
Bumping the minimum required OpenSSL version makes it possible for ext-openssl to remove a bunch of
conditional code, and assume that TLS 1.3 (shipped with OpenSSL 1.1.1) will be supported everywhere.
- Debian buster: 1.1.1[^2]
- Ubuntu 20.04: 1.1.1[^3]
- CentOS/RHEL 7: 1.0.2
- RHEL 8/Rocky 8/EL 8: 1.1.1
- Fedora 38: 3.0.9 (`openssl11` provides OpenSSL 1.1 as well)
RHEL/CentOS 7 reaches EOL mid 2024, so for PHP 8.4 scheduled towards the end of this year, we can safely
bump the minimum OpenSSL version.
[^1]: https://www.openssl.org/blog/blog/2023/03/28/1.1.1-EOL/index.html
[^2]: https://packages.debian.org/buster/libssl-dev
[^3]: https://packages.ubuntu.com/focal/libssl-dev
The issue referenced here doesn't contain a reproducer, but I recently
received an email of a user with the exact same problem. I was able to
recreate the scenario locally using vsftpd and setting
`require_ssl_reuse=YES` in the vsftpd configuration.
It turns out that our session resumption code is broken. It only works a
single time: the first time a data connection opens. Subsequent data
connections fail to reuse the session. This is because on every data
connection a new session is negotiated, but the current code always
tries to reuse the (stale) session of the control connection.
To fix this, we use SSL_CTX_sess_set_new_cb() to setup a callback that
gets called every time a new session is negotiated. We take a strong
reference using SSL_get1_session() and store it in the ftpbuf_t struct.
Every time we open a data connection we'll take that session.
This works because every control connection has at most a single
associated data connection.
Also disable internal session caching storage to not fill the cache up
with useless sessions.
There is no phpt for this because PHP does not support enforcing SSL
session reuse.
It is however testable manually by setting up vsftpd and setting the
`require_ssl_reuse=YES` function from before.
Closes GH-12851.
When the user does not fully consume the data stream, but instead opens
a new one, a memory leak occurs. Moreover, the state is invalid: when
more commands arrive they'll be handled out-of-sync because the state of
the client does not match what the server is doing.
This leads to all sorts of weirdness, for example:
Warning: ftp_nb_fget(): OK.
Fix it by gracefully closing the old data stream when a new data stream
is started.
Closes GH-11606.
The char arrays were too small for a long on 64-bit systems, which
resulted in cutting off the string at the end with a NUL byte. Use a
size of MAX_LENGTH_OF_LONG to fix this issue instead of a fixed size
of 11 chars.
Closes GH-10525.
The docs say that this function returns true on success, and false on
error. This function always returns true in the current implementation
because the success return value from ftp_close() is never propagated to
userland. This affects one test: since the test server exits after an
invalid login, the ftp close correctly fails (because the server has
gone away).
@cname currently refers to the constant name in C. However, it is not always a (constant) name, but sometimes a function invocation, so naming it as @cvalue would be more appropriate.