From ea67883a1ff3528d233491e844549a04da975622 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Mon, 27 Apr 2026 15:05:32 +0100 Subject: [PATCH 001/213] ext/phar: refactor phar_create_signature() to return a zend_string* (#21843) Instead of using out parameters. --- ext/phar/phar.c | 15 +++++---------- ext/phar/phar_internal.h | 2 +- ext/phar/tar.c | 18 +++++++++--------- ext/phar/util.c | 39 +++++++++++++++++++-------------------- ext/phar/zip.c | 24 +++++++++++------------- 5 files changed, 45 insertions(+), 53 deletions(-) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 2ab799ab8c83..a81a62a188f9 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -2995,17 +2995,12 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *phar, zen switch(phar->sig_flags) { default: { - char *digest = NULL; - size_t digest_len; - char *signature_error = NULL; - if (FAILURE == phar_create_signature(phar, newfile, &digest, &digest_len, &signature_error)) { + zend_string *signature = phar_create_signature(phar, newfile, &signature_error); + if (!signature) { spprintf(error, 0, "phar error: unable to write signature: %s", signature_error); efree(signature_error); - if (digest) { - efree(digest); - } if (must_close_old_file) { php_stream_close(oldfile); } @@ -3013,14 +3008,14 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_flush_ex(phar_archive_data *phar, zen return EOF; } - php_stream_write(newfile, digest, digest_len); - efree(digest); + php_stream_write(newfile, ZSTR_VAL(signature), ZSTR_LEN(signature)); if (phar->sig_flags == PHAR_SIG_OPENSSL || phar->sig_flags == PHAR_SIG_OPENSSL_SHA256 || phar->sig_flags == PHAR_SIG_OPENSSL_SHA512) { - phar_set_32(sig_buf, digest_len); + phar_set_32(sig_buf, ZSTR_LEN(signature)); php_stream_write(newfile, sig_buf, 4); } + zend_string_release_ex(signature, false); break; } } diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 36fa2b543501..df4e58c7adbf 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -413,7 +413,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *ali zend_result phar_free_alias(const phar_archive_data *phar); zend_result phar_get_archive(phar_archive_data **archive, const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error); zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, const char *fname, char **signature, size_t *signature_len, char **error); -ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error); +ZEND_ATTRIBUTE_NONNULL zend_string* phar_create_signature(phar_archive_data *phar, php_stream *fp, char **error); /* utility functions */ zend_string *phar_create_default_stub(const zend_string *php_index_str, const zend_string *web_index_str, char **error); diff --git a/ext/phar/tar.c b/ext/phar/tar.c index a7c02e352731..761246000dd2 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -968,9 +968,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze phar_entry_info entry = {0}; php_stream *oldfile, *newfile; bool must_close_old_file = false; - size_t signature_length; struct _phar_pass_tar_info pass; - char *buf, *signature, sigbuf[8]; + char *buf, sigbuf[8]; entry.flags = PHAR_ENT_PERM_DEF_FILE; entry.timestamp = time(NULL); @@ -1168,7 +1167,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze /* add signature for executable tars or tars explicitly set with setSignatureAlgorithm */ if (!phar->is_data || phar->sig_flags) { char *signature_error = NULL; - if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, &signature_error)) { + zend_string *signature = phar_create_signature(phar, newfile, &signature_error); + if (!signature) { spprintf(error, 0, "phar error: unable to write signature to tar-based phar: %s", signature_error); efree(signature_error); @@ -1184,7 +1184,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze if (entry.fp == NULL) { *error = estrdup("phar error: unable to create temporary file"); - efree(signature); + zend_string_release_ex(signature, false); if (must_close_old_file) { php_stream_close(oldfile); } @@ -1203,10 +1203,10 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze # define PHAR_SET_32(destination, source) memcpy(destination, &source, 4) #endif PHAR_SET_32(sigbuf, phar->sig_flags); - PHAR_SET_32(sigbuf + 4, signature_length); + PHAR_SET_32(sigbuf + 4, ZSTR_LEN(signature)); - if (8 != php_stream_write(entry.fp, sigbuf, 8) || signature_length != php_stream_write(entry.fp, signature, signature_length)) { - efree(signature); + if (8 != php_stream_write(entry.fp, sigbuf, 8) || ZSTR_LEN(signature) != php_stream_write(entry.fp, ZSTR_VAL(signature), ZSTR_LEN(signature))) { + zend_string_release_ex(signature, false); spprintf(error, 0, "phar error: unable to write signature to tar-based phar %s", ZSTR_VAL(phar->fname)); if (must_close_old_file) { @@ -1218,11 +1218,11 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, ze ALLOCA_FLAG(use_heap); ZSTR_ALLOCA_INIT(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1, use_heap); - efree(signature); - entry.uncompressed_filesize = entry.compressed_filesize = signature_length + 8; + entry.uncompressed_filesize = entry.compressed_filesize = ZSTR_LEN(signature) + 8; /* throw out return value and write the signature */ phar_tar_writeheaders_int(&entry, &pass); ZSTR_ALLOCA_FREE(entry.filename, use_heap); + zend_string_release_ex(signature, false); if (*error) { if (must_close_old_file) { diff --git a/ext/phar/util.c b/ext/phar/util.c index 491a07c4dd21..ad7cdd6c9ae5 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -1783,8 +1783,9 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s } /* }}} */ -ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar, php_stream *fp, char **signature, size_t *signature_length, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL zend_string* phar_create_signature(phar_archive_data *phar, php_stream *fp, char **error) /* {{{ */ { + zend_string *signature = NULL; unsigned char buf[1024]; size_t sig_len; @@ -1807,8 +1808,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar } PHP_SHA512Final(digest, &context); - *signature = estrndup((char *) digest, 64); - *signature_length = 64; + signature = zend_string_init((const char*)digest, 64, false); break; } default: @@ -1825,8 +1825,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar } PHP_SHA256Final(digest, &context); - *signature = estrndup((char *) digest, 32); - *signature_length = 32; + signature = zend_string_init((const char*)digest, 32, false); break; } case PHAR_SIG_OPENSSL_SHA512: @@ -1852,7 +1851,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar if (in == NULL) { spprintf(error, 0, "unable to write to phar \"%s\" with requested openssl signature", ZSTR_VAL(phar->fname)); - return FAILURE; + return NULL; } key = PEM_read_bio_PrivateKey(in, NULL,NULL, ""); @@ -1860,14 +1859,14 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar if (!key) { *error = estrdup("unable to process private key"); - return FAILURE; + return NULL; } md_ctx = EVP_MD_CTX_create(); if (md_ctx == NULL) { EVP_PKEY_free(key); spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", ZSTR_VAL(phar->fname)); - return FAILURE; + return NULL; } siglen = EVP_PKEY_size(key); @@ -1878,7 +1877,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar EVP_MD_CTX_destroy(md_ctx); efree(sigbuf); spprintf(error, 0, "unable to initialize openssl signature for phar \"%s\"", ZSTR_VAL(phar->fname)); - return FAILURE; + return NULL; } while ((sig_len = php_stream_read(fp, (char*)buf, sizeof(buf))) > 0) { @@ -1887,7 +1886,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar EVP_MD_CTX_destroy(md_ctx); efree(sigbuf); spprintf(error, 0, "unable to update the openssl signature for phar \"%s\"", ZSTR_VAL(phar->fname)); - return FAILURE; + return NULL; } } @@ -1896,12 +1895,14 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar EVP_MD_CTX_destroy(md_ctx); efree(sigbuf); spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", ZSTR_VAL(phar->fname)); - return FAILURE; + return NULL; } sigbuf[siglen] = '\0'; EVP_PKEY_free(key); EVP_MD_CTX_destroy(md_ctx); + signature = zend_string_init((const char*)sigbuf, siglen, false); + efree(sigbuf); #else size_t siglen; sigbuf = NULL; @@ -1910,11 +1911,11 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar if (FAILURE == phar_call_openssl_signverify(true, fp, php_stream_tell(fp), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen, phar->sig_flags)) { spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", ZSTR_VAL(phar->fname)); - return FAILURE; + return NULL; } + signature = zend_string_init((const char*)sigbuf, siglen, false); + efree(sigbuf); #endif - *signature = (char *) sigbuf; - *signature_length = siglen; } break; case PHAR_SIG_SHA1: { @@ -1928,8 +1929,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar } PHP_SHA1Final(digest, &context); - *signature = estrndup((char *) digest, 20); - *signature_length = 20; + signature = zend_string_init((const char*)digest, 20, false); break; } case PHAR_SIG_MD5: { @@ -1943,14 +1943,13 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_create_signature(phar_archive_data *phar } PHP_MD5Final(digest, &context); - *signature = estrndup((char *) digest, 16); - *signature_length = 16; + signature = zend_string_init((const char*)digest, 16, false); break; } } - phar->sig_len = phar_hex_str((const char *)*signature, *signature_length, &phar->signature); - return SUCCESS; + phar->sig_len = phar_hex_str(ZSTR_VAL(signature), ZSTR_LEN(signature), &phar->signature); + return signature; } /* }}} */ diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 28e1a3d5641e..da934a4c0041 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -1148,8 +1148,7 @@ static zend_result phar_zip_applysignature(phar_archive_data *phar, struct _phar { /* add signature for executable tars or tars explicitly set with setSignatureAlgorithm */ if (!phar->is_data || phar->sig_flags) { - size_t signature_length; - char *signature, sigbuf[8]; + char sigbuf[8]; phar_entry_info entry = {0}; php_stream *newfile; zend_off_t tell; @@ -1171,11 +1170,10 @@ static zend_result phar_zip_applysignature(phar_archive_data *phar, struct _phar } char *signature_error = NULL; - if (FAILURE == phar_create_signature(phar, newfile, &signature, &signature_length, &signature_error)) { - if (signature_error) { - spprintf(pass->error, 0, "phar error: unable to write signature to zip-based phar: %s", signature_error); - efree(signature_error); - } + zend_string *signature = phar_create_signature(phar, newfile, &signature_error); + if (!signature) { + spprintf(pass->error, 0, "phar error: unable to write signature to zip-based phar: %s", signature_error); + efree(signature_error); php_stream_close(newfile); return FAILURE; @@ -1185,17 +1183,17 @@ static zend_result phar_zip_applysignature(phar_archive_data *phar, struct _phar entry.fp_type = PHAR_MOD; entry.is_modified = 1; if (entry.fp == NULL) { - efree(signature); + zend_string_release_ex(signature, false); spprintf(pass->error, 0, "phar error: unable to create temporary file for signature"); php_stream_close(newfile); return FAILURE; } PHAR_SET_32(sigbuf, phar->sig_flags); - PHAR_SET_32(sigbuf + 4, signature_length); + PHAR_SET_32(sigbuf + 4, ZSTR_LEN(signature)); - if (Z_UL(8) != php_stream_write(entry.fp, sigbuf, 8) || signature_length != php_stream_write(entry.fp, signature, signature_length)) { - efree(signature); + if (Z_UL(8) != php_stream_write(entry.fp, sigbuf, 8) || ZSTR_LEN(signature) != php_stream_write(entry.fp, ZSTR_VAL(signature), ZSTR_LEN(signature))) { + zend_string_release_ex(signature, false); if (pass->error) { spprintf(pass->error, 0, "phar error: unable to write signature to zip-based phar %s", ZSTR_VAL(phar->fname)); } @@ -1206,13 +1204,13 @@ static zend_result phar_zip_applysignature(phar_archive_data *phar, struct _phar ALLOCA_FLAG(use_heap); ZSTR_ALLOCA_INIT(entry.filename, ".phar/signature.bin", sizeof(".phar/signature.bin")-1, use_heap); - efree(signature); - entry.uncompressed_filesize = entry.compressed_filesize = signature_length + 8; + entry.uncompressed_filesize = entry.compressed_filesize = ZSTR_LEN(signature) + 8; entry.phar = phar; /* throw out return value and write the signature */ phar_zip_changed_apply_int(&entry, (void *)pass); ZSTR_ALLOCA_FREE(entry.filename, use_heap); php_stream_close(newfile); + zend_string_release_ex(signature, false); if (pass->error && *(pass->error)) { /* error is set by writeheaders */ From 542256ce24dab84af3a6feac1d1a44c969f906a6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Mon, 27 Apr 2026 20:11:48 +0200 Subject: [PATCH 002/213] uri: Update to uriparser-1.0.1 (#21890) This fixes CVE-2026-42371. --- ext/uri/uriparser/include/uriparser/Uri.h | 2 +- ext/uri/uriparser/include/uriparser/UriBase.h | 2 +- ext/uri/uriparser/src/UriCommon.c | 15 ++++++++++----- ext/uri/uriparser/src/UriMemory.c | 19 ++++++++++++++++--- 4 files changed, 28 insertions(+), 10 deletions(-) diff --git a/ext/uri/uriparser/include/uriparser/Uri.h b/ext/uri/uriparser/include/uriparser/Uri.h index 88976a484627..f041f8113531 100644 --- a/ext/uri/uriparser/include/uriparser/Uri.h +++ b/ext/uri/uriparser/include/uriparser/Uri.h @@ -1,4 +1,4 @@ -/* 5abed1007be99942f49ffe603a894d277066b79b9cb824547af0f3b9481cb9ca (1.0.0+) +/* 53c1cb9f2f728652fe001dc72fa0fa7a0e9fa0b8baaaa9e37561c6cdf88ac4df (1.0.1+) * * uriparser - RFC 3986 URI parsing library * diff --git a/ext/uri/uriparser/include/uriparser/UriBase.h b/ext/uri/uriparser/include/uriparser/UriBase.h index 3a9a868e3bb1..abadcae0dbdc 100644 --- a/ext/uri/uriparser/include/uriparser/UriBase.h +++ b/ext/uri/uriparser/include/uriparser/UriBase.h @@ -52,7 +52,7 @@ /* Version */ # define URI_VER_MAJOR 1 # define URI_VER_MINOR 0 -# define URI_VER_RELEASE 0 +# define URI_VER_RELEASE 1 # define URI_VER_SUFFIX_ANSI "" # define URI_VER_SUFFIX_UNICODE URI_ANSI_TO_UNICODE(URI_VER_SUFFIX_ANSI) diff --git a/ext/uri/uriparser/src/UriCommon.c b/ext/uri/uriparser/src/UriCommon.c index 3644e8828f35..00256f201f7e 100644 --- a/ext/uri/uriparser/src/UriCommon.c +++ b/ext/uri/uriparser/src/UriCommon.c @@ -66,6 +66,7 @@ # endif # include +# include /*extern*/ const URI_CHAR * const URI_FUNC(SafeToPointTo) = _UT("X"); /*extern*/ const URI_CHAR * const URI_FUNC(ConstPwd) = _UT("."); @@ -106,6 +107,8 @@ int URI_FUNC(FreeUriPath)(URI_TYPE(Uri) * uri, UriMemoryManager * memory) { /* Compares two text ranges for equal text content */ int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRange) * b) { int diff; + ptrdiff_t lenA; + ptrdiff_t lenB; /* NOTE: Both NULL means equal! */ if ((a == NULL) || (b == NULL)) { @@ -117,14 +120,16 @@ int URI_FUNC(CompareRange)(const URI_TYPE(TextRange) * a, const URI_TYPE(TextRan return ((a->first == NULL) ? 0 : 1) - ((b->first == NULL) ? 0 : 1); } - diff = ((int)(a->afterLast - a->first) - (int)(b->afterLast - b->first)); - if (diff > 0) { + lenA = a->afterLast - a->first; + lenB = b->afterLast - b->first; + + if (lenA > lenB) { return 1; - } else if (diff < 0) { + } else if (lenA < lenB) { return -1; } - diff = URI_STRNCMP(a->first, b->first, (a->afterLast - a->first)); + diff = URI_STRNCMP(a->first, b->first, (size_t)lenA); if (diff > 0) { return 1; @@ -727,7 +732,7 @@ UriBool URI_FUNC(FixPathNoScheme)(URI_TYPE(Uri) * uri, UriMemoryManager * memory } /* When dropping a host from a URI without a scheme, an absolute path - * and and empty first path segment, a consecutive reparse would rightfully + * and empty first path segment, a consecutive reparse would rightfully * mis-classify the first path segment as a host marker due to the "//". * To protect against this case, we prepend an artificial "." segment * to the path in here; the function is called after the host has diff --git a/ext/uri/uriparser/src/UriMemory.c b/ext/uri/uriparser/src/UriMemory.c index 3caf8199dc45..669f48dd6827 100644 --- a/ext/uri/uriparser/src/UriMemory.c +++ b/ext/uri/uriparser/src/UriMemory.c @@ -45,12 +45,25 @@ #include "UriConfig.h" /* for HAVE_REALLOCARRAY */ #ifdef HAVE_REALLOCARRAY -# ifndef _GNU_SOURCE -# define _GNU_SOURCE 1 +// For glibc >=2.29 of 2019-02-01 +# if !defined(_DEFAULT_SOURCE) +# define _DEFAULT_SOURCE 1 # endif -# ifdef __NetBSD__ + +// For NetBSD (stdlib.h revision 1.122 of 2020-05-26) +# if defined(__NetBSD__) && !defined(_OPENBSD_SOURCE) # define _OPENBSD_SOURCE 1 # endif + +// POSIX 2024 (XPG8) for e.g. Illumos/SmartOS +# if !defined(_XOPEN_SOURCE) || (_XOPEN_SOURCE - 0 < 800) +# undef _XOPEN_SOURCE +# define _XOPEN_SOURCE 800 +# endif +# if !defined(_POSIX_C_SOURCE) || (_POSIX_C_SOURCE - 0 < 202405L) +# undef _POSIX_C_SOURCE +# define _POSIX_C_SOURCE 202405L +# endif #endif #include From 936f7271066b4dfeec3a8cddde562c3d611c898f Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Mon, 27 Apr 2026 11:14:56 -0700 Subject: [PATCH 003/213] CI: update download-bundled for uriparser 1.0.1 Follow-up to #21890 --- .github/scripts/download-bundled/uriparser.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/scripts/download-bundled/uriparser.sh b/.github/scripts/download-bundled/uriparser.sh index 8820a67333f0..8973962fb5d4 100755 --- a/.github/scripts/download-bundled/uriparser.sh +++ b/.github/scripts/download-bundled/uriparser.sh @@ -5,7 +5,7 @@ cd "$(dirname "$0")/../../.." tmp_dir=/tmp/php-src-download-bundled/uriparser rm -rf "$tmp_dir" -revision=refs/tags/uriparser-1.0.0 +revision=refs/tags/uriparser-1.0.1 git clone --depth 1 --revision="$revision" https://github.com/uriparser/uriparser.git "$tmp_dir" From cc56225339784aa3c084969027fae417dc5d206a Mon Sep 17 00:00:00 2001 From: tekimen Date: Tue, 28 Apr 2026 11:06:53 +0900 Subject: [PATCH 004/213] [RFC][mbregex] Set deprecate Oniguruma(mbregex) (#21490) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Set deprecate Oniguruma(mbregex) Thank you for Oniguruma. Co-authored-by: Tim Düsterhus --- ext/mbstring/mbstring.c | 1 + ext/mbstring/mbstring.stub.php | 17 + ext/mbstring/mbstring_arginfo.h | 177 ++++++++- ext/mbstring/tests/bug43994.phpt | 6 +- ext/mbstring/tests/bug69151.phpt | 9 +- ext/mbstring/tests/bug72164.phpt | 3 +- ext/mbstring/tests/bug72399.phpt | 7 +- ext/mbstring/tests/bug72402.phpt | 3 +- ext/mbstring/tests/bug72691.phpt | 27 +- ext/mbstring/tests/bug72693.phpt | 25 +- ext/mbstring/tests/bug72694.phpt | 11 +- ext/mbstring/tests/bug72710.phpt | 2 + ext/mbstring/tests/bug73532.phpt | 3 +- ext/mbstring/tests/bug73646.phpt | 2 + ext/mbstring/tests/bug76999.phpt | 13 +- ext/mbstring/tests/bug77367.phpt | 5 +- ext/mbstring/tests/bug77370.phpt | 2 + ext/mbstring/tests/bug77371.phpt | 2 + ext/mbstring/tests/bug77381.phpt | 8 + ext/mbstring/tests/bug77418.phpt | 5 +- ext/mbstring/tests/bug77428.phpt | 9 +- ext/mbstring/tests/bug77514.phpt | 3 +- ext/mbstring/tests/bug78559.phpt | 3 +- ext/mbstring/tests/bug78633.phpt | 3 +- ext/mbstring/tests/empty_pattern.phpt | 7 +- ext/mbstring/tests/gh18901.phpt | 11 +- ext/mbstring/tests/mb_ereg-compat-01.phpt | 5 +- ext/mbstring/tests/mb_ereg-compat-02.phpt | 3 +- ext/mbstring/tests/mb_ereg.phpt | 51 ++- ext/mbstring/tests/mb_ereg1.phpt | 11 +- ext/mbstring/tests/mb_ereg2.phpt | 5 +- ext/mbstring/tests/mb_ereg_basic.phpt | 20 +- ext/mbstring/tests/mb_ereg_dupnames.phpt | 7 +- ext/mbstring/tests/mb_ereg_match_basic.phpt | 11 +- .../tests/mb_ereg_named_subpatterns.phpt | 9 +- .../tests/mb_ereg_replace-compat-01.phpt | 3 +- .../tests/mb_ereg_replace-compat-02.phpt | 3 +- .../tests/mb_ereg_replace-compat-03.phpt | 3 +- .../tests/mb_ereg_replace-compat-04.phpt | 3 +- .../tests/mb_ereg_replace-compat-05.phpt | 3 +- .../tests/mb_ereg_replace-compat-06.phpt | 3 +- .../tests/mb_ereg_replace-compat-07.phpt | 3 +- .../tests/mb_ereg_replace-compat-08.phpt | 3 +- .../tests/mb_ereg_replace-compat-09.phpt | 3 +- .../tests/mb_ereg_replace-compat-10.phpt | 3 +- .../tests/mb_ereg_replace-compat-11.phpt | 3 +- .../tests/mb_ereg_replace-compat-12.phpt | 3 +- .../tests/mb_ereg_replace-compat-13.phpt | 3 +- ext/mbstring/tests/mb_ereg_replace.phpt | 7 +- ext/mbstring/tests/mb_ereg_replace_basic.phpt | 12 +- .../tests/mb_ereg_replace_callback.phpt | 5 +- .../mb_ereg_replace_named_subpatterns.phpt | 19 +- .../tests/mb_ereg_replace_variation1.phpt | 24 +- ext/mbstring/tests/mb_ereg_search.phpt | 19 +- .../tests/mb_ereg_search_invalid_pattern.phpt | 7 + .../mb_ereg_search_named_subpatterns_1.phpt | 2 +- .../mb_ereg_search_named_subpatterns_2.phpt | 11 +- ext/mbstring/tests/mb_ereg_search_pos.phpt | 7 +- ext/mbstring/tests/mb_ereg_search_regs.phpt | 5 +- ext/mbstring/tests/mb_ereg_search_setpos.phpt | 41 +- ext/mbstring/tests/mb_ereg_search_syntax.phpt | 5 +- ext/mbstring/tests/mb_ereg_search_xxx.phpt | 363 +++++++++++++++++- ext/mbstring/tests/mb_ereg_variation3.phpt | 30 +- ext/mbstring/tests/mb_ereg_variation4.phpt | 30 +- ext/mbstring/tests/mb_ereg_variation5.phpt | 16 +- ext/mbstring/tests/mb_ereg_variation6.phpt | 36 +- ext/mbstring/tests/mb_ereg_variation7.phpt | 8 +- ext/mbstring/tests/mb_eregi.phpt | 9 +- ext/mbstring/tests/mb_eregi_replace.phpt | 135 ++++++- .../tests/mb_regex_encoding_basic.phpt | 6 + .../tests/mb_regex_encoding_error2.phpt | 4 +- .../tests/mb_regex_encoding_variation2.phpt | 338 +++++++++++++++- ext/mbstring/tests/mb_regex_set_options.phpt | 11 +- ext/mbstring/tests/mb_split-compat-01.phpt | 3 +- ext/mbstring/tests/mb_split.phpt | 25 +- ext/mbstring/tests/mb_split_empty_match.phpt | 5 +- ext/mbstring/tests/mbregex_stack_limit.phpt | 9 +- ext/mbstring/tests/mbregex_stack_limit2.phpt | 6 +- ext/mbstring/tests/php_gr_jp_10830.phpt | 3 +- ext/mbstring/tests/php_gr_jp_dev_884-1.phpt | 4 +- ext/mbstring/tests/php_gr_jp_dev_884-2.phpt | 5 +- ext/mbstring/tests/retry_limit.phpt | 7 +- 82 files changed, 1643 insertions(+), 99 deletions(-) diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c index 8780712aee96..91474510bea5 100644 --- a/ext/mbstring/mbstring.c +++ b/ext/mbstring/mbstring.c @@ -54,6 +54,7 @@ #include "mb_gpc.h" #ifdef HAVE_MBREGEX +# include "zend_attributes.h" # include "php_mbregex.h" #endif diff --git a/ext/mbstring/mbstring.stub.php b/ext/mbstring/mbstring.stub.php index af9c5cbb93ea..109a3ad564d8 100644 --- a/ext/mbstring/mbstring.stub.php +++ b/ext/mbstring/mbstring.stub.php @@ -7,6 +7,7 @@ * @var string * @cvalue php_mb_oniguruma_version */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] const MB_ONIGURUMA_VERSION = UNKNOWN; #endif @@ -197,57 +198,73 @@ function mb_str_pad(string $string, int $length, string $pad_string = " ", int $ #ifdef HAVE_MBREGEX /** @refcount 1 */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_regex_encoding(?string $encoding = null): string|bool {} /** @param array $matches */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_ereg(string $pattern, string $string, &$matches = null): bool {} /** @param array $matches */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_eregi(string $pattern, string $string, &$matches = null): bool {} /** @refcount 1 */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_ereg_replace(string $pattern, string $replacement, string $string, ?string $options = null): string|false|null {} /** @refcount 1 */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_eregi_replace(string $pattern, string $replacement, string $string, ?string $options = null): string|false|null {} /** @refcount 1 */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_ereg_replace_callback(string $pattern, callable $callback, string $string, ?string $options = null): string|false|null {} /** * @return array|false * @refcount 1 */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_split(string $pattern, string $string, int $limit = -1): array|false {} +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_ereg_match(string $pattern, string $string, ?string $options = null): bool {} +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_ereg_search(?string $pattern = null, ?string $options = null): bool {} /** * @return array|false * @refcount 1 */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_ereg_search_pos(?string $pattern = null, ?string $options = null): array|false {} /** * @return array|false * @refcount 1 */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_ereg_search_regs(?string $pattern = null, ?string $options = null): array|false {} +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_ereg_search_init(string $string, ?string $pattern = null, ?string $options = null): bool {} /** * @return array|false * @refcount 1 */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_ereg_search_getregs(): array|false {} +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_ereg_search_getpos(): int {} +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_ereg_search_setpos(int $offset): bool {} /** @refcount 1 */ +#[\Deprecated(since: '8.6', message: "because the underlying library is no longer maintained")] function mb_regex_set_options(?string $options = null): string {} #endif diff --git a/ext/mbstring/mbstring_arginfo.h b/ext/mbstring/mbstring_arginfo.h index 8fb83425ee1d..bc9db3d415c1 100644 --- a/ext/mbstring/mbstring_arginfo.h +++ b/ext/mbstring/mbstring_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit mbstring.stub.php instead. - * Stub hash: 03c07f68bea7d7b96e6dc11f180f45663b859ed3 */ + * Stub hash: f02c317efd6814f902ea75c9d222893713546845 */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_MASK_EX(arginfo_mb_language, 0, 0, MAY_BE_STRING|MAY_BE_BOOL) ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, language, IS_STRING, 1, "null") @@ -413,22 +413,22 @@ static const zend_function_entry ext_functions[] = { ZEND_FE(mb_chr, arginfo_mb_chr) ZEND_FE(mb_str_pad, arginfo_mb_str_pad) #if defined(HAVE_MBREGEX) - ZEND_FE(mb_regex_encoding, arginfo_mb_regex_encoding) - ZEND_FE(mb_ereg, arginfo_mb_ereg) - ZEND_FE(mb_eregi, arginfo_mb_eregi) - ZEND_FE(mb_ereg_replace, arginfo_mb_ereg_replace) - ZEND_FE(mb_eregi_replace, arginfo_mb_eregi_replace) - ZEND_FE(mb_ereg_replace_callback, arginfo_mb_ereg_replace_callback) - ZEND_FE(mb_split, arginfo_mb_split) - ZEND_FE(mb_ereg_match, arginfo_mb_ereg_match) - ZEND_FE(mb_ereg_search, arginfo_mb_ereg_search) - ZEND_FE(mb_ereg_search_pos, arginfo_mb_ereg_search_pos) - ZEND_FE(mb_ereg_search_regs, arginfo_mb_ereg_search_regs) - ZEND_FE(mb_ereg_search_init, arginfo_mb_ereg_search_init) - ZEND_FE(mb_ereg_search_getregs, arginfo_mb_ereg_search_getregs) - ZEND_FE(mb_ereg_search_getpos, arginfo_mb_ereg_search_getpos) - ZEND_FE(mb_ereg_search_setpos, arginfo_mb_ereg_search_setpos) - ZEND_FE(mb_regex_set_options, arginfo_mb_regex_set_options) + ZEND_RAW_FENTRY("mb_regex_encoding", zif_mb_regex_encoding, arginfo_mb_regex_encoding, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_ereg", zif_mb_ereg, arginfo_mb_ereg, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_eregi", zif_mb_eregi, arginfo_mb_eregi, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_ereg_replace", zif_mb_ereg_replace, arginfo_mb_ereg_replace, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_eregi_replace", zif_mb_eregi_replace, arginfo_mb_eregi_replace, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_ereg_replace_callback", zif_mb_ereg_replace_callback, arginfo_mb_ereg_replace_callback, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_split", zif_mb_split, arginfo_mb_split, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_ereg_match", zif_mb_ereg_match, arginfo_mb_ereg_match, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_ereg_search", zif_mb_ereg_search, arginfo_mb_ereg_search, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_ereg_search_pos", zif_mb_ereg_search_pos, arginfo_mb_ereg_search_pos, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_ereg_search_regs", zif_mb_ereg_search_regs, arginfo_mb_ereg_search_regs, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_ereg_search_init", zif_mb_ereg_search_init, arginfo_mb_ereg_search_init, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_ereg_search_getregs", zif_mb_ereg_search_getregs, arginfo_mb_ereg_search_getregs, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_ereg_search_getpos", zif_mb_ereg_search_getpos, arginfo_mb_ereg_search_getpos, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_ereg_search_setpos", zif_mb_ereg_search_setpos, arginfo_mb_ereg_search_setpos, ZEND_ACC_DEPRECATED, NULL, NULL) + ZEND_RAW_FENTRY("mb_regex_set_options", zif_mb_regex_set_options, arginfo_mb_regex_set_options, ZEND_ACC_DEPRECATED, NULL, NULL) #endif ZEND_FE_END }; @@ -436,7 +436,7 @@ static const zend_function_entry ext_functions[] = { static void register_mbstring_symbols(int module_number) { #if defined(HAVE_MBREGEX) - REGISTER_STRING_CONSTANT("MB_ONIGURUMA_VERSION", php_mb_oniguruma_version, CONST_PERSISTENT); + zend_constant *const_MB_ONIGURUMA_VERSION = REGISTER_STRING_CONSTANT("MB_ONIGURUMA_VERSION", php_mb_oniguruma_version, CONST_PERSISTENT | CONST_DEPRECATED); #endif REGISTER_LONG_CONSTANT("MB_CASE_UPPER", PHP_UNICODE_CASE_UPPER, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MB_CASE_LOWER", PHP_UNICODE_CASE_LOWER, CONST_PERSISTENT); @@ -446,4 +446,145 @@ static void register_mbstring_symbols(int module_number) REGISTER_LONG_CONSTANT("MB_CASE_LOWER_SIMPLE", PHP_UNICODE_CASE_LOWER_SIMPLE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MB_CASE_TITLE_SIMPLE", PHP_UNICODE_CASE_TITLE_SIMPLE, CONST_PERSISTENT); REGISTER_LONG_CONSTANT("MB_CASE_FOLD_SIMPLE", PHP_UNICODE_CASE_FOLD_SIMPLE, CONST_PERSISTENT); + +#if defined(HAVE_MBREGEX) + + zend_attribute *attribute_Deprecated_func_mb_regex_encoding_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_regex_encoding", sizeof("mb_regex_encoding") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_regex_encoding_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_regex_encoding_0->args[0].value, attribute_Deprecated_func_mb_regex_encoding_0_arg0_str); + attribute_Deprecated_func_mb_regex_encoding_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_regex_encoding_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_regex_encoding_0->args[1].value, attribute_Deprecated_func_mb_regex_encoding_0_arg1_str); + attribute_Deprecated_func_mb_regex_encoding_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_ereg_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_ereg", sizeof("mb_ereg") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_ereg_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_0->args[0].value, attribute_Deprecated_func_mb_ereg_0_arg0_str); + attribute_Deprecated_func_mb_ereg_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_ereg_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_0->args[1].value, attribute_Deprecated_func_mb_ereg_0_arg1_str); + attribute_Deprecated_func_mb_ereg_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_eregi_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_eregi", sizeof("mb_eregi") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_eregi_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_eregi_0->args[0].value, attribute_Deprecated_func_mb_eregi_0_arg0_str); + attribute_Deprecated_func_mb_eregi_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_eregi_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_eregi_0->args[1].value, attribute_Deprecated_func_mb_eregi_0_arg1_str); + attribute_Deprecated_func_mb_eregi_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_ereg_replace_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_ereg_replace", sizeof("mb_ereg_replace") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_ereg_replace_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_replace_0->args[0].value, attribute_Deprecated_func_mb_ereg_replace_0_arg0_str); + attribute_Deprecated_func_mb_ereg_replace_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_ereg_replace_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_replace_0->args[1].value, attribute_Deprecated_func_mb_ereg_replace_0_arg1_str); + attribute_Deprecated_func_mb_ereg_replace_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_eregi_replace_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_eregi_replace", sizeof("mb_eregi_replace") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_eregi_replace_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_eregi_replace_0->args[0].value, attribute_Deprecated_func_mb_eregi_replace_0_arg0_str); + attribute_Deprecated_func_mb_eregi_replace_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_eregi_replace_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_eregi_replace_0->args[1].value, attribute_Deprecated_func_mb_eregi_replace_0_arg1_str); + attribute_Deprecated_func_mb_eregi_replace_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_ereg_replace_callback_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_ereg_replace_callback", sizeof("mb_ereg_replace_callback") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_ereg_replace_callback_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_replace_callback_0->args[0].value, attribute_Deprecated_func_mb_ereg_replace_callback_0_arg0_str); + attribute_Deprecated_func_mb_ereg_replace_callback_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_ereg_replace_callback_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_replace_callback_0->args[1].value, attribute_Deprecated_func_mb_ereg_replace_callback_0_arg1_str); + attribute_Deprecated_func_mb_ereg_replace_callback_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_split_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_split", sizeof("mb_split") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_split_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_split_0->args[0].value, attribute_Deprecated_func_mb_split_0_arg0_str); + attribute_Deprecated_func_mb_split_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_split_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_split_0->args[1].value, attribute_Deprecated_func_mb_split_0_arg1_str); + attribute_Deprecated_func_mb_split_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_ereg_match_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_ereg_match", sizeof("mb_ereg_match") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_ereg_match_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_match_0->args[0].value, attribute_Deprecated_func_mb_ereg_match_0_arg0_str); + attribute_Deprecated_func_mb_ereg_match_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_ereg_match_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_match_0->args[1].value, attribute_Deprecated_func_mb_ereg_match_0_arg1_str); + attribute_Deprecated_func_mb_ereg_match_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_ereg_search_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_ereg_search", sizeof("mb_ereg_search") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_ereg_search_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_0->args[0].value, attribute_Deprecated_func_mb_ereg_search_0_arg0_str); + attribute_Deprecated_func_mb_ereg_search_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_ereg_search_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_0->args[1].value, attribute_Deprecated_func_mb_ereg_search_0_arg1_str); + attribute_Deprecated_func_mb_ereg_search_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_ereg_search_pos_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_ereg_search_pos", sizeof("mb_ereg_search_pos") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_ereg_search_pos_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_pos_0->args[0].value, attribute_Deprecated_func_mb_ereg_search_pos_0_arg0_str); + attribute_Deprecated_func_mb_ereg_search_pos_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_ereg_search_pos_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_pos_0->args[1].value, attribute_Deprecated_func_mb_ereg_search_pos_0_arg1_str); + attribute_Deprecated_func_mb_ereg_search_pos_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_ereg_search_regs_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_ereg_search_regs", sizeof("mb_ereg_search_regs") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_ereg_search_regs_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_regs_0->args[0].value, attribute_Deprecated_func_mb_ereg_search_regs_0_arg0_str); + attribute_Deprecated_func_mb_ereg_search_regs_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_ereg_search_regs_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_regs_0->args[1].value, attribute_Deprecated_func_mb_ereg_search_regs_0_arg1_str); + attribute_Deprecated_func_mb_ereg_search_regs_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_ereg_search_init_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_ereg_search_init", sizeof("mb_ereg_search_init") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_ereg_search_init_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_init_0->args[0].value, attribute_Deprecated_func_mb_ereg_search_init_0_arg0_str); + attribute_Deprecated_func_mb_ereg_search_init_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_ereg_search_init_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_init_0->args[1].value, attribute_Deprecated_func_mb_ereg_search_init_0_arg1_str); + attribute_Deprecated_func_mb_ereg_search_init_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_ereg_search_getregs_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_ereg_search_getregs", sizeof("mb_ereg_search_getregs") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_ereg_search_getregs_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_getregs_0->args[0].value, attribute_Deprecated_func_mb_ereg_search_getregs_0_arg0_str); + attribute_Deprecated_func_mb_ereg_search_getregs_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_ereg_search_getregs_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_getregs_0->args[1].value, attribute_Deprecated_func_mb_ereg_search_getregs_0_arg1_str); + attribute_Deprecated_func_mb_ereg_search_getregs_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_ereg_search_getpos_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_ereg_search_getpos", sizeof("mb_ereg_search_getpos") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_ereg_search_getpos_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_getpos_0->args[0].value, attribute_Deprecated_func_mb_ereg_search_getpos_0_arg0_str); + attribute_Deprecated_func_mb_ereg_search_getpos_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_ereg_search_getpos_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_getpos_0->args[1].value, attribute_Deprecated_func_mb_ereg_search_getpos_0_arg1_str); + attribute_Deprecated_func_mb_ereg_search_getpos_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_ereg_search_setpos_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_ereg_search_setpos", sizeof("mb_ereg_search_setpos") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_ereg_search_setpos_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_setpos_0->args[0].value, attribute_Deprecated_func_mb_ereg_search_setpos_0_arg0_str); + attribute_Deprecated_func_mb_ereg_search_setpos_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_ereg_search_setpos_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_ereg_search_setpos_0->args[1].value, attribute_Deprecated_func_mb_ereg_search_setpos_0_arg1_str); + attribute_Deprecated_func_mb_ereg_search_setpos_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); + + zend_attribute *attribute_Deprecated_func_mb_regex_set_options_0 = zend_add_function_attribute(zend_hash_str_find_ptr(CG(function_table), "mb_regex_set_options", sizeof("mb_regex_set_options") - 1), ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_func_mb_regex_set_options_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_regex_set_options_0->args[0].value, attribute_Deprecated_func_mb_regex_set_options_0_arg0_str); + attribute_Deprecated_func_mb_regex_set_options_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_func_mb_regex_set_options_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_func_mb_regex_set_options_0->args[1].value, attribute_Deprecated_func_mb_regex_set_options_0_arg1_str); + attribute_Deprecated_func_mb_regex_set_options_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); +#endif +#if defined(HAVE_MBREGEX) + + zend_attribute *attribute_Deprecated_const_MB_ONIGURUMA_VERSION_0 = zend_add_global_constant_attribute(const_MB_ONIGURUMA_VERSION, ZSTR_KNOWN(ZEND_STR_DEPRECATED_CAPITALIZED), 2); + zend_string *attribute_Deprecated_const_MB_ONIGURUMA_VERSION_0_arg0_str = zend_string_init("8.6", strlen("8.6"), 1); + ZVAL_STR(&attribute_Deprecated_const_MB_ONIGURUMA_VERSION_0->args[0].value, attribute_Deprecated_const_MB_ONIGURUMA_VERSION_0_arg0_str); + attribute_Deprecated_const_MB_ONIGURUMA_VERSION_0->args[0].name = ZSTR_KNOWN(ZEND_STR_SINCE); + zend_string *attribute_Deprecated_const_MB_ONIGURUMA_VERSION_0_arg1_str = zend_string_init("because the underlying library is no longer maintained", strlen("because the underlying library is no longer maintained"), 1); + ZVAL_STR(&attribute_Deprecated_const_MB_ONIGURUMA_VERSION_0->args[1].value, attribute_Deprecated_const_MB_ONIGURUMA_VERSION_0_arg1_str); + attribute_Deprecated_const_MB_ONIGURUMA_VERSION_0->args[1].name = ZSTR_KNOWN(ZEND_STR_MESSAGE); +#endif } diff --git a/ext/mbstring/tests/bug43994.phpt b/ext/mbstring/tests/bug43994.phpt index b4ae29ff40e7..cc6953808cc6 100644 --- a/ext/mbstring/tests/bug43994.phpt +++ b/ext/mbstring/tests/bug43994.phpt @@ -31,9 +31,13 @@ try { var_dump($mb_regs); ?> ---EXPECT-- +--EXPECTF-- Without $regs arg: + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_ereg(): Argument #1 ($pattern) must not be empty With $regs arg: + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_ereg(): Argument #1 ($pattern) must not be empty NULL diff --git a/ext/mbstring/tests/bug69151.phpt b/ext/mbstring/tests/bug69151.phpt index c95fa05c49f8..9dd546d2eee6 100644 --- a/ext/mbstring/tests/bug69151.phpt +++ b/ext/mbstring/tests/bug69151.phpt @@ -18,9 +18,16 @@ var_dump(NULL === mb_ereg_replace('.', "\\0", $str)); var_dump(false === mb_ereg_search_init("\x80", '.')); var_dump(false === mb_ereg_search()); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_eregi() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) bool(true) + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) diff --git a/ext/mbstring/tests/bug72164.phpt b/ext/mbstring/tests/bug72164.phpt index e4ed04ba5eba..2b8f3950d92c 100644 --- a/ext/mbstring/tests/bug72164.phpt +++ b/ext/mbstring/tests/bug72164.phpt @@ -19,5 +19,6 @@ try { } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d Option "e" is not supported diff --git a/ext/mbstring/tests/bug72399.phpt b/ext/mbstring/tests/bug72399.phpt index 4d3ea6d28c0b..bf9880c0ab42 100644 --- a/ext/mbstring/tests/bug72399.phpt +++ b/ext/mbstring/tests/bug72399.phpt @@ -19,7 +19,12 @@ try { echo $e->getMessage() . \PHP_EOL; } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(0) "" + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d No pattern was provided diff --git a/ext/mbstring/tests/bug72402.phpt b/ext/mbstring/tests/bug72402.phpt index 0441887e33c7..511c18bfec2c 100644 --- a/ext/mbstring/tests/bug72402.phpt +++ b/ext/mbstring/tests/bug72402.phpt @@ -17,5 +17,6 @@ try { } catch(Exception $e) {} ?> DONE ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace_callback() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d DONE diff --git a/ext/mbstring/tests/bug72691.phpt b/ext/mbstring/tests/bug72691.phpt index db299e9d9dbc..9147d149fcb3 100644 --- a/ext/mbstring/tests/bug72691.phpt +++ b/ext/mbstring/tests/bug72691.phpt @@ -27,23 +27,48 @@ mb_ereg_search('\Z'); var_dump(mb_ereg_search_getpos()); var_dump(mb_ereg_search_getregs()); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(0) + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(1) { [0]=> string(0) "" } + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(0) + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(1) { [0]=> string(0) "" } + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(3) + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(1) { [0]=> string(3) "foo" } + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(3) + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(1) { [0]=> string(0) "" diff --git a/ext/mbstring/tests/bug72693.phpt b/ext/mbstring/tests/bug72693.phpt index 6596eadd5fea..7b120164afab 100644 --- a/ext/mbstring/tests/bug72693.phpt +++ b/ext/mbstring/tests/bug72693.phpt @@ -26,18 +26,41 @@ var_dump(mb_ereg_search_getpos()); var_dump(mb_ereg_search('\Z')); var_dump(mb_ereg_search_getpos()); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(0) + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(0) + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(3) + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(1) { [0]=> string(3) "foo" } + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(3) + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(3) diff --git a/ext/mbstring/tests/bug72694.phpt b/ext/mbstring/tests/bug72694.phpt index ed7d2e79250e..0789f3620817 100644 --- a/ext/mbstring/tests/bug72694.phpt +++ b/ext/mbstring/tests/bug72694.phpt @@ -16,8 +16,17 @@ var_dump(mb_ereg_search_getpos()); var_dump(mb_ereg_search('\Z')); var_dump(mb_ereg_search_getpos()); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_setpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(3) + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(3) diff --git a/ext/mbstring/tests/bug72710.phpt b/ext/mbstring/tests/bug72710.phpt index ca1558c2ff1f..614abcf542f8 100644 --- a/ext/mbstring/tests/bug72710.phpt +++ b/ext/mbstring/tests/bug72710.phpt @@ -11,4 +11,6 @@ if (!function_exists('mb_ereg')) die('skip mbregex support not available'); mb_ereg('(?<0>a)', 'a'); ?> --EXPECTF-- +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + Warning: mb_ereg(): mbregex compile err: invalid group name <0> in %s on line %d diff --git a/ext/mbstring/tests/bug73532.phpt b/ext/mbstring/tests/bug73532.phpt index 27269296894c..1af3e2422904 100644 --- a/ext/mbstring/tests/bug73532.phpt +++ b/ext/mbstring/tests/bug73532.phpt @@ -10,5 +10,6 @@ if (!function_exists('mb_ereg')) die('skip mbregex support not available'); ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_eregi() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) diff --git a/ext/mbstring/tests/bug73646.phpt b/ext/mbstring/tests/bug73646.phpt index 9897b866439e..7b3e98164989 100644 --- a/ext/mbstring/tests/bug73646.phpt +++ b/ext/mbstring/tests/bug73646.phpt @@ -11,5 +11,7 @@ if (!function_exists('mb_ereg')) die('skip mbregex support not available'); var_dump(mb_ereg_search_init(NULL)); ?> --EXPECTF-- +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + Deprecated: mb_ereg_search_init(): Passing null to parameter #1 ($string) of type string is deprecated in %s on line %d bool(true) diff --git a/ext/mbstring/tests/bug76999.phpt b/ext/mbstring/tests/bug76999.phpt index 57e286af3b8a..5c6dc442573f 100644 --- a/ext/mbstring/tests/bug76999.phpt +++ b/ext/mbstring/tests/bug76999.phpt @@ -19,9 +19,20 @@ try { } var_dump(mb_regex_set_options()); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(2) "pr" + +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(2) "mr" + +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(3) "imd" + +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d Option "a" is not supported + +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(2) "mr" diff --git a/ext/mbstring/tests/bug77367.phpt b/ext/mbstring/tests/bug77367.phpt index ad1dac2e07c8..f4a1a373a98f 100644 --- a/ext/mbstring/tests/bug77367.phpt +++ b/ext/mbstring/tests/bug77367.phpt @@ -11,5 +11,8 @@ if (!function_exists('mb_split')) die('skip mb_split() not available'); mb_regex_encoding('UTF-8'); var_dump(mb_split("\\w", "\xfc")); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) diff --git a/ext/mbstring/tests/bug77370.phpt b/ext/mbstring/tests/bug77370.phpt index a2e3759c120a..8ccb169f83e0 100644 --- a/ext/mbstring/tests/bug77370.phpt +++ b/ext/mbstring/tests/bug77370.phpt @@ -11,5 +11,7 @@ if (!function_exists('mb_split')) die('skip mb_split() not available'); var_dump(mb_split(" \xfd","")); ?> --EXPECTF-- +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line 2 + Warning: mb_split(): Pattern is not valid under UTF-8 encoding in %s on line %d bool(false) diff --git a/ext/mbstring/tests/bug77371.phpt b/ext/mbstring/tests/bug77371.phpt index 767533c66a4e..b4a88ffc5124 100644 --- a/ext/mbstring/tests/bug77371.phpt +++ b/ext/mbstring/tests/bug77371.phpt @@ -11,5 +11,7 @@ if (!function_exists('mb_ereg')) die('skip mb_ereg() not available'); var_dump(mb_ereg("()0\xfc00000\xfc00000\xfc00000\xfc","")); ?> --EXPECTF-- +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + Warning: mb_ereg(): Pattern is not valid under UTF-8 encoding in %s on line %d bool(false) diff --git a/ext/mbstring/tests/bug77381.phpt b/ext/mbstring/tests/bug77381.phpt index 76607bc9ceba..cde197c49a68 100644 --- a/ext/mbstring/tests/bug77381.phpt +++ b/ext/mbstring/tests/bug77381.phpt @@ -14,14 +14,22 @@ var_dump(mb_ereg("0000\\"."\xf5","0")); var_dump(mb_ereg("(?i)FFF00000000000000000\xfd","")); ?> --EXPECTF-- +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + Warning: mb_ereg(): Pattern is not valid under UTF-8 encoding in %s on line %d bool(false) +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + Warning: mb_ereg(): Pattern is not valid under UTF-8 encoding in %s on line %d bool(false) +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + Warning: mb_ereg(): Pattern is not valid under UTF-8 encoding in %s on line %d bool(false) +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + Warning: mb_ereg(): Pattern is not valid under UTF-8 encoding in %s on line %d bool(false) diff --git a/ext/mbstring/tests/bug77418.phpt b/ext/mbstring/tests/bug77418.phpt index 352e125d689e..2227eef44a1b 100644 --- a/ext/mbstring/tests/bug77418.phpt +++ b/ext/mbstring/tests/bug77418.phpt @@ -12,5 +12,8 @@ mb_regex_encoding("UTF-32"); var_dump(mb_split("\x00\x00\x00\x5c\x00\x00\x00B","000000000000000000000000000000")); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) diff --git a/ext/mbstring/tests/bug77428.phpt b/ext/mbstring/tests/bug77428.phpt index c65cd000042f..71f9e09b0b1e 100644 --- a/ext/mbstring/tests/bug77428.phpt +++ b/ext/mbstring/tests/bug77428.phpt @@ -15,6 +15,9 @@ var_dump(mb_ereg_replace('(%)', '\\\1', 'a%c')); var_dump(mb_ereg_replace('(%)', '\\\\1', 'a%c')); ?> ---EXPECT-- -string(4) "a\%c" -string(4) "a\%c" +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d +string(4) "a\%%c" + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d +string(4) "a\%%c" diff --git a/ext/mbstring/tests/bug77514.phpt b/ext/mbstring/tests/bug77514.phpt index 4b33cca8a309..f6b7ca5d1808 100644 --- a/ext/mbstring/tests/bug77514.phpt +++ b/ext/mbstring/tests/bug77514.phpt @@ -13,5 +13,6 @@ $a="abc123"; var_dump(mb_ereg_replace("123","def\\",$a)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(7) "abcdef\" diff --git a/ext/mbstring/tests/bug78559.phpt b/ext/mbstring/tests/bug78559.phpt index e107d1ba864a..18b1fe00f83a 100644 --- a/ext/mbstring/tests/bug78559.phpt +++ b/ext/mbstring/tests/bug78559.phpt @@ -12,5 +12,6 @@ $str = "5b5b5b5b5b5b5b492a5bce946b5c4b5d5c6b5c4b5d5c4b5d1cceb04b5d1cceb07a73717e $str = hex2bin($str); var_dump(mb_eregi($str, $str)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_eregi() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) diff --git a/ext/mbstring/tests/bug78633.phpt b/ext/mbstring/tests/bug78633.phpt index a5dcd48b9bf9..42a1ccc4ed2d 100644 --- a/ext/mbstring/tests/bug78633.phpt +++ b/ext/mbstring/tests/bug78633.phpt @@ -15,5 +15,6 @@ if (is_bool($res)) { var_dump($res); } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_eregi() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d ok diff --git a/ext/mbstring/tests/empty_pattern.phpt b/ext/mbstring/tests/empty_pattern.phpt index 64e63147ee78..c7a2ca285c29 100644 --- a/ext/mbstring/tests/empty_pattern.phpt +++ b/ext/mbstring/tests/empty_pattern.phpt @@ -24,6 +24,11 @@ try { } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_ereg_search_init(): Argument #2 ($pattern) must not be empty + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_regs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d No pattern was provided diff --git a/ext/mbstring/tests/gh18901.phpt b/ext/mbstring/tests/gh18901.phpt index 8d862a537c3b..55e41d48377d 100644 --- a/ext/mbstring/tests/gh18901.phpt +++ b/ext/mbstring/tests/gh18901.phpt @@ -13,7 +13,8 @@ foreach ($vals as $val) { var_dump(mb_split('\d', '123', $val)); } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(4) { [0]=> string(0) "" @@ -24,6 +25,8 @@ array(4) { [3]=> string(0) "" } + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(4) { [0]=> string(0) "" @@ -34,6 +37,8 @@ array(4) { [3]=> string(0) "" } + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(4) { [0]=> string(0) "" @@ -44,10 +49,14 @@ array(4) { [3]=> string(0) "" } + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(1) { [0]=> string(3) "123" } + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(1) { [0]=> string(3) "123" diff --git a/ext/mbstring/tests/mb_ereg-compat-01.phpt b/ext/mbstring/tests/mb_ereg-compat-01.phpt index e9d407d1013b..c5752806d5c5 100644 --- a/ext/mbstring/tests/mb_ereg-compat-01.phpt +++ b/ext/mbstring/tests/mb_ereg-compat-01.phpt @@ -17,6 +17,9 @@ function_exists('mb_ereg') or die("skip mb_ereg() is not available in this build echo "ok\n"; } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d ok + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d ok diff --git a/ext/mbstring/tests/mb_ereg-compat-02.phpt b/ext/mbstring/tests/mb_ereg-compat-02.phpt index d30b9927cc53..a47f9c665bc8 100644 --- a/ext/mbstring/tests/mb_ereg-compat-02.phpt +++ b/ext/mbstring/tests/mb_ereg-compat-02.phpt @@ -19,7 +19,8 @@ function_exists('mb_ereg') or die("skip mb_ereg() is not available in this build echo $registers[2]; echo "\n"; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d 1 This is a nice and simple string is diff --git a/ext/mbstring/tests/mb_ereg.phpt b/ext/mbstring/tests/mb_ereg.phpt index 53bb58e15a86..5b3f9c125fcd 100644 --- a/ext/mbstring/tests/mb_ereg.phpt +++ b/ext/mbstring/tests/mb_ereg.phpt @@ -31,16 +31,65 @@ output_handler= do_tests( $enc ); } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)6162632064656620676869206a6b6c2064656620676869206a6b6c + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)a3e1a3e2a3e320a4a2a4aaa4a420a4aba4b3a4ca20a4efa4f1a4f320a3e1a3e2a3e320a4a2a4aaa4a420a4ab20a4b3a4ca20a4efa4f1a4f3 + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)a3eda3faa3f8a3e6a3f020a4a6a4aaa4ab20a4ada4ab20a4f2a4f020a3eda3faa3f8a3e6a3f020a4a6a4aaa4ab2020a4ada4ab20a4f2a4f0 + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)6162632064656620676869206a6b6c2064656620676869206a6b6c + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)a3e1a3e2a3e320a4a2a4aaa4a420a4aba4b3a4ca20a4efa4f1a4f320a3e1a3e2a3e320a4a2a4aaa4a420a4ab20a4b3a4ca20a4efa4f1a4f3 + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)a3eda3faa3f8a3e6a3f020a4a6a4aaa4ab20a4ada4ab20a4f2a4f020a3eda3faa3f8a3e6a3f020a4a6a4aaa4ab2020a4ada4ab20a4f2a4f0 + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)6162632064656620676869206a6b6c2064656620676869206a6b6c + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)a3e1a3e2a3e320a4a2a4aaa4a420a4aba4b3a4ca20a4efa4f1a4f320a3e1a3e2a3e320a4a2a4aaa4a420a4ab20a4b3a4ca20a4efa4f1a4f3 + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)a3eda3faa3f8a3e6a3f020a4a6a4aaa4ab20a4ada4ab20a4f2a4f020a3eda3faa3f8a3e6a3f020a4a6a4aaa4ab2020a4ada4ab20a4f2a4f0 + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)6162632064656620676869206a6b6c2064656620676869206a6b6c + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)a3e1a3e2a3e320a4a2a4aaa4a420a4aba4b3a4ca20a4efa4f1a4f320a3e1a3e2a3e320a4a2a4aaa4a420a4ab20a4b3a4ca20a4efa4f1a4f3 + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d (1)a3eda3faa3f8a3e6a3f020a4a6a4aaa4ab20a4ada4ab20a4f2a4f020a3eda3faa3f8a3e6a3f020a4a6a4aaa4ab2020a4ada4ab20a4f2a4f0 diff --git a/ext/mbstring/tests/mb_ereg1.phpt b/ext/mbstring/tests/mb_ereg1.phpt index 813fe5e41ef0..a92b796423de 100644 --- a/ext/mbstring/tests/mb_ereg1.phpt +++ b/ext/mbstring/tests/mb_ereg1.phpt @@ -24,7 +24,8 @@ foreach ($a as $args) { var_dump($args); } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) array(3) { [0]=> @@ -35,6 +36,8 @@ array(3) { array(0) { } } + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d ValueError: mb_ereg(): Argument #1 ($pattern) must not be empty array(3) { [0]=> @@ -44,6 +47,8 @@ array(3) { [2]=> string(0) "" } + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d TypeError: mb_ereg(): Argument #1 ($pattern) must be of type string, array given array(3) { [0]=> @@ -54,6 +59,8 @@ array(3) { [2]=> string(0) "" } + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d TypeError: mb_ereg(): Argument #2 ($string) must be of type string, array given array(3) { [0]=> @@ -64,6 +71,8 @@ array(3) { [2]=> string(0) "" } + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) array(3) { [0]=> diff --git a/ext/mbstring/tests/mb_ereg2.phpt b/ext/mbstring/tests/mb_ereg2.phpt index f87b5c5410a8..22cd29199dda 100644 --- a/ext/mbstring/tests/mb_ereg2.phpt +++ b/ext/mbstring/tests/mb_ereg2.phpt @@ -18,13 +18,16 @@ var_dump($a, $b, $c); echo "Done\n"; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(-1) int(-1) array(1) { [0]=> string(2) "-1" } + +Deprecated: Function mb_eregi() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(-1) int(-1) array(1) { diff --git a/ext/mbstring/tests/mb_ereg_basic.phpt b/ext/mbstring/tests/mb_ereg_basic.phpt index 094f2949ea43..d54f3bb3be80 100644 --- a/ext/mbstring/tests/mb_ereg_basic.phpt +++ b/ext/mbstring/tests/mb_ereg_basic.phpt @@ -71,15 +71,23 @@ function base64_encode_var_dump($regs) { } } ?> ---EXPECT-- +--EXPECTF-- *** Testing mb_ereg() : basic functionality *** + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d Regex encoding set to utf-8 **-- ASCII String --** -- Without $regs argument-- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) --With $regs argument -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(2) { [0]=> @@ -87,6 +95,8 @@ array(2) { [1]=> string(24) "VGhpcyBpcyBhbiBFbmdsaXM=" } + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -95,9 +105,15 @@ array(1) { **-- Multibyte String --** -- Without $regs argument -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) -- With $regs argument -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(3) { [0]=> @@ -107,6 +123,8 @@ array(3) { [2]=> string(8) "MTIzNA==" } + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) array(0) { } diff --git a/ext/mbstring/tests/mb_ereg_dupnames.phpt b/ext/mbstring/tests/mb_ereg_dupnames.phpt index cf4444682f57..104dba927189 100644 --- a/ext/mbstring/tests/mb_ereg_dupnames.phpt +++ b/ext/mbstring/tests/mb_ereg_dupnames.phpt @@ -15,7 +15,10 @@ function_exists('mb_ereg') or die("skip mb_ereg() is not available in this build mb_ereg($pattern, '中ï¼', $m); var_dump($m); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(4) { [0]=> string(6) "中?" @@ -26,6 +29,8 @@ array(4) { ["punct"]=> string(3) "?" } + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(4) { [0]=> string(6) "中ï¼" diff --git a/ext/mbstring/tests/mb_ereg_match_basic.phpt b/ext/mbstring/tests/mb_ereg_match_basic.phpt index 5b7a8c2a5402..671a72d27272 100644 --- a/ext/mbstring/tests/mb_ereg_match_basic.phpt +++ b/ext/mbstring/tests/mb_ereg_match_basic.phpt @@ -38,18 +38,27 @@ var_dump(mb_ereg_match($regex2, $string_mb)); echo "Done"; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d *** Testing mb_ereg_match() : basic functionality *** -- ASCII string 1 -- + +Deprecated: Function mb_ereg_match() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) -- ASCII string 2 -- + +Deprecated: Function mb_ereg_match() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) -- Multibyte string 1 -- + +Deprecated: Function mb_ereg_match() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) -- Multibyte string 2 -- + +Deprecated: Function mb_ereg_match() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) Done diff --git a/ext/mbstring/tests/mb_ereg_named_subpatterns.phpt b/ext/mbstring/tests/mb_ereg_named_subpatterns.phpt index 80c17b729d70..7756b49d2128 100644 --- a/ext/mbstring/tests/mb_ereg_named_subpatterns.phpt +++ b/ext/mbstring/tests/mb_ereg_named_subpatterns.phpt @@ -16,7 +16,10 @@ function_exists('mb_ereg') or die("skip mb_ereg() is not available in this build mb_ereg('(\s*)(?\w+)', ' 中国', $m); var_dump($m); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(5) { [0]=> string(8) " 中国" @@ -29,6 +32,8 @@ array(5) { ["word"]=> string(6) "中国" } + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(5) { [0]=> string(3) "国" @@ -41,6 +46,8 @@ array(5) { ["word"]=> string(3) "国" } + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(3) { [0]=> string(8) " 中国" diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-01.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-01.phpt index 9ce201725219..057460ff01e4 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-01.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-01.phpt @@ -12,5 +12,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab $a="abc123"; echo mb_ereg_replace("123","def",$a); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d abcdef diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-02.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-02.phpt index 8fec03b486af..b9bebcf8d71f 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-02.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-02.phpt @@ -12,5 +12,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab $a="abc123"; echo mb_ereg_replace("123","",$a); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d abc diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-03.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-03.phpt index 0e589a8665bb..167eb6986c87 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-03.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-03.phpt @@ -12,5 +12,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab $a="\\'test"; echo mb_ereg_replace("\\\\'","'",$a); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d 'test diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-04.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-04.phpt index a9a4fc953281..70d29c8d1805 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-04.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-04.phpt @@ -12,5 +12,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab $a="This is a nice and simple string"; echo mb_ereg_replace("^This","That",$a); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d That is a nice and simple string diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-05.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-05.phpt index 4e15d8bfb8eb..0eaa22615b10 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-05.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-05.phpt @@ -13,5 +13,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab $b=mb_ereg_replace("abcd","",$a); echo "strlen(\$b)=".strlen($b); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d strlen($b)=0 diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-06.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-06.phpt index 396c8e870a26..6c169388387f 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-06.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-06.phpt @@ -11,5 +11,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab /* (counterpart: ext/standard/tests/reg/008.phpt) */ echo mb_ereg_replace("([a-z]*)([-=+|]*)([0-9]+)","\\3 \\1 \\2\n","abc+-|=123"); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d 123 abc +-|= diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-07.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-07.phpt index f0cd2edfe273..bc5ff9a6ca30 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-07.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-07.phpt @@ -12,5 +12,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab $a="abc122222222223"; echo mb_ereg_replace("1(2*)3","\\1def\\1",$a); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d abc2222222222def2222222222 diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-08.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-08.phpt index 8e23aba9cff9..8368e21a2a88 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-08.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-08.phpt @@ -12,5 +12,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab $a="abc123"; echo mb_ereg_replace("123","def\\0ghi",$a); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d abcdef123ghi diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-09.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-09.phpt index cb8fce9135d8..efa1eb0e9dc4 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-09.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-09.phpt @@ -12,5 +12,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab $a="abc123"; echo mb_ereg_replace("123",'def\1ghi',$a); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d abcdef\1ghi diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-10.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-10.phpt index 96c762bc4d5f..d280e93574cb 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-10.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-10.phpt @@ -12,5 +12,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab $a="abc123"; echo mb_ereg_replace("123","def\\g\\\\hi\\",$a); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d abcdef\g\\hi\ diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-11.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-11.phpt index a88f358b4b55..8f4b4fe5b295 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-11.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-11.phpt @@ -12,5 +12,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab $a="a\\2bxc"; echo mb_ereg_replace("a(.*)b(.*)c","\\1",$a); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d \2 diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-12.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-12.phpt index 0f371053e508..1dbc9a0416de 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-12.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-12.phpt @@ -11,5 +11,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab /* (counterpart: ext/standard/tests/reg/015.phpt) */ echo mb_ereg_replace("^","z","abc123"); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d zabc123 diff --git a/ext/mbstring/tests/mb_ereg_replace-compat-13.phpt b/ext/mbstring/tests/mb_ereg_replace-compat-13.phpt index a271eeff405c..4e6eaf017bc4 100644 --- a/ext/mbstring/tests/mb_ereg_replace-compat-13.phpt +++ b/ext/mbstring/tests/mb_ereg_replace-compat-13.phpt @@ -11,5 +11,6 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab /* (counterpart: ext/standard/tests/reg/016.phpt) */ echo mb_ereg_replace('\?',"abc","?123?"); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d abc123abc diff --git a/ext/mbstring/tests/mb_ereg_replace.phpt b/ext/mbstring/tests/mb_ereg_replace.phpt index 455b13e23ce5..1221b6b366b0 100644 --- a/ext/mbstring/tests/mb_ereg_replace.phpt +++ b/ext/mbstring/tests/mb_ereg_replace.phpt @@ -12,6 +12,11 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab print mb_ereg_replace( ' ', '-', 'a b c d e' )."\n"; print mb_ereg_replace( '([a-z]+)','[\\1]', 'abc def ghi' ); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d a-b-c-d-e + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d [abc] [def] [ghi] diff --git a/ext/mbstring/tests/mb_ereg_replace_basic.phpt b/ext/mbstring/tests/mb_ereg_replace_basic.phpt index a3f18952d375..7faac7371abd 100644 --- a/ext/mbstring/tests/mb_ereg_replace_basic.phpt +++ b/ext/mbstring/tests/mb_ereg_replace_basic.phpt @@ -41,18 +41,28 @@ var_dump(bin2hex($result_4)); echo "Done"; ?> ---EXPECT-- +--EXPECTF-- *** Testing mb_ereg_replace() : basic functionality *** +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + -- ASCII string 1 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(16) "6162632020313233" -- ASCII string 2 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(14) "61626320646566" -- Multibyte string 1 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(72) "e697a5e69cace8aa9e5f5f5f5f5f31323334efbc95efbc96efbc97efbc98efbc99e38082" -- Multibyte string 2 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(106) "e697a5e69cace8aa9ee38386e382ade382b9e38388e381a7e38199e380823031323334efbc95efbc96efbc97efbc98efbc99e38082" Done diff --git a/ext/mbstring/tests/mb_ereg_replace_callback.phpt b/ext/mbstring/tests/mb_ereg_replace_callback.phpt index 40120c03eab2..d4541d09cafa 100644 --- a/ext/mbstring/tests/mb_ereg_replace_callback.phpt +++ b/ext/mbstring/tests/mb_ereg_replace_callback.phpt @@ -18,6 +18,9 @@ echo mb_ereg_replace_callback('(?\w+) (?\d+).*', function ($m) { return sprintf("%s-%s", $m['digit'], $m['word']); }, $str), "\n"; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace_callback() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d abc(3) 123(3) #",;(4) $foo(4) + +Deprecated: Function mb_ereg_replace_callback() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d 123-abc diff --git a/ext/mbstring/tests/mb_ereg_replace_named_subpatterns.phpt b/ext/mbstring/tests/mb_ereg_replace_named_subpatterns.phpt index 7e4d8e2e4940..8a58e95dffdf 100644 --- a/ext/mbstring/tests/mb_ereg_replace_named_subpatterns.phpt +++ b/ext/mbstring/tests/mb_ereg_replace_named_subpatterns.phpt @@ -26,12 +26,29 @@ function_exists('mb_ereg_replace') or die("skip mb_ereg_replace() is not availab // An unclosed backref is ignored echo mb_ereg_replace('(?\w+)', '-\k ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d _a_ _b_ _c_ _d_ _e_ + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d 123456789aa-a- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d 123456789aa-a- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d a_\k<01> + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d -\1- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d -\k<>- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d -\k ---EXPECT-- +--EXPECTF-- *** Testing mb_ereg_replace() : usage variations *** -- Iteration 1 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "string_val" -- Iteration 2 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "string_val" -- Iteration 3 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "string_val" -- Iteration 4 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "string_val" -- Iteration 5 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "string_val" -- Iteration 6 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "string_val" -- Iteration 7 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "string_val" -- Iteration 8 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "string_val" -- Iteration 9 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "string_val" -- Iteration 10 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(120) "string_valsstring_valtstring_valrstring_valistring_valnstring_valgstring_val_string_valvstring_valastring_vallstring_val" -- Iteration 11 -- + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "string_val" Done diff --git a/ext/mbstring/tests/mb_ereg_search.phpt b/ext/mbstring/tests/mb_ereg_search.phpt index f167b9d7607d..25f581b7dd8d 100644 --- a/ext/mbstring/tests/mb_ereg_search.phpt +++ b/ext/mbstring/tests/mb_ereg_search.phpt @@ -32,9 +32,26 @@ function_exists('mb_ereg_search') or die("skip mb_ereg_search() is not available while($r); } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(9) "中国abc" + +Deprecated: Function mb_ereg_search_regs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(3) "abc" + +Deprecated: Function mb_ereg_search_regs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "字符" + +Deprecated: Function mb_ereg_search_regs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "china" + +Deprecated: Function mb_ereg_search_regs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "string" + +Deprecated: Function mb_ereg_search_regs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d diff --git a/ext/mbstring/tests/mb_ereg_search_invalid_pattern.phpt b/ext/mbstring/tests/mb_ereg_search_invalid_pattern.phpt index 6979816fe8e0..33ad520e5fe6 100644 --- a/ext/mbstring/tests/mb_ereg_search_invalid_pattern.phpt +++ b/ext/mbstring/tests/mb_ereg_search_invalid_pattern.phpt @@ -14,8 +14,15 @@ var_dump(mb_ereg_search_getregs()); ?> --EXPECTF-- +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + Warning: mb_ereg_search(): Pattern is not valid under UTF-8 encoding in %s on line %d bool(false) + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) diff --git a/ext/mbstring/tests/mb_ereg_search_named_subpatterns_1.phpt b/ext/mbstring/tests/mb_ereg_search_named_subpatterns_1.phpt index 03161cf27cec..bcf73b6b3f40 100644 --- a/ext/mbstring/tests/mb_ereg_search_named_subpatterns_1.phpt +++ b/ext/mbstring/tests/mb_ereg_search_named_subpatterns_1.phpt @@ -5,7 +5,7 @@ mbstring --SKIPIF-- --FILE-- =') or die("skip requires oniguruma >= 6.9.4"); +@version_compare(MB_ONIGURUMA_VERSION, '6.9.4', '>=') or die("skip requires oniguruma >= 6.9.4"); ?> --FILE-- =') or die("skip requires onigu mb_ereg_search('(?\s*)(?\w+)(?[?ï¼])'); var_dump(mb_ereg_search_getregs()); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(7) { [0]=> string(11) " 中国?" diff --git a/ext/mbstring/tests/mb_ereg_search_pos.phpt b/ext/mbstring/tests/mb_ereg_search_pos.phpt index 7f8f99f0c5d2..2c88cff01e04 100644 --- a/ext/mbstring/tests/mb_ereg_search_pos.phpt +++ b/ext/mbstring/tests/mb_ereg_search_pos.phpt @@ -22,7 +22,12 @@ else{ var_dump("false"); } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(2) { [0]=> int(5) diff --git a/ext/mbstring/tests/mb_ereg_search_regs.phpt b/ext/mbstring/tests/mb_ereg_search_regs.phpt index eb883387e620..dd28df903729 100644 --- a/ext/mbstring/tests/mb_ereg_search_regs.phpt +++ b/ext/mbstring/tests/mb_ereg_search_regs.phpt @@ -22,7 +22,10 @@ function_exists('mb_ereg_search_regs') or die("skip mb_ereg_search_regs() not av ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_regs() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(1) { [0]=> string(4) "ов" diff --git a/ext/mbstring/tests/mb_ereg_search_setpos.phpt b/ext/mbstring/tests/mb_ereg_search_setpos.phpt index 6a953447174d..6153d86282df 100644 --- a/ext/mbstring/tests/mb_ereg_search_setpos.phpt +++ b/ext/mbstring/tests/mb_ereg_search_setpos.phpt @@ -35,38 +35,77 @@ foreach($positions as $pos) { } } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search_setpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_setpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_ereg_search_setpos(): Argument #1 ($offset) is out of range +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + * Position: 5 : + +Deprecated: Function mb_ereg_search_setpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(5) * Position: 20 : + +Deprecated: Function mb_ereg_search_setpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(20) * Position: 21 : + +Deprecated: Function mb_ereg_search_setpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_ereg_search_setpos(): Argument #1 ($offset) is out of range + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(20) * Position: 25 : + +Deprecated: Function mb_ereg_search_setpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_ereg_search_setpos(): Argument #1 ($offset) is out of range + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(20) * Position: 0 : + +Deprecated: Function mb_ereg_search_setpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(0) * Position: -5 : + +Deprecated: Function mb_ereg_search_setpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(15) * Position: -20 : + +Deprecated: Function mb_ereg_search_setpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(0) * Position: -30 : + +Deprecated: Function mb_ereg_search_setpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_ereg_search_setpos(): Argument #1 ($offset) is out of range + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d int(0) diff --git a/ext/mbstring/tests/mb_ereg_search_syntax.phpt b/ext/mbstring/tests/mb_ereg_search_syntax.phpt index 5e16a91c3695..f6b427a3c7e6 100644 --- a/ext/mbstring/tests/mb_ereg_search_syntax.phpt +++ b/ext/mbstring/tests/mb_ereg_search_syntax.phpt @@ -13,5 +13,8 @@ mb_ereg_search_init("a"); var_dump(mb_ereg_search("a\\{1,2\\}", "b")); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_search() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) diff --git a/ext/mbstring/tests/mb_ereg_search_xxx.phpt b/ext/mbstring/tests/mb_ereg_search_xxx.phpt index 238dcc0e87a5..33d21052ecd3 100644 --- a/ext/mbstring/tests/mb_ereg_search_xxx.phpt +++ b/ext/mbstring/tests/mb_ereg_search_xxx.phpt @@ -35,48 +35,409 @@ output_handler= do_tests( $enc, 'x' ); } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (EUC-JP) (10) ¡¦¢Ï + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (EUC-JP) (5) abcde + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (EUC-JP) (14) abdeabcf + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (EUC-JP) (22) abc + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (EUC-JP) (31) abcd + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (EUC-JP) (5) ¢Ï¡¦ + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (EUC-JP) (10) ¡¦¢Ï + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (EUC-JP) (5) abcde + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (EUC-JP) (14) abdeabcf + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (EUC-JP) (22) abc + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (EUC-JP) (31) abcd + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (Shift_JIS) (10) ¡¦¢Ï + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (Shift_JIS) (5) abcde + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (Shift_JIS) (14) abdeabcf + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (Shift_JIS) (22) abc + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (Shift_JIS) (31) abcd + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (Shift_JIS) (5) ¢Ï¡¦ + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (Shift_JIS) (10) ¡¦¢Ï + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (Shift_JIS) (5) abcde + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (Shift_JIS) (14) abdeabcf + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (Shift_JIS) (22) abc + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (Shift_JIS) (31) abcd + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (SJIS) (10) ¡¦¢Ï + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (SJIS) (5) abcde + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (SJIS) (14) abdeabcf + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (SJIS) (22) abc + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (SJIS) (31) abcd + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (SJIS) (5) ¢Ï¡¦ + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (SJIS) (10) ¡¦¢Ï + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (SJIS) (5) abcde + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (SJIS) (14) abdeabcf + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (SJIS) (22) abc + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (SJIS) (31) abcd + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (UTF-8) (14) ¡¦¢Ï + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (UTF-8) (5) abcde + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (UTF-8) (14) abdeabcf + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (UTF-8) (22) abc + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (UTF-8) (31) abcd + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (UTF-8) (7) ¢Ï¡¦ + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (UTF-8) (14) ¡¦¢Ï + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_init() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (UTF-8) (5) abcde + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (UTF-8) (14) abdeabcf + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (UTF-8) (22) abc + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getregs() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_search_getpos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d (UTF-8) (31) abcd + +Deprecated: Function mb_ereg_search_pos() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d diff --git a/ext/mbstring/tests/mb_ereg_variation3.phpt b/ext/mbstring/tests/mb_ereg_variation3.phpt index 329c5597d440..5735e8248ef2 100644 --- a/ext/mbstring/tests/mb_ereg_variation3.phpt +++ b/ext/mbstring/tests/mb_ereg_variation3.phpt @@ -5,7 +5,7 @@ mbstring --SKIPIF-- =') or die("skip requires oniguruma >= 6.1.0"); +@version_compare(MB_ONIGURUMA_VERSION, '6.1.0', '>=') or die("skip requires oniguruma >= 6.1.0"); ?> --FILE-- ---EXPECT-- +--EXPECTF-- *** Testing mb_ereg() : variation *** +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + -- Iteration 1 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -77,6 +81,8 @@ array(1) { } -- Iteration 2 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -84,6 +90,8 @@ array(1) { } -- Iteration 3 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -91,6 +99,8 @@ array(1) { } -- Iteration 4 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -98,6 +108,8 @@ array(1) { } -- Iteration 5 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -105,6 +117,8 @@ array(1) { } -- Iteration 6 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -112,6 +126,8 @@ array(1) { } -- Iteration 7 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -119,6 +135,8 @@ array(1) { } -- Iteration 8 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -126,6 +144,8 @@ array(1) { } -- Iteration 9 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -133,6 +153,8 @@ array(1) { } -- Iteration 10 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -140,6 +162,8 @@ array(1) { } -- Iteration 11 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -147,6 +171,8 @@ array(1) { } -- Iteration 12 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> diff --git a/ext/mbstring/tests/mb_ereg_variation4.phpt b/ext/mbstring/tests/mb_ereg_variation4.phpt index 05b96a9bf40f..559c5fd467cd 100644 --- a/ext/mbstring/tests/mb_ereg_variation4.phpt +++ b/ext/mbstring/tests/mb_ereg_variation4.phpt @@ -69,10 +69,14 @@ function base64_encode_var_dump($regs) { echo "Done"; ?> ---EXPECT-- +--EXPECTF-- *** Testing mb_ereg() : usage variations *** +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + -- Iteration 1 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(true) array(1) { [0]=> @@ -80,6 +84,8 @@ array(1) { } -- Iteration 2 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(true) array(1) { [0]=> @@ -87,6 +93,8 @@ array(1) { } -- Iteration 3 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(true) array(1) { [0]=> @@ -94,12 +102,18 @@ array(1) { } -- Iteration 4 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(false) -- Iteration 5 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(false) -- Iteration 6 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(true) array(1) { [0]=> @@ -107,6 +121,8 @@ array(1) { } -- Iteration 7 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(true) array(1) { [0]=> @@ -114,9 +130,13 @@ array(1) { } -- Iteration 8 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(false) -- Iteration 9 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(true) array(1) { [0]=> @@ -124,6 +144,8 @@ array(1) { } -- Iteration 10 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(true) array(1) { [0]=> @@ -131,12 +153,18 @@ array(1) { } -- Iteration 11 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(false) -- Iteration 12 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(false) -- Iteration 13 -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d bool(true) array(1) { [0]=> diff --git a/ext/mbstring/tests/mb_ereg_variation5.phpt b/ext/mbstring/tests/mb_ereg_variation5.phpt index 569162534dcd..37cb325bf84b 100644 --- a/ext/mbstring/tests/mb_ereg_variation5.phpt +++ b/ext/mbstring/tests/mb_ereg_variation5.phpt @@ -57,19 +57,29 @@ function base64_encode_var_dump($regs) { } } ?> ---EXPECT-- +--EXPECTF-- *** Testing mb_ereg() : usage variations *** -ASCII String without $regs arg: bool(true) +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +ASCII String without $regs arg: +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d +bool(true) ASCII String with $regs arg: + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> string(52) "VGhpcyBpcyBhbiBFbmdsaXNoIHN0cmluZy4gMDEyMzQ1Njc4OS4=" } -Multibyte String without $regs arg: bool(true) +Multibyte String without $regs arg: +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d +bool(true) Multubyte String with $regs arg: + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> diff --git a/ext/mbstring/tests/mb_ereg_variation6.phpt b/ext/mbstring/tests/mb_ereg_variation6.phpt index cea3fcf661b2..33df1eaf051a 100644 --- a/ext/mbstring/tests/mb_ereg_variation6.phpt +++ b/ext/mbstring/tests/mb_ereg_variation6.phpt @@ -73,18 +73,24 @@ function base64_encode_var_dump($regs) { echo "Done"; ?> ---EXPECT-- +--EXPECTF-- *** Testing mb_ereg() : usage variations *** + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d Regex encoding set to utf-8 --** Pattern is: \w+ **-- -- ASCII String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> string(8) "VGhpcw==" } -- Multibyte String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -93,12 +99,16 @@ array(1) { --** Pattern is: \W+ **-- -- ASCII String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> string(4) "IA==" } -- Multibyte String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -107,23 +117,31 @@ array(1) { --** Pattern is: \s+ **-- -- ASCII String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> string(4) "IA==" } -- Multibyte String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) NULL --** Pattern is: \S+ **-- -- ASCII String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> string(8) "VGhpcw==" } -- Multibyte String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -132,12 +150,16 @@ array(1) { --** Pattern is: \d+ **-- -- ASCII String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> string(16) "MDEyMzQ1Njc4OQ==" } -- Multibyte String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -146,12 +168,16 @@ array(1) { --** Pattern is: \D+ **-- -- ASCII String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> string(36) "VGhpcyBpcyBhbiBFbmdsaXNoIHN0cmluZy4g" } -- Multibyte String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -160,12 +186,16 @@ array(1) { --** Pattern is: \b **-- -- ASCII String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> bool(false) } -- Multibyte String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> @@ -174,12 +204,16 @@ array(1) { --** Pattern is: \B **-- -- ASCII String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> bool(false) } -- Multibyte String: -- + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(1) { [0]=> diff --git a/ext/mbstring/tests/mb_ereg_variation7.phpt b/ext/mbstring/tests/mb_ereg_variation7.phpt index 832bbbfb6f3b..8e6ad836668a 100644 --- a/ext/mbstring/tests/mb_ereg_variation7.phpt +++ b/ext/mbstring/tests/mb_ereg_variation7.phpt @@ -58,9 +58,13 @@ function base64_encode_var_dump($regs) { echo "Done"; ?> ---EXPECT-- +--EXPECTF-- *** Testing mb_ereg() : usage variations *** + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d Regex encoding set to utf-8 + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(5) { [0]=> @@ -74,6 +78,8 @@ array(5) { [4]=> string(4) "ODk=" } + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) array(5) { [0]=> diff --git a/ext/mbstring/tests/mb_eregi.phpt b/ext/mbstring/tests/mb_eregi.phpt index 2cdef03a6cb4..1660f154fbf1 100644 --- a/ext/mbstring/tests/mb_eregi.phpt +++ b/ext/mbstring/tests/mb_eregi.phpt @@ -15,7 +15,14 @@ var_dump(mb_eregi('z', 'XYZ')); var_dump(mb_eregi('xyzp', 'XYZ')); var_dump(mb_eregi('ö', 'Öäü')); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_eregi() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) + +Deprecated: Function mb_eregi() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) diff --git a/ext/mbstring/tests/mb_eregi_replace.phpt b/ext/mbstring/tests/mb_eregi_replace.phpt index b03874701f95..89963c922761 100644 --- a/ext/mbstring/tests/mb_eregi_replace.phpt +++ b/ext/mbstring/tests/mb_eregi_replace.phpt @@ -33,7 +33,140 @@ function do_translit($st) { mb_regex_encoding('ISO-8859-1'); echo do_translit("Пеар"); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_eregi_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d Pear --CREDITS-- Testfest Wuerzburg 2009-06-20 (modified by rui 2011-10-15) diff --git a/ext/mbstring/tests/mb_regex_encoding_basic.phpt b/ext/mbstring/tests/mb_regex_encoding_basic.phpt index 8492369aceff..745cb0cf021b 100644 --- a/ext/mbstring/tests/mb_regex_encoding_basic.phpt +++ b/ext/mbstring/tests/mb_regex_encoding_basic.phpt @@ -25,7 +25,13 @@ echo "Done"; ?> --EXPECTF-- *** Testing mb_regex_encoding() : basic functionality *** + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(%d) "%s" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UTF-8" Done diff --git a/ext/mbstring/tests/mb_regex_encoding_error2.phpt b/ext/mbstring/tests/mb_regex_encoding_error2.phpt index 6874f5379a6a..ee665e5aa8bd 100644 --- a/ext/mbstring/tests/mb_regex_encoding_error2.phpt +++ b/ext/mbstring/tests/mb_regex_encoding_error2.phpt @@ -21,6 +21,8 @@ try { } ?> ---EXPECT-- +--EXPECTF-- *** Testing mb_regex_encoding() : error conditions *** + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line 9 mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "unknown" given diff --git a/ext/mbstring/tests/mb_regex_encoding_variation2.phpt b/ext/mbstring/tests/mb_regex_encoding_variation2.phpt index 5d46b3ad7936..55d139eb3ad7 100644 --- a/ext/mbstring/tests/mb_regex_encoding_variation2.phpt +++ b/ext/mbstring/tests/mb_regex_encoding_variation2.phpt @@ -87,286 +87,622 @@ foreach($encoding as $enc) { } echo "Done"; ?> ---EXPECT-- +--EXPECTF-- *** Testing mb_regex_encoding() : usage variations *** -- Iteration 1 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UTF-8" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UCS-4" -- Iteration 2 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UCS-4" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "UCS-4BE" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UCS-4" -- Iteration 3 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UCS-4" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(7) "UCS-4LE" -- Iteration 4 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(7) "UCS-4LE" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "UCS-2" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(7) "UCS-4LE" -- Iteration 5 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(7) "UCS-4LE" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "UCS-2BE" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(7) "UCS-4LE" -- Iteration 6 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(7) "UCS-4LE" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "UCS-2LE" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(7) "UCS-4LE" -- Iteration 7 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(7) "UCS-4LE" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UCS-4" -- Iteration 8 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UCS-4" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UCS-4" -- Iteration 9 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UCS-4" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(7) "UCS-4LE" -- Iteration 10 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(7) "UCS-4LE" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "UTF-16" -- Iteration 11 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "UTF-16" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "UTF-16" -- Iteration 12 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "UTF-16" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(8) "UTF-16LE" -- Iteration 13 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(8) "UTF-16LE" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "UTF-7" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(8) "UTF-16LE" -- Iteration 14 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(8) "UTF-16LE" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "UTF7-IMAP" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(8) "UTF-16LE" -- Iteration 15 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(8) "UTF-16LE" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UTF-8" -- Iteration 16 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "UTF-8" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "ASCII" -- Iteration 17 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "ASCII" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-JP" -- Iteration 18 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-JP" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "SJIS" -- Iteration 19 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "SJIS" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-JP" -- Iteration 20 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-JP" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "SJIS" -- Iteration 21 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "SJIS" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "ISO-2022-JP" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "SJIS" -- Iteration 22 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "SJIS" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "JIS" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "SJIS" -- Iteration 23 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "SJIS" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-1" -- Iteration 24 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-1" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-2" -- Iteration 25 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-2" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-3" -- Iteration 26 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-3" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-4" -- Iteration 27 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-4" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-5" -- Iteration 28 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-5" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-6" -- Iteration 29 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-6" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-7" -- Iteration 30 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-7" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-8" -- Iteration 31 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-8" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-9" -- Iteration 32 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(10) "ISO-8859-9" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-10" -- Iteration 33 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-10" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-13" -- Iteration 34 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-13" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-14" -- Iteration 35 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-14" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" -- Iteration 36 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "byte2be" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" -- Iteration 37 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "byte2le" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" -- Iteration 38 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "byte4be" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" -- Iteration 39 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "byte4le" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" -- Iteration 40 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "BASE64" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" -- Iteration 41 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "HTML-ENTITIES" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" -- Iteration 42 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "7bit" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" -- Iteration 43 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "8bit" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" -- Iteration 44 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(11) "ISO-8859-15" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-CN" -- Iteration 45 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-CN" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "CP936" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-CN" -- Iteration 46 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-CN" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "HZ" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-CN" -- Iteration 47 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-CN" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-TW" -- Iteration 48 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-TW" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "CP950" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-TW" -- Iteration 49 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-TW" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "BIG5" -- Iteration 50 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "BIG5" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" -- Iteration 51 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "UHC" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" -- Iteration 52 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "ISO-2022-KR" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" -- Iteration 53 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "Windows-1251" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" -- Iteration 54 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "Windows-1252" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" -- Iteration 55 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "CP866" given + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" -- Iteration 56 -- + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(6) "EUC-KR" + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(5) "KOI8R" Done diff --git a/ext/mbstring/tests/mb_regex_set_options.phpt b/ext/mbstring/tests/mb_regex_set_options.phpt index a5fb611cacf3..f6994049f502 100644 --- a/ext/mbstring/tests/mb_regex_set_options.phpt +++ b/ext/mbstring/tests/mb_regex_set_options.phpt @@ -14,5 +14,12 @@ function_exists('mb_regex_set_options') or die("skip\n"); mb_regex_set_options( '' ); print mb_ereg_replace(' -', '+', '- - - - -' ); ?> ---EXPECT-- -+ + + + +-++++ +--EXPECTF-- +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s line %d + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d ++ + + + + +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d +-++++ diff --git a/ext/mbstring/tests/mb_split-compat-01.phpt b/ext/mbstring/tests/mb_split-compat-01.phpt index 69d398cb0de3..8c5dcc0b4f10 100644 --- a/ext/mbstring/tests/mb_split-compat-01.phpt +++ b/ext/mbstring/tests/mb_split-compat-01.phpt @@ -16,7 +16,8 @@ test"); echo $a[$i] . "\n"; } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d 4 this is diff --git a/ext/mbstring/tests/mb_split.phpt b/ext/mbstring/tests/mb_split.phpt index 208848ee2bf5..8b8df7411a81 100644 --- a/ext/mbstring/tests/mb_split.phpt +++ b/ext/mbstring/tests/mb_split.phpt @@ -33,13 +33,36 @@ function_exists('mb_split') or die("skip mb_split() is not available in this bui verify_split( "\xa1\xa1+", "\xa1\xa1\xa1\xa2\xa2\xa1\xa1\xa1\xa1\xa1\xa1\xa2\xa2\xa1\xa1\xa1", $i ); } ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_regex_encoding() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d ok + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d ok + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d ok + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d ok + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d ok + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d 2-2 + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d 3-3 + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d 4-4 diff --git a/ext/mbstring/tests/mb_split_empty_match.phpt b/ext/mbstring/tests/mb_split_empty_match.phpt index 56ee59c31c6d..14604adfa98b 100644 --- a/ext/mbstring/tests/mb_split_empty_match.phpt +++ b/ext/mbstring/tests/mb_split_empty_match.phpt @@ -11,7 +11,10 @@ function_exists('mb_split') or die("skip mb_split() is not available in this bui mb_regex_set_options('m'); var_dump(mb_split('^', "a\nb\nc")); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_regex_set_options() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + +Deprecated: Function mb_split() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d array(3) { [0]=> string(2) "a diff --git a/ext/mbstring/tests/mbregex_stack_limit.phpt b/ext/mbstring/tests/mbregex_stack_limit.phpt index a291c280b18d..5b1ac5b2f080 100644 --- a/ext/mbstring/tests/mbregex_stack_limit.phpt +++ b/ext/mbstring/tests/mbregex_stack_limit.phpt @@ -5,7 +5,7 @@ mbstring --SKIPIF-- @@ -24,8 +24,13 @@ var_dump(mb_ereg('\\s+$', $s)); echo 'OK'; ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) OK diff --git a/ext/mbstring/tests/mbregex_stack_limit2.phpt b/ext/mbstring/tests/mbregex_stack_limit2.phpt index 9c2efcc39ec2..e7860654f3c0 100644 --- a/ext/mbstring/tests/mbregex_stack_limit2.phpt +++ b/ext/mbstring/tests/mbregex_stack_limit2.phpt @@ -6,7 +6,7 @@ iconv --SKIPIF-- @@ -28,6 +28,10 @@ var_dump(mb_trim_regex(str_repeat(' ', 10000))); echo 'OK'; ?> --EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d + Warning: mb_ereg_replace(): mbregex search failure in php_mbereg_replace_exec(): match-stack limit over in %s on line %d + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(0) "" OK diff --git a/ext/mbstring/tests/php_gr_jp_10830.phpt b/ext/mbstring/tests/php_gr_jp_10830.phpt index 02b46c01d3db..4b7517fd6e0f 100644 --- a/ext/mbstring/tests/php_gr_jp_10830.phpt +++ b/ext/mbstring/tests/php_gr_jp_10830.phpt @@ -13,6 +13,7 @@ $a="aaa\n<>"; var_dump( mb_ereg("^[^><]+$",$a) ); var_dump( !!preg_match("/^[^><]+$/",$a) ); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) bool(false) diff --git a/ext/mbstring/tests/php_gr_jp_dev_884-1.phpt b/ext/mbstring/tests/php_gr_jp_dev_884-1.phpt index b9d82bf9af9f..4bf317499527 100644 --- a/ext/mbstring/tests/php_gr_jp_dev_884-1.phpt +++ b/ext/mbstring/tests/php_gr_jp_dev_884-1.phpt @@ -12,6 +12,8 @@ set_time_limit(2); var_dump(preg_replace("/.*/", "b", "a")); var_dump(mb_ereg_replace(".*", "b", "a")); ?> ---EXPECT-- +--EXPECTF-- string(2) "bb" + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(2) "bb" diff --git a/ext/mbstring/tests/php_gr_jp_dev_884-2.phpt b/ext/mbstring/tests/php_gr_jp_dev_884-2.phpt index 51086285ed61..405a9f6bf96f 100644 --- a/ext/mbstring/tests/php_gr_jp_dev_884-2.phpt +++ b/ext/mbstring/tests/php_gr_jp_dev_884-2.phpt @@ -13,8 +13,11 @@ var_dump(preg_replace("/C?$/", "Z", "ABC")); var_dump(mb_ereg_replace("C*$", "Z", "ABC")); var_dump(preg_replace("/C*$/", "Z", "ABC")); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "ABZZ" string(4) "ABZZ" + +Deprecated: Function mb_ereg_replace() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d string(4) "ABZZ" string(4) "ABZZ" diff --git a/ext/mbstring/tests/retry_limit.phpt b/ext/mbstring/tests/retry_limit.phpt index bcb1a1def5c0..1ada020e68c6 100644 --- a/ext/mbstring/tests/retry_limit.phpt +++ b/ext/mbstring/tests/retry_limit.phpt @@ -5,7 +5,7 @@ mbstring --SKIPIF-- = 6.9.3'); } ?> @@ -19,6 +19,9 @@ ini_set('mbstring.regex_retry_limit', '100000'); var_dump(mb_ereg($regex, $str)); ?> ---EXPECT-- +--EXPECTF-- +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(true) + +Deprecated: Function mb_ereg() is deprecated since 8.6, because the underlying library is no longer maintained in %s on line %d bool(false) From 8db314629a12bac94ddb198cedc9568b3fa399d7 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Mon, 27 Apr 2026 19:17:32 -0700 Subject: [PATCH 005/213] Update NEWS for URI cherry-pick to 8.5.6 --- NEWS | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/NEWS b/NEWS index 42cbe1c875cd..c5edd0657347 100644 --- a/NEWS +++ b/NEWS @@ -85,6 +85,10 @@ PHP NEWS . Fixed bug GH-21468 (Segfault in file_get_contents w/ a https URL and a proxy set). (ndossche) +- URI: + . Fixed CVE-2026-42371 (uriparser before 1.0.1 has numeric truncation in + text range comparison). (CVE-2026-42371) (Joshua W. Windle) + 26 Mar 2026, PHP 8.5.5 - Core: From dcf653339c245e25ea319248d0fc071a9405d688 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 28 Apr 2026 09:26:25 +0200 Subject: [PATCH 006/213] NEWS/UPGRADING for #21490 --- NEWS | 1 + UPGRADING | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/NEWS b/NEWS index 5be5ffd18ac4..45f40a076078 100644 --- a/NEWS +++ b/NEWS @@ -83,6 +83,7 @@ PHP NEWS recursive array references). (alexandre-daubois) . Fixed bug GH-21223; mb_guess_encoding no longer crashes when passed huge list of candidate encodings (with 200,000+ entries). (Jordi Kroon) + . mbregex has been deprecated. (youkidearitai) - Mysqli: . Added mysqli_quote_string() and mysqli::quote_string(). (Kamil Tekiela) diff --git a/UPGRADING b/UPGRADING index 6c6115ebcc84..df81eb889699 100644 --- a/UPGRADING +++ b/UPGRADING @@ -154,6 +154,11 @@ PHP 8.6 UPGRADE NOTES 4. Deprecated Functionality ======================================== +- Mbstring: + . Mbregex has been deprecated, because the underlying Oniguruma library + is no longer maintained. + RFC: https://wiki.php.net/rfc/eol-oniguruma + ======================================== 5. Changed Functions ======================================== From 61e62a4dc9f2140745a426559652e031fe6162fa Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Tue, 28 Apr 2026 18:58:51 +0200 Subject: [PATCH 007/213] Update ext/{pdo_sqlite,sqlite3} tests (#21198) - Added SKIPIF sections for tests that use Pdo\Sqlite::DETERMINISTIC as it is available since libsqlite 3.8.3. - Removed outdated SKIPIF sections for libsqlite versions 3.7.4 When using libsqlite 3.7.17 there are two more failing tests due to different warning messages: - ext/sqlite3/tests/sqlite3_38_extended_error.phpt - ext/sqlite3/tests/sqlite3_39_toggleExtended.phpt This fix doesn't address these as minimum required libsqlite will be updated in the future PHP versions anyway at some point and this won't be an issue anymore then. --- .../tests/pdo_sqlite_createfunction_with_flags.phpt | 2 +- ext/pdo_sqlite/tests/php_8.5_deprecations.phpt | 4 ++++ ext/pdo_sqlite/tests/subclasses/pdo_sqlite_constants.phpt | 4 ++++ .../subclasses/pdo_sqlite_createfunction_with_flags.phpt | 2 +- ext/pdo_sqlite/tests/subclasses/pdosqlite_001.phpt | 4 ++++ ext/pdo_sqlite/tests/subclasses/pdosqlite_002.phpt | 4 ++++ ext/sqlite3/tests/sqlite3_35_stmt_readonly.phpt | 7 ------- ext/sqlite3/tests/sqlite3_37_createfunction_flags.phpt | 2 +- ext/sqlite3/tests/sqlite3_stmt_busy.phpt | 5 ----- 9 files changed, 19 insertions(+), 15 deletions(-) diff --git a/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_with_flags.phpt b/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_with_flags.phpt index 9f0c777e83d8..fafa4f6bfa21 100644 --- a/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_with_flags.phpt +++ b/ext/pdo_sqlite/tests/pdo_sqlite_createfunction_with_flags.phpt @@ -4,7 +4,7 @@ PDO_sqlite: Testing sqliteCreateFunction() with flags pdo_sqlite --SKIPIF-- = 3.8.3'); ?> --FILE-- = 3.8.3'); +?> --FILE-- = 3.8.3'); +?> --FILE-- = 3.8.3'); ?> --FILE-- = 3.8.3'); +?> --FILE-- = 3.8.3'); +?> --FILE-- --FILE-- = 3.8.3'); ?> --FILE-- --FILE-- Date: Tue, 28 Apr 2026 22:12:56 +0200 Subject: [PATCH 008/213] tree-wide: Replace `XtOffsetOf` by its definition (#21899) `offsetof()` is in `stddef.h` and thus always available. The extra macro is an unnecessary layer of indirection. --- UPGRADING.INTERNALS | 2 ++ Zend/Optimizer/zend_optimizer.c | 4 ++-- Zend/zend_ast.h | 2 +- Zend/zend_closures.c | 2 +- Zend/zend_compile.c | 4 ++-- Zend/zend_compile.h | 2 +- Zend/zend_enum.c | 2 +- Zend/zend_enum.h | 2 +- Zend/zend_fibers.h | 2 +- Zend/zend_ini.h | 12 ++++++------ Zend/zend_portability.h | 4 ---- Zend/zend_string.h | 2 +- Zend/zend_weakrefs.c | 8 ++++---- ext/bcmath/bcmath.c | 4 ++-- ext/curl/curl_private.h | 4 ++-- ext/curl/interface.c | 2 +- ext/curl/multi.c | 4 ++-- ext/curl/share.c | 4 ++-- ext/date/php_date.c | 8 ++++---- ext/date/php_date.h | 8 ++++---- ext/dba/dba.c | 4 ++-- ext/dom/namespace_compat.c | 2 +- ext/dom/php_dom.c | 10 +++++----- ext/dom/php_dom.h | 4 ++-- ext/dom/token_list.c | 4 ++-- ext/dom/token_list.h | 4 ++-- ext/dom/xml_common.h | 2 +- ext/dom/xpath.c | 2 +- ext/enchant/enchant.c | 8 ++++---- ext/fileinfo/fileinfo.c | 4 ++-- ext/ftp/php_ftp.c | 2 +- ext/gd/gd.c | 6 +++--- ext/gmp/gmp.c | 2 +- ext/gmp/php_gmp_int.h | 2 +- ext/hash/hash.c | 2 +- ext/intl/breakiterator/breakiterator_class.cpp | 2 +- ext/intl/breakiterator/breakiterator_class.h | 2 +- ext/intl/calendar/calendar_class.cpp | 2 +- ext/intl/calendar/calendar_class.h | 2 +- ext/intl/collator/collator_class.cpp | 2 +- ext/intl/collator/collator_class.h | 2 +- ext/intl/common/common_enum.cpp | 2 +- ext/intl/common/common_enum.h | 2 +- ext/intl/converter/converter.cpp | 4 ++-- ext/intl/dateformat/dateformat_class.cpp | 2 +- ext/intl/dateformat/dateformat_class.h | 2 +- ext/intl/dateformat/datepatterngenerator_class.cpp | 2 +- ext/intl/dateformat/datepatterngenerator_class.h | 2 +- ext/intl/formatter/formatter_class.cpp | 2 +- ext/intl/formatter/formatter_class.h | 2 +- ext/intl/listformatter/listformatter_class.cpp | 2 +- ext/intl/listformatter/listformatter_class.h | 2 +- ext/intl/msgformat/msgformat_class.cpp | 2 +- ext/intl/msgformat/msgformat_class.h | 2 +- ext/intl/rangeformatter/rangeformatter_class.cpp | 2 +- ext/intl/rangeformatter/rangeformatter_class.h | 2 +- ext/intl/resourcebundle/resourcebundle_class.cpp | 2 +- ext/intl/resourcebundle/resourcebundle_class.h | 2 +- ext/intl/spoofchecker/spoofchecker_class.cpp | 2 +- ext/intl/spoofchecker/spoofchecker_class.h | 2 +- ext/intl/timezone/timezone_class.cpp | 2 +- ext/intl/timezone/timezone_class.h | 2 +- ext/intl/transliterator/transliterator_class.cpp | 2 +- ext/intl/transliterator/transliterator_class.h | 2 +- ext/ldap/ldap.c | 14 +++++++------- ext/mysqli/mysqli.c | 2 +- ext/mysqli/php_mysqli_structs.h | 2 +- ext/odbc/php_odbc.c | 8 ++++---- ext/openssl/openssl.c | 6 +++--- ext/openssl/php_openssl.h | 6 +++--- ext/pdo/pdo_dbh.c | 2 +- ext/pdo/pdo_stmt.c | 4 ++-- ext/pdo/php_pdo_driver.h | 8 ++++---- ext/pgsql/pgsql.c | 14 +++++++------- ext/random/php_random.h | 4 ++-- ext/random/random.c | 10 +++++----- ext/reflection/php_reflection.c | 4 ++-- ext/shmop/shmop.c | 4 ++-- ext/simplexml/php_simplexml_exports.h | 2 +- ext/simplexml/simplexml.c | 2 +- ext/snmp/php_snmp.h | 2 +- ext/snmp/snmp.c | 4 ++-- ext/soap/php_soap.h | 2 +- ext/soap/soap.c | 14 +++++++------- ext/sockets/php_sockets.h | 2 +- ext/sockets/sockets.c | 8 ++++---- ext/spl/spl_array.c | 4 ++-- ext/spl/spl_directory.c | 8 ++++---- ext/spl/spl_dllist.c | 4 ++-- ext/spl/spl_fixedarray.c | 4 ++-- ext/spl/spl_heap.c | 6 +++--- ext/spl/spl_iterators.c | 8 ++++---- ext/spl/spl_observer.c | 4 ++-- ext/sqlite3/php_sqlite3_structs.h | 6 +++--- ext/sqlite3/sqlite3.c | 6 +++--- ext/standard/url_scanner_ex.re | 2 +- ext/sysvmsg/sysvmsg.c | 4 ++-- ext/sysvsem/sysvsem.c | 4 ++-- ext/sysvshm/sysvshm.c | 4 ++-- ext/tidy/tidy.c | 4 ++-- ext/uri/php_uri.c | 4 ++-- ext/uri/php_uri_common.h | 2 +- ext/xml/xml.c | 4 ++-- ext/xmlreader/php_xmlreader.c | 2 +- ext/xmlreader/php_xmlreader.h | 2 +- ext/xmlwriter/php_xmlwriter.c | 2 +- ext/xmlwriter/php_xmlwriter.h | 2 +- ext/xsl/php_xsl.c | 2 +- ext/xsl/php_xsl.h | 2 +- ext/zend_test/test.c | 6 +++--- ext/zip/php_zip.c | 2 +- ext/zip/php_zip.h | 2 +- ext/zlib/zlib.c | 8 ++++---- main/fastcgi.c | 2 +- main/streams/xp_socket.c | 4 ++-- sapi/phpdbg/phpdbg_watch.c | 10 +++++----- 116 files changed, 223 insertions(+), 225 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index cfeaf9c30afe..c0815a781d78 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -96,6 +96,8 @@ PHP 8.6 INTERNALS UPGRADE NOTES and ZEND_PARSE_PARAMS_THROW have been removed due to being misleading, since ZPP always throws, unless ZEND_PARSE_PARAMS_QUIET is given. Use the non-throw versions. + . The XtOffsetOf() alias of C’s offsetof() macro has been removed. Use + offsetof() directly. ======================== 2. Build system changes diff --git a/Zend/Optimizer/zend_optimizer.c b/Zend/Optimizer/zend_optimizer.c index 59a87823eb56..245c67c45446 100644 --- a/Zend/Optimizer/zend_optimizer.c +++ b/Zend/Optimizer/zend_optimizer.c @@ -780,7 +780,7 @@ static bool zend_optimizer_ignore_class(zval *ce_zv, const zend_string *filename if (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE) { return true; } - const Bucket *ce_bucket = (const Bucket*)((uintptr_t)ce_zv - XtOffsetOf(Bucket, val)); + const Bucket *ce_bucket = (const Bucket*)((uintptr_t)ce_zv - offsetof(Bucket, val)); size_t offset = ce_bucket - EG(class_table)->arData; if (offset < EG(persistent_classes_count)) { return false; @@ -801,7 +801,7 @@ static bool zend_optimizer_ignore_function(zval *fbc_zv, const zend_string *file if (CG(compiler_options) & ZEND_COMPILE_WITH_FILE_CACHE) { return true; } - const Bucket *fbc_bucket = (const Bucket*)((uintptr_t)fbc_zv - XtOffsetOf(Bucket, val)); + const Bucket *fbc_bucket = (const Bucket*)((uintptr_t)fbc_zv - offsetof(Bucket, val)); size_t offset = fbc_bucket - EG(function_table)->arData; if (offset < EG(persistent_functions_count)) { return false; diff --git a/Zend/zend_ast.h b/Zend/zend_ast.h index 32882f5205f7..24b77d7d3493 100644 --- a/Zend/zend_ast.h +++ b/Zend/zend_ast.h @@ -358,7 +358,7 @@ typedef void (*zend_ast_apply_func)(zend_ast **ast_ptr, void *context); ZEND_API void zend_ast_apply(zend_ast *ast, zend_ast_apply_func fn, void *context); static zend_always_inline size_t zend_ast_size(uint32_t children) { - return XtOffsetOf(zend_ast, child) + (sizeof(zend_ast *) * children); + return offsetof(zend_ast, child) + (sizeof(zend_ast *) * children); } static zend_always_inline bool zend_ast_is_special(const zend_ast *ast) { diff --git a/Zend/zend_closures.c b/Zend/zend_closures.c index 314abede4063..b46085c80afa 100644 --- a/Zend/zend_closures.c +++ b/Zend/zend_closures.c @@ -829,7 +829,7 @@ static void zend_create_closure_ex(zval *res, zend_function *func, zend_class_en /* wrap internal function handler to avoid memory leak */ if (UNEXPECTED(closure->func.internal_function.handler == zend_closure_internal_handler)) { /* avoid infinity recursion, by taking handler from nested closure */ - zend_closure *nested = (zend_closure*)((char*)func - XtOffsetOf(zend_closure, func)); + zend_closure *nested = (zend_closure*)((char*)func - offsetof(zend_closure, func)); ZEND_ASSERT(nested->std.ce == zend_ce_closure); closure->orig_internal_handler = nested->orig_internal_handler; } else { diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c index 96433e16e713..a96af71aa900 100644 --- a/Zend/zend_compile.c +++ b/Zend/zend_compile.c @@ -5175,7 +5175,7 @@ static zend_result zend_compile_func_array_map(znode *result, zend_ast_list *arg opline->lineno = lineno; opline->extended_value = (2 << 16) | IS_ARRAY; const zval *fbc_zv = zend_hash_find(CG(function_table), lcname); - const Bucket *fbc_bucket = (const Bucket*)((uintptr_t)fbc_zv - XtOffsetOf(Bucket, val)); + const Bucket *fbc_bucket = (const Bucket*)((uintptr_t)fbc_zv - offsetof(Bucket, val)); Z_EXTRA_P(CT_CONSTANT(opline->op1)) = fbc_bucket - CG(function_table)->arData; /* Initialize the result array. */ @@ -5472,7 +5472,7 @@ static void zend_compile_call(znode *result, const zend_ast *ast, uint32_t type) /* Store offset to function from symbol table in op2.extra. */ if (fbc->type == ZEND_INTERNAL_FUNCTION) { - const Bucket *fbc_bucket = (const Bucket*)((uintptr_t)fbc_zv - XtOffsetOf(Bucket, val)); + const Bucket *fbc_bucket = (const Bucket*)((uintptr_t)fbc_zv - offsetof(Bucket, val)); Z_EXTRA_P(CT_CONSTANT(opline->op2)) = fbc_bucket - CG(function_table)->arData; } diff --git a/Zend/zend_compile.h b/Zend/zend_compile.h index 8f67fee2a52b..0e31332c97f0 100644 --- a/Zend/zend_compile.h +++ b/Zend/zend_compile.h @@ -481,7 +481,7 @@ typedef struct _zend_property_info { #define OBJ_PROP_NUM(obj, num) \ (&(obj)->properties_table[(num)]) #define OBJ_PROP_TO_OFFSET(num) \ - ((uint32_t)(XtOffsetOf(zend_object, properties_table) + sizeof(zval) * (num))) + ((uint32_t)(offsetof(zend_object, properties_table) + sizeof(zval) * (num))) #define OBJ_PROP_TO_NUM(offset) \ (((offset) - OBJ_PROP_TO_OFFSET(0)) / sizeof(zval)) #define OBJ_PROP_SLOT_TO_OFFSET(obj, slot) \ diff --git a/Zend/zend_enum.c b/Zend/zend_enum.c index f175e3e6bcc9..136f89d2a633 100644 --- a/Zend/zend_enum.c +++ b/Zend/zend_enum.c @@ -176,7 +176,7 @@ void zend_register_enum_ce(void) zend_ce_backed_enum->interface_gets_implemented = zend_implement_backed_enum; memcpy(&zend_enum_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - zend_enum_object_handlers.offset = XtOffsetOf(zend_enum_obj, std); + zend_enum_object_handlers.offset = offsetof(zend_enum_obj, std); zend_enum_object_handlers.clone_obj = NULL; zend_enum_object_handlers.compare = zend_objects_not_comparable; } diff --git a/Zend/zend_enum.h b/Zend/zend_enum.h index 96c9317d47c0..4e65ebf728a6 100644 --- a/Zend/zend_enum.h +++ b/Zend/zend_enum.h @@ -36,7 +36,7 @@ typedef struct zend_enum_obj { static inline zend_enum_obj *zend_enum_obj_from_obj(zend_object *zobj) { ZEND_ASSERT(zobj->ce->ce_flags & ZEND_ACC_ENUM); - return (zend_enum_obj*)((char*)(zobj) - XtOffsetOf(zend_enum_obj, std)); + return (zend_enum_obj*)((char*)(zobj) - offsetof(zend_enum_obj, std)); } void zend_enum_startup(void); diff --git a/Zend/zend_fibers.h b/Zend/zend_fibers.h index d4726f97ddd2..7c0d30acab37 100644 --- a/Zend/zend_fibers.h +++ b/Zend/zend_fibers.h @@ -154,7 +154,7 @@ static zend_always_inline zend_fiber *zend_fiber_from_context(zend_fiber_context { ZEND_ASSERT(context->kind == zend_ce_fiber && "Fiber context does not belong to a Zend fiber"); - return (zend_fiber *)(((char *) context) - XtOffsetOf(zend_fiber, context)); + return (zend_fiber *)(((char *) context) - offsetof(zend_fiber, context)); } static zend_always_inline zend_fiber_context *zend_fiber_get_context(zend_fiber *fiber) diff --git a/Zend/zend_ini.h b/Zend/zend_ini.h index 16bc234d5849..dbe650675b66 100644 --- a/Zend/zend_ini.h +++ b/Zend/zend_ini.h @@ -182,18 +182,18 @@ END_EXTERN_C() #ifdef ZTS #define STD_ZEND_INI_ENTRY(name, default_value, modifiable, on_modify, property_name, struct_type, struct_ptr) \ - ZEND_INI_ENTRY2(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr##_id) + ZEND_INI_ENTRY2(name, default_value, modifiable, on_modify, (void *) offsetof(struct_type, property_name), (void *) &struct_ptr##_id) #define STD_ZEND_INI_ENTRY_EX(name, default_value, modifiable, on_modify, property_name, struct_type, struct_ptr, displayer) \ - ZEND_INI_ENTRY2_EX(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr##_id, displayer) + ZEND_INI_ENTRY2_EX(name, default_value, modifiable, on_modify, (void *) offsetof(struct_type, property_name), (void *) &struct_ptr##_id, displayer) #define STD_ZEND_INI_BOOLEAN(name, default_value, modifiable, on_modify, property_name, struct_type, struct_ptr) \ - ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr##_id, NULL, zend_ini_boolean_displayer_cb) + ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, (void *) offsetof(struct_type, property_name), (void *) &struct_ptr##_id, NULL, zend_ini_boolean_displayer_cb) #else #define STD_ZEND_INI_ENTRY(name, default_value, modifiable, on_modify, property_name, struct_type, struct_ptr) \ - ZEND_INI_ENTRY2(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr) + ZEND_INI_ENTRY2(name, default_value, modifiable, on_modify, (void *) offsetof(struct_type, property_name), (void *) &struct_ptr) #define STD_ZEND_INI_ENTRY_EX(name, default_value, modifiable, on_modify, property_name, struct_type, struct_ptr, displayer) \ - ZEND_INI_ENTRY2_EX(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr, displayer) + ZEND_INI_ENTRY2_EX(name, default_value, modifiable, on_modify, (void *) offsetof(struct_type, property_name), (void *) &struct_ptr, displayer) #define STD_ZEND_INI_BOOLEAN(name, default_value, modifiable, on_modify, property_name, struct_type, struct_ptr) \ - ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, (void *) XtOffsetOf(struct_type, property_name), (void *) &struct_ptr, NULL, zend_ini_boolean_displayer_cb) + ZEND_INI_ENTRY3_EX(name, default_value, modifiable, on_modify, (void *) offsetof(struct_type, property_name), (void *) &struct_ptr, NULL, zend_ini_boolean_displayer_cb) #endif #define REGISTER_INI_ENTRIES() zend_register_ini_entries_ex(ini_entries, module_number, type) diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index cd26aa174712..450e72a60eb5 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -430,10 +430,6 @@ char *alloca(); # define UNEXPECTED(condition) (condition) #endif -#ifndef XtOffsetOf -# define XtOffsetOf(s_type, field) offsetof(s_type, field) -#endif - #ifndef ZEND_WIN32 # define SETJMP(a) sigsetjmp(a, 0) # define LONGJMP(a,b) siglongjmp(a, b) diff --git a/Zend/zend_string.h b/Zend/zend_string.h index d2b382390009..3f0c9abd2596 100644 --- a/Zend/zend_string.h +++ b/Zend/zend_string.h @@ -115,7 +115,7 @@ static zend_always_inline zend_string *ZSTR_KNOWN(size_t idx) { return zend_known_strings[idx]; } -#define _ZSTR_HEADER_SIZE XtOffsetOf(zend_string, val) +#define _ZSTR_HEADER_SIZE offsetof(zend_string, val) #define _ZSTR_STRUCT_SIZE(len) (_ZSTR_HEADER_SIZE + len + 1) diff --git a/Zend/zend_weakrefs.c b/Zend/zend_weakrefs.c index 7303226a5d42..066f43f6524e 100644 --- a/Zend/zend_weakrefs.c +++ b/Zend/zend_weakrefs.c @@ -58,10 +58,10 @@ static zend_class_entry *zend_ce_weakmap; static zend_object_handlers zend_weakref_handlers; static zend_object_handlers zend_weakmap_handlers; -#define zend_weakref_from(o) ((zend_weakref*)(((char*) o) - XtOffsetOf(zend_weakref, std))) +#define zend_weakref_from(o) ((zend_weakref*)(((char*) o) - offsetof(zend_weakref, std))) #define zend_weakref_fetch(z) zend_weakref_from(Z_OBJ_P(z)) -#define zend_weakmap_from(o) ((zend_weakmap*)(((char*) o) - XtOffsetOf(zend_weakmap, std))) +#define zend_weakmap_from(o) ((zend_weakmap*)(((char*) o) - offsetof(zend_weakmap, std))) #define zend_weakmap_fetch(z) zend_weakmap_from(Z_OBJ_P(z)) static inline void zend_weakref_unref_single( @@ -796,7 +796,7 @@ void zend_register_weakref_ce(void) /* {{{ */ zend_ce_weakref->default_object_handlers = &zend_weakref_handlers; memcpy(&zend_weakref_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - zend_weakref_handlers.offset = XtOffsetOf(zend_weakref, std); + zend_weakref_handlers.offset = offsetof(zend_weakref, std); zend_weakref_handlers.free_obj = zend_weakref_free; zend_weakref_handlers.get_debug_info = zend_weakref_get_debug_info; @@ -809,7 +809,7 @@ void zend_register_weakref_ce(void) /* {{{ */ zend_ce_weakmap->default_object_handlers = &zend_weakmap_handlers; memcpy(&zend_weakmap_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - zend_weakmap_handlers.offset = XtOffsetOf(zend_weakmap, std); + zend_weakmap_handlers.offset = offsetof(zend_weakmap, std); zend_weakmap_handlers.free_obj = zend_weakmap_free_obj; zend_weakmap_handlers.read_dimension = zend_weakmap_read_dimension; zend_weakmap_handlers.write_dimension = zend_weakmap_write_dimension; diff --git a/ext/bcmath/bcmath.c b/ext/bcmath/bcmath.c index a1e6d48be523..1c9e5ef2612c 100644 --- a/ext/bcmath/bcmath.c +++ b/ext/bcmath/bcmath.c @@ -877,7 +877,7 @@ static int bcmath_number_compare(zval *op1, zval *op2); static zend_always_inline bcmath_number_obj_t *get_bcmath_number_from_obj(const zend_object *obj) { - return (bcmath_number_obj_t*)((char*)(obj) - XtOffsetOf(bcmath_number_obj_t, std)); + return (bcmath_number_obj_t*)((char*)(obj) - offsetof(bcmath_number_obj_t, std)); } static zend_always_inline bcmath_number_obj_t *get_bcmath_number_from_zval(const zval *zv) @@ -1024,7 +1024,7 @@ static void bcmath_number_register_class(void) bcmath_number_ce->default_object_handlers = &bcmath_number_obj_handlers; memcpy(&bcmath_number_obj_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - bcmath_number_obj_handlers.offset = XtOffsetOf(bcmath_number_obj_t, std); + bcmath_number_obj_handlers.offset = offsetof(bcmath_number_obj_t, std); bcmath_number_obj_handlers.free_obj = bcmath_number_free; bcmath_number_obj_handlers.clone_obj = bcmath_number_clone; bcmath_number_obj_handlers.do_operation = bcmath_number_do_operation; diff --git a/ext/curl/curl_private.h b/ext/curl/curl_private.h index 7058e9df9241..f097e1118f00 100644 --- a/ext/curl/curl_private.h +++ b/ext/curl/curl_private.h @@ -152,13 +152,13 @@ void _php_setup_easy_copy_handlers(php_curl *ch, php_curl *source); zend_long php_curl_get_long(zval *zv); static inline php_curl *curl_from_obj(zend_object *obj) { - return (php_curl *)((char *)(obj) - XtOffsetOf(php_curl, std)); + return (php_curl *)((char *)(obj) - offsetof(php_curl, std)); } #define Z_CURL_P(zv) curl_from_obj(Z_OBJ_P(zv)) static inline php_curlsh *curl_share_from_obj(zend_object *obj) { - return (php_curlsh *)((char *)(obj) - XtOffsetOf(php_curlsh, std)); + return (php_curlsh *)((char *)(obj) - offsetof(php_curlsh, std)); } #define Z_CURL_SHARE_P(zv) curl_share_from_obj(Z_OBJ_P(zv)) diff --git a/ext/curl/interface.c b/ext/curl/interface.c index 33f8cebd5a6c..ed544866a886 100644 --- a/ext/curl/interface.c +++ b/ext/curl/interface.c @@ -357,7 +357,7 @@ PHP_MINIT_FUNCTION(curl) curl_ce->default_object_handlers = &curl_object_handlers; memcpy(&curl_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - curl_object_handlers.offset = XtOffsetOf(php_curl, std); + curl_object_handlers.offset = offsetof(php_curl, std); curl_object_handlers.free_obj = curl_free_obj; curl_object_handlers.get_gc = curl_get_gc; curl_object_handlers.get_constructor = curl_get_constructor; diff --git a/ext/curl/multi.c b/ext/curl/multi.c index 98a5e62b5564..2994c992a7af 100644 --- a/ext/curl/multi.c +++ b/ext/curl/multi.c @@ -49,7 +49,7 @@ zend_class_entry *curl_multi_ce; static inline php_curlm *curl_multi_from_obj(zend_object *obj) { - return (php_curlm *)((char *)(obj) - XtOffsetOf(php_curlm, std)); + return (php_curlm *)((char *)(obj) - offsetof(php_curlm, std)); } #define Z_CURL_MULTI_P(zv) curl_multi_from_obj(Z_OBJ_P(zv)) @@ -605,7 +605,7 @@ void curl_multi_register_handlers(void) { curl_multi_ce->default_object_handlers = &curl_multi_handlers; memcpy(&curl_multi_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - curl_multi_handlers.offset = XtOffsetOf(php_curlm, std); + curl_multi_handlers.offset = offsetof(php_curlm, std); curl_multi_handlers.free_obj = curl_multi_free_obj; curl_multi_handlers.get_gc = curl_multi_get_gc; curl_multi_handlers.get_constructor = curl_multi_get_constructor; diff --git a/ext/curl/share.c b/ext/curl/share.c index bfd12238eec1..56cd804658a4 100644 --- a/ext/curl/share.c +++ b/ext/curl/share.c @@ -303,7 +303,7 @@ void curl_share_register_handlers(void) { curl_share_ce->default_object_handlers = &curl_share_handlers; memcpy(&curl_share_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - curl_share_handlers.offset = XtOffsetOf(php_curlsh, std); + curl_share_handlers.offset = offsetof(php_curlsh, std); curl_share_handlers.free_obj = curl_share_free_obj; curl_share_handlers.get_constructor = curl_share_get_constructor; curl_share_handlers.clone_obj = NULL; @@ -324,7 +324,7 @@ void curl_share_persistent_register_handlers(void) { curl_share_persistent_ce->default_object_handlers = &curl_share_persistent_handlers; memcpy(&curl_share_persistent_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - curl_share_persistent_handlers.offset = XtOffsetOf(php_curlsh, std); + curl_share_persistent_handlers.offset = offsetof(php_curlsh, std); curl_share_persistent_handlers.get_constructor = curl_share_persistent_get_constructor; curl_share_persistent_handlers.clone_obj = NULL; curl_share_persistent_handlers.compare = zend_objects_not_comparable; diff --git a/ext/date/php_date.c b/ext/date/php_date.c index 6c5dc29627d4..18ac305e8430 100644 --- a/ext/date/php_date.c +++ b/ext/date/php_date.c @@ -1754,7 +1754,7 @@ static void date_register_classes(void) /* {{{ */ date_ce_date->create_object = date_object_new_date; date_ce_date->default_object_handlers = &date_object_handlers_date; memcpy(&date_object_handlers_date, &std_object_handlers, sizeof(zend_object_handlers)); - date_object_handlers_date.offset = XtOffsetOf(php_date_obj, std); + date_object_handlers_date.offset = offsetof(php_date_obj, std); date_object_handlers_date.free_obj = date_object_free_storage_date; date_object_handlers_date.clone_obj = date_object_clone_date; date_object_handlers_date.compare = date_object_compare_date; @@ -1774,7 +1774,7 @@ static void date_register_classes(void) /* {{{ */ date_ce_timezone->create_object = date_object_new_timezone; date_ce_timezone->default_object_handlers = &date_object_handlers_timezone; memcpy(&date_object_handlers_timezone, &std_object_handlers, sizeof(zend_object_handlers)); - date_object_handlers_timezone.offset = XtOffsetOf(php_timezone_obj, std); + date_object_handlers_timezone.offset = offsetof(php_timezone_obj, std); date_object_handlers_timezone.free_obj = date_object_free_storage_timezone; date_object_handlers_timezone.clone_obj = date_object_clone_timezone; date_object_handlers_timezone.get_properties_for = date_object_get_properties_for_timezone; @@ -1786,7 +1786,7 @@ static void date_register_classes(void) /* {{{ */ date_ce_interval->create_object = date_object_new_interval; date_ce_interval->default_object_handlers = &date_object_handlers_interval; memcpy(&date_object_handlers_interval, &std_object_handlers, sizeof(zend_object_handlers)); - date_object_handlers_interval.offset = XtOffsetOf(php_interval_obj, std); + date_object_handlers_interval.offset = offsetof(php_interval_obj, std); date_object_handlers_interval.free_obj = date_object_free_storage_interval; date_object_handlers_interval.clone_obj = date_object_clone_interval; date_object_handlers_interval.has_property = date_interval_has_property; @@ -1802,7 +1802,7 @@ static void date_register_classes(void) /* {{{ */ date_ce_period->default_object_handlers = &date_object_handlers_period; date_ce_period->get_iterator = date_object_period_get_iterator; memcpy(&date_object_handlers_period, &std_object_handlers, sizeof(zend_object_handlers)); - date_object_handlers_period.offset = XtOffsetOf(php_period_obj, std); + date_object_handlers_period.offset = offsetof(php_period_obj, std); date_object_handlers_period.free_obj = date_object_free_storage_period; date_object_handlers_period.clone_obj = date_object_clone_period; date_object_handlers_period.get_gc = date_object_get_gc_period; diff --git a/ext/date/php_date.h b/ext/date/php_date.h index 4553d3e93c72..d480283643db 100644 --- a/ext/date/php_date.h +++ b/ext/date/php_date.h @@ -59,7 +59,7 @@ struct _php_date_obj { }; static inline php_date_obj *php_date_obj_from_obj(zend_object *obj) { - return (php_date_obj*)((char*)(obj) - XtOffsetOf(php_date_obj, std)); + return (php_date_obj*)((char*)(obj) - offsetof(php_date_obj, std)); } #define Z_PHPDATE_P(zv) php_date_obj_from_obj(Z_OBJ_P((zv))) @@ -76,7 +76,7 @@ struct _php_timezone_obj { }; static inline php_timezone_obj *php_timezone_obj_from_obj(zend_object *obj) { - return (php_timezone_obj*)((char*)(obj) - XtOffsetOf(php_timezone_obj, std)); + return (php_timezone_obj*)((char*)(obj) - offsetof(php_timezone_obj, std)); } #define Z_PHPTIMEZONE_P(zv) php_timezone_obj_from_obj(Z_OBJ_P((zv))) @@ -94,7 +94,7 @@ struct _php_interval_obj { }; static inline php_interval_obj *php_interval_obj_from_obj(zend_object *obj) { - return (php_interval_obj*)((char*)(obj) - XtOffsetOf(php_interval_obj, std)); + return (php_interval_obj*)((char*)(obj) - offsetof(php_interval_obj, std)); } #define Z_PHPINTERVAL_P(zv) php_interval_obj_from_obj(Z_OBJ_P((zv))) @@ -113,7 +113,7 @@ struct _php_period_obj { }; static inline php_period_obj *php_period_obj_from_obj(zend_object *obj) { - return (php_period_obj*)((char*)(obj) - XtOffsetOf(php_period_obj, std)); + return (php_period_obj*)((char*)(obj) - offsetof(php_period_obj, std)); } #define Z_PHPPERIOD_P(zv) php_period_obj_from_obj(Z_OBJ_P((zv))) diff --git a/ext/dba/dba.c b/ext/dba/dba.c index a70951467be5..07123d0e301f 100644 --- a/ext/dba/dba.c +++ b/ext/dba/dba.c @@ -337,7 +337,7 @@ static zend_result dba_connection_cast_object(zend_object *obj, zval *result, in static inline dba_connection *dba_connection_from_obj(zend_object *obj) { - return (dba_connection *)((char *)(obj) - XtOffsetOf(dba_connection, std)); + return (dba_connection *)((char *)(obj) - offsetof(dba_connection, std)); } #define Z_DBA_CONNECTION_P(zv) dba_connection_from_obj(Z_OBJ_P(zv)) @@ -409,7 +409,7 @@ PHP_MINIT_FUNCTION(dba) dba_connection_ce->default_object_handlers = &dba_connection_object_handlers; memcpy(&dba_connection_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - dba_connection_object_handlers.offset = XtOffsetOf(dba_connection, std); + dba_connection_object_handlers.offset = offsetof(dba_connection, std); dba_connection_object_handlers.free_obj = dba_connection_free_obj; dba_connection_object_handlers.get_constructor = dba_connection_get_constructor; dba_connection_object_handlers.clone_obj = NULL; diff --git a/ext/dom/namespace_compat.c b/ext/dom/namespace_compat.c index 569daabc78ea..377abbd01dc7 100644 --- a/ext/dom/namespace_compat.c +++ b/ext/dom/namespace_compat.c @@ -59,7 +59,7 @@ static HashTable *php_dom_libxml_ns_mapper_ensure_prefix_map(php_dom_libxml_ns_m zend_hash_add_new(&mapper->uri_to_prefix_map, *uri, &zv_prefix_map); } else { /* cast to Bucket* only works if this holds, I would prefer a static assert but we're stuck at C99. */ - ZEND_ASSERT(XtOffsetOf(Bucket, val) == 0); + ZEND_ASSERT(offsetof(Bucket, val) == 0); ZEND_ASSERT(Z_TYPE_P(zv) == IS_ARRAY); Bucket *bucket = (Bucket *) zv; /* Make sure we take the value from the key string that lives long enough. */ diff --git a/ext/dom/php_dom.c b/ext/dom/php_dom.c index ec1a2ea1c6cf..eccbe4ed2984 100644 --- a/ext/dom/php_dom.c +++ b/ext/dom/php_dom.c @@ -792,7 +792,7 @@ HashTable *dom_xpath_get_gc(zend_object *object, zval **table, int *n); PHP_MINIT_FUNCTION(dom) { memcpy(&dom_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - dom_object_handlers.offset = XtOffsetOf(dom_object, std); + dom_object_handlers.offset = offsetof(dom_object, std); dom_object_handlers.free_obj = dom_objects_free_storage; dom_object_handlers.read_property = dom_read_property; dom_object_handlers.write_property = dom_write_property; @@ -837,12 +837,12 @@ PHP_MINIT_FUNCTION(dom) dom_html_collection_object_handlers.get_gc = dom_html_collection_get_gc; memcpy(&dom_object_namespace_node_handlers, &dom_object_handlers, sizeof(zend_object_handlers)); - dom_object_namespace_node_handlers.offset = XtOffsetOf(dom_object_namespace_node, dom.std); + dom_object_namespace_node_handlers.offset = offsetof(dom_object_namespace_node, dom.std); dom_object_namespace_node_handlers.free_obj = dom_object_namespace_node_free_storage; dom_object_namespace_node_handlers.clone_obj = dom_object_namespace_node_clone_obj; memcpy(&dom_token_list_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers)); - dom_token_list_object_handlers.offset = XtOffsetOf(dom_token_list_object, dom.std); + dom_token_list_object_handlers.offset = offsetof(dom_token_list_object, dom.std); dom_token_list_object_handlers.free_obj = dom_token_list_free_obj; /* The Web IDL (Web Interface Description Language - https://webidl.spec.whatwg.org) has the [SameObject] constraint * for this object, which is incompatible with cloning because it imposes that there is only one instance @@ -1333,7 +1333,7 @@ PHP_MINIT_FUNCTION(dom) #ifdef LIBXML_XPATH_ENABLED memcpy(&dom_xpath_object_handlers, &dom_object_handlers, sizeof(zend_object_handlers)); - dom_xpath_object_handlers.offset = XtOffsetOf(dom_xpath_object, dom) + XtOffsetOf(dom_object, std); + dom_xpath_object_handlers.offset = offsetof(dom_xpath_object, dom) + offsetof(dom_object, std); dom_xpath_object_handlers.free_obj = dom_xpath_objects_free_storage; dom_xpath_object_handlers.get_gc = dom_xpath_get_gc; dom_xpath_object_handlers.clone_obj = NULL; @@ -1570,7 +1570,7 @@ zend_object *dom_xpath_objects_new(zend_class_entry *class_type) /* The char pointer MUST refer to the char* of a zend_string struct */ static void dom_zend_string_release_from_char_pointer(xmlChar *ptr) { - zend_string_release((zend_string*) (ptr - XtOffsetOf(zend_string, val))); + zend_string_release((zend_string*) (ptr - offsetof(zend_string, val))); } void dom_nnodemap_objects_free_storage(zend_object *object) /* {{{ */ diff --git a/ext/dom/php_dom.h b/ext/dom/php_dom.h index d424b26cc694..2cb306f1f5d1 100644 --- a/ext/dom/php_dom.h +++ b/ext/dom/php_dom.h @@ -68,7 +68,7 @@ typedef struct dom_xpath_object { static inline dom_xpath_object *php_xpath_obj_from_obj(zend_object *obj) { return (dom_xpath_object*)((char*)(obj) - - XtOffsetOf(dom_xpath_object, dom) - XtOffsetOf(dom_object, std)); + - offsetof(dom_xpath_object, dom) - offsetof(dom_object, std)); } #define Z_XPATHOBJ_P(zv) php_xpath_obj_from_obj(Z_OBJ_P((zv))) @@ -94,7 +94,7 @@ struct php_dom_libxml_ns_mapper; typedef struct php_dom_libxml_ns_mapper php_dom_libxml_ns_mapper; static inline dom_object_namespace_node *php_dom_namespace_node_obj_from_obj(zend_object *obj) { - return (dom_object_namespace_node*)((char*)(obj) - XtOffsetOf(dom_object_namespace_node, dom.std)); + return (dom_object_namespace_node*)((char*)(obj) - offsetof(dom_object_namespace_node, dom.std)); } #include "domexception.h" diff --git a/ext/dom/token_list.c b/ext/dom/token_list.c index 28dfc695ddc7..de449465b768 100644 --- a/ext/dom/token_list.c +++ b/ext/dom/token_list.c @@ -575,7 +575,7 @@ PHP_METHOD(Dom_TokenList, toggle) HashTable *token_set = TOKEN_LIST_GET_SET(intern); zval *found_token = zend_hash_find(token_set, token); if (found_token != NULL) { - ZEND_ASSERT(XtOffsetOf(Bucket, val) == 0 && "the cast only works if this is true"); + ZEND_ASSERT(offsetof(Bucket, val) == 0 && "the cast only works if this is true"); Bucket *bucket = (Bucket *) found_token; /* 3.1. If force is either not given or is false, then remove token from this’s token set, @@ -625,7 +625,7 @@ PHP_METHOD(Dom_TokenList, replace) } /* 4. Replace token in this’s token set with newToken. */ - ZEND_ASSERT(XtOffsetOf(Bucket, val) == 0 && "the cast only works if this is true"); + ZEND_ASSERT(offsetof(Bucket, val) == 0 && "the cast only works if this is true"); Bucket *bucket = (Bucket *) found_token; if (zend_hash_set_bucket_key(token_set, bucket, new_token) == NULL) { /* It already exists, remove token instead. */ diff --git a/ext/dom/token_list.h b/ext/dom/token_list.h index d5eb071f1882..cf44f5016b82 100644 --- a/ext/dom/token_list.h +++ b/ext/dom/token_list.h @@ -25,12 +25,12 @@ typedef struct dom_token_list_object { static inline dom_token_list_object *php_dom_token_list_from_obj(zend_object *obj) { - return (dom_token_list_object *)((char *) obj - XtOffsetOf(dom_token_list_object, dom.std)); + return (dom_token_list_object *)((char *) obj - offsetof(dom_token_list_object, dom.std)); } static inline dom_token_list_object *php_dom_token_list_from_dom_obj(dom_object *obj) { - return (dom_token_list_object *)((char *) obj - XtOffsetOf(dom_token_list_object, dom)); + return (dom_token_list_object *)((char *) obj - offsetof(dom_token_list_object, dom)); } void dom_ordered_set_parser(HashTable *token_set, const char *position, bool to_lowercase); diff --git a/ext/dom/xml_common.h b/ext/dom/xml_common.h index 419886bae4f7..c1e283b3f3d9 100644 --- a/ext/dom/xml_common.h +++ b/ext/dom/xml_common.h @@ -28,7 +28,7 @@ typedef struct _dom_object { } dom_object; static inline dom_object *php_dom_obj_from_obj(zend_object *obj) { - return (dom_object*)((char*)(obj) - XtOffsetOf(dom_object, std)); + return (dom_object*)((char*)(obj) - offsetof(dom_object, std)); } #define Z_DOMOBJ_P(zv) php_dom_obj_from_obj(Z_OBJ_P((zv))) diff --git a/ext/dom/xpath.c b/ext/dom/xpath.c index 012fa9789e0d..a06583d5d087 100644 --- a/ext/dom/xpath.c +++ b/ext/dom/xpath.c @@ -189,7 +189,7 @@ zend_result dom_xpath_document_read(dom_object *obj, zval *retval) /* {{{ registerNodeNamespaces bool*/ static inline dom_xpath_object *php_xpath_obj_from_dom_obj(dom_object *obj) { - return (dom_xpath_object*)((char*)(obj) - XtOffsetOf(dom_xpath_object, dom)); + return (dom_xpath_object*)((char*)(obj) - offsetof(dom_xpath_object, dom)); } zend_result dom_xpath_register_node_ns_read(dom_object *obj, zval *retval) diff --git a/ext/enchant/enchant.c b/ext/enchant/enchant.c index 3c09be9077b0..99c2cc74f6f1 100644 --- a/ext/enchant/enchant.c +++ b/ext/enchant/enchant.c @@ -49,7 +49,7 @@ zend_class_entry *enchant_broker_ce; static zend_object_handlers enchant_broker_handlers; static inline enchant_broker *enchant_broker_from_obj(zend_object *obj) { - return (enchant_broker *)((char *)(obj) - XtOffsetOf(enchant_broker, std)); + return (enchant_broker *)((char *)(obj) - offsetof(enchant_broker, std)); } #define Z_ENCHANT_BROKER_P(zv) enchant_broker_from_obj(Z_OBJ_P(zv)) @@ -67,7 +67,7 @@ zend_class_entry *enchant_dict_ce; static zend_object_handlers enchant_dict_handlers; static inline enchant_dict *enchant_dict_from_obj(zend_object *obj) { - return (enchant_dict *)((char *)(obj) - XtOffsetOf(enchant_dict, std)); + return (enchant_dict *)((char *)(obj) - offsetof(enchant_dict, std)); } #define Z_ENCHANT_DICT_P(zv) enchant_dict_from_obj(Z_OBJ_P(zv)) @@ -190,7 +190,7 @@ PHP_MINIT_FUNCTION(enchant) enchant_broker_ce->default_object_handlers = &enchant_broker_handlers; memcpy(&enchant_broker_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - enchant_broker_handlers.offset = XtOffsetOf(enchant_broker, std); + enchant_broker_handlers.offset = offsetof(enchant_broker, std); enchant_broker_handlers.free_obj = php_enchant_broker_free; enchant_broker_handlers.clone_obj = NULL; enchant_broker_handlers.compare = zend_objects_not_comparable; @@ -200,7 +200,7 @@ PHP_MINIT_FUNCTION(enchant) enchant_dict_ce->default_object_handlers = &enchant_dict_handlers; memcpy(&enchant_dict_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - enchant_dict_handlers.offset = XtOffsetOf(enchant_dict, std); + enchant_dict_handlers.offset = offsetof(enchant_dict, std); enchant_dict_handlers.free_obj = php_enchant_dict_free; enchant_dict_handlers.clone_obj = NULL; enchant_dict_handlers.compare = zend_objects_not_comparable; diff --git a/ext/fileinfo/fileinfo.c b/ext/fileinfo/fileinfo.c index 6aa4520ffcc8..972529100d7e 100644 --- a/ext/fileinfo/fileinfo.c +++ b/ext/fileinfo/fileinfo.c @@ -44,7 +44,7 @@ typedef struct _finfo_object { } finfo_object; static inline finfo_object *php_finfo_fetch_object(zend_object *obj) { - return (finfo_object *)((char*)(obj) - XtOffsetOf(finfo_object, zo)); + return (finfo_object *)((char*)(obj) - offsetof(finfo_object, zo)); } #define Z_FINFO_P(zv) php_finfo_fetch_object(Z_OBJ_P((zv))) @@ -82,7 +82,7 @@ PHP_MINIT_FUNCTION(finfo) /* copy the standard object handlers to you handler table */ memcpy(&finfo_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - finfo_object_handlers.offset = XtOffsetOf(finfo_object, zo); + finfo_object_handlers.offset = offsetof(finfo_object, zo); finfo_object_handlers.free_obj = finfo_objects_free; finfo_object_handlers.clone_obj = NULL; diff --git a/ext/ftp/php_ftp.c b/ext/ftp/php_ftp.c index 8285f36a5628..501ce9bc68d7 100644 --- a/ext/ftp/php_ftp.c +++ b/ext/ftp/php_ftp.c @@ -99,7 +99,7 @@ PHP_MINIT_FUNCTION(ftp) php_ftp_ce->create_object = ftp_object_create; memcpy(&ftp_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - ftp_object_handlers.offset = XtOffsetOf(php_ftp_object, std); + ftp_object_handlers.offset = offsetof(php_ftp_object, std); ftp_object_handlers.get_constructor = ftp_object_get_constructor; ftp_object_handlers.free_obj = ftp_object_destroy; ftp_object_handlers.clone_obj = NULL; diff --git a/ext/gd/gd.c b/ext/gd/gd.c index c0cf361be055..343dd127378d 100644 --- a/ext/gd/gd.c +++ b/ext/gd/gd.c @@ -150,7 +150,7 @@ static zend_function *php_gd_image_object_get_constructor(zend_object *object) static zend_always_inline php_gd_image_object* php_gd_exgdimage_from_zobj_p(zend_object* obj) { - return (php_gd_image_object *) ((char *) (obj) - XtOffsetOf(php_gd_image_object, std)); + return (php_gd_image_object *) ((char *) (obj) - offsetof(php_gd_image_object, std)); } /** @@ -206,7 +206,7 @@ static void php_gd_object_minit_helper(void) php_gd_image_object_handlers.free_obj = php_gd_image_object_free; php_gd_image_object_handlers.get_constructor = php_gd_image_object_get_constructor; php_gd_image_object_handlers.compare = zend_objects_not_comparable; - php_gd_image_object_handlers.offset = XtOffsetOf(php_gd_image_object, std); + php_gd_image_object_handlers.offset = offsetof(php_gd_image_object, std); } static zend_class_entry *gd_font_ce = NULL; @@ -271,7 +271,7 @@ static void php_gd_font_minit_helper(void) php_gd_font_object_handlers.clone_obj = NULL; php_gd_font_object_handlers.free_obj = php_gd_font_object_free; php_gd_font_object_handlers.get_constructor = php_gd_font_object_get_constructor; - php_gd_font_object_handlers.offset = XtOffsetOf(php_gd_font_object, std); + php_gd_font_object_handlers.offset = offsetof(php_gd_font_object, std); } /********************************************************* diff --git a/ext/gmp/gmp.c b/ext/gmp/gmp.c index b04fc9f5c1ba..6fa1fe7dd899 100644 --- a/ext/gmp/gmp.c +++ b/ext/gmp/gmp.c @@ -586,7 +586,7 @@ ZEND_MINIT_FUNCTION(gmp) gmp_ce->unserialize = gmp_unserialize; memcpy(&gmp_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - gmp_object_handlers.offset = XtOffsetOf(gmp_object, std); + gmp_object_handlers.offset = offsetof(gmp_object, std); gmp_object_handlers.free_obj = gmp_free_object_storage; gmp_object_handlers.cast_object = gmp_cast_object; gmp_object_handlers.get_debug_info = gmp_get_debug_info; diff --git a/ext/gmp/php_gmp_int.h b/ext/gmp/php_gmp_int.h index d6d0a6163ac4..98f0ddbc63bb 100644 --- a/ext/gmp/php_gmp_int.h +++ b/ext/gmp/php_gmp_int.h @@ -36,7 +36,7 @@ typedef struct _gmp_object { } gmp_object; static inline gmp_object *php_gmp_object_from_zend_object(zend_object *zobj) { - return (gmp_object *)( ((char *)zobj) - XtOffsetOf(gmp_object, std) ); + return (gmp_object *)( ((char *)zobj) - offsetof(gmp_object, std) ); } PHP_GMP_API zend_class_entry *php_gmp_class_entry(void); diff --git a/ext/hash/hash.c b/ext/hash/hash.c index 0f7d24275722..248f5ba8b0e3 100644 --- a/ext/hash/hash.c +++ b/ext/hash/hash.c @@ -1652,7 +1652,7 @@ PHP_MINIT_FUNCTION(hash) memcpy(&php_hashcontext_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - php_hashcontext_handlers.offset = XtOffsetOf(php_hashcontext_object, std); + php_hashcontext_handlers.offset = offsetof(php_hashcontext_object, std); php_hashcontext_handlers.free_obj = php_hashcontext_free; php_hashcontext_handlers.clone_obj = php_hashcontext_clone; diff --git a/ext/intl/breakiterator/breakiterator_class.cpp b/ext/intl/breakiterator/breakiterator_class.cpp index 901ed1015536..7b6a59d839fc 100644 --- a/ext/intl/breakiterator/breakiterator_class.cpp +++ b/ext/intl/breakiterator/breakiterator_class.cpp @@ -212,7 +212,7 @@ U_CFUNC void breakiterator_register_BreakIterator_class(void) memcpy(&BreakIterator_handlers, &std_object_handlers, sizeof BreakIterator_handlers); - BreakIterator_handlers.offset = XtOffsetOf(BreakIterator_object, zo); + BreakIterator_handlers.offset = offsetof(BreakIterator_object, zo); BreakIterator_handlers.compare = BreakIterator_compare_objects; BreakIterator_handlers.clone_obj = BreakIterator_clone_obj; BreakIterator_handlers.get_debug_info = BreakIterator_get_debug_info; diff --git a/ext/intl/breakiterator/breakiterator_class.h b/ext/intl/breakiterator/breakiterator_class.h index 96d8bba626e2..e7a80c0aaae9 100644 --- a/ext/intl/breakiterator/breakiterator_class.h +++ b/ext/intl/breakiterator/breakiterator_class.h @@ -42,7 +42,7 @@ typedef struct { } BreakIterator_object; static inline BreakIterator_object *php_intl_breakiterator_fetch_object(zend_object *obj) { - return (BreakIterator_object *)((char*)(obj) - XtOffsetOf(BreakIterator_object, zo)); + return (BreakIterator_object *)((char*)(obj) - offsetof(BreakIterator_object, zo)); } #define Z_INTL_BREAKITERATOR_P(zv) php_intl_breakiterator_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/calendar/calendar_class.cpp b/ext/intl/calendar/calendar_class.cpp index d09f04454790..9ec9e617cb4d 100644 --- a/ext/intl/calendar/calendar_class.cpp +++ b/ext/intl/calendar/calendar_class.cpp @@ -256,7 +256,7 @@ void calendar_register_IntlCalendar_class(void) memcpy( &Calendar_handlers, &std_object_handlers, sizeof Calendar_handlers); - Calendar_handlers.offset = XtOffsetOf(Calendar_object, zo); + Calendar_handlers.offset = offsetof(Calendar_object, zo); Calendar_handlers.clone_obj = Calendar_clone_obj; Calendar_handlers.get_debug_info = Calendar_get_debug_info; Calendar_handlers.free_obj = Calendar_objects_free; diff --git a/ext/intl/calendar/calendar_class.h b/ext/intl/calendar/calendar_class.h index 540646ba3049..b60777d7557b 100644 --- a/ext/intl/calendar/calendar_class.h +++ b/ext/intl/calendar/calendar_class.h @@ -39,7 +39,7 @@ typedef struct { } Calendar_object; static inline Calendar_object *php_intl_calendar_fetch_object(zend_object *obj) { - return (Calendar_object *)((char*)(obj) - XtOffsetOf(Calendar_object, zo)); + return (Calendar_object *)((char*)(obj) - offsetof(Calendar_object, zo)); } #define Z_INTL_CALENDAR_P(zv) php_intl_calendar_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/collator/collator_class.cpp b/ext/intl/collator/collator_class.cpp index 33c25845a864..4fd991bd156c 100644 --- a/ext/intl/collator/collator_class.cpp +++ b/ext/intl/collator/collator_class.cpp @@ -76,7 +76,7 @@ U_CFUNC void collator_register_Collator_symbols(int module_number) sizeof Collator_handlers); /* Collator has no usable clone semantics - ucol_cloneBinary/ucol_openBinary require binary buffer for which we don't have the place to keep */ - Collator_handlers.offset = XtOffsetOf(Collator_object, zo); + Collator_handlers.offset = offsetof(Collator_object, zo); Collator_handlers.clone_obj = nullptr; Collator_handlers.free_obj = Collator_objects_free; } diff --git a/ext/intl/collator/collator_class.h b/ext/intl/collator/collator_class.h index af564f31e51b..abbe4fe93ebf 100644 --- a/ext/intl/collator/collator_class.h +++ b/ext/intl/collator/collator_class.h @@ -48,7 +48,7 @@ typedef struct { #define COLLATOR_ERROR_CODE_P(co) &(INTL_ERROR_CODE(COLLATOR_ERROR(co))) static inline Collator_object *php_intl_collator_fetch_object(zend_object *obj) { - return (Collator_object *)((char*)(obj) - XtOffsetOf(Collator_object, zo)); + return (Collator_object *)((char*)(obj) - offsetof(Collator_object, zo)); } #define Z_INTL_COLLATOR_P(zv) php_intl_collator_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/common/common_enum.cpp b/ext/intl/common/common_enum.cpp index 114dabdcc00a..379561866941 100644 --- a/ext/intl/common/common_enum.cpp +++ b/ext/intl/common/common_enum.cpp @@ -294,7 +294,7 @@ U_CFUNC void intl_register_common_symbols(int module_number) memcpy(&IntlIterator_handlers, &std_object_handlers, sizeof IntlIterator_handlers); - IntlIterator_handlers.offset = XtOffsetOf(IntlIterator_object, zo); + IntlIterator_handlers.offset = offsetof(IntlIterator_object, zo); IntlIterator_handlers.clone_obj = NULL; IntlIterator_handlers.dtor_obj = IntlIterator_objects_dtor; IntlIterator_handlers.free_obj = IntlIterator_objects_free; diff --git a/ext/intl/common/common_enum.h b/ext/intl/common/common_enum.h index 5c1f7495762f..e32fc78a2782 100644 --- a/ext/intl/common/common_enum.h +++ b/ext/intl/common/common_enum.h @@ -53,7 +53,7 @@ typedef struct { static inline IntlIterator_object *php_intl_iterator_fetch_object(zend_object *obj) { - return (IntlIterator_object *)((char*)(obj) - XtOffsetOf(IntlIterator_object, zo)); + return (IntlIterator_object *)((char*)(obj) - offsetof(IntlIterator_object, zo)); } #define Z_INTL_ITERATOR_P(zv) php_intl_iterator_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/converter/converter.cpp b/ext/intl/converter/converter.cpp index 8921728fc9d7..051f3ca8bd3a 100644 --- a/ext/intl/converter/converter.cpp +++ b/ext/intl/converter/converter.cpp @@ -37,7 +37,7 @@ typedef struct _php_converter_object { static inline php_converter_object *php_converter_fetch_object(zend_object *obj) { - return (php_converter_object *)((char*)(obj) - XtOffsetOf(php_converter_object, obj)); + return (php_converter_object *)((char*)(obj) - offsetof(php_converter_object, obj)); } #define Z_INTL_CONVERTER_P(zv) php_converter_fetch_object(Z_OBJ_P(zv)) @@ -975,7 +975,7 @@ U_CFUNC int php_converter_minit(INIT_FUNC_ARGS) { php_converter_ce->create_object = php_converter_create_object; php_converter_ce->default_object_handlers = &php_converter_object_handlers; memcpy(&php_converter_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - php_converter_object_handlers.offset = XtOffsetOf(php_converter_object, obj); + php_converter_object_handlers.offset = offsetof(php_converter_object, obj); php_converter_object_handlers.clone_obj = php_converter_clone_object; php_converter_object_handlers.free_obj = php_converter_free_object; diff --git a/ext/intl/dateformat/dateformat_class.cpp b/ext/intl/dateformat/dateformat_class.cpp index 03f2bc9a2d6a..2ee2c4540305 100644 --- a/ext/intl/dateformat/dateformat_class.cpp +++ b/ext/intl/dateformat/dateformat_class.cpp @@ -104,7 +104,7 @@ void dateformat_register_IntlDateFormatter_class( void ) memcpy(&IntlDateFormatter_handlers, &std_object_handlers, sizeof IntlDateFormatter_handlers); - IntlDateFormatter_handlers.offset = XtOffsetOf(IntlDateFormatter_object, zo); + IntlDateFormatter_handlers.offset = offsetof(IntlDateFormatter_object, zo); IntlDateFormatter_handlers.clone_obj = IntlDateFormatter_object_clone; IntlDateFormatter_handlers.free_obj = IntlDateFormatter_object_free; } diff --git a/ext/intl/dateformat/dateformat_class.h b/ext/intl/dateformat/dateformat_class.h index 458313a92502..ac3d5b4e291f 100644 --- a/ext/intl/dateformat/dateformat_class.h +++ b/ext/intl/dateformat/dateformat_class.h @@ -37,7 +37,7 @@ typedef struct { } IntlDateFormatter_object; static inline IntlDateFormatter_object *php_intl_dateformatter_fetch_object(zend_object *obj) { - return (IntlDateFormatter_object *)((char*)(obj) - XtOffsetOf(IntlDateFormatter_object, zo)); + return (IntlDateFormatter_object *)((char*)(obj) - offsetof(IntlDateFormatter_object, zo)); } #define Z_INTL_DATEFORMATTER_P(zv) php_intl_dateformatter_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/dateformat/datepatterngenerator_class.cpp b/ext/intl/dateformat/datepatterngenerator_class.cpp index 6a218fab72ff..b58dc38ce82e 100644 --- a/ext/intl/dateformat/datepatterngenerator_class.cpp +++ b/ext/intl/dateformat/datepatterngenerator_class.cpp @@ -106,7 +106,7 @@ void dateformat_register_IntlDatePatternGenerator_class( void ) memcpy(&IntlDatePatternGenerator_handlers, &std_object_handlers, sizeof IntlDatePatternGenerator_handlers); - IntlDatePatternGenerator_handlers.offset = XtOffsetOf(IntlDatePatternGenerator_object, zo); + IntlDatePatternGenerator_handlers.offset = offsetof(IntlDatePatternGenerator_object, zo); IntlDatePatternGenerator_handlers.clone_obj = IntlDatePatternGenerator_object_clone; IntlDatePatternGenerator_handlers.free_obj = IntlDatePatternGenerator_object_free; } diff --git a/ext/intl/dateformat/datepatterngenerator_class.h b/ext/intl/dateformat/datepatterngenerator_class.h index 017bea2cca07..c6132a032f3f 100644 --- a/ext/intl/dateformat/datepatterngenerator_class.h +++ b/ext/intl/dateformat/datepatterngenerator_class.h @@ -37,7 +37,7 @@ typedef struct { } IntlDatePatternGenerator_object; static inline IntlDatePatternGenerator_object *php_intl_datepatterngenerator_fetch_object(zend_object *obj) { - return (IntlDatePatternGenerator_object *)((char*)(obj) - XtOffsetOf(IntlDatePatternGenerator_object, zo)); + return (IntlDatePatternGenerator_object *)((char*)(obj) - offsetof(IntlDatePatternGenerator_object, zo)); } #define Z_INTL_DATEPATTERNGENERATOR_P(zv) php_intl_datepatterngenerator_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/formatter/formatter_class.cpp b/ext/intl/formatter/formatter_class.cpp index 82843ba90911..ce367096d856 100644 --- a/ext/intl/formatter/formatter_class.cpp +++ b/ext/intl/formatter/formatter_class.cpp @@ -101,7 +101,7 @@ U_CFUNC void formatter_register_class( void ) memcpy(&NumberFormatter_handlers, &std_object_handlers, sizeof(NumberFormatter_handlers)); - NumberFormatter_handlers.offset = XtOffsetOf(NumberFormatter_object, zo); + NumberFormatter_handlers.offset = offsetof(NumberFormatter_object, zo); NumberFormatter_handlers.clone_obj = NumberFormatter_object_clone; NumberFormatter_handlers.free_obj = NumberFormatter_object_free; } diff --git a/ext/intl/formatter/formatter_class.h b/ext/intl/formatter/formatter_class.h index 1d3393fdd522..465c9edaceba 100644 --- a/ext/intl/formatter/formatter_class.h +++ b/ext/intl/formatter/formatter_class.h @@ -34,7 +34,7 @@ typedef struct { } NumberFormatter_object; static inline NumberFormatter_object *php_intl_number_format_fetch_object(zend_object *obj) { - return (NumberFormatter_object *)((char*)(obj) - XtOffsetOf(NumberFormatter_object, zo)); + return (NumberFormatter_object *)((char*)(obj) - offsetof(NumberFormatter_object, zo)); } #define Z_INTL_NUMBERFORMATTER_P(zv) php_intl_number_format_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/listformatter/listformatter_class.cpp b/ext/intl/listformatter/listformatter_class.cpp index d50374393cce..f39e86f66734 100644 --- a/ext/intl/listformatter/listformatter_class.cpp +++ b/ext/intl/listformatter/listformatter_class.cpp @@ -238,7 +238,7 @@ void listformatter_register_class(void) class_entry->create_object = listformatter_create_object; memcpy(&listformatter_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - listformatter_handlers.offset = XtOffsetOf(ListFormatter_object, zo); + listformatter_handlers.offset = offsetof(ListFormatter_object, zo); listformatter_handlers.free_obj = listformatter_free_obj; listformatter_handlers.clone_obj = nullptr; } diff --git a/ext/intl/listformatter/listformatter_class.h b/ext/intl/listformatter/listformatter_class.h index 6aa43740604e..dc40b7a8be0c 100644 --- a/ext/intl/listformatter/listformatter_class.h +++ b/ext/intl/listformatter/listformatter_class.h @@ -37,7 +37,7 @@ typedef struct { } ListFormatter_object; static inline ListFormatter_object *php_intl_listformatter_fetch_object(zend_object *obj) { - return (ListFormatter_object *)((char*)(obj) - XtOffsetOf(ListFormatter_object, zo)); + return (ListFormatter_object *)((char*)(obj) - offsetof(ListFormatter_object, zo)); } #define Z_INTL_LISTFORMATTER_P(zv) php_intl_listformatter_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/msgformat/msgformat_class.cpp b/ext/intl/msgformat/msgformat_class.cpp index 06ba7fa6fa67..ef1a3fd8ec3d 100644 --- a/ext/intl/msgformat/msgformat_class.cpp +++ b/ext/intl/msgformat/msgformat_class.cpp @@ -96,7 +96,7 @@ void msgformat_register_class( void ) memcpy(&MessageFormatter_handlers, &std_object_handlers, sizeof MessageFormatter_handlers); - MessageFormatter_handlers.offset = XtOffsetOf(MessageFormatter_object, zo); + MessageFormatter_handlers.offset = offsetof(MessageFormatter_object, zo); MessageFormatter_handlers.clone_obj = MessageFormatter_object_clone; MessageFormatter_handlers.free_obj = MessageFormatter_object_free; } diff --git a/ext/intl/msgformat/msgformat_class.h b/ext/intl/msgformat/msgformat_class.h index e80c75cf2e17..d88b95b0ba77 100644 --- a/ext/intl/msgformat/msgformat_class.h +++ b/ext/intl/msgformat/msgformat_class.h @@ -32,7 +32,7 @@ typedef struct { static inline MessageFormatter_object *php_intl_messageformatter_fetch_object(zend_object *obj) { - return (MessageFormatter_object *)((char*)(obj) - XtOffsetOf(MessageFormatter_object, zo)); + return (MessageFormatter_object *)((char*)(obj) - offsetof(MessageFormatter_object, zo)); } #define Z_INTL_MESSAGEFORMATTER_P(zv) php_intl_messageformatter_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/rangeformatter/rangeformatter_class.cpp b/ext/intl/rangeformatter/rangeformatter_class.cpp index e80e3bc02079..5a19df083167 100644 --- a/ext/intl/rangeformatter/rangeformatter_class.cpp +++ b/ext/intl/rangeformatter/rangeformatter_class.cpp @@ -219,7 +219,7 @@ void rangeformatter_register_class(void) class_entry_IntlNumberRangeFormatter->create_object = IntlNumberRangeFormatter_object_create; memcpy(&rangeformatter_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - rangeformatter_handlers.offset = XtOffsetOf(IntlNumberRangeFormatter_object, zo); + rangeformatter_handlers.offset = offsetof(IntlNumberRangeFormatter_object, zo); rangeformatter_handlers.free_obj = IntlNumberRangeFormatter_object_free; rangeformatter_handlers.clone_obj = NULL; } diff --git a/ext/intl/rangeformatter/rangeformatter_class.h b/ext/intl/rangeformatter/rangeformatter_class.h index 6e911403be3f..fefa7b6c35aa 100644 --- a/ext/intl/rangeformatter/rangeformatter_class.h +++ b/ext/intl/rangeformatter/rangeformatter_class.h @@ -37,7 +37,7 @@ typedef struct { } IntlNumberRangeFormatter_object; static inline IntlNumberRangeFormatter_object *php_intl_numberrangeformatter_fetch_object(zend_object *obj) { - return (IntlNumberRangeFormatter_object *)((char*)(obj) - XtOffsetOf(IntlNumberRangeFormatter_object, zo)); + return (IntlNumberRangeFormatter_object *)((char*)(obj) - offsetof(IntlNumberRangeFormatter_object, zo)); } #define Z_INTL_RANGEFORMATTER_P(zv) php_intl_numberrangeformatter_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/resourcebundle/resourcebundle_class.cpp b/ext/intl/resourcebundle/resourcebundle_class.cpp index b6e62f2a4d4f..43823137e605 100644 --- a/ext/intl/resourcebundle/resourcebundle_class.cpp +++ b/ext/intl/resourcebundle/resourcebundle_class.cpp @@ -424,7 +424,7 @@ U_CFUNC void resourcebundle_register_class( void ) ResourceBundle_ce_ptr->get_iterator = resourcebundle_get_iterator; ResourceBundle_object_handlers = std_object_handlers; - ResourceBundle_object_handlers.offset = XtOffsetOf(ResourceBundle_object, zend); + ResourceBundle_object_handlers.offset = offsetof(ResourceBundle_object, zend); ResourceBundle_object_handlers.clone_obj = NULL; /* ICU ResourceBundle has no clone implementation */ ResourceBundle_object_handlers.free_obj = ResourceBundle_object_free; ResourceBundle_object_handlers.read_dimension = resourcebundle_array_get; diff --git a/ext/intl/resourcebundle/resourcebundle_class.h b/ext/intl/resourcebundle/resourcebundle_class.h index f21ac5690930..2293df7b3e38 100644 --- a/ext/intl/resourcebundle/resourcebundle_class.h +++ b/ext/intl/resourcebundle/resourcebundle_class.h @@ -36,7 +36,7 @@ typedef struct { } ResourceBundle_object; static inline ResourceBundle_object *php_intl_resourcebundle_fetch_object(zend_object *obj) { - return (ResourceBundle_object *)((char*)(obj) - XtOffsetOf(ResourceBundle_object, zend)); + return (ResourceBundle_object *)((char*)(obj) - offsetof(ResourceBundle_object, zend)); } #define Z_INTL_RESOURCEBUNDLE_P(zv) php_intl_resourcebundle_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/spoofchecker/spoofchecker_class.cpp b/ext/intl/spoofchecker/spoofchecker_class.cpp index e3bc04766610..2d23aee677c6 100644 --- a/ext/intl/spoofchecker/spoofchecker_class.cpp +++ b/ext/intl/spoofchecker/spoofchecker_class.cpp @@ -98,7 +98,7 @@ U_CFUNC void spoofchecker_register_Spoofchecker_class(void) memcpy(&Spoofchecker_handlers, &std_object_handlers, sizeof Spoofchecker_handlers); - Spoofchecker_handlers.offset = XtOffsetOf(Spoofchecker_object, zo); + Spoofchecker_handlers.offset = offsetof(Spoofchecker_object, zo); Spoofchecker_handlers.clone_obj = spoofchecker_clone_obj; Spoofchecker_handlers.free_obj = Spoofchecker_objects_free; } diff --git a/ext/intl/spoofchecker/spoofchecker_class.h b/ext/intl/spoofchecker/spoofchecker_class.h index 0b0244c69528..d97ab8cff03a 100644 --- a/ext/intl/spoofchecker/spoofchecker_class.h +++ b/ext/intl/spoofchecker/spoofchecker_class.h @@ -43,7 +43,7 @@ typedef struct { } Spoofchecker_object; static inline Spoofchecker_object *php_intl_spoofchecker_fetch_object(zend_object *obj) { - return (Spoofchecker_object *)((char*)(obj) - XtOffsetOf(Spoofchecker_object, zo)); + return (Spoofchecker_object *)((char*)(obj) - offsetof(Spoofchecker_object, zo)); } #define Z_INTL_SPOOFCHECKER_P(zv) php_intl_spoofchecker_fetch_object((Z_OBJ_P(zv))) diff --git a/ext/intl/timezone/timezone_class.cpp b/ext/intl/timezone/timezone_class.cpp index cf528f1cc09d..8aad4fb2b6bd 100644 --- a/ext/intl/timezone/timezone_class.cpp +++ b/ext/intl/timezone/timezone_class.cpp @@ -357,7 +357,7 @@ U_CFUNC void timezone_register_IntlTimeZone_class(void) memcpy(&TimeZone_handlers, &std_object_handlers, sizeof TimeZone_handlers); - TimeZone_handlers.offset = XtOffsetOf(TimeZone_object, zo); + TimeZone_handlers.offset = offsetof(TimeZone_object, zo); TimeZone_handlers.clone_obj = TimeZone_clone_obj; TimeZone_handlers.compare = TimeZone_compare_objects; TimeZone_handlers.get_debug_info = TimeZone_get_debug_info; diff --git a/ext/intl/timezone/timezone_class.h b/ext/intl/timezone/timezone_class.h index d1f1c5f8fe2c..b383db558fcb 100644 --- a/ext/intl/timezone/timezone_class.h +++ b/ext/intl/timezone/timezone_class.h @@ -47,7 +47,7 @@ typedef struct { } TimeZone_object; static inline TimeZone_object *php_intl_timezone_fetch_object(zend_object *obj) { - return (TimeZone_object *)((char*)(obj) - XtOffsetOf(TimeZone_object, zo)); + return (TimeZone_object *)((char*)(obj) - offsetof(TimeZone_object, zo)); } #define Z_INTL_TIMEZONE_P(zv) php_intl_timezone_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/intl/transliterator/transliterator_class.cpp b/ext/intl/transliterator/transliterator_class.cpp index 1da1dbdab8ea..f261efb57ede 100644 --- a/ext/intl/transliterator/transliterator_class.cpp +++ b/ext/intl/transliterator/transliterator_class.cpp @@ -167,7 +167,7 @@ U_CFUNC void transliterator_register_Transliterator_class( void ) Transliterator_ce_ptr->create_object = Transliterator_object_create; Transliterator_ce_ptr->default_object_handlers = &Transliterator_handlers; memcpy( &Transliterator_handlers, &std_object_handlers, sizeof Transliterator_handlers ); - Transliterator_handlers.offset = XtOffsetOf(Transliterator_object, zo); + Transliterator_handlers.offset = offsetof(Transliterator_object, zo); Transliterator_handlers.free_obj = Transliterator_objects_free; Transliterator_handlers.clone_obj = Transliterator_clone_obj; } diff --git a/ext/intl/transliterator/transliterator_class.h b/ext/intl/transliterator/transliterator_class.h index 9d41f0ea2bbc..0268b8fa2065 100644 --- a/ext/intl/transliterator/transliterator_class.h +++ b/ext/intl/transliterator/transliterator_class.h @@ -39,7 +39,7 @@ typedef struct { } Transliterator_object; static inline Transliterator_object *php_intl_transliterator_fetch_object(zend_object *obj) { - return (Transliterator_object *)((char*)(obj) - XtOffsetOf(Transliterator_object, zo)); + return (Transliterator_object *)((char*)(obj) - offsetof(Transliterator_object, zo)); } #define Z_INTL_TRANSLITERATOR_P(zv) php_intl_transliterator_fetch_object(Z_OBJ_P(zv)) diff --git a/ext/ldap/ldap.c b/ext/ldap/ldap.c index f97761a42a2d..89bf6c2258c7 100644 --- a/ext/ldap/ldap.c +++ b/ext/ldap/ldap.c @@ -101,7 +101,7 @@ ZEND_GET_MODULE(ldap) #endif static inline ldap_linkdata *ldap_link_from_obj(zend_object *obj) { - return (ldap_linkdata *)((char *)(obj) - XtOffsetOf(ldap_linkdata, std)); + return (ldap_linkdata *)((char *)(obj) - offsetof(ldap_linkdata, std)); } #define Z_LDAP_LINK_P(zv) ldap_link_from_obj(Z_OBJ_P(zv)) @@ -148,7 +148,7 @@ static void ldap_link_free_obj(zend_object *obj) } static inline ldap_resultdata *ldap_result_from_obj(zend_object *obj) { - return (ldap_resultdata *)((char *)(obj) - XtOffsetOf(ldap_resultdata, std)); + return (ldap_resultdata *)((char *)(obj) - offsetof(ldap_resultdata, std)); } #define Z_LDAP_RESULT_P(zv) ldap_result_from_obj(Z_OBJ_P(zv)) @@ -185,7 +185,7 @@ static void ldap_result_free_obj(zend_object *obj) } static inline ldap_result_entry *ldap_result_entry_from_obj(zend_object *obj) { - return (ldap_result_entry *)((char *)(obj) - XtOffsetOf(ldap_result_entry, std)); + return (ldap_result_entry *)((char *)(obj) - offsetof(ldap_result_entry, std)); } #define Z_LDAP_RESULT_ENTRY_P(zv) ldap_result_entry_from_obj(Z_OBJ_P(zv)) @@ -271,7 +271,7 @@ static zend_string* php_ldap_try_get_ldap_value_from_zval(zval *zv) { /* The char pointer MUST refer to the char* of a zend_string struct */ static void php_ldap_zend_string_release_from_char_pointer(char *ptr) { - zend_string_release((zend_string*) (ptr - XtOffsetOf(zend_string, val))); + zend_string_release((zend_string*) (ptr - offsetof(zend_string, val))); } /* {{{ Parse controls from and to arrays */ @@ -877,7 +877,7 @@ PHP_MINIT_FUNCTION(ldap) ldap_link_ce->default_object_handlers = &ldap_link_object_handlers; memcpy(&ldap_link_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - ldap_link_object_handlers.offset = XtOffsetOf(ldap_linkdata, std); + ldap_link_object_handlers.offset = offsetof(ldap_linkdata, std); ldap_link_object_handlers.free_obj = ldap_link_free_obj; ldap_link_object_handlers.get_constructor = ldap_link_get_constructor; ldap_link_object_handlers.clone_obj = NULL; @@ -888,7 +888,7 @@ PHP_MINIT_FUNCTION(ldap) ldap_result_ce->default_object_handlers = &ldap_result_object_handlers; memcpy(&ldap_result_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - ldap_result_object_handlers.offset = XtOffsetOf(ldap_resultdata, std); + ldap_result_object_handlers.offset = offsetof(ldap_resultdata, std); ldap_result_object_handlers.free_obj = ldap_result_free_obj; ldap_result_object_handlers.get_constructor = ldap_result_get_constructor; ldap_result_object_handlers.clone_obj = NULL; @@ -899,7 +899,7 @@ PHP_MINIT_FUNCTION(ldap) ldap_result_entry_ce->default_object_handlers = &ldap_result_entry_object_handlers; memcpy(&ldap_result_entry_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - ldap_result_entry_object_handlers.offset = XtOffsetOf(ldap_result_entry, std); + ldap_result_entry_object_handlers.offset = offsetof(ldap_result_entry, std); ldap_result_entry_object_handlers.free_obj = ldap_result_entry_free_obj; ldap_result_entry_object_handlers.get_constructor = ldap_result_entry_get_constructor; ldap_result_entry_object_handlers.clone_obj = NULL; diff --git a/ext/mysqli/mysqli.c b/ext/mysqli/mysqli.c index c7d349706e45..b45e7416c773 100644 --- a/ext/mysqli/mysqli.c +++ b/ext/mysqli/mysqli.c @@ -479,7 +479,7 @@ PHP_MINIT_FUNCTION(mysqli) REGISTER_INI_ENTRIES(); memcpy(&mysqli_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - mysqli_object_handlers.offset = XtOffsetOf(mysqli_object, zo); + mysqli_object_handlers.offset = offsetof(mysqli_object, zo); mysqli_object_handlers.free_obj = mysqli_objects_free_storage; mysqli_object_handlers.clone_obj = NULL; mysqli_object_handlers.read_property = mysqli_read_property; diff --git a/ext/mysqli/php_mysqli_structs.h b/ext/mysqli/php_mysqli_structs.h index 40d3f7fcdeef..7f43bf4edf56 100644 --- a/ext/mysqli/php_mysqli_structs.h +++ b/ext/mysqli/php_mysqli_structs.h @@ -62,7 +62,7 @@ typedef struct _mysqli_object { } mysqli_object; /* extends zend_object */ static inline mysqli_object *php_mysqli_fetch_object(zend_object *obj) { - return (mysqli_object *)((char*)(obj) - XtOffsetOf(mysqli_object, zo)); + return (mysqli_object *)((char*)(obj) - offsetof(mysqli_object, zo)); } #define Z_MYSQLI_P(zv) php_mysqli_fetch_object(Z_OBJ_P((zv))) diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 95c872c293f1..2d6331b0f544 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -87,7 +87,7 @@ static void odbc_insert_new_result(odbc_connection *connection, zval *result) static inline odbc_link *odbc_link_from_obj(zend_object *obj) { - return (odbc_link *)((char *)(obj) - XtOffsetOf(odbc_link, std)); + return (odbc_link *)((char *)(obj) - offsetof(odbc_link, std)); } static int _close_pconn_with_res(zval *zv, void *p) @@ -204,7 +204,7 @@ static void odbc_connection_free_obj(zend_object *obj) static inline odbc_result *odbc_result_from_obj(zend_object *obj) { - return (odbc_result *)((char *)(obj) - XtOffsetOf(odbc_result, std)); + return (odbc_result *)((char *)(obj) - offsetof(odbc_result, std)); } static zend_object *odbc_result_create_object(zend_class_entry *class_type) @@ -507,7 +507,7 @@ PHP_MINIT_FUNCTION(odbc) odbc_connection_ce->default_object_handlers = &odbc_connection_object_handlers; memcpy(&odbc_connection_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - odbc_connection_object_handlers.offset = XtOffsetOf(odbc_link, std); + odbc_connection_object_handlers.offset = offsetof(odbc_link, std); odbc_connection_object_handlers.free_obj = odbc_connection_free_obj; odbc_connection_object_handlers.get_constructor = odbc_connection_get_constructor; odbc_connection_object_handlers.clone_obj = NULL; @@ -519,7 +519,7 @@ PHP_MINIT_FUNCTION(odbc) odbc_result_ce->default_object_handlers = &odbc_result_object_handlers; memcpy(&odbc_result_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - odbc_result_object_handlers.offset = XtOffsetOf(odbc_result, std); + odbc_result_object_handlers.offset = offsetof(odbc_result, std); odbc_result_object_handlers.free_obj = odbc_result_free_obj; odbc_result_object_handlers.get_constructor = odbc_result_get_constructor; odbc_result_object_handlers.clone_obj = NULL; diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index de52191c441a..09440b2660af 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -386,7 +386,7 @@ PHP_MINIT_FUNCTION(openssl) php_openssl_certificate_ce->default_object_handlers = &php_openssl_certificate_object_handlers; memcpy(&php_openssl_certificate_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - php_openssl_certificate_object_handlers.offset = XtOffsetOf(php_openssl_certificate_object, std); + php_openssl_certificate_object_handlers.offset = offsetof(php_openssl_certificate_object, std); php_openssl_certificate_object_handlers.free_obj = php_openssl_certificate_free_obj; php_openssl_certificate_object_handlers.get_constructor = php_openssl_certificate_get_constructor; php_openssl_certificate_object_handlers.clone_obj = NULL; @@ -397,7 +397,7 @@ PHP_MINIT_FUNCTION(openssl) php_openssl_request_ce->default_object_handlers = &php_openssl_request_object_handlers; memcpy(&php_openssl_request_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - php_openssl_request_object_handlers.offset = XtOffsetOf(php_openssl_request_object, std); + php_openssl_request_object_handlers.offset = offsetof(php_openssl_request_object, std); php_openssl_request_object_handlers.free_obj = php_openssl_request_free_obj; php_openssl_request_object_handlers.get_constructor = php_openssl_request_get_constructor; php_openssl_request_object_handlers.clone_obj = NULL; @@ -408,7 +408,7 @@ PHP_MINIT_FUNCTION(openssl) php_openssl_pkey_ce->default_object_handlers = &php_openssl_pkey_object_handlers; memcpy(&php_openssl_pkey_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - php_openssl_pkey_object_handlers.offset = XtOffsetOf(php_openssl_pkey_object, std); + php_openssl_pkey_object_handlers.offset = offsetof(php_openssl_pkey_object, std); php_openssl_pkey_object_handlers.free_obj = php_openssl_pkey_free_obj; php_openssl_pkey_object_handlers.get_constructor = php_openssl_pkey_get_constructor; php_openssl_pkey_object_handlers.clone_obj = NULL; diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index 9801f5458a76..df5ee3f7cd68 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -162,7 +162,7 @@ typedef struct _php_openssl_certificate_object { extern zend_class_entry *php_openssl_certificate_ce; static inline php_openssl_certificate_object *php_openssl_certificate_from_obj(zend_object *obj) { - return (php_openssl_certificate_object *)((char *)(obj) - XtOffsetOf(php_openssl_certificate_object, std)); + return (php_openssl_certificate_object *)((char *)(obj) - offsetof(php_openssl_certificate_object, std)); } #define Z_OPENSSL_CERTIFICATE_P(zv) php_openssl_certificate_from_obj(Z_OBJ_P(zv)) @@ -177,7 +177,7 @@ typedef struct _php_openssl_x509_request_object { } php_openssl_request_object; static inline php_openssl_request_object *php_openssl_request_from_obj(zend_object *obj) { - return (php_openssl_request_object *)((char *)(obj) - XtOffsetOf(php_openssl_request_object, std)); + return (php_openssl_request_object *)((char *)(obj) - offsetof(php_openssl_request_object, std)); } #define Z_OPENSSL_REQUEST_P(zv) php_openssl_request_from_obj(Z_OBJ_P(zv)) @@ -193,7 +193,7 @@ typedef struct _php_openssl_pkey_object { } php_openssl_pkey_object; static inline php_openssl_pkey_object *php_openssl_pkey_from_obj(zend_object *obj) { - return (php_openssl_pkey_object *)((char *)(obj) - XtOffsetOf(php_openssl_pkey_object, std)); + return (php_openssl_pkey_object *)((char *)(obj) - offsetof(php_openssl_pkey_object, std)); } #define Z_OPENSSL_PKEY_P(zv) php_openssl_pkey_from_obj(Z_OBJ_P(zv)) diff --git a/ext/pdo/pdo_dbh.c b/ext/pdo/pdo_dbh.c index 21002ce3a93d..6a47ec30c862 100644 --- a/ext/pdo/pdo_dbh.c +++ b/ext/pdo/pdo_dbh.c @@ -1529,7 +1529,7 @@ void pdo_dbh_init(int module_number) pdo_dbh_ce->default_object_handlers = &pdo_dbh_object_handlers; memcpy(&pdo_dbh_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - pdo_dbh_object_handlers.offset = XtOffsetOf(pdo_dbh_object_t, std); + pdo_dbh_object_handlers.offset = offsetof(pdo_dbh_object_t, std); pdo_dbh_object_handlers.free_obj = pdo_dbh_free_storage; pdo_dbh_object_handlers.clone_obj = NULL; pdo_dbh_object_handlers.get_method = dbh_method_get; diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c index a8564cd8d39c..2b4e5a8f8239 100644 --- a/ext/pdo/pdo_stmt.c +++ b/ext/pdo/pdo_stmt.c @@ -2420,7 +2420,7 @@ void pdo_stmt_init(void) pdo_dbstmt_ce->default_object_handlers = &pdo_dbstmt_object_handlers; memcpy(&pdo_dbstmt_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - pdo_dbstmt_object_handlers.offset = XtOffsetOf(pdo_stmt_t, std); + pdo_dbstmt_object_handlers.offset = offsetof(pdo_stmt_t, std); pdo_dbstmt_object_handlers.free_obj = pdo_dbstmt_free_storage; pdo_dbstmt_object_handlers.write_property = dbstmt_prop_write; pdo_dbstmt_object_handlers.unset_property = dbstmt_prop_delete; @@ -2434,7 +2434,7 @@ void pdo_stmt_init(void) pdo_row_ce->default_object_handlers = &pdo_row_object_handlers; memcpy(&pdo_row_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - pdo_row_object_handlers.offset = XtOffsetOf(pdo_row_t, std); + pdo_row_object_handlers.offset = offsetof(pdo_row_t, std); pdo_row_object_handlers.free_obj = pdo_row_free_storage; pdo_row_object_handlers.clone_obj = NULL; pdo_row_object_handlers.get_property_ptr_ptr = pdo_row_get_property_ptr_ptr; diff --git a/ext/pdo/php_pdo_driver.h b/ext/pdo/php_pdo_driver.h index 9dc18f75bfe1..611b0ab4ccb1 100644 --- a/ext/pdo/php_pdo_driver.h +++ b/ext/pdo/php_pdo_driver.h @@ -518,11 +518,11 @@ struct _pdo_dbh_object_t { }; static inline pdo_dbh_t *php_pdo_dbh_fetch_inner(zend_object *obj) { - return (pdo_dbh_t *)(((pdo_dbh_object_t *)((char*)(obj) - XtOffsetOf(pdo_dbh_object_t, std)))->inner); + return (pdo_dbh_t *)(((pdo_dbh_object_t *)((char*)(obj) - offsetof(pdo_dbh_object_t, std)))->inner); } static inline pdo_dbh_object_t *php_pdo_dbh_fetch_object(zend_object *obj) { - return (pdo_dbh_object_t *)((char*)(obj) - XtOffsetOf(pdo_dbh_object_t, std)); + return (pdo_dbh_object_t *)((char*)(obj) - offsetof(pdo_dbh_object_t, std)); } #define Z_PDO_DBH_P(zv) php_pdo_dbh_fetch_inner(Z_OBJ_P((zv))) @@ -640,7 +640,7 @@ struct _pdo_stmt_t { static inline pdo_stmt_t *php_pdo_stmt_fetch_object(zend_object *obj) { - return (pdo_stmt_t *)((char*)(obj) - XtOffsetOf(pdo_stmt_t, std)); + return (pdo_stmt_t *)((char*)(obj) - offsetof(pdo_stmt_t, std)); } #define Z_PDO_STMT_P(zv) php_pdo_stmt_fetch_object(Z_OBJ_P((zv))) @@ -651,7 +651,7 @@ struct _pdo_row_t { }; static inline pdo_row_t *php_pdo_row_fetch_object(zend_object *obj) { - return (pdo_row_t *)((char*)(obj) - XtOffsetOf(pdo_row_t, std)); + return (pdo_row_t *)((char*)(obj) - offsetof(pdo_row_t, std)); } struct _pdo_scanner_t { diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 27c736348239..1674625429ad 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -152,7 +152,7 @@ static zend_class_entry *pgsql_link_ce, *pgsql_result_ce, *pgsql_lob_ce; static zend_object_handlers pgsql_link_object_handlers, pgsql_result_object_handlers, pgsql_lob_object_handlers; static inline pgsql_link_handle *pgsql_link_from_obj(zend_object *obj) { - return (pgsql_link_handle *)((char *)(obj) - XtOffsetOf(pgsql_link_handle, std)); + return (pgsql_link_handle *)((char *)(obj) - offsetof(pgsql_link_handle, std)); } #define Z_PGSQL_LINK_P(zv) pgsql_link_from_obj(Z_OBJ_P(zv)) @@ -208,7 +208,7 @@ static void pgsql_link_free_obj(zend_object *obj) } static inline pgsql_result_handle *pgsql_result_from_obj(zend_object *obj) { - return (pgsql_result_handle *)((char *)(obj) - XtOffsetOf(pgsql_result_handle, std)); + return (pgsql_result_handle *)((char *)(obj) - offsetof(pgsql_result_handle, std)); } #define Z_PGSQL_RESULT_P(zv) pgsql_result_from_obj(Z_OBJ_P(zv)) @@ -245,7 +245,7 @@ static void pgsql_result_free_obj(zend_object *obj) } static inline pgLofp *pgsql_lob_from_obj(zend_object *obj) { - return (pgLofp *)((char *)(obj) - XtOffsetOf(pgLofp, std)); + return (pgLofp *)((char *)(obj) - offsetof(pgLofp, std)); } #define Z_PGSQL_LOB_P(zv) pgsql_lob_from_obj(Z_OBJ_P(zv)) @@ -574,7 +574,7 @@ PHP_MINIT_FUNCTION(pgsql) pgsql_link_ce->default_object_handlers = &pgsql_link_object_handlers; memcpy(&pgsql_link_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - pgsql_link_object_handlers.offset = XtOffsetOf(pgsql_link_handle, std); + pgsql_link_object_handlers.offset = offsetof(pgsql_link_handle, std); pgsql_link_object_handlers.free_obj = pgsql_link_free_obj; pgsql_link_object_handlers.get_constructor = pgsql_link_get_constructor; pgsql_link_object_handlers.clone_obj = NULL; @@ -585,7 +585,7 @@ PHP_MINIT_FUNCTION(pgsql) pgsql_result_ce->default_object_handlers = &pgsql_result_object_handlers; memcpy(&pgsql_result_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - pgsql_result_object_handlers.offset = XtOffsetOf(pgsql_result_handle, std); + pgsql_result_object_handlers.offset = offsetof(pgsql_result_handle, std); pgsql_result_object_handlers.free_obj = pgsql_result_free_obj; pgsql_result_object_handlers.get_constructor = pgsql_result_get_constructor; pgsql_result_object_handlers.clone_obj = NULL; @@ -596,7 +596,7 @@ PHP_MINIT_FUNCTION(pgsql) pgsql_lob_ce->default_object_handlers = &pgsql_lob_object_handlers; memcpy(&pgsql_lob_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - pgsql_lob_object_handlers.offset = XtOffsetOf(pgLofp, std); + pgsql_lob_object_handlers.offset = offsetof(pgLofp, std); pgsql_lob_object_handlers.free_obj = pgsql_lob_free_obj; pgsql_lob_object_handlers.get_constructor = pgsql_lob_get_constructor; pgsql_lob_object_handlers.clone_obj = NULL; @@ -1228,7 +1228,7 @@ PHP_FUNCTION(pg_query) /* The char pointer MUST refer to the char* of a zend_string struct */ static void php_pgsql_zend_string_release_from_char_pointer(char *ptr) { - zend_string_release((zend_string*) (ptr - XtOffsetOf(zend_string, val))); + zend_string_release((zend_string*) (ptr - offsetof(zend_string, val))); } static void _php_pgsql_free_params(char **params, uint32_t num_params) diff --git a/ext/random/php_random.h b/ext/random/php_random.h index 7c17cd40790f..ccc06b1fba69 100644 --- a/ext/random/php_random.h +++ b/ext/random/php_random.h @@ -126,11 +126,11 @@ extern PHPAPI zend_class_entry *random_ce_Random_Randomizer; extern PHPAPI zend_class_entry *random_ce_Random_IntervalBoundary; static inline php_random_engine *php_random_engine_from_obj(zend_object *object) { - return (php_random_engine *)((char *)(object) - XtOffsetOf(php_random_engine, std)); + return (php_random_engine *)((char *)(object) - offsetof(php_random_engine, std)); } static inline php_random_randomizer *php_random_randomizer_from_obj(zend_object *object) { - return (php_random_randomizer *)((char *)(object) - XtOffsetOf(php_random_randomizer, std)); + return (php_random_randomizer *)((char *)(object) - offsetof(php_random_randomizer, std)); } # define Z_RANDOM_ENGINE_P(zval) php_random_engine_from_obj(Z_OBJ_P(zval)) diff --git a/ext/random/random.c b/ext/random/random.c index dbc7ee50a080..81d0172748d8 100644 --- a/ext/random/random.c +++ b/ext/random/random.c @@ -745,7 +745,7 @@ PHP_MINIT_FUNCTION(random) random_ce_Random_Engine_Mt19937->create_object = php_random_engine_mt19937_new; random_ce_Random_Engine_Mt19937->default_object_handlers = &random_engine_mt19937_object_handlers; memcpy(&random_engine_mt19937_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - random_engine_mt19937_object_handlers.offset = XtOffsetOf(php_random_engine, std); + random_engine_mt19937_object_handlers.offset = offsetof(php_random_engine, std); random_engine_mt19937_object_handlers.free_obj = php_random_engine_common_free_object; random_engine_mt19937_object_handlers.clone_obj = php_random_engine_common_clone_object; @@ -754,7 +754,7 @@ PHP_MINIT_FUNCTION(random) random_ce_Random_Engine_PcgOneseq128XslRr64->create_object = php_random_engine_pcgoneseq128xslrr64_new; random_ce_Random_Engine_PcgOneseq128XslRr64->default_object_handlers = &random_engine_pcgoneseq128xslrr64_object_handlers; memcpy(&random_engine_pcgoneseq128xslrr64_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - random_engine_pcgoneseq128xslrr64_object_handlers.offset = XtOffsetOf(php_random_engine, std); + random_engine_pcgoneseq128xslrr64_object_handlers.offset = offsetof(php_random_engine, std); random_engine_pcgoneseq128xslrr64_object_handlers.free_obj = php_random_engine_common_free_object; random_engine_pcgoneseq128xslrr64_object_handlers.clone_obj = php_random_engine_common_clone_object; @@ -763,7 +763,7 @@ PHP_MINIT_FUNCTION(random) random_ce_Random_Engine_Xoshiro256StarStar->create_object = php_random_engine_xoshiro256starstar_new; random_ce_Random_Engine_Xoshiro256StarStar->default_object_handlers = &random_engine_xoshiro256starstar_object_handlers; memcpy(&random_engine_xoshiro256starstar_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - random_engine_xoshiro256starstar_object_handlers.offset = XtOffsetOf(php_random_engine, std); + random_engine_xoshiro256starstar_object_handlers.offset = offsetof(php_random_engine, std); random_engine_xoshiro256starstar_object_handlers.free_obj = php_random_engine_common_free_object; random_engine_xoshiro256starstar_object_handlers.clone_obj = php_random_engine_common_clone_object; @@ -772,7 +772,7 @@ PHP_MINIT_FUNCTION(random) random_ce_Random_Engine_Secure->create_object = php_random_engine_secure_new; random_ce_Random_Engine_Secure->default_object_handlers = &random_engine_secure_object_handlers; memcpy(&random_engine_secure_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - random_engine_secure_object_handlers.offset = XtOffsetOf(php_random_engine, std); + random_engine_secure_object_handlers.offset = offsetof(php_random_engine, std); random_engine_secure_object_handlers.free_obj = php_random_engine_common_free_object; random_engine_secure_object_handlers.clone_obj = NULL; @@ -781,7 +781,7 @@ PHP_MINIT_FUNCTION(random) random_ce_Random_Randomizer->create_object = php_random_randomizer_new; random_ce_Random_Randomizer->default_object_handlers = &random_randomizer_object_handlers; memcpy(&random_randomizer_object_handlers, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - random_randomizer_object_handlers.offset = XtOffsetOf(php_random_randomizer, std); + random_randomizer_object_handlers.offset = offsetof(php_random_randomizer, std); random_randomizer_object_handlers.free_obj = randomizer_free_obj; random_randomizer_object_handlers.clone_obj = NULL; diff --git a/ext/reflection/php_reflection.c b/ext/reflection/php_reflection.c index e74b7fcb27a7..94d8bb7d149c 100644 --- a/ext/reflection/php_reflection.c +++ b/ext/reflection/php_reflection.c @@ -175,7 +175,7 @@ typedef struct { } reflection_object; static inline reflection_object *reflection_object_from_obj(zend_object *obj) { - return (reflection_object*)((char*)(obj) - XtOffsetOf(reflection_object, zo)); + return (reflection_object*)((char*)(obj) - offsetof(reflection_object, zo)); } #define Z_REFLECTION_P(zv) reflection_object_from_obj(Z_OBJ_P((zv))) @@ -8159,7 +8159,7 @@ ZEND_METHOD(ReflectionConstant, __toString) PHP_MINIT_FUNCTION(reflection) /* {{{ */ { memcpy(&reflection_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - reflection_object_handlers.offset = XtOffsetOf(reflection_object, zo); + reflection_object_handlers.offset = offsetof(reflection_object, zo); reflection_object_handlers.free_obj = reflection_free_objects_storage; reflection_object_handlers.clone_obj = NULL; reflection_object_handlers.write_property = _reflection_write_property; diff --git a/ext/shmop/shmop.c b/ext/shmop/shmop.c index 18e6cac9a0c9..bbf5b1b9ef82 100644 --- a/ext/shmop/shmop.c +++ b/ext/shmop/shmop.c @@ -70,7 +70,7 @@ static zend_object_handlers shmop_object_handlers; static inline php_shmop *shmop_from_obj(zend_object *obj) { - return (php_shmop *)((char *)(obj) - XtOffsetOf(php_shmop, std)); + return (php_shmop *)((char *)(obj) - offsetof(php_shmop, std)); } #define Z_SHMOP_P(zv) shmop_from_obj(Z_OBJ_P(zv)) @@ -108,7 +108,7 @@ PHP_MINIT_FUNCTION(shmop) shmop_ce->default_object_handlers = &shmop_object_handlers; memcpy(&shmop_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - shmop_object_handlers.offset = XtOffsetOf(php_shmop, std); + shmop_object_handlers.offset = offsetof(php_shmop, std); shmop_object_handlers.free_obj = shmop_free_obj; shmop_object_handlers.get_constructor = shmop_get_constructor; shmop_object_handlers.clone_obj = NULL; diff --git a/ext/simplexml/php_simplexml_exports.h b/ext/simplexml/php_simplexml_exports.h index f1f519e85e12..61cee427f739 100644 --- a/ext/simplexml/php_simplexml_exports.h +++ b/ext/simplexml/php_simplexml_exports.h @@ -36,7 +36,7 @@ PHP_SXE_API zend_object *sxe_object_new(zend_class_entry *ce); static inline php_sxe_object *php_sxe_fetch_object(zend_object *obj) /* {{{ */ { - return (php_sxe_object *)((char*)(obj) - XtOffsetOf(php_sxe_object, zo)); + return (php_sxe_object *)((char*)(obj) - offsetof(php_sxe_object, zo)); } /* }}} */ diff --git a/ext/simplexml/simplexml.c b/ext/simplexml/simplexml.c index 5b749a462492..d86198c7639e 100644 --- a/ext/simplexml/simplexml.c +++ b/ext/simplexml/simplexml.c @@ -2631,7 +2631,7 @@ PHP_MINIT_FUNCTION(simplexml) ce_SimpleXMLElement->get_iterator = php_sxe_get_iterator; memcpy(&sxe_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - sxe_object_handlers.offset = XtOffsetOf(php_sxe_object, zo); + sxe_object_handlers.offset = offsetof(php_sxe_object, zo); sxe_object_handlers.free_obj = sxe_object_free_storage; sxe_object_handlers.clone_obj = sxe_object_clone; sxe_object_handlers.read_property = sxe_property_read; diff --git a/ext/snmp/php_snmp.h b/ext/snmp/php_snmp.h index 21d544fa7b8b..8e51a9430e94 100644 --- a/ext/snmp/php_snmp.h +++ b/ext/snmp/php_snmp.h @@ -57,7 +57,7 @@ typedef struct _php_snmp_object { } php_snmp_object; static inline php_snmp_object *php_snmp_fetch_object(zend_object *obj) { - return (php_snmp_object *)((char*)(obj) - XtOffsetOf(php_snmp_object, zo)); + return (php_snmp_object *)((char*)(obj) - offsetof(php_snmp_object, zo)); } #define Z_SNMP_P(zv) php_snmp_fetch_object(Z_OBJ_P((zv))) diff --git a/ext/snmp/snmp.c b/ext/snmp/snmp.c index ecea48883d52..44f714bf0368 100644 --- a/ext/snmp/snmp.c +++ b/ext/snmp/snmp.c @@ -624,7 +624,7 @@ static void php_snmp_internal(INTERNAL_FUNCTION_PARAMETERS, int st, static void php_snmp_zend_string_release_from_char_pointer(char *ptr) { if (ptr) { - zend_string *pptr = (zend_string *)(ptr - XtOffsetOf(zend_string, val)); + zend_string *pptr = (zend_string *)(ptr - offsetof(zend_string, val)); zend_string_release(pptr); } } @@ -2144,7 +2144,7 @@ PHP_MINIT_FUNCTION(snmp) php_snmp_ce = register_class_SNMP(); php_snmp_ce->create_object = php_snmp_object_new; php_snmp_ce->default_object_handlers = &php_snmp_object_handlers; - php_snmp_object_handlers.offset = XtOffsetOf(php_snmp_object, zo); + php_snmp_object_handlers.offset = offsetof(php_snmp_object, zo); php_snmp_object_handlers.clone_obj = NULL; php_snmp_object_handlers.free_obj = php_snmp_object_free_storage; diff --git a/ext/soap/php_soap.h b/ext/soap/php_soap.h index ebae8ca58a79..a2363c7a2211 100644 --- a/ext/soap/php_soap.h +++ b/ext/soap/php_soap.h @@ -260,7 +260,7 @@ typedef struct soap_url_object { static inline soap_url_object *soap_url_object_fetch(zend_object *obj) { - return (soap_url_object *) ((char *) obj - XtOffsetOf(soap_url_object, std)); + return (soap_url_object *) ((char *) obj - offsetof(soap_url_object, std)); } #define Z_SOAP_URL_P(zv) soap_url_object_fetch(Z_OBJ_P(zv)) diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 0c8e7070b359..cbe8b05312ff 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -206,11 +206,11 @@ typedef struct { } soap_client_object; static inline soap_client_object *soap_client_object_fetch(zend_object *obj) { - return (soap_client_object *) ((char *) obj - XtOffsetOf(soap_client_object, std)); + return (soap_client_object *) ((char *) obj - offsetof(soap_client_object, std)); } static inline soap_server_object *soap_server_object_fetch(zend_object *obj) { - return (soap_server_object *) ((char *) obj - XtOffsetOf(soap_server_object, std)); + return (soap_server_object *) ((char *) obj - offsetof(soap_server_object, std)); } static zend_object *soap_client_object_create(zend_class_entry *ce) @@ -288,7 +288,7 @@ static zend_result soap_url_cast_object(zend_object *obj, zval *result, int type static inline soap_sdl_object *soap_sdl_object_fetch(zend_object *obj) { - return (soap_sdl_object *) ((char *) obj - XtOffsetOf(soap_sdl_object, std)); + return (soap_sdl_object *) ((char *) obj - offsetof(soap_sdl_object, std)); } #define Z_SOAP_SDL_P(zv) soap_sdl_object_fetch(Z_OBJ_P(zv)) @@ -532,7 +532,7 @@ PHP_MINIT_FUNCTION(soap) soap_class_entry->default_object_handlers = &soap_client_object_handlers; memcpy(&soap_client_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - soap_client_object_handlers.offset = XtOffsetOf(soap_client_object, std); + soap_client_object_handlers.offset = offsetof(soap_client_object, std); soap_client_object_handlers.free_obj = soap_client_object_free; soap_client_object_handlers.clone_obj = NULL; @@ -545,7 +545,7 @@ PHP_MINIT_FUNCTION(soap) soap_server_class_entry->default_object_handlers = &soap_server_object_handlers; memcpy(&soap_server_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - soap_server_object_handlers.offset = XtOffsetOf(soap_server_object, std); + soap_server_object_handlers.offset = offsetof(soap_server_object, std); soap_server_object_handlers.free_obj = soap_server_object_free; soap_server_object_handlers.clone_obj = NULL; @@ -562,7 +562,7 @@ PHP_MINIT_FUNCTION(soap) soap_url_class_entry->default_object_handlers = &soap_url_object_handlers; memcpy(&soap_url_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - soap_url_object_handlers.offset = XtOffsetOf(soap_url_object, std); + soap_url_object_handlers.offset = offsetof(soap_url_object, std); soap_url_object_handlers.free_obj = soap_url_object_free; soap_url_object_handlers.get_constructor = soap_url_object_get_constructor; soap_url_object_handlers.clone_obj = NULL; @@ -574,7 +574,7 @@ PHP_MINIT_FUNCTION(soap) soap_sdl_class_entry->default_object_handlers = &soap_sdl_object_handlers; memcpy(&soap_sdl_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - soap_sdl_object_handlers.offset = XtOffsetOf(soap_sdl_object, std); + soap_sdl_object_handlers.offset = offsetof(soap_sdl_object, std); soap_sdl_object_handlers.free_obj = soap_sdl_object_free; soap_sdl_object_handlers.get_constructor = soap_sdl_object_get_constructor; soap_sdl_object_handlers.clone_obj = NULL; diff --git a/ext/sockets/php_sockets.h b/ext/sockets/php_sockets.h index 437d35b41032..b7fe1e5af611 100644 --- a/ext/sockets/php_sockets.h +++ b/ext/sockets/php_sockets.h @@ -76,7 +76,7 @@ typedef struct { extern PHP_SOCKETS_API zend_class_entry *socket_ce; static inline php_socket *socket_from_obj(zend_object *obj) { - return (php_socket *)((char *)(obj) - XtOffsetOf(php_socket, std)); + return (php_socket *)((char *)(obj) - offsetof(php_socket, std)); } #define Z_SOCKET_P(zv) socket_from_obj(Z_OBJ_P(zv)) diff --git a/ext/sockets/sockets.c b/ext/sockets/sockets.c index fa84a7877ad6..82ff0e80fcf3 100644 --- a/ext/sockets/sockets.c +++ b/ext/sockets/sockets.c @@ -181,7 +181,7 @@ zend_class_entry *address_info_ce; static zend_object_handlers address_info_object_handlers; static inline php_addrinfo *address_info_from_obj(zend_object *obj) { - return (php_addrinfo *)((char *)(obj) - XtOffsetOf(php_addrinfo, std)); + return (php_addrinfo *)((char *)(obj) - offsetof(php_addrinfo, std)); } #define Z_ADDRESS_INFO_P(zv) address_info_from_obj(Z_OBJ_P(zv)) @@ -484,7 +484,7 @@ static PHP_MINIT_FUNCTION(sockets) socket_ce->default_object_handlers = &socket_object_handlers; memcpy(&socket_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - socket_object_handlers.offset = XtOffsetOf(php_socket, std); + socket_object_handlers.offset = offsetof(php_socket, std); socket_object_handlers.free_obj = socket_free_obj; socket_object_handlers.get_constructor = socket_get_constructor; socket_object_handlers.clone_obj = NULL; @@ -496,7 +496,7 @@ static PHP_MINIT_FUNCTION(sockets) address_info_ce->default_object_handlers = &address_info_object_handlers; memcpy(&address_info_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - address_info_object_handlers.offset = XtOffsetOf(php_addrinfo, std); + address_info_object_handlers.offset = offsetof(php_addrinfo, std); address_info_object_handlers.free_obj = address_info_free_obj; address_info_object_handlers.get_constructor = address_info_get_constructor; address_info_object_handlers.clone_obj = NULL; @@ -1272,7 +1272,7 @@ PHP_FUNCTION(socket_connect) s_un.sun_family = AF_UNIX; memcpy(&s_un.sun_path, ZSTR_VAL(addr), ZSTR_LEN(addr)); retval = connect(php_sock->bsd_socket, (struct sockaddr *) &s_un, - (socklen_t)(XtOffsetOf(struct sockaddr_un, sun_path) + ZSTR_LEN(addr))); + (socklen_t)(offsetof(struct sockaddr_un, sun_path) + ZSTR_LEN(addr))); break; } diff --git a/ext/spl/spl_array.c b/ext/spl/spl_array.c index 737260ad6f0d..1f9f87d35841 100644 --- a/ext/spl/spl_array.c +++ b/ext/spl/spl_array.c @@ -52,7 +52,7 @@ typedef struct _spl_array_object { } spl_array_object; static inline spl_array_object *spl_array_from_obj(zend_object *obj) /* {{{ */ { - return (spl_array_object*)((char*)(obj) - XtOffsetOf(spl_array_object, std)); + return (spl_array_object*)((char*)(obj) - offsetof(spl_array_object, std)); } /* }}} */ @@ -1847,7 +1847,7 @@ PHP_MINIT_FUNCTION(spl_array) memcpy(&spl_handler_ArrayObject, &std_object_handlers, sizeof(zend_object_handlers)); - spl_handler_ArrayObject.offset = XtOffsetOf(spl_array_object, std); + spl_handler_ArrayObject.offset = offsetof(spl_array_object, std); spl_handler_ArrayObject.clone_obj = spl_array_object_clone; spl_handler_ArrayObject.read_dimension = spl_array_read_dimension; diff --git a/ext/spl/spl_directory.c b/ext/spl/spl_directory.c index 89af25dd9d35..47a0e38720bc 100644 --- a/ext/spl/spl_directory.c +++ b/ext/spl/spl_directory.c @@ -50,7 +50,7 @@ PHPAPI zend_class_entry *spl_ce_SplTempFileObject; /* Object helper */ static inline spl_filesystem_object *spl_filesystem_from_obj(zend_object *obj) /* {{{ */ { - return (spl_filesystem_object*)((char*)(obj) - XtOffsetOf(spl_filesystem_object, std)); + return (spl_filesystem_object*)((char*)(obj) - offsetof(spl_filesystem_object, std)); } /* }}} */ @@ -188,8 +188,8 @@ static zend_object *spl_filesystem_object_new(zend_class_entry *class_type) intern = emalloc(sizeof(spl_filesystem_object) + zend_object_properties_size(class_type)); /* Avoid initializing the entirety of spl_filesystem_object.u.dir.entry. */ memset(intern, 0, - MAX(XtOffsetOf(spl_filesystem_object, u.dir.entry), - XtOffsetOf(spl_filesystem_object, u.file.escape) + sizeof(int))); + MAX(offsetof(spl_filesystem_object, u.dir.entry), + offsetof(spl_filesystem_object, u.file.escape) + sizeof(int))); /* intern->type = SPL_FS_INFO; done by set 0 */ intern->file_class = spl_ce_SplFileObject; intern->info_class = spl_ce_SplFileInfo; @@ -2682,7 +2682,7 @@ PHP_MINIT_FUNCTION(spl_directory) spl_ce_SplFileInfo->default_object_handlers = &spl_filesystem_object_handlers; memcpy(&spl_filesystem_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - spl_filesystem_object_handlers.offset = XtOffsetOf(spl_filesystem_object, std); + spl_filesystem_object_handlers.offset = offsetof(spl_filesystem_object, std); spl_filesystem_object_handlers.clone_obj = spl_filesystem_object_clone; spl_filesystem_object_handlers.dtor_obj = spl_filesystem_object_destroy_object; spl_filesystem_object_handlers.free_obj = spl_filesystem_object_free_storage; diff --git a/ext/spl/spl_dllist.c b/ext/spl/spl_dllist.c index a4d89dc87bcf..eaadec03cf84 100644 --- a/ext/spl/spl_dllist.c +++ b/ext/spl/spl_dllist.c @@ -86,7 +86,7 @@ struct _spl_dllist_it { }; static inline spl_dllist_object *spl_dllist_from_obj(zend_object *obj) /* {{{ */ { - return (spl_dllist_object*)((char*)(obj) - XtOffsetOf(spl_dllist_object, std)); + return (spl_dllist_object*)((char*)(obj) - offsetof(spl_dllist_object, std)); } /* }}} */ @@ -1207,7 +1207,7 @@ PHP_MINIT_FUNCTION(spl_dllist) /* {{{ */ memcpy(&spl_handler_SplDoublyLinkedList, &std_object_handlers, sizeof(zend_object_handlers)); - spl_handler_SplDoublyLinkedList.offset = XtOffsetOf(spl_dllist_object, std); + spl_handler_SplDoublyLinkedList.offset = offsetof(spl_dllist_object, std); spl_handler_SplDoublyLinkedList.clone_obj = spl_dllist_object_clone; spl_handler_SplDoublyLinkedList.count_elements = spl_dllist_object_count_elements; spl_handler_SplDoublyLinkedList.get_gc = spl_dllist_object_get_gc; diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 82e09702219a..f016a313f2e8 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -55,7 +55,7 @@ typedef struct _spl_fixedarray_it { static spl_fixedarray_object *spl_fixed_array_from_obj(zend_object *obj) { - return (spl_fixedarray_object*)((char*)(obj) - XtOffsetOf(spl_fixedarray_object, std)); + return (spl_fixedarray_object*)((char*)(obj) - offsetof(spl_fixedarray_object, std)); } #define Z_SPLFIXEDARRAY_P(zv) spl_fixed_array_from_obj(Z_OBJ_P((zv))) @@ -952,7 +952,7 @@ PHP_MINIT_FUNCTION(spl_fixedarray) memcpy(&spl_handler_SplFixedArray, &std_object_handlers, sizeof(zend_object_handlers)); - spl_handler_SplFixedArray.offset = XtOffsetOf(spl_fixedarray_object, std); + spl_handler_SplFixedArray.offset = offsetof(spl_fixedarray_object, std); spl_handler_SplFixedArray.clone_obj = spl_fixedarray_object_clone; spl_handler_SplFixedArray.read_dimension = spl_fixedarray_object_read_dimension; spl_handler_SplFixedArray.write_dimension = spl_fixedarray_object_write_dimension; diff --git a/ext/spl/spl_heap.c b/ext/spl/spl_heap.c index 642fe4b95f05..ffc9485bd798 100644 --- a/ext/spl/spl_heap.c +++ b/ext/spl/spl_heap.c @@ -71,7 +71,7 @@ typedef struct _spl_pqueue_elem { } spl_pqueue_elem; static inline spl_heap_object *spl_heap_from_obj(zend_object *obj) /* {{{ */ { - return (spl_heap_object*)((char*)(obj) - XtOffsetOf(spl_heap_object, std)); + return (spl_heap_object*)((char*)(obj) - offsetof(spl_heap_object, std)); } /* }}} */ @@ -1332,7 +1332,7 @@ PHP_MINIT_FUNCTION(spl_heap) /* {{{ */ memcpy(&spl_handler_SplHeap, &std_object_handlers, sizeof(zend_object_handlers)); - spl_handler_SplHeap.offset = XtOffsetOf(spl_heap_object, std); + spl_handler_SplHeap.offset = offsetof(spl_heap_object, std); spl_handler_SplHeap.clone_obj = spl_heap_object_clone; spl_handler_SplHeap.count_elements = spl_heap_object_count_elements; spl_handler_SplHeap.get_gc = spl_heap_object_get_gc; @@ -1353,7 +1353,7 @@ PHP_MINIT_FUNCTION(spl_heap) /* {{{ */ memcpy(&spl_handler_SplPriorityQueue, &std_object_handlers, sizeof(zend_object_handlers)); - spl_handler_SplPriorityQueue.offset = XtOffsetOf(spl_heap_object, std); + spl_handler_SplPriorityQueue.offset = offsetof(spl_heap_object, std); spl_handler_SplPriorityQueue.clone_obj = spl_heap_object_clone; spl_handler_SplPriorityQueue.count_elements = spl_heap_object_count_elements; spl_handler_SplPriorityQueue.get_gc = spl_pqueue_object_get_gc; diff --git a/ext/spl/spl_iterators.c b/ext/spl/spl_iterators.c index c77aa9c1cf4b..f96cc3dd9f98 100644 --- a/ext/spl/spl_iterators.c +++ b/ext/spl/spl_iterators.c @@ -137,14 +137,14 @@ static zend_object_handlers spl_handlers_rec_it_it; static zend_object_handlers spl_handlers_dual_it; static inline spl_recursive_it_object *spl_recursive_it_from_obj(zend_object *obj) /* {{{ */ { - return (spl_recursive_it_object*)((char*)(obj) - XtOffsetOf(spl_recursive_it_object, std)); + return (spl_recursive_it_object*)((char*)(obj) - offsetof(spl_recursive_it_object, std)); } /* }}} */ #define Z_SPLRECURSIVE_IT_P(zv) spl_recursive_it_from_obj(Z_OBJ_P((zv))) static inline spl_dual_it_object *spl_dual_it_from_obj(zend_object *obj) /* {{{ */ { - return (spl_dual_it_object*)((char*)(obj) - XtOffsetOf(spl_dual_it_object, std)); + return (spl_dual_it_object*)((char*)(obj) - offsetof(spl_dual_it_object, std)); } /* }}} */ #define Z_SPLDUAL_IT_P(zv) spl_dual_it_from_obj(Z_OBJ_P((zv))) @@ -3134,14 +3134,14 @@ PHP_MINIT_FUNCTION(spl_iterators) spl_ce_RecursiveIteratorIterator->get_iterator = spl_recursive_it_get_iterator; memcpy(&spl_handlers_rec_it_it, &std_object_handlers, sizeof(zend_object_handlers)); - spl_handlers_rec_it_it.offset = XtOffsetOf(spl_recursive_it_object, std); + spl_handlers_rec_it_it.offset = offsetof(spl_recursive_it_object, std); spl_handlers_rec_it_it.get_method = spl_recursive_it_get_method; spl_handlers_rec_it_it.clone_obj = NULL; spl_handlers_rec_it_it.free_obj = spl_RecursiveIteratorIterator_free_storage; spl_handlers_rec_it_it.get_gc = spl_RecursiveIteratorIterator_get_gc; memcpy(&spl_handlers_dual_it, &std_object_handlers, sizeof(zend_object_handlers)); - spl_handlers_dual_it.offset = XtOffsetOf(spl_dual_it_object, std); + spl_handlers_dual_it.offset = offsetof(spl_dual_it_object, std); spl_handlers_dual_it.get_method = spl_dual_it_get_method; spl_handlers_dual_it.clone_obj = NULL; spl_handlers_dual_it.free_obj = spl_dual_it_free_storage; diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index 6e9ea0e1ba99..a25cf3cd1bb7 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -63,7 +63,7 @@ typedef struct _spl_SplObjectStorageElement { } spl_SplObjectStorageElement; /* }}} */ static inline spl_SplObjectStorage *spl_object_storage_from_obj(zend_object *obj) /* {{{ */ { - return (spl_SplObjectStorage*)((char*)(obj) - XtOffsetOf(spl_SplObjectStorage, std)); + return (spl_SplObjectStorage*)((char*)(obj) - offsetof(spl_SplObjectStorage, std)); } /* }}} */ @@ -1378,7 +1378,7 @@ PHP_MINIT_FUNCTION(spl_observer) memcpy(&spl_handler_SplObjectStorage, &std_object_handlers, sizeof(zend_object_handlers)); - spl_handler_SplObjectStorage.offset = XtOffsetOf(spl_SplObjectStorage, std); + spl_handler_SplObjectStorage.offset = offsetof(spl_SplObjectStorage, std); spl_handler_SplObjectStorage.compare = spl_object_storage_compare_objects; spl_handler_SplObjectStorage.clone_obj = spl_object_storage_clone; spl_handler_SplObjectStorage.get_gc = spl_object_storage_get_gc; diff --git a/ext/sqlite3/php_sqlite3_structs.h b/ext/sqlite3/php_sqlite3_structs.h index a43b2f76ca32..942224ebf81c 100644 --- a/ext/sqlite3/php_sqlite3_structs.h +++ b/ext/sqlite3/php_sqlite3_structs.h @@ -73,7 +73,7 @@ typedef struct _php_sqlite3_db_object { } php_sqlite3_db_object; static inline php_sqlite3_db_object *php_sqlite3_db_from_obj(zend_object *obj) { - return (php_sqlite3_db_object*)((char*)(obj) - XtOffsetOf(php_sqlite3_db_object, zo)); + return (php_sqlite3_db_object*)((char*)(obj) - offsetof(php_sqlite3_db_object, zo)); } #define Z_SQLITE3_DB_P(zv) php_sqlite3_db_from_obj(Z_OBJ_P((zv))) @@ -102,7 +102,7 @@ struct _php_sqlite3_result_object { }; static inline php_sqlite3_result *php_sqlite3_result_from_obj(zend_object *obj) { - return (php_sqlite3_result*)((char*)(obj) - XtOffsetOf(php_sqlite3_result, zo)); + return (php_sqlite3_result*)((char*)(obj) - offsetof(php_sqlite3_result, zo)); } #define Z_SQLITE3_RESULT_P(zv) php_sqlite3_result_from_obj(Z_OBJ_P((zv))) @@ -120,7 +120,7 @@ struct _php_sqlite3_stmt_object { }; static inline php_sqlite3_stmt *php_sqlite3_stmt_from_obj(zend_object *obj) { - return (php_sqlite3_stmt*)((char*)(obj) - XtOffsetOf(php_sqlite3_stmt, zo)); + return (php_sqlite3_stmt*)((char*)(obj) - offsetof(php_sqlite3_stmt, zo)); } #define Z_SQLITE3_STMT_P(zv) php_sqlite3_stmt_from_obj(Z_OBJ_P((zv))) diff --git a/ext/sqlite3/sqlite3.c b/ext/sqlite3/sqlite3.c index 7d73b9923695..8b69eca42061 100644 --- a/ext/sqlite3/sqlite3.c +++ b/ext/sqlite3/sqlite3.c @@ -2480,7 +2480,7 @@ PHP_MINIT_FUNCTION(sqlite3) memcpy(&sqlite3_result_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); /* Register SQLite 3 Class */ - sqlite3_object_handlers.offset = XtOffsetOf(php_sqlite3_db_object, zo); + sqlite3_object_handlers.offset = offsetof(php_sqlite3_db_object, zo); sqlite3_object_handlers.clone_obj = NULL; sqlite3_object_handlers.free_obj = php_sqlite3_object_free_storage; sqlite3_object_handlers.get_gc = php_sqlite3_get_gc; @@ -2489,7 +2489,7 @@ PHP_MINIT_FUNCTION(sqlite3) php_sqlite3_sc_entry->default_object_handlers = &sqlite3_object_handlers; /* Register SQLite 3 Prepared Statement Class */ - sqlite3_stmt_object_handlers.offset = XtOffsetOf(php_sqlite3_stmt, zo); + sqlite3_stmt_object_handlers.offset = offsetof(php_sqlite3_stmt, zo); sqlite3_stmt_object_handlers.clone_obj = NULL; sqlite3_stmt_object_handlers.free_obj = php_sqlite3_stmt_object_free_storage; php_sqlite3_stmt_entry = register_class_SQLite3Stmt(); @@ -2497,7 +2497,7 @@ PHP_MINIT_FUNCTION(sqlite3) php_sqlite3_stmt_entry->default_object_handlers = &sqlite3_stmt_object_handlers; /* Register SQLite 3 Result Class */ - sqlite3_result_object_handlers.offset = XtOffsetOf(php_sqlite3_result, zo); + sqlite3_result_object_handlers.offset = offsetof(php_sqlite3_result, zo); sqlite3_result_object_handlers.clone_obj = NULL; sqlite3_result_object_handlers.free_obj = php_sqlite3_result_object_free_storage; php_sqlite3_result_entry = register_class_SQLite3Result(); diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re index af605b8886cc..137bfd798147 100644 --- a/ext/standard/url_scanner_ex.re +++ b/ext/standard/url_scanner_ex.re @@ -661,7 +661,7 @@ static void php_url_scanner_ex_activate(bool is_session) ctx = &BG(url_adapt_output_ex); } - memset(ctx, 0, XtOffsetOf(url_adapt_state_ex_t, tags)); + memset(ctx, 0, offsetof(url_adapt_state_ex_t, tags)); } static void php_url_scanner_ex_deactivate(bool is_session) diff --git a/ext/sysvmsg/sysvmsg.c b/ext/sysvmsg/sysvmsg.c index c86404fc5c45..533cc44cbec3 100644 --- a/ext/sysvmsg/sysvmsg.c +++ b/ext/sysvmsg/sysvmsg.c @@ -66,7 +66,7 @@ zend_class_entry *sysvmsg_queue_ce; static zend_object_handlers sysvmsg_queue_object_handlers; static inline sysvmsg_queue_t *sysvmsg_queue_from_obj(zend_object *obj) { - return (sysvmsg_queue_t *)((char *)(obj) - XtOffsetOf(sysvmsg_queue_t, std)); + return (sysvmsg_queue_t *)((char *)(obj) - offsetof(sysvmsg_queue_t, std)); } #define Z_SYSVMSG_QUEUE_P(zv) sysvmsg_queue_from_obj(Z_OBJ_P(zv)) @@ -101,7 +101,7 @@ PHP_MINIT_FUNCTION(sysvmsg) sysvmsg_queue_ce->default_object_handlers = &sysvmsg_queue_object_handlers; memcpy(&sysvmsg_queue_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - sysvmsg_queue_object_handlers.offset = XtOffsetOf(sysvmsg_queue_t, std); + sysvmsg_queue_object_handlers.offset = offsetof(sysvmsg_queue_t, std); sysvmsg_queue_object_handlers.free_obj = sysvmsg_queue_free_obj; sysvmsg_queue_object_handlers.get_constructor = sysvmsg_queue_get_constructor; sysvmsg_queue_object_handlers.clone_obj = NULL; diff --git a/ext/sysvsem/sysvsem.c b/ext/sysvsem/sysvsem.c index e29283ea3f6e..3672f1ac7afe 100644 --- a/ext/sysvsem/sysvsem.c +++ b/ext/sysvsem/sysvsem.c @@ -83,7 +83,7 @@ zend_class_entry *sysvsem_ce; static zend_object_handlers sysvsem_object_handlers; static inline sysvsem_sem *sysvsem_from_obj(zend_object *obj) { - return (sysvsem_sem *)((char *)(obj) - XtOffsetOf(sysvsem_sem, std)); + return (sysvsem_sem *)((char *)(obj) - offsetof(sysvsem_sem, std)); } #define Z_SYSVSEM_P(zv) sysvsem_from_obj(Z_OBJ_P(zv)) @@ -147,7 +147,7 @@ PHP_MINIT_FUNCTION(sysvsem) sysvsem_ce->default_object_handlers = &sysvsem_object_handlers; memcpy(&sysvsem_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - sysvsem_object_handlers.offset = XtOffsetOf(sysvsem_sem, std); + sysvsem_object_handlers.offset = offsetof(sysvsem_sem, std); sysvsem_object_handlers.free_obj = sysvsem_free_obj; sysvsem_object_handlers.get_constructor = sysvsem_get_constructor; sysvsem_object_handlers.clone_obj = NULL; diff --git a/ext/sysvshm/sysvshm.c b/ext/sysvshm/sysvshm.c index 29f153b19662..d9082f269b60 100644 --- a/ext/sysvshm/sysvshm.c +++ b/ext/sysvshm/sysvshm.c @@ -34,7 +34,7 @@ zend_class_entry *sysvshm_ce; static zend_object_handlers sysvshm_object_handlers; static inline sysvshm_shm *sysvshm_from_obj(zend_object *obj) { - return (sysvshm_shm *)((char *)(obj) - XtOffsetOf(sysvshm_shm, std)); + return (sysvshm_shm *)((char *)(obj) - offsetof(sysvshm_shm, std)); } #define Z_SYSVSHM_P(zv) sysvshm_from_obj(Z_OBJ_P(zv)) @@ -100,7 +100,7 @@ PHP_MINIT_FUNCTION(sysvshm) sysvshm_ce->default_object_handlers = &sysvshm_object_handlers; memcpy(&sysvshm_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - sysvshm_object_handlers.offset = XtOffsetOf(sysvshm_shm, std); + sysvshm_object_handlers.offset = offsetof(sysvshm_shm, std); sysvshm_object_handlers.free_obj = sysvshm_free_obj; sysvshm_object_handlers.get_constructor = sysvshm_get_constructor; sysvshm_object_handlers.clone_obj = NULL; diff --git a/ext/tidy/tidy.c b/ext/tidy/tidy.c index ba22c06ef494..7e695a6c422b 100644 --- a/ext/tidy/tidy.c +++ b/ext/tidy/tidy.c @@ -105,7 +105,7 @@ struct _PHPTidyObj { }; static inline PHPTidyObj *php_tidy_fetch_object(zend_object *obj) { - return (PHPTidyObj *)((char*)(obj) - XtOffsetOf(PHPTidyObj, std)); + return (PHPTidyObj *)((char*)(obj) - offsetof(PHPTidyObj, std)); } #define Z_TIDY_P(zv) php_tidy_fetch_object(Z_OBJ_P((zv))) @@ -848,7 +848,7 @@ static PHP_MINIT_FUNCTION(tidy) tidy_object_handlers_doc.cast_object = tidy_doc_cast_handler; tidy_object_handlers_node.cast_object = tidy_node_cast_handler; - tidy_object_handlers_node.offset = tidy_object_handlers_doc.offset = XtOffsetOf(PHPTidyObj, std); + tidy_object_handlers_node.offset = tidy_object_handlers_doc.offset = offsetof(PHPTidyObj, std); tidy_object_handlers_node.free_obj = tidy_object_handlers_doc.free_obj = tidy_object_free_storage; register_tidy_symbols(module_number); diff --git a/ext/uri/php_uri.c b/ext/uri/php_uri.c index a9e20d09996f..d25c310ed0da 100644 --- a/ext/uri/php_uri.c +++ b/ext/uri/php_uri.c @@ -1074,7 +1074,7 @@ static PHP_MINIT_FUNCTION(uri) php_uri_ce_rfc3986_uri->create_object = php_uri_object_create_rfc3986; php_uri_ce_rfc3986_uri->default_object_handlers = &object_handlers_rfc3986_uri; memcpy(&object_handlers_rfc3986_uri, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - object_handlers_rfc3986_uri.offset = XtOffsetOf(php_uri_object, std); + object_handlers_rfc3986_uri.offset = offsetof(php_uri_object, std); object_handlers_rfc3986_uri.free_obj = php_uri_object_handler_free; object_handlers_rfc3986_uri.clone_obj = php_uri_object_handler_clone; @@ -1082,7 +1082,7 @@ static PHP_MINIT_FUNCTION(uri) php_uri_ce_whatwg_url->create_object = php_uri_object_create_whatwg; php_uri_ce_whatwg_url->default_object_handlers = &object_handlers_whatwg_uri; memcpy(&object_handlers_whatwg_uri, zend_get_std_object_handlers(), sizeof(zend_object_handlers)); - object_handlers_whatwg_uri.offset = XtOffsetOf(php_uri_object, std); + object_handlers_whatwg_uri.offset = offsetof(php_uri_object, std); object_handlers_whatwg_uri.free_obj = php_uri_object_handler_free; object_handlers_whatwg_uri.clone_obj = php_uri_object_handler_clone; diff --git a/ext/uri/php_uri_common.h b/ext/uri/php_uri_common.h index f081fd6b6fd0..888a38245453 100644 --- a/ext/uri/php_uri_common.h +++ b/ext/uri/php_uri_common.h @@ -147,7 +147,7 @@ typedef struct php_uri_object { } php_uri_object; static inline php_uri_object *php_uri_object_from_obj(zend_object *object) { - return (php_uri_object*)((char*)(object) - XtOffsetOf(php_uri_object, std)); + return (php_uri_object*)((char*)(object) - offsetof(php_uri_object, std)); } #define Z_URI_OBJECT_P(zv) php_uri_object_from_obj(Z_OBJ_P((zv))) diff --git a/ext/xml/xml.c b/ext/xml/xml.c index d9df7920bb92..06c7e2c196d4 100644 --- a/ext/xml/xml.c +++ b/ext/xml/xml.c @@ -222,7 +222,7 @@ PHP_MINIT_FUNCTION(xml) xml_parser_ce->default_object_handlers = &xml_parser_object_handlers; memcpy(&xml_parser_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - xml_parser_object_handlers.offset = XtOffsetOf(xml_parser, std); + xml_parser_object_handlers.offset = offsetof(xml_parser, std); xml_parser_object_handlers.free_obj = xml_parser_free_obj; xml_parser_object_handlers.get_gc = xml_parser_get_gc; xml_parser_object_handlers.get_constructor = xml_parser_get_constructor; @@ -296,7 +296,7 @@ static void xml_xmlchar_zval(const XML_Char *s, int len, const XML_Char *encodin /* }}} */ static inline xml_parser *xml_parser_from_obj(zend_object *obj) { - return (xml_parser *)((char *)(obj) - XtOffsetOf(xml_parser, std)); + return (xml_parser *)((char *)(obj) - offsetof(xml_parser, std)); } #define Z_XMLPARSER_P(zv) xml_parser_from_obj(Z_OBJ_P(zv)) diff --git a/ext/xmlreader/php_xmlreader.c b/ext/xmlreader/php_xmlreader.c index 18a2612d9ede..6a7fb65e2af0 100644 --- a/ext/xmlreader/php_xmlreader.c +++ b/ext/xmlreader/php_xmlreader.c @@ -1343,7 +1343,7 @@ PHP_MINIT_FUNCTION(xmlreader) { memcpy(&xmlreader_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - xmlreader_object_handlers.offset = XtOffsetOf(xmlreader_object, std); + xmlreader_object_handlers.offset = offsetof(xmlreader_object, std); xmlreader_object_handlers.free_obj = xmlreader_objects_free_storage; xmlreader_object_handlers.has_property = xmlreader_has_property; xmlreader_object_handlers.read_property = xmlreader_read_property; diff --git a/ext/xmlreader/php_xmlreader.h b/ext/xmlreader/php_xmlreader.h index 74d11c6bdbea..66585666a4fc 100644 --- a/ext/xmlreader/php_xmlreader.h +++ b/ext/xmlreader/php_xmlreader.h @@ -45,7 +45,7 @@ typedef struct _xmlreader_object { } xmlreader_object; static inline xmlreader_object *php_xmlreader_fetch_object(zend_object *obj) { - return (xmlreader_object *)((char*)(obj) - XtOffsetOf(xmlreader_object, std)); + return (xmlreader_object *)((char*)(obj) - offsetof(xmlreader_object, std)); } #define Z_XMLREADER_P(zv) php_xmlreader_fetch_object(Z_OBJ_P((zv))) diff --git a/ext/xmlwriter/php_xmlwriter.c b/ext/xmlwriter/php_xmlwriter.c index 838d5fdc481d..fe7604edb52a 100644 --- a/ext/xmlwriter/php_xmlwriter.c +++ b/ext/xmlwriter/php_xmlwriter.c @@ -1048,7 +1048,7 @@ PHP_FUNCTION(xmlwriter_flush) static PHP_MINIT_FUNCTION(xmlwriter) { memcpy(&xmlwriter_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - xmlwriter_object_handlers.offset = XtOffsetOf(ze_xmlwriter_object, std); + xmlwriter_object_handlers.offset = offsetof(ze_xmlwriter_object, std); xmlwriter_object_handlers.dtor_obj = xmlwriter_object_dtor; xmlwriter_object_handlers.clone_obj = NULL; xmlwriter_class_entry_ce = register_class_XMLWriter(); diff --git a/ext/xmlwriter/php_xmlwriter.h b/ext/xmlwriter/php_xmlwriter.h index 6a0ae1c37abc..39ca1c66b3eb 100644 --- a/ext/xmlwriter/php_xmlwriter.h +++ b/ext/xmlwriter/php_xmlwriter.h @@ -38,7 +38,7 @@ typedef struct _ze_xmlwriter_object { } ze_xmlwriter_object; static inline ze_xmlwriter_object *php_xmlwriter_fetch_object(zend_object *obj) { - return (ze_xmlwriter_object *)((char*)(obj) - XtOffsetOf(ze_xmlwriter_object, std)); + return (ze_xmlwriter_object *)((char*)(obj) - offsetof(ze_xmlwriter_object, std)); } #define Z_XMLWRITER_P(zv) php_xmlwriter_fetch_object(Z_OBJ_P((zv))) diff --git a/ext/xsl/php_xsl.c b/ext/xsl/php_xsl.c index 474d167905df..b87f9578b215 100644 --- a/ext/xsl/php_xsl.c +++ b/ext/xsl/php_xsl.c @@ -266,7 +266,7 @@ static void xsl_libxslt_error_handler(void *ctx, const char *msg, ...) PHP_MINIT_FUNCTION(xsl) { memcpy(&xsl_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - xsl_object_handlers.offset = XtOffsetOf(xsl_object, std); + xsl_object_handlers.offset = offsetof(xsl_object, std); xsl_object_handlers.clone_obj = NULL; xsl_object_handlers.free_obj = xsl_objects_free_storage; xsl_object_handlers.get_gc = xsl_objects_get_gc; diff --git a/ext/xsl/php_xsl.h b/ext/xsl/php_xsl.h index 54f19e866269..2f2cf170d75b 100644 --- a/ext/xsl/php_xsl.h +++ b/ext/xsl/php_xsl.h @@ -61,7 +61,7 @@ typedef struct xsl_object { } xsl_object; static inline xsl_object *php_xsl_fetch_object(zend_object *obj) { - return (xsl_object *)((char*)(obj) - XtOffsetOf(xsl_object, std)); + return (xsl_object *)((char*)(obj) - offsetof(xsl_object, std)); } #define Z_XSL_P(zv) php_xsl_fetch_object(Z_OBJ_P((zv))) diff --git a/ext/zend_test/test.c b/ext/zend_test/test.c index 96f8db83c116..b947ad3302ae 100644 --- a/ext/zend_test/test.c +++ b/ext/zend_test/test.c @@ -1044,7 +1044,7 @@ static zend_object *zend_test_class_new(zend_class_entry *class_type) static void zend_test_class_free_obj(zend_object *object) { - zend_test_object *intern = (zend_test_object*)((char*)object - XtOffsetOf(zend_test_object, std)); + zend_test_object *intern = (zend_test_object*)((char*)object - offsetof(zend_test_object, std)); if (intern->tmp_method) { zend_internal_function *func = intern->tmp_method; @@ -1059,7 +1059,7 @@ static void zend_test_class_free_obj(zend_object *object) static zend_function *zend_test_class_method_get(zend_object **object, zend_string *name, const zval *key) { - zend_test_object *intern = (zend_test_object*)((char*)(*object) - XtOffsetOf(zend_test_object, std)); + zend_test_object *intern = (zend_test_object*)((char*)(*object) - offsetof(zend_test_object, std)); if (zend_string_equals_literal_ci(name, "test")) { zend_internal_function *fptr; @@ -1526,7 +1526,7 @@ PHP_MINIT_FUNCTION(zend_test) zend_test_class_handlers.get_method = zend_test_class_method_get; zend_test_class_handlers.clone_obj = NULL; zend_test_class_handlers.free_obj = zend_test_class_free_obj; - zend_test_class_handlers.offset = XtOffsetOf(zend_test_object, std); + zend_test_class_handlers.offset = offsetof(zend_test_object, std); zend_test_gen_stub_flag_compatibility_test = register_class_ZendTestGenStubFlagCompatibilityTest(); diff --git a/ext/zip/php_zip.c b/ext/zip/php_zip.c index 1a65a1e87220..a8289a41a304 100644 --- a/ext/zip/php_zip.c +++ b/ext/zip/php_zip.c @@ -3051,7 +3051,7 @@ static void php_zip_free_prop_handler(zval *el) /* {{{ */ { static PHP_MINIT_FUNCTION(zip) { memcpy(&zip_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - zip_object_handlers.offset = XtOffsetOf(ze_zip_object, zo); + zip_object_handlers.offset = offsetof(ze_zip_object, zo); zip_object_handlers.free_obj = php_zip_object_free_storage; zip_object_handlers.dtor_obj = php_zip_object_dtor; zip_object_handlers.clone_obj = NULL; diff --git a/ext/zip/php_zip.h b/ext/zip/php_zip.h index 4c7661256538..6af1e3fb8b6a 100644 --- a/ext/zip/php_zip.h +++ b/ext/zip/php_zip.h @@ -82,7 +82,7 @@ typedef struct _ze_zip_object { } ze_zip_object; static inline ze_zip_object *php_zip_fetch_object(zend_object *obj) { - return (ze_zip_object *)((char*)(obj) - XtOffsetOf(ze_zip_object, zo)); + return (ze_zip_object *)((char*)(obj) - offsetof(ze_zip_object, zo)); } #define Z_ZIP_P(zv) php_zip_fetch_object(Z_OBJ_P((zv))) diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index 115eedbc894a..ae03496b7c19 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -48,7 +48,7 @@ zend_class_entry *inflate_context_ce; static zend_object_handlers inflate_context_object_handlers; static inline php_zlib_context *inflate_context_from_obj(zend_object *obj) { - return (php_zlib_context *)((char *)(obj) - XtOffsetOf(php_zlib_context, std)); + return (php_zlib_context *)((char *)(obj) - offsetof(php_zlib_context, std)); } #define Z_INFLATE_CONTEXT_P(zv) inflate_context_from_obj(Z_OBJ_P(zv)) @@ -86,7 +86,7 @@ zend_class_entry *deflate_context_ce; static zend_object_handlers deflate_context_object_handlers; static inline php_zlib_context *deflate_context_from_obj(zend_object *obj) { - return (php_zlib_context *)((char *)(obj) - XtOffsetOf(php_zlib_context, std)); + return (php_zlib_context *)((char *)(obj) - offsetof(php_zlib_context, std)); } #define Z_DEFLATE_CONTEXT_P(zv) deflate_context_from_obj(Z_OBJ_P(zv)) @@ -1342,7 +1342,7 @@ static PHP_MINIT_FUNCTION(zlib) inflate_context_ce->default_object_handlers = &inflate_context_object_handlers; memcpy(&inflate_context_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - inflate_context_object_handlers.offset = XtOffsetOf(php_zlib_context, std); + inflate_context_object_handlers.offset = offsetof(php_zlib_context, std); inflate_context_object_handlers.free_obj = inflate_context_free_obj; inflate_context_object_handlers.get_constructor = inflate_context_get_constructor; inflate_context_object_handlers.clone_obj = NULL; @@ -1353,7 +1353,7 @@ static PHP_MINIT_FUNCTION(zlib) deflate_context_ce->default_object_handlers = &deflate_context_object_handlers; memcpy(&deflate_context_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); - deflate_context_object_handlers.offset = XtOffsetOf(php_zlib_context, std); + deflate_context_object_handlers.offset = offsetof(php_zlib_context, std); deflate_context_object_handlers.free_obj = deflate_context_free_obj; deflate_context_object_handlers.get_constructor = deflate_context_get_constructor; deflate_context_object_handlers.clone_obj = NULL; diff --git a/main/fastcgi.c b/main/fastcgi.c index a4853d8f0535..02ef614f4639 100644 --- a/main/fastcgi.c +++ b/main/fastcgi.c @@ -735,7 +735,7 @@ int fcgi_listen(const char *path, int backlog) memset(&sa.sa_unix, 0, sizeof(sa.sa_unix)); sa.sa_unix.sun_family = AF_UNIX; memcpy(sa.sa_unix.sun_path, path, path_len + 1); - sock_len = XtOffsetOf(struct sockaddr_un, sun_path) + path_len; + sock_len = offsetof(struct sockaddr_un, sun_path) + path_len; #ifdef HAVE_STRUCT_SOCKADDR_UN_SUN_LEN sa.sa_unix.sun_len = sock_len; #endif diff --git a/main/streams/xp_socket.c b/main/streams/xp_socket.c index 77977a557fc6..f2b2bb54ec6e 100644 --- a/main/streams/xp_socket.c +++ b/main/streams/xp_socket.c @@ -698,7 +698,7 @@ static inline int php_tcp_sockop_bind(php_stream *stream, php_netstream_data_t * parse_unix_address(xparam, &unix_addr); int result = bind(sock->socket, (const struct sockaddr *)&unix_addr, - (socklen_t) XtOffsetOf(struct sockaddr_un, sun_path) + xparam->inputs.namelen); + (socklen_t) offsetof(struct sockaddr_un, sun_path) + xparam->inputs.namelen); if (result == -1 && xparam->want_errortext) { char errstr[256]; xparam->outputs.error_text = strpprintf(0, "%s", php_socket_strerror_s(errno, errstr, sizeof(errstr))); @@ -834,7 +834,7 @@ static inline int php_tcp_sockop_connect(php_stream *stream, php_netstream_data_ parse_unix_address(xparam, &unix_addr); ret = php_network_connect_socket(sock->socket, - (const struct sockaddr *)&unix_addr, (socklen_t) XtOffsetOf(struct sockaddr_un, sun_path) + xparam->inputs.namelen, + (const struct sockaddr *)&unix_addr, (socklen_t) offsetof(struct sockaddr_un, sun_path) + xparam->inputs.namelen, xparam->op == STREAM_XPORT_OP_CONNECT_ASYNC, xparam->inputs.timeout, xparam->want_errortext ? &xparam->outputs.error_text : NULL, &err); diff --git a/sapi/phpdbg/phpdbg_watch.c b/sapi/phpdbg/phpdbg_watch.c index 4ba46f3c326f..b6d5e543a19c 100644 --- a/sapi/phpdbg/phpdbg_watch.c +++ b/sapi/phpdbg/phpdbg_watch.c @@ -148,7 +148,7 @@ bool phpdbg_check_watch_diff(phpdbg_watchtype type, void *oldPtr, void *newPtr) case WATCH_ON_REFCOUNTED: return memcmp(oldPtr, newPtr, sizeof(uint32_t) /* no zend_refcounted metadata info */) != 0; case WATCH_ON_STR: - return memcmp(oldPtr, newPtr, *(size_t *) oldPtr + XtOffsetOf(zend_string, val) - XtOffsetOf(zend_string, len)) != 0; + return memcmp(oldPtr, newPtr, *(size_t *) oldPtr + offsetof(zend_string, val) - offsetof(zend_string, len)) != 0; case WATCH_ON_HASHDATA: ZEND_UNREACHABLE(); } @@ -200,11 +200,11 @@ void phpdbg_print_watch_diff(phpdbg_watchtype type, zend_string *name, void *old case WATCH_ON_STR: phpdbg_out("Old value: "); - zend_write((char *) oldPtr + XtOffsetOf(zend_string, val) - XtOffsetOf(zend_string, len), *(size_t *) oldPtr); + zend_write((char *) oldPtr + offsetof(zend_string, val) - offsetof(zend_string, len), *(size_t *) oldPtr); phpdbg_out("\n"); phpdbg_out("New value: "); - zend_write((char *) newPtr + XtOffsetOf(zend_string, val) - XtOffsetOf(zend_string, len), *(size_t *) newPtr); + zend_write((char *) newPtr + offsetof(zend_string, val) - offsetof(zend_string, len), *(size_t *) newPtr); phpdbg_out("\n"); break; @@ -378,7 +378,7 @@ void phpdbg_watch_backup_data(phpdbg_watchpoint_t *watch) { if (watch->backup.str) { zend_string_release(watch->backup.str); } - watch->backup.str = zend_string_init((char *) watch->addr.ptr + XtOffsetOf(zend_string, val) - XtOffsetOf(zend_string, len), *(size_t *) watch->addr.ptr, 1); + watch->backup.str = zend_string_init((char *) watch->addr.ptr + offsetof(zend_string, val) - offsetof(zend_string, len), *(size_t *) watch->addr.ptr, 1); GC_MAKE_PERSISTENT_LOCAL(watch->backup.str); break; case WATCH_ON_HASHTABLE: @@ -449,7 +449,7 @@ void phpdbg_update_watch_ref(phpdbg_watchpoint_t *watch) { phpdbg_watch_backup_data(&coll->reference); } else if (Z_TYPE_P(watch->addr.zv) == IS_STRING) { coll->reference.type = WATCH_ON_STR; - phpdbg_set_addr_watchpoint(&Z_STRLEN_P(watch->addr.zv), XtOffsetOf(zend_string, val) - XtOffsetOf(zend_string, len) + Z_STRLEN_P(watch->addr.zv) + 1, &coll->reference); + phpdbg_set_addr_watchpoint(&Z_STRLEN_P(watch->addr.zv), offsetof(zend_string, val) - offsetof(zend_string, len) + Z_STRLEN_P(watch->addr.zv) + 1, &coll->reference); coll->reference.coll = coll; phpdbg_store_watchpoint_btree(&coll->reference); phpdbg_activate_watchpoint(&coll->reference); From 777a79cac9d669160733b4d056414cf93de27454 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 28 Apr 2026 22:43:48 +0200 Subject: [PATCH 009/213] =?UTF-8?q?zend=5Fobject=5Fhandlers:=20Fix=20type?= =?UTF-8?q?=20of=20`struct=20=5Fzend=5Fobject=5Fhandlers`=E2=80=99s=20`off?= =?UTF-8?q?set`=20field=20(#21900)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is used with `offsetof()` which evaluates to `size_t`. --- Zend/zend_object_handlers.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Zend/zend_object_handlers.h b/Zend/zend_object_handlers.h index ec71c427ffce..d0dd804e8a41 100644 --- a/Zend/zend_object_handlers.h +++ b/Zend/zend_object_handlers.h @@ -204,7 +204,7 @@ typedef zend_result (*zend_object_do_operation_t)(uint8_t opcode, zval *result, struct _zend_object_handlers { /* offset of real object header (usually zero) */ - int offset; + size_t offset; /* object handlers */ zend_object_free_obj_t free_obj; /* required */ zend_object_dtor_obj_t dtor_obj; /* required */ From 60b3fa3c76f54c56255c7b07c6543f7853958d2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 28 Apr 2026 23:52:44 +0200 Subject: [PATCH 010/213] version_compare: Fix handling of version numbers with a trailing dot (#21689) --- NEWS | 3 +++ ext/standard/tests/versioning/version_compare.phpt | 5 +++++ ext/standard/versioning.c | 10 +++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index b110b17bef21..ef713ddd7255 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.4.22 +- Standard: + . Fixed bug GH-21689 (version_compare() incorrectly handles versions ending + with a dot). (timwolla) 07 May 2026, PHP 8.4.21 diff --git a/ext/standard/tests/versioning/version_compare.phpt b/ext/standard/tests/versioning/version_compare.phpt index 07550dd410f4..e22ddabfa56b 100644 --- a/ext/standard/tests/versioning/version_compare.phpt +++ b/ext/standard/tests/versioning/version_compare.phpt @@ -22,6 +22,9 @@ foreach ($special_forms as $f1) { test("1.0$f1", "1.0$f2"); } } +test("1.2.", "1.2."); +test("1.2..", "1.2.."); + print "TESTING OPERATORS\n"; foreach ($special_forms as $f1) { foreach ($special_forms as $f2) { @@ -106,6 +109,8 @@ TESTING COMPARE 1.0pl1 > 1.0rc1 1.0pl1 > 1.0 1.0pl1 = 1.0pl1 +1.2. = 1.2. +1.2.. = 1.2.. TESTING OPERATORS 1.0-dev lt 1.0-dev : false 1.0-dev < 1.0-dev : false diff --git a/ext/standard/versioning.c b/ext/standard/versioning.c index 6995569fbf87..0ec061d0d86e 100644 --- a/ext/standard/versioning.c +++ b/ext/standard/versioning.c @@ -68,7 +68,15 @@ php_canonicalize_version(const char *version) } lp = *p++; } - *q++ = '\0'; + + /* Check if the last component is empty (i.e. the last character is a dot) + * and remove it if it is. */ + if (*(q - 1) == '.') { + *(q - 1) = '\0'; + } else { + *q = '\0'; + } + return buf; } From dec3658d75de6e79b711b5b1cd714434ff84d8cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 29 Apr 2026 08:01:54 +0200 Subject: [PATCH 011/213] zend_API: Make `array_init()` and `array_init_size()` inline functions (#21905) --- Zend/zend_API.h | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 7990726f7e69..7cc9b6ff38dd 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -524,8 +524,16 @@ ZEND_API const char *zend_get_type_by_const(int type); #define DLEXPORT #endif -#define array_init(arg) ZVAL_ARR((arg), zend_new_array(0)) -#define array_init_size(arg, size) ZVAL_ARR((arg), zend_new_array(size)) +static zend_always_inline void array_init_size(zval *arg, uint32_t size) +{ + ZVAL_ARR(arg, zend_new_array(size)); +} + +static zend_always_inline void array_init(zval *arg) +{ + array_init_size(arg, 0); +} + ZEND_API void object_init(zval *arg); ZEND_API zend_result object_init_ex(zval *arg, zend_class_entry *ce); ZEND_API zend_result object_init_with_constructor(zval *arg, zend_class_entry *class_type, uint32_t param_count, zval *params, HashTable *named_params); From 43889fa5cc813c47358ff677a72620d97ad0fdf3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Wed, 29 Apr 2026 08:03:14 +0200 Subject: [PATCH 012/213] zend_portability: Use `[[fallthrough]]` for C23 and C++ (#21904) --- Zend/zend_portability.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Zend/zend_portability.h b/Zend/zend_portability.h index 450e72a60eb5..c5b5fe02929f 100644 --- a/Zend/zend_portability.h +++ b/Zend/zend_portability.h @@ -130,7 +130,9 @@ #endif /* pseudo fallthrough keyword; */ -#if defined(__GNUC__) && __GNUC__ >= 7 +#if __STDC_VERSION__ >= 202311L || defined(__cplusplus) +# define ZEND_FALLTHROUGH [[fallthrough]] +#elif defined(__GNUC__) && __GNUC__ >= 7 # define ZEND_FALLTHROUGH __attribute__((__fallthrough__)) #else # define ZEND_FALLTHROUGH ((void)0) From 70f0ca5f19f6d93ce9114f360addaffc3623d2ca Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Wed, 29 Apr 2026 14:45:45 +0800 Subject: [PATCH 013/213] Zlib: Improve type checking of several integer options in deflate_init() (#21860) `zval_get_long()` does a forceful cast and will even cast values like arrays or objects into integers, something that points to a bug. Use the more modern `zval_try_get_long()` API instead. Create a helper function to handle the options consistently. Co-authored-by: Gina Peter Banyard --- NEWS | 3 +- UPGRADING | 2 +- .../deflate_init_strategy_type_error.phpt | 32 +++++++++-- ext/zlib/zlib.c | 53 ++++++++++++------- 4 files changed, 65 insertions(+), 25 deletions(-) diff --git a/NEWS b/NEWS index 45f40a076078..3da5464750cc 100644 --- a/NEWS +++ b/NEWS @@ -205,6 +205,7 @@ PHP NEWS - Zlib: . deflate_init() now raises a TypeError when the value for option - "strategy" is not of type int. (Weilin Du) + "level", "memory", "window", or "strategy" is not of type int. + (Weilin Du) <<< NOTE: Insert NEWS from last stable release here prior to actual release! >>> diff --git a/UPGRADING b/UPGRADING index df81eb889699..56049f30cf93 100644 --- a/UPGRADING +++ b/UPGRADING @@ -103,7 +103,7 @@ PHP 8.6 UPGRADE NOTES - Zlib: . deflate_init() now raises a TypeError when the value for option - "strategy" is not of type int. + "level", "memory", "window", or "strategy" is not of type int. ======================================== 2. New Features diff --git a/ext/zlib/tests/deflate_init_strategy_type_error.phpt b/ext/zlib/tests/deflate_init_strategy_type_error.phpt index 0227d1bf6c29..2a59082bc320 100644 --- a/ext/zlib/tests/deflate_init_strategy_type_error.phpt +++ b/ext/zlib/tests/deflate_init_strategy_type_error.phpt @@ -1,16 +1,42 @@ --TEST-- -deflate_init(): strategy option type validation +deflate_init(): options type validation --EXTENSIONS-- zlib --FILE-- []]); + deflate_init(ZLIB_ENCODING_DEFLATE, ['level' => 'foo']); } catch (TypeError $e) { echo $e->getMessage(), PHP_EOL; } +try { + deflate_init(ZLIB_ENCODING_DEFLATE, ['memory' => []]); +} catch (TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + deflate_init(ZLIB_ENCODING_DEFLATE, ['window' => new A()]); +} catch (TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +try { + deflate_init(ZLIB_ENCODING_DEFLATE, ['strategy' => $fp]); +} catch (TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +fclose($fp); + ?> --EXPECT-- -deflate_init(): Argument #2 ($options) the value for option "strategy" must be of type int, array given +deflate_init(): Argument #2 ($options) the value for option "level" must be of type int, string given +deflate_init(): Argument #2 ($options) the value for option "memory" must be of type int, array given +deflate_init(): Argument #2 ($options) the value for option "window" must be of type int, A given +deflate_init(): Argument #2 ($options) the value for option "strategy" must be of type int, resource given diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index ae03496b7c19..b1ee09635e5a 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -854,6 +854,30 @@ static bool zlib_create_dictionary_string(HashTable *options, char **dict, size_ return true; } +ZEND_ATTRIBUTE_NONNULL static bool zlib_get_long_option(HashTable *options, const char *option_name, size_t option_name_len, zend_long *value) +{ + bool failed = false; + zval *option_buffer = zend_hash_str_find(options, option_name, option_name_len); + + if (!option_buffer) { + return true; + } + + /* The |H ZPP specifier may leave HashTable entries wrapped in IS_INDIRECT. */ + ZVAL_DEINDIRECT(option_buffer); + *value = zval_try_get_long(option_buffer, &failed); + if (UNEXPECTED(failed)) { + zend_argument_type_error( + 2, + "the value for option \"%.*s\" must be of type int, %s given", + (int) option_name_len, option_name, zend_zval_value_name(option_buffer) + ); + return false; + } + + return true; +} + /* {{{ Initialize an incremental inflate context with the specified encoding */ PHP_FUNCTION(inflate_init) { @@ -1080,49 +1104,38 @@ PHP_FUNCTION(deflate_init) zend_long encoding, level = -1, memory = 8, window = 15, strategy = Z_DEFAULT_STRATEGY; char *dict = NULL; size_t dictlen = 0; - HashTable *options = NULL; - zval *option_buffer; + HashTable *options = (HashTable*)&zend_empty_array; if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "l|H", &encoding, &options)) { RETURN_THROWS(); } - if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("level"))) != NULL) { - ZVAL_DEINDIRECT(option_buffer); - level = zval_get_long(option_buffer); + if (!zlib_get_long_option(options, ZEND_STRL("level"), &level)) { + RETURN_THROWS(); } if (level < -1 || level > 9) { zend_value_error("deflate_init(): \"level\" option must be between -1 and 9"); RETURN_THROWS(); } - if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("memory"))) != NULL) { - ZVAL_DEINDIRECT(option_buffer); - memory = zval_get_long(option_buffer); + if (!zlib_get_long_option(options, ZEND_STRL("memory"), &memory)) { + RETURN_THROWS(); } if (memory < 1 || memory > 9) { zend_value_error("deflate_init(): \"memory\" option must be between 1 and 9"); RETURN_THROWS(); } - if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("window"))) != NULL) { - ZVAL_DEINDIRECT(option_buffer); - window = zval_get_long(option_buffer); + if (!zlib_get_long_option(options, ZEND_STRL("window"), &window)) { + RETURN_THROWS(); } if (window < 8 || window > 15) { zend_value_error("deflate_init(): \"window\" option must be between 8 and 15"); RETURN_THROWS(); } - if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("strategy"))) != NULL) { - bool failed = false; - - ZVAL_DEINDIRECT(option_buffer); - strategy = zval_try_get_long(option_buffer, &failed); - if (UNEXPECTED(failed)) { - zend_argument_type_error(2, "the value for option \"strategy\" must be of type int, %s given", zend_zval_value_name(option_buffer)); - RETURN_THROWS(); - } + if (!zlib_get_long_option(options, ZEND_STRL("strategy"), &strategy)) { + RETURN_THROWS(); } switch (strategy) { case Z_FILTERED: From 1095cf560d97432374edb5fb6387a8265025e573 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Wed, 29 Apr 2026 07:51:41 +0100 Subject: [PATCH 014/213] ext/phar: split calling openssl_verify and openssl_sign functions (#21836) The only thing vaguely similar is the setting up of arguments, and even that is not identical due to the by-ref arg for openssl_sign(). Splitting makes the code more legible, as we can add const qualifiers and use a zend_string directly, reducing allocations --- ext/phar/phar_internal.h | 2 +- ext/phar/util.c | 159 ++++++++++++++++++++++++--------------- 2 files changed, 98 insertions(+), 63 deletions(-) diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index df4e58c7adbf..8206856f6ca4 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -412,7 +412,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(z ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error); zend_result phar_free_alias(const phar_archive_data *phar); zend_result phar_get_archive(phar_archive_data **archive, const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error); -zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, const char *fname, char **signature, size_t *signature_len, char **error); +zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, const char *sig, size_t sig_len, const char *fname, char **signature, size_t *signature_len, char **error); ZEND_ATTRIBUTE_NONNULL zend_string* phar_create_signature(phar_archive_data *phar, php_stream *fp, char **error); /* utility functions */ diff --git a/ext/phar/util.c b/ext/phar/util.c index ad7cdd6c9ae5..cf3e6a90e51f 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -34,7 +34,8 @@ #include #include #else -static zend_result phar_call_openssl_signverify(bool is_sign, php_stream *fp, zend_off_t end, const char *key, size_t key_len, char **signature, size_t *signature_len, uint32_t sig_type); +ZEND_ATTRIBUTE_NONNULL static bool phar_call_openssl_verify(php_stream *fp, zend_off_t end, zend_string *public_key, const char *signature, size_t signature_len, uint32_t sig_type); +static zend_result phar_call_openssl_sign(php_stream *fp, zend_off_t end, const char *key, size_t key_len, char **signature, size_t *signature_len, uint32_t sig_type); #endif /* for links to relative location, prepend cwd of the entry */ @@ -1372,36 +1373,44 @@ static int phar_hex_str(const char *digest, size_t digest_len, char **signature) /* }}} */ #ifndef PHAR_HAVE_OPENSSL -static zend_result phar_call_openssl_signverify(bool is_sign, php_stream *fp, zend_off_t end, const char *key, size_t key_len, char **signature, size_t *signature_len, uint32_t sig_type) /* {{{ */ -{ - zval retval, zp[4]; - zend_string *str; - - zend_function *fn = NULL; - if (is_sign) { - fn = zend_hash_str_find_ptr(CG(function_table), ZEND_STRL("openssl_sign")); - } else { - fn = zend_hash_str_find_ptr(CG(function_table), ZEND_STRL("openssl_verify")); - } +ZEND_ATTRIBUTE_NONNULL static bool phar_call_openssl_verify( + php_stream *fp, + zend_off_t end, + zend_string *public_key, + const char *signature, + size_t signature_len, + uint32_t sig_type +) { + ZEND_ASSERT(signature_len != 0); + zend_function *fn = zend_hash_str_find_ptr(CG(function_table), ZEND_STRL("openssl_verify")); /* OpenSSL is not available, even as a shared module */ - if (fn == NULL) { - return FAILURE; + if (UNEXPECTED(fn == NULL)) { + return false; } - if (*signature_len) { - ZVAL_STRINGL(&zp[1], *signature, *signature_len); - } else { - ZVAL_EMPTY_STRING(&zp[1]); - } - ZVAL_STRINGL(&zp[2], key, key_len); + /* Read and copy stream content */ php_stream_rewind(fp); - str = php_stream_copy_to_mem(fp, (size_t) end, 0); - if (str) { - ZVAL_STR(&zp[0], str); - } else { - ZVAL_EMPTY_STRING(&zp[0]); - } + zend_string *str = php_stream_copy_to_mem(fp, (size_t) end, false); + /* No content thus signing must fail */ + if (UNEXPECTED(str == NULL)) { + return false; + } + + /* Set up parameters for call to openssl_verify() + * openssl_verify( + * string $data, + * string $signature, + * OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $public_key, + * string|int $algorithm = OPENSSL_ALGO_SHA1, + * int $padding = 0 + * ): int|false + */ + zval retval, zp[4]; + ZVAL_STR(&zp[0], str); + ZVAL_STRINGL(&zp[1], signature, signature_len); + /* Note we do not own the lifetime of the public key, but it is fine as calling the function will increase the refcount) */ + ZVAL_STR(&zp[2], public_key); if (sig_type == PHAR_SIG_OPENSSL_SHA512) { ZVAL_LONG(&zp[3], 9); /* value from openssl.c #define OPENSSL_ALGO_SHA512 9 */ } else if (sig_type == PHAR_SIG_OPENSSL_SHA256) { @@ -1410,52 +1419,84 @@ static zend_result phar_call_openssl_signverify(bool is_sign, php_stream *fp, ze /* don't rely on default value which may change in the future */ ZVAL_LONG(&zp[3], 1); /* value from openssl.c #define OPENSSL_ALGO_SHA1 1 */ } + zend_call_known_function(fn, NULL, NULL, &retval, /* param_count */ 4, zp, NULL); + /* Free string arguments that we own */ + zval_ptr_dtor_str(&zp[0]); + zval_ptr_dtor_str(&zp[1]); + + /* Returns 1 if the signature is correct, 0 if it is incorrect, and -1 or false on error. */ + switch (Z_TYPE(retval)) { + case IS_LONG: + if (1 == Z_LVAL(retval)) { + return true; + } + ZEND_FALLTHROUGH; + default: + /* Unlikely, but the openssl_verify() function may be disabled and redefined in userland and return bollocks */ + zval_ptr_dtor(&retval); + return false; + } +} + +static zend_result phar_call_openssl_sign(php_stream *fp, zend_off_t end, const char *key, size_t key_len, char **signature, size_t *signature_len, uint32_t sig_type) /* {{{ */ +{ + ZEND_ASSERT(end != 0); + ZEND_ASSERT(*signature_len == 0); + zval retval, zp[4]; - if ((size_t)end != Z_STRLEN(zp[0])) { - zval_ptr_dtor_str(&zp[0]); - zval_ptr_dtor_str(&zp[1]); - zval_ptr_dtor_str(&zp[2]); + zend_function *fn = zend_hash_str_find_ptr(CG(function_table), ZEND_STRL("openssl_sign")); + + /* OpenSSL is not available, even as a shared module */ + if (fn == NULL) { + return FAILURE; + } + + /* Read and copy stream content */ + php_stream_rewind(fp); + zend_string *str = php_stream_copy_to_mem(fp, (size_t) end, false); + /* No content thus signing must fail */ + if (!str || (size_t)end != ZSTR_LEN(str)) { return FAILURE; } - Z_ADDREF(zp[0]); - if (is_sign) { - ZVAL_NEW_REF(&zp[1], &zp[1]); + /* Set up parameters for call to openssl_sign() + * openssl_sign( + * string $data, + * string &$signature, + * #[\SensitiveParameter] OpenSSLAsymmetricKey|OpenSSLCertificate|array|string $private_key, + * string|int $algorithm = OPENSSL_ALGO_SHA1, + * int $padding = 0 + * ): bool + */ + ZVAL_STR(&zp[0], str); + ZVAL_EMPTY_STRING(&zp[1]); + ZVAL_NEW_REF(&zp[1], &zp[1]); + ZVAL_STRINGL(&zp[2], key, key_len); + if (sig_type == PHAR_SIG_OPENSSL_SHA512) { + ZVAL_LONG(&zp[3], 9); /* value from openssl.c #define OPENSSL_ALGO_SHA512 9 */ + } else if (sig_type == PHAR_SIG_OPENSSL_SHA256) { + ZVAL_LONG(&zp[3], 7); /* value from openssl.c #define OPENSSL_ALGO_SHA256 7 */ } else { - Z_ADDREF(zp[1]); + /* don't rely on default value which may change in the future */ + ZVAL_LONG(&zp[3], 1); /* value from openssl.c #define OPENSSL_ALGO_SHA1 1 */ } - Z_ADDREF(zp[2]); zend_call_known_function(fn, NULL, NULL, &retval, /* param_count */ 4, zp, NULL); - Z_DELREF(zp[0]); - - if (is_sign) { - ZVAL_UNREF(&zp[1]); - } else { - Z_DELREF(zp[1]); - } - Z_DELREF(zp[2]); + ZVAL_UNREF(&zp[1]); zval_ptr_dtor_str(&zp[0]); zval_ptr_dtor_str(&zp[2]); switch (Z_TYPE(retval)) { - case IS_LONG: - zval_ptr_dtor(&zp[1]); - if (1 == Z_LVAL(retval)) { - return SUCCESS; - } - return FAILURE; case IS_TRUE: *signature = estrndup(Z_STRVAL(zp[1]), Z_STRLEN(zp[1])); *signature_len = Z_STRLEN(zp[1]); zval_ptr_dtor(&zp[1]); return SUCCESS; default: + /* Unlikely, but the openssl_sign() function may be disabled and redefined in userland and return bollocks */ zval_ptr_dtor(&retval); - ZEND_FALLTHROUGH; - case IS_FALSE: zval_ptr_dtor(&zp[1]); return FAILURE; } @@ -1463,7 +1504,7 @@ static zend_result phar_call_openssl_signverify(bool is_sign, php_stream *fp, ze /* }}} */ #endif /* #ifndef PHAR_HAVE_OPENSSL */ -zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, char *sig, size_t sig_len, const char *fname, char **signature, size_t *signature_len, char **error) /* {{{ */ +zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, const char *sig, size_t sig_len, const char *fname, char **signature, size_t *signature_len, char **error) /* {{{ */ { size_t read_size, len; zend_off_t read_len; @@ -1488,8 +1529,6 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s } else { mdtype = EVP_sha1(); } -#else - size_t tempsig; #endif zend_string *pubkey = NULL; char *pfile; @@ -1524,9 +1563,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s } #ifndef PHAR_HAVE_OPENSSL - tempsig = sig_len; - - if (FAILURE == phar_call_openssl_signverify(false, fp, end_of_phar, ZSTR_VAL(pubkey), ZSTR_LEN(pubkey), &sig, &tempsig, sig_type)) { + if (!phar_call_openssl_verify(fp, end_of_phar, pubkey, sig, sig_len, sig_type)) { zend_string_release_ex(pubkey, 0); if (error) { @@ -1536,9 +1573,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s return FAILURE; } - zend_string_release_ex(pubkey, 0); - - sig_len = tempsig; + zend_string_release_ex(pubkey, false); #else in = BIO_new_mem_buf(ZSTR_VAL(pubkey), ZSTR_LEN(pubkey)); @@ -1610,7 +1645,7 @@ zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t s EVP_MD_CTX_destroy(md_ctx); #endif - *signature_len = phar_hex_str((const char*)sig, sig_len, signature); + *signature_len = phar_hex_str(sig, sig_len, signature); } break; case PHAR_SIG_SHA512: { @@ -1909,7 +1944,7 @@ ZEND_ATTRIBUTE_NONNULL zend_string* phar_create_signature(phar_archive_data *pha siglen = 0; php_stream_seek(fp, 0, SEEK_END); - if (FAILURE == phar_call_openssl_signverify(true, fp, php_stream_tell(fp), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen, phar->sig_flags)) { + if (FAILURE == phar_call_openssl_sign(fp, php_stream_tell(fp), PHAR_G(openssl_privatekey), PHAR_G(openssl_privatekey_len), (char **)&sigbuf, &siglen, phar->sig_flags)) { spprintf(error, 0, "unable to write phar \"%s\" with requested openssl signature", ZSTR_VAL(phar->fname)); return NULL; } From 036689961566f82f6d2e5bc517ab3d8693efbeca Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Wed, 29 Apr 2026 09:03:36 +0100 Subject: [PATCH 015/213] ext/phar: refactor phar_get_archive() to return phar_archive_data* (#21858) Instead of using an out param. --- ext/phar/dirstream.c | 20 ++--- ext/phar/func_interceptors.c | 20 +++-- ext/phar/phar.c | 5 +- ext/phar/phar_internal.h | 2 +- ext/phar/phar_object.c | 8 +- ext/phar/stream.c | 21 +++-- ext/phar/util.c | 147 ++++++++++++++++------------------- ext/phar/zip.c | 3 +- 8 files changed, 104 insertions(+), 122 deletions(-) diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 4bef14dfe6ae..2b74a566411f 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -248,7 +248,6 @@ static php_stream *phar_make_dirstream(const char *dir, size_t dirlen, const Has php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path, const char *mode, int options, zend_string **opened_path, php_stream_context *context STREAMS_DC) /* {{{ */ { char *error; - phar_archive_data *phar; php_url *resource = phar_parse_url(wrapper, path, mode, options); if (!resource) { @@ -276,7 +275,8 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path, phar_request_initialize(); - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error)) { + const phar_archive_data *phar = phar_get_archive(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error); + if (!phar) { if (error) { php_stream_wrapper_log_error(wrapper, options, "%s", error); efree(error); @@ -340,7 +340,6 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path, int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mode, int options, php_stream_context *context) /* {{{ */ { phar_entry_info entry; - phar_archive_data *phar = NULL; char *error; php_url *resource = NULL; @@ -351,9 +350,7 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo return 0; } - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL)) { - phar = NULL; - } + phar_archive_data *phar = phar_get_archive(ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); zend_string_release_ex(arch, false); @@ -379,7 +376,8 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo return 0; } - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error)) { + phar = phar_get_archive(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error); + if (!phar) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot create directory \"%s\" in phar \"%s\", error retrieving phar information: %s", ZSTR_VAL(resource->path) + 1, ZSTR_VAL(resource->host), error); efree(error); php_url_free(resource); @@ -467,7 +465,6 @@ int phar_wrapper_mkdir(php_stream_wrapper *wrapper, const char *url_from, int mo */ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options, php_stream_context *context) /* {{{ */ { - phar_archive_data *phar = NULL; char *error; /* pre-readonly check, we need to know if this is a data phar */ @@ -477,9 +474,7 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options return 0; } - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL)) { - phar = NULL; - } + phar_archive_data *phar = phar_get_archive(ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); zend_string_release_ex(arch, false); @@ -506,7 +501,8 @@ int phar_wrapper_rmdir(php_stream_wrapper *wrapper, const char *url, int options return 0; } - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error)) { + phar = phar_get_archive(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, &error); + if (!phar) { php_stream_wrapper_log_error(wrapper, options, "phar error: cannot remove directory \"%s\" in phar \"%s\", error retrieving phar information: %s", ZSTR_VAL(resource->path)+1, ZSTR_VAL(resource->host), error); efree(error); php_url_free(resource); diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c index 61bb9050550f..e2b45ac2a0ae 100644 --- a/ext/phar/func_interceptors.c +++ b/ext/phar/func_interceptors.c @@ -98,8 +98,8 @@ static zend_string* phar_get_name_for_relative_paths(zend_string *filename, bool /* fopen within phar, if :// is not in the url, then prepend phar:/// */ /* retrieving a file defaults to within the current directory, so use this if possible */ - phar_archive_data *phar; - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL)) { + phar_archive_data *phar = phar_get_archive(ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); + if (!phar) { zend_string_release_ex(arch, false); return NULL; } @@ -492,9 +492,9 @@ static void phar_file_stat(const char *filename, size_t filename_length, int typ zend_string *arch = phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 2, 0); if (arch) { /* fopen within phar, if :// is not in the url, then prepend phar:/// */ - zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); + phar = phar_get_archive(ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); zend_string_release_ex(arch, false); - if (FAILURE == has_archive) { + if (!phar) { goto skip_phar; } splitted:; @@ -727,13 +727,13 @@ PHP_FUNCTION(phar_is_file) /* {{{ */ zend_string *arch = phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 2, 0); if (arch) { - phar_archive_data *phar; + ; /* fopen within phar, if :// is not in the url, then prepend phar:/// */ /* retrieving a file within the current directory, so use this if possible */ - zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); + phar_archive_data *phar = phar_get_archive(ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); zend_string_release_ex(arch, false); - if (has_archive == SUCCESS) { + if (phar) { phar_entry_info *etemp; zend_string *entry = phar_fix_filepath(filename, filename_len, true); @@ -784,13 +784,11 @@ PHP_FUNCTION(phar_is_link) /* {{{ */ zend_string *arch = phar_split_fname(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 2, 0); if (arch) { - phar_archive_data *phar; - /* fopen within phar, if :// is not in the url, then prepend phar:/// */ /* retrieving a file within the current directory, so use this if possible */ - zend_result has_archive = phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); + phar_archive_data *phar = phar_get_archive(ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); zend_string_release_ex(arch, false); - if (has_archive == SUCCESS) { + if (phar) { phar_entry_info *etemp; zend_string *entry = phar_fix_filepath(filename, filename_len, true); diff --git a/ext/phar/phar.c b/ext/phar/phar.c index a81a62a188f9..6d9dd5324945 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -486,7 +486,6 @@ ZEND_ATTRIBUTE_NONNULL void phar_entry_remove(phar_entry_data *idata, char **err */ static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { - phar_archive_data *phar; #ifdef PHP_WIN32 char *save_fname; ALLOCA_FLAG(fname_use_heap) @@ -504,12 +503,12 @@ static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *al phar_unixify_path_separators(fname, fname_len); } #endif - zend_result archive_retrieved = phar_get_archive(&phar, fname, fname_len, alias, alias_len, error); + phar_archive_data *phar = phar_get_archive(fname, fname_len, alias, alias_len, error); /* logic is as follows: - If no alias was passed in, then it can match either and be valid - If an explicit alias was requested, ensure the filename passed in matches the phar's filename. */ - bool process_phar = SUCCESS == archive_retrieved && (!alias || zend_string_equals_cstr(phar->fname, fname, fname_len)); + bool process_phar = phar && (!alias || zend_string_equals_cstr(phar->fname, fname, fname_len)); #ifdef PHP_WIN32 if (fname != save_fname) { free_alloca(fname, fname_use_heap); diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 8206856f6ca4..b45fb2d2a13a 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -411,7 +411,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(ze ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error); zend_result phar_free_alias(const phar_archive_data *phar); -zend_result phar_get_archive(phar_archive_data **archive, const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error); +phar_archive_data* phar_get_archive(const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error); zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, const char *sig, size_t sig_len, const char *fname, char **signature, size_t *signature_len, char **error); ZEND_ATTRIBUTE_NONNULL zend_string* phar_create_signature(phar_archive_data *phar, php_stream *fp, char **error); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index bc55c175f7ba..1766d9f778eb 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -752,8 +752,8 @@ PHP_METHOD(Phar, webPhar) entry_len = sizeof("/index.php")-1; } - if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) || - (info = phar_get_entry_info(phar, entry, entry_len, NULL, false)) == NULL) { + phar = phar_get_archive(fname, fname_len, NULL, 0, NULL); + if (!phar || (info = phar_get_entry_info(phar, entry, entry_len, NULL, false)) == NULL) { phar_do_404(phar, fname, fname_len, f404); } else { char *tmp = NULL, sa = '\0'; @@ -793,8 +793,8 @@ PHP_METHOD(Phar, webPhar) goto cleanup_skip_entry; } - if (FAILURE == phar_get_archive(&phar, fname, fname_len, NULL, 0, NULL) || - (info = phar_get_entry_info(phar, entry, entry_len, NULL, false)) == NULL) { + phar = phar_get_archive(fname, fname_len, NULL, 0, NULL); + if (!phar || (info = phar_get_entry_info(phar, entry, entry_len, NULL, false)) == NULL) { phar_do_404(phar, fname, fname_len, f404); goto cleanup; } diff --git a/ext/phar/stream.c b/ext/phar/stream.c index f49bc5e2deba..9d24fa64d75c 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -230,7 +230,8 @@ static php_stream * phar_wrapper_open_url(php_stream_wrapper *wrapper, const cha } else { if (!*internal_file && (options & STREAM_OPEN_FOR_INCLUDE)) { /* retrieve the stub */ - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, NULL)) { + phar = phar_get_archive(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, NULL); + if (!phar) { php_stream_wrapper_log_error(wrapper, options, "file %s is not a valid phar archive", ZSTR_VAL(resource->host)); efree(internal_file); php_url_free(resource); @@ -554,7 +555,6 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f php_stream_statbuf *ssb, php_stream_context *context) /* {{{ */ { char *internal_file; - phar_archive_data *phar; size_t internal_file_len; php_url *resource = phar_parse_url(wrapper, url, "r", flags|PHP_STREAM_URL_STAT_QUIET); @@ -577,7 +577,8 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f internal_file = ZSTR_VAL(resource->path) + 1; /* strip leading "/" */ /* find the phar in our trusty global hash indexed by alias (host of phar://blah.phar/file.whatever) */ - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, NULL)) { + phar_archive_data *phar = phar_get_archive(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, NULL); + if (!phar) { php_url_free(resource); return FAILURE; } @@ -725,7 +726,6 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from, const char *url_to, int options, php_stream_context *context) /* {{{ */ { char *error; - phar_archive_data *phar, *pfrom, *pto; bool is_dir = false; bool is_modified = false; @@ -736,9 +736,8 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid or non-writable url \"%s\"", url_from, url_to, url_from); return 0; } - if (SUCCESS != phar_get_archive(&pfrom, ZSTR_VAL(resource_from->host), ZSTR_LEN(resource_from->host), NULL, 0, NULL)) { - pfrom = NULL; - } + + phar_archive_data *pfrom = phar_get_archive(ZSTR_VAL(resource_from->host), ZSTR_LEN(resource_from->host), NULL, 0, NULL); if (PHAR_G(readonly) && (!pfrom || !pfrom->is_data)) { php_url_free(resource_from); php_error_docref(NULL, E_WARNING, "phar error: Write operations disabled by the php.ini setting phar.readonly"); @@ -751,9 +750,8 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": invalid or non-writable url \"%s\"", url_from, url_to, url_to); return 0; } - if (SUCCESS != phar_get_archive(&pto, ZSTR_VAL(resource_to->host), ZSTR_LEN(resource_to->host), NULL, 0, NULL)) { - pto = NULL; - } + + phar_archive_data *pto = phar_get_archive(ZSTR_VAL(resource_to->host), ZSTR_LEN(resource_to->host), NULL, 0, NULL); if (PHAR_G(readonly) && (!pto || !pto->is_data)) { php_url_free(resource_from); php_url_free(resource_to); @@ -797,7 +795,8 @@ static int phar_wrapper_rename(php_stream_wrapper *wrapper, const char *url_from return 0; } - if (SUCCESS != phar_get_archive(&phar, ZSTR_VAL(resource_from->host), ZSTR_LEN(resource_from->host), NULL, 0, &error)) { + phar_archive_data *phar = phar_get_archive(ZSTR_VAL(resource_from->host), ZSTR_LEN(resource_from->host), NULL, 0, &error); + if (!phar) { php_url_free(resource_from); php_url_free(resource_to); php_error_docref(NULL, E_WARNING, "phar error: cannot rename \"%s\" to \"%s\": %s", url_from, url_to, error); diff --git a/ext/phar/util.c b/ext/phar/util.c index cf3e6a90e51f..331bbf6511ba 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -309,7 +309,8 @@ zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data } if (*ZSTR_VAL(filename) == '.') { - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL)) { + phar = phar_get_archive(ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, NULL); + if (!phar) { zend_string_release_ex(arch, false); return NULL; } @@ -469,7 +470,6 @@ ZEND_ATTRIBUTE_NONNULL static zend_result phar_separate_entry_fp(phar_entry_info */ ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, const zend_string *fname, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security) /* {{{ */ { - phar_archive_data *phar; phar_entry_info *entry; bool for_write = mode[0] != 'r' || mode[1] == '+'; bool for_append = mode[0] == 'a'; @@ -479,7 +479,8 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, co *ret = NULL; *error = NULL; - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 0, error)) { + phar_archive_data *phar = phar_get_archive(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 0, error); + if (!phar) { return FAILURE; } @@ -614,7 +615,6 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_get_entry_data(phar_entry_data **ret, co */ ZEND_ATTRIBUTE_NONNULL phar_entry_data *phar_get_or_create_entry_data(zend_string *fname, char *path, size_t path_len, const char *mode, char allow_dir, char **error, bool security, uint32_t timestamp) /* {{{ */ { - phar_archive_data *phar; phar_entry_info etemp; phar_entry_data *ret; const char *pcr_error; @@ -626,7 +626,8 @@ ZEND_ATTRIBUTE_NONNULL phar_entry_data *phar_get_or_create_entry_data(zend_strin is_dir = (path_len && path[path_len - 1] == '/') ? 1 : 0; - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 0, error)) { + phar_archive_data *phar = phar_get_archive(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 0, error); + if (!phar) { return NULL; } @@ -961,9 +962,9 @@ zend_result phar_free_alias(const phar_archive_data *phar) /* {{{ */ * Looks up a phar archive in the filename map, connecting it to the alias * (if any) or returns null */ -zend_result phar_get_archive(phar_archive_data **archive, const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error) /* {{{ */ +phar_archive_data* phar_get_archive(const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error) /* {{{ */ { - phar_archive_data *fd_ptr; + phar_archive_data *archive; phar_request_initialize(); @@ -971,142 +972,132 @@ zend_result phar_get_archive(phar_archive_data **archive, const char *fname, siz *error = NULL; } - *archive = NULL; - if (PHAR_G(last_phar) && zend_string_equals_cstr(PHAR_G(last_phar_name), fname, fname_len)) { - *archive = PHAR_G(last_phar); + archive = PHAR_G(last_phar); if (alias && alias_len) { if (!PHAR_G(last_phar)->is_temporary_alias && (alias_len != PHAR_G(last_phar)->alias_len || memcmp(PHAR_G(last_phar)->alias, alias, alias_len))) { if (error) { spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, ZSTR_VAL(PHAR_G(last_phar)->fname), fname); } - *archive = NULL; - return FAILURE; + return NULL; } if (PHAR_G(last_phar)->alias_len && zend_hash_str_exists(&(PHAR_G(phar_alias_map)), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len)) { zend_hash_str_del(&(PHAR_G(phar_alias_map)), PHAR_G(last_phar)->alias, PHAR_G(last_phar)->alias_len); } - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, *archive); + zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, archive); PHAR_G(last_alias) = alias; PHAR_G(last_alias_len) = alias_len; } - return SUCCESS; + return archive; } if (alias && alias_len) { /* If the alias stored in the last_phar cache matches, just use it directly */ if (PHAR_G(last_phar) && alias_len == PHAR_G(last_alias_len) && !memcmp(alias, PHAR_G(last_alias), alias_len)) { - fd_ptr = PHAR_G(last_phar); + archive = PHAR_G(last_phar); } else { - fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len); + archive = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len); } /* If we didn't find the alias, check in the cached manifest to see if we can find it */ - if (!fd_ptr && PHAR_G(manifest_cached)) { - fd_ptr = zend_hash_str_find_ptr(&cached_alias, alias, alias_len); + if (!archive && PHAR_G(manifest_cached)) { + archive = zend_hash_str_find_ptr(&cached_alias, alias, alias_len); } - if (fd_ptr) { - if (!zend_string_equals_cstr(fd_ptr->fname, fname, fname_len)) { + if (archive) { + if (!zend_string_equals_cstr(archive->fname, fname, fname_len)) { if (error) { - spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, ZSTR_VAL(fd_ptr->fname), fname); + spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, ZSTR_VAL(archive->fname), fname); } - if (SUCCESS == phar_free_alias(fd_ptr)) { + if (SUCCESS == phar_free_alias(archive)) { if (error) { efree(*error); *error = NULL; } } - return FAILURE; + return NULL; } - *archive = fd_ptr; - PHAR_G(last_phar) = fd_ptr; - PHAR_G(last_phar_name) = fd_ptr->fname; + PHAR_G(last_phar) = archive; + PHAR_G(last_phar_name) = archive->fname; PHAR_G(last_alias) = alias; PHAR_G(last_alias_len) = alias_len; - return SUCCESS; + return archive; } } if (fname && fname_len) { - fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len); - if (fd_ptr) { - *archive = fd_ptr; - + archive = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), fname, fname_len); + if (archive) { if (alias && alias_len) { - if (!fd_ptr->is_temporary_alias && (alias_len != fd_ptr->alias_len || memcmp(fd_ptr->alias, alias, alias_len))) { + if (!archive->is_temporary_alias && (alias_len != archive->alias_len || memcmp(archive->alias, alias, alias_len))) { if (error) { - spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, ZSTR_VAL(fd_ptr->fname), fname); + spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, ZSTR_VAL(archive->fname), fname); } - return FAILURE; + return NULL; } - if (fd_ptr->alias_len && zend_hash_str_exists(&(PHAR_G(phar_alias_map)), fd_ptr->alias, fd_ptr->alias_len)) { - zend_hash_str_del(&(PHAR_G(phar_alias_map)), fd_ptr->alias, fd_ptr->alias_len); + if (archive->alias_len && zend_hash_str_exists(&(PHAR_G(phar_alias_map)), archive->alias, archive->alias_len)) { + zend_hash_str_del(&(PHAR_G(phar_alias_map)), archive->alias, archive->alias_len); } - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, fd_ptr); + zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, archive); } - PHAR_G(last_phar) = fd_ptr; - PHAR_G(last_phar_name) = fd_ptr->fname; - PHAR_G(last_alias) = fd_ptr->alias; - PHAR_G(last_alias_len) = fd_ptr->alias_len; + PHAR_G(last_phar) = archive; + PHAR_G(last_phar_name) = archive->fname; + PHAR_G(last_alias) = archive->alias; + PHAR_G(last_alias_len) = archive->alias_len; - return SUCCESS; + return archive; } - if (PHAR_G(manifest_cached) && NULL != (fd_ptr = zend_hash_str_find_ptr(&cached_phars, fname, fname_len))) { - *archive = fd_ptr; - + if (PHAR_G(manifest_cached) && NULL != (archive = zend_hash_str_find_ptr(&cached_phars, fname, fname_len))) { /* this could be problematic - alias should never be different from manifest alias for cached phars */ - if (!fd_ptr->is_temporary_alias && alias && alias_len) { - if (alias_len != fd_ptr->alias_len || memcmp(fd_ptr->alias, alias, alias_len)) { + if (!archive->is_temporary_alias && alias && alias_len) { + if (alias_len != archive->alias_len || memcmp(archive->alias, alias, alias_len)) { if (error) { - spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, ZSTR_VAL(fd_ptr->fname), fname); + spprintf(error, 0, "alias \"%s\" is already used for archive \"%s\" cannot be overloaded with \"%s\"", alias, ZSTR_VAL(archive->fname), fname); } - return FAILURE; + return NULL; } } - PHAR_G(last_phar) = fd_ptr; - PHAR_G(last_phar_name) = fd_ptr->fname; - PHAR_G(last_alias) = fd_ptr->alias; - PHAR_G(last_alias_len) = fd_ptr->alias_len; + PHAR_G(last_phar) = archive; + PHAR_G(last_phar_name) = archive->fname; + PHAR_G(last_alias) = archive->alias; + PHAR_G(last_alias_len) = archive->alias_len; - return SUCCESS; + return archive; } - fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), fname, fname_len); + archive = zend_hash_str_find_ptr(&(PHAR_G(phar_alias_map)), fname, fname_len); /* If we didn't find the fname in the alias map, check in the cached manifest to see if we can find it */ - if (!fd_ptr && PHAR_G(manifest_cached)) { - fd_ptr = zend_hash_str_find_ptr(&cached_alias, fname, fname_len); + if (!archive && PHAR_G(manifest_cached)) { + archive = zend_hash_str_find_ptr(&cached_alias, fname, fname_len); } - if (fd_ptr) { - *archive = fd_ptr; - - PHAR_G(last_phar) = fd_ptr; - PHAR_G(last_phar_name) = fd_ptr->fname; - PHAR_G(last_alias) = fd_ptr->alias; - PHAR_G(last_alias_len) = fd_ptr->alias_len; + if (archive) { + PHAR_G(last_phar) = archive; + PHAR_G(last_phar_name) = archive->fname; + PHAR_G(last_alias) = archive->alias; + PHAR_G(last_alias_len) = archive->alias_len; - return SUCCESS; + return archive; } /* not found, try converting \ to / */ char *my_realpath = expand_filepath(fname, NULL); if (UNEXPECTED(!my_realpath)) { - return FAILURE; + return NULL; } size_t my_realpath_len = strlen(my_realpath); @@ -1114,31 +1105,29 @@ zend_result phar_get_archive(phar_archive_data **archive, const char *fname, siz phar_unixify_path_separators(my_realpath, my_realpath_len); #endif - fd_ptr = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), my_realpath, my_realpath_len); + archive = zend_hash_str_find_ptr(&(PHAR_G(phar_fname_map)), my_realpath, my_realpath_len); /* If we didn't find the path in the fname map, check in the cached manifest to see if we can find it */ - if (!fd_ptr && PHAR_G(manifest_cached)) { - fd_ptr = zend_hash_str_find_ptr(&cached_phars, my_realpath, my_realpath_len); + if (!archive && PHAR_G(manifest_cached)) { + archive = zend_hash_str_find_ptr(&cached_phars, my_realpath, my_realpath_len); } efree(my_realpath); - if (fd_ptr) { - *archive = fd_ptr; - + if (archive) { if (alias && alias_len) { - zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, fd_ptr); + zend_hash_str_add_ptr(&(PHAR_G(phar_alias_map)), alias, alias_len, archive); } - PHAR_G(last_phar) = fd_ptr; - PHAR_G(last_phar_name) = fd_ptr->fname; - PHAR_G(last_alias) = fd_ptr->alias; - PHAR_G(last_alias_len) = fd_ptr->alias_len; + PHAR_G(last_phar) = archive; + PHAR_G(last_phar_name) = archive->fname; + PHAR_G(last_alias) = archive->alias; + PHAR_G(last_alias_len) = archive->alias_len; - return SUCCESS; + return archive; } } - return FAILURE; + return NULL; } /* }}} */ diff --git a/ext/phar/zip.c b/ext/phar/zip.c index da934a4c0041..8f61977a3835 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -1271,7 +1271,8 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_zip_flush(phar_archive_data *phar, ze /* register alias */ if (phar->alias_len) { - if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(phar->fname), ZSTR_LEN(phar->fname), phar->alias, phar->alias_len, error)) { + phar = phar_get_archive(ZSTR_VAL(phar->fname), ZSTR_LEN(phar->fname), phar->alias, phar->alias_len, error); + if (!phar) { return EOF; } } From abf1ce5f0e5af31ca8d84abbba0276d864d1f0c9 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Wed, 29 Apr 2026 10:30:46 +0100 Subject: [PATCH 016/213] ext/phar: add const qualifiers (#21907) --- ext/phar/dirstream.c | 2 +- ext/phar/phar.c | 16 ++++++++-------- ext/phar/phar_internal.h | 14 +++++++------- ext/phar/phar_object.c | 5 +++-- ext/phar/stream.c | 11 +++++------ ext/phar/tar.c | 6 +++--- ext/phar/util.c | 2 +- ext/phar/zip.c | 2 +- 8 files changed, 29 insertions(+), 29 deletions(-) diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index 2b74a566411f..bb46ece5b918 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -300,7 +300,7 @@ php_stream *phar_wrapper_open_dir(php_stream_wrapper *wrapper, const char *path, const char *internal_file = ZSTR_VAL(resource->path) + 1; /* strip leading "/" */ size_t internal_file_len = ZSTR_LEN(resource->path) - 1; - phar_entry_info *entry = zend_hash_str_find_ptr(&phar->manifest, internal_file, internal_file_len); + const phar_entry_info *entry = zend_hash_str_find_ptr(&phar->manifest, internal_file, internal_file_len); php_stream *ret; if (NULL != entry && !entry->is_dir) { diff --git a/ext/phar/phar.c b/ext/phar/phar.c index 6d9dd5324945..cd363fbd88ee 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -484,7 +484,7 @@ ZEND_ATTRIBUTE_NONNULL void phar_entry_remove(phar_entry_data *idata, char **err /** * Open an already loaded phar */ -static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +static zend_result phar_open_parsed_phar(char *fname, size_t fname_len, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { #ifdef PHP_WIN32 char *save_fname; @@ -720,7 +720,7 @@ void phar_parse_metadata_lazy(const char *buffer, phar_metadata_tracker *tracker * This is used by phar_open_from_filename to process the manifest, but can be called * directly. */ -static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname_len, char *alias, size_t alias_len, zend_long halt_offset, phar_archive_data** pphar, uint32_t compression, char **error) /* {{{ */ +static zend_result phar_parse_pharfile(php_stream *fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, zend_long halt_offset, phar_archive_data** pphar, uint32_t compression, char **error) /* {{{ */ { char b32[4], *buffer, *endbuffer, *savebuf; phar_archive_data *mydata = NULL; @@ -1302,7 +1302,7 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname /** * Create or open a phar for writing */ -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { const char *ext_str, *z; char *my_error; @@ -1366,9 +1366,9 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(ze } /* }}} */ -static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error); +static zend_result phar_open_from_fp(php_stream* fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error); -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { php_stream *fp; zend_string *actual = NULL; @@ -1507,7 +1507,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(z * that the manifest is proper, then pass it to phar_parse_pharfile(). SUCCESS * or FAILURE is returned and pphar is set to a pointer to the phar's manifest */ -zend_result phar_open_from_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +zend_result phar_open_from_filename(char *fname, size_t fname_len, const char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { php_stream *fp; zend_string *actual; @@ -1564,7 +1564,7 @@ zend_result phar_open_from_filename(char *fname, size_t fname_len, char *alias, * that the manifest is proper, then pass it to phar_parse_pharfile(). SUCCESS * or FAILURE is returned and pphar is set to a pointer to the phar's manifest */ -static zend_result phar_open_from_fp(php_stream* fp, char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +static zend_result phar_open_from_fp(php_stream* fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { static const char token[] = "__HALT_COMPILER();"; static const char zip_magic[] = "PK\x03\x04"; @@ -2252,7 +2252,7 @@ zend_string* phar_split_fname(const char *filename, size_t filename_len, zend_st * Invoked when a user calls Phar::mapPhar() from within an executing .phar * to set up its manifest directly */ -ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(const char *alias, size_t alias_len, char **error) /* {{{ */ { *error = NULL; diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index b45fb2d2a13a..7a923fd15e18 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -406,10 +406,10 @@ void phar_object_init(void); void phar_destroy_phar_data(phar_archive_data *phar); ZEND_ATTRIBUTE_NONNULL zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip); -zend_result phar_open_from_filename(char *fname, size_t fname_len, char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error); -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); -ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(char *alias, size_t alias_len, char **error); +zend_result phar_open_from_filename(char *fname, size_t fname_len, const char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(const char *alias, size_t alias_len, char **error); zend_result phar_free_alias(const phar_archive_data *phar); phar_archive_data* phar_get_archive(const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error); zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, const char *sig, size_t sig_len, const char *fname, char **signature, size_t *signature_len, char **error); @@ -423,7 +423,7 @@ const char *phar_compress_filter(const phar_entry_info *entry, bool return_unkno /* void phar_remove_virtual_dirs(phar_archive_data *phar, char *filename, size_t filename_len); */ void phar_add_virtual_dirs(phar_archive_data *phar, const char *filename, size_t filename_len); zend_result phar_mount_entry(phar_archive_data *phar, const char *filename, size_t filename_len, char *path, size_t path_len); -zend_string *phar_find_in_include_path(zend_string *file, phar_archive_data **pphar); +zend_string *phar_find_in_include_path(const zend_string *file, phar_archive_data **pphar); zend_string* phar_fix_filepath(const char *path, size_t path_length, bool use_cwd); ZEND_ATTRIBUTE_NONNULL phar_entry_info * phar_open_jit(const phar_archive_data *phar, phar_entry_info *entry, char **error); void phar_parse_metadata_lazy(const char *buffer, phar_metadata_tracker *tracker, uint32_t zip_metadata_len, bool persistent); @@ -446,12 +446,12 @@ zend_result phar_copy_on_write(phar_archive_data **pphar); /* tar functions in tar.c */ bool phar_is_tar(const char *buf, const char *fname); zend_result phar_parse_tarfile(php_stream* fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, phar_archive_data** pphar, uint32_t compression, char **error); -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_tar(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_tar(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_tar_flush(phar_archive_data *phar, zend_string *user_stub, bool is_default_stub, char **error); /* zip functions in zip.c */ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_len, const char *alias, size_t alias_len, phar_archive_data** pphar, char **error); -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_zip(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_zip(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); ZEND_ATTRIBUTE_NONNULL_ARGS(1, 4) int phar_zip_flush(phar_archive_data *archive, zend_string *user_stub, bool is_default_stub, char **error); #ifdef PHAR_MAIN diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 1766d9f778eb..00a5ebf3058f 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -349,9 +349,10 @@ static void phar_do_404(phar_archive_data *phar, char *fname, size_t fname_len, /* post-process REQUEST_URI and retrieve the actual request URI. This is for cases like http://localhost/blah.phar/path/to/file.php/extra/stuff which calls "blah.phar" file "path/to/file.php" with PATH_INFO "/extra/stuff" */ -static void phar_postprocess_ru_web(const char *fname, size_t fname_len, char *entry, size_t *entry_len, char **ru, size_t *ru_len) /* {{{ */ +static void phar_postprocess_ru_web(const char *fname, size_t fname_len, const char *entry, size_t *entry_len, char **ru, size_t *ru_len) /* {{{ */ { - char *e = entry + 1, *u1 = NULL, *u = NULL, *saveu = NULL; + const char *e = entry + 1; + char *u1 = NULL, *u = NULL, *saveu = NULL; size_t e_len = *entry_len - 1, u_len = 0; phar_archive_data *pphar; diff --git a/ext/phar/stream.c b/ext/phar/stream.c index 9d24fa64d75c..f38f179238ff 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -364,7 +364,7 @@ static ssize_t phar_stream_read(php_stream *stream, char *buf, size_t count) /* { phar_entry_data *data = (phar_entry_data *)stream->abstract; ssize_t got; - phar_entry_info *entry; + const phar_entry_info *entry; if (data->internal_file->symlink) { entry = phar_get_link_source(data->internal_file); @@ -394,7 +394,7 @@ static ssize_t phar_stream_read(php_stream *stream, char *buf, size_t count) /* static int phar_stream_seek(php_stream *stream, zend_off_t offset, int whence, zend_off_t *newoffset) /* {{{ */ { phar_entry_data *data = (phar_entry_data *)stream->abstract; - phar_entry_info *entry; + const phar_entry_info *entry; int res; zend_ulong temp; @@ -462,7 +462,7 @@ static int phar_stream_flush(php_stream *stream) /* {{{ */ { char *error; int ret; - phar_entry_data *data = (phar_entry_data *) stream->abstract; + const phar_entry_data *data = stream->abstract; if (data->internal_file->is_modified) { data->internal_file->timestamp = time(0); @@ -536,7 +536,7 @@ void phar_dostat(phar_archive_data *phar, phar_entry_info *data, php_stream_stat */ static int phar_stream_stat(php_stream *stream, php_stream_statbuf *ssb) /* {{{ */ { - phar_entry_data *data = (phar_entry_data *)stream->abstract; + const phar_entry_data *data = stream->abstract; /* If ssb is NULL then someone is misbehaving */ if (!ssb) { @@ -659,7 +659,6 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int char *internal_file, *error; size_t internal_file_len; phar_entry_data *idata; - phar_archive_data *pphar; php_url *resource = phar_parse_url(wrapper, url, "rb", options); if (!resource) { @@ -682,7 +681,7 @@ static int phar_wrapper_unlink(php_stream_wrapper *wrapper, const char *url, int phar_request_initialize(); - pphar = zend_hash_find_ptr(&(PHAR_G(phar_fname_map)), resource->host); + const phar_archive_data *pphar = zend_hash_find_ptr(&(PHAR_G(phar_fname_map)), resource->host); if (PHAR_G(readonly) && (!pphar || !pphar->is_data)) { php_url_free(resource); php_stream_wrapper_log_error(wrapper, options, "phar error: write operations disabled by the php.ini setting phar.readonly"); diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 761246000dd2..edb0707a6ff7 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -126,7 +126,7 @@ bool phar_is_tar(const char *buf, const char *fname) /* {{{ */ } /* }}} */ -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_tar(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_tar(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *phar; zend_result ret = phar_create_or_parse_filename(fname, alias, alias_len, is_data, options, &phar, error); @@ -802,7 +802,7 @@ static int phar_tar_writeheaders_int(phar_entry_info *entry, void *argument) /* /* write header */ entry->header_offset = php_stream_tell(fp->new); - if (sizeof(header) != php_stream_write(fp->new, (char *) &header, sizeof(header))) { + if (sizeof(header) != php_stream_write(fp->new, (const char *) &header, sizeof(header))) { if (fp->error) { spprintf(fp->error, 4096, "tar-based phar \"%s\" cannot be created, header for file \"%s\" could not be written", ZSTR_VAL(entry->phar->fname), ZSTR_VAL(entry->filename)); } @@ -906,7 +906,7 @@ ZEND_ATTRIBUTE_NONNULL static int phar_tar_setmetadata(const phar_metadata_track ZEND_ATTRIBUTE_NONNULL static int phar_tar_setupmetadata(zval *zv, void *argument) /* {{{ */ { - struct _phar_pass_tar_info *i = (struct _phar_pass_tar_info *)argument; + const struct _phar_pass_tar_info *i = (struct _phar_pass_tar_info *)argument; char **error = i->error; phar_entry_info *entry = (phar_entry_info *)Z_PTR_P(zv), newentry = {0}; diff --git a/ext/phar/util.c b/ext/phar/util.c index 331bbf6511ba..e501ccfaceba 100644 --- a/ext/phar/util.c +++ b/ext/phar/util.c @@ -264,7 +264,7 @@ zend_result phar_mount_entry(phar_archive_data *phar, const char *filename, size } /* }}} */ -zend_string *phar_find_in_include_path(zend_string *filename, phar_archive_data **pphar) /* {{{ */ +zend_string *phar_find_in_include_path(const zend_string *filename, phar_archive_data **pphar) /* {{{ */ { zend_string *ret; char *path; diff --git a/ext/phar/zip.c b/ext/phar/zip.c index 8f61977a3835..900b41f9c794 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -794,7 +794,7 @@ zend_result phar_parse_zipfile(php_stream *fp, const char *fname, size_t fname_l /** * Create or open a zip-based phar for writing */ -ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_zip(zend_string *fname, char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_zip(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { phar_archive_data *phar; zend_result ret = phar_create_or_parse_filename(fname, alias, alias_len, is_data, options, &phar, error); From f1d6391f77e61a05a8d78ee07d14aa3fb2618e88 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Wed, 29 Apr 2026 10:31:36 +0100 Subject: [PATCH 017/213] ext/phar: mark phar_dostat() as static and mark parameters as const (#21908) And remove unused declaration from dirstream.c file --- ext/phar/dirstream.c | 2 -- ext/phar/stream.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/ext/phar/dirstream.c b/ext/phar/dirstream.c index bb46ece5b918..6c356c04e5e1 100644 --- a/ext/phar/dirstream.c +++ b/ext/phar/dirstream.c @@ -19,8 +19,6 @@ #include "phar_internal.h" #include "dirstream.h" -void phar_dostat(phar_archive_data *phar, phar_entry_info *data, php_stream_statbuf *ssb, bool is_dir); - static const php_stream_ops phar_dir_ops = { phar_dir_write, /* write */ phar_dir_read, /* read */ diff --git a/ext/phar/stream.c b/ext/phar/stream.c index f38f179238ff..f9d19a04122a 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -482,7 +482,7 @@ static int phar_stream_flush(php_stream *stream) /* {{{ */ /** * stat an opened phar file handle stream, used by phar_stat() */ -void phar_dostat(phar_archive_data *phar, phar_entry_info *data, php_stream_statbuf *ssb, bool is_temp_dir) +static void phar_dostat(const phar_archive_data *phar, const phar_entry_info *data, php_stream_statbuf *ssb, bool is_temp_dir) { memset(ssb, 0, sizeof(php_stream_statbuf)); From 392a84d7e1d39a55081bf00ee49f85cf45412d06 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Mon, 27 Apr 2026 12:39:01 +0100 Subject: [PATCH 018/213] ext/pgsql: clean up pg_fetch_object() constructor handling. Move object_init_ex() before php_pgsql_fetch_hash() so abstract, interface and enum errors surface earlier, look up the constructor via the get_constructor handler (under EG(fake_scope)) so classes with overridden handlers work, and mark the object as ctor-failed when the constructor throws. The ValueError for ctor args on a class without a constructor now reports argument 4 ($constructor_args) instead of argument 3 ($class). close GH-21884 --- NEWS | 4 ++ UPGRADING | 7 ++ ext/pgsql/pgsql.c | 41 +++++++---- .../tests/pg_fetch_object_ctor_paths.phpt | 69 +++++++++++++++++++ 4 files changed, 107 insertions(+), 14 deletions(-) create mode 100644 ext/pgsql/tests/pg_fetch_object_ctor_paths.phpt diff --git a/NEWS b/NEWS index 3da5464750cc..3144cdf88c59 100644 --- a/NEWS +++ b/NEWS @@ -104,6 +104,10 @@ PHP NEWS - PGSQL: . Enabled 64 bits support for pg_lo_truncate()/pg_lo_tell() if the server supports it. (KentarouTakeda) + . pg_fetch_object() now surfaces non-instantiable class errors + before fetching, resolves the constructor via the get_constructor + handler, and reports the empty-constructor ValueError on the + $constructor_args argument. (David Carlier) - Phar: . Support reference values in Phar::mungServer(). (ndossche) diff --git a/UPGRADING b/UPGRADING index 56049f30cf93..6777820642f6 100644 --- a/UPGRADING +++ b/UPGRADING @@ -47,6 +47,13 @@ PHP 8.6 UPGRADE NOTES . Phar::mungServer() now raises a ValueError when an invalid argument value is passed instead of being silently ignored. +- PGSQL: + . pg_fetch_object() now reports the ValueError for a non-empty + $constructor_args on a class without a constructor on the + $constructor_args argument instead of $class. Errors raised when + the requested class is not instantiable (abstract, interface, enum) + now surface before the row is fetched. + - Posix: . posix_access() now raises a ValueError when an invalid $flags argument value is passed. diff --git a/ext/pgsql/pgsql.c b/ext/pgsql/pgsql.c index 1674625429ad..8cb022c79cd1 100644 --- a/ext/pgsql/pgsql.c +++ b/ext/pgsql/pgsql.c @@ -2129,26 +2129,17 @@ PHP_FUNCTION(pg_fetch_object) ce = zend_standard_class_def; } - if (!ce->constructor && ctor_params && zend_hash_num_elements(ctor_params) > 0) { - zend_argument_value_error(3, - "must be empty when the specified class (%s) does not have a constructor", - ZSTR_VAL(ce->name) - ); + if (UNEXPECTED(object_init_ex(return_value, ce) == FAILURE)) { RETURN_THROWS(); } zval dataset; if (UNEXPECTED(!php_pgsql_fetch_hash(&dataset, result, row, row_is_null, PGSQL_ASSOC))) { /* Either an exception is thrown, or we return false */ + zval_ptr_dtor(return_value); RETURN_FALSE; } - // TODO: Check CE is an instantiable class earlier? - zend_result obj_initialized = object_init_ex(return_value, ce); - if (UNEXPECTED(obj_initialized == FAILURE)) { - zval_ptr_dtor(&dataset); - RETURN_THROWS(); - } if (!ce->default_properties_count && !ce->__set) { Z_OBJ_P(return_value)->properties = Z_ARR(dataset); } else { @@ -2156,10 +2147,32 @@ PHP_FUNCTION(pg_fetch_object) zval_ptr_dtor(&dataset); } - // TODO: Need to grab constructor via object handler as this allows instantiating internal objects with overridden get_constructor - if (ce->constructor) { - zend_call_known_function(ce->constructor, Z_OBJ_P(return_value), Z_OBJCE_P(return_value), + zend_object *obj = Z_OBJ_P(return_value); + const zend_class_entry *old = EG(fake_scope); + EG(fake_scope) = ce; + zend_function *constructor = obj->handlers->get_constructor(obj); + EG(fake_scope) = old; + + if (UNEXPECTED(EG(exception))) { + /* visibility error or override refused - VM dtors return_value */ + return; + } + + if (UNEXPECTED(!constructor && ctor_params && zend_hash_num_elements(ctor_params) > 0)) { + zend_argument_value_error(4, + "must be empty when the specified class (%s) does not have a constructor", + ZSTR_VAL(ce->name) + ); + RETURN_THROWS(); + } + + if (constructor) { + zend_call_known_function(constructor, obj, ce, /* retval */ NULL, /* argc */ 0, /* params */ NULL, ctor_params); + if (EG(exception)) { + zend_object_store_ctor_failed(obj); + RETURN_THROWS(); + } } } /* }}} */ diff --git a/ext/pgsql/tests/pg_fetch_object_ctor_paths.phpt b/ext/pgsql/tests/pg_fetch_object_ctor_paths.phpt new file mode 100644 index 000000000000..bd3df73acba4 --- /dev/null +++ b/ext/pgsql/tests/pg_fetch_object_ctor_paths.phpt @@ -0,0 +1,69 @@ +--TEST-- +pg_fetch_object() constructor handling: ctor_params validation, throwing constructor, property visibility +--EXTENSIONS-- +pgsql +--SKIPIF-- + +--FILE-- +num}, str={$this->str}\n"; + } + public function __destruct() { + echo "SeesProps::__destruct called\n"; + } +} + +$table_name = "pg_fetch_object_ctor_paths"; +$db = pg_connect($conn_str); +pg_query($db, "CREATE TABLE {$table_name} (num int, str text)"); +pg_query($db, "INSERT INTO {$table_name} VALUES(1, 'hello')"); + +$sql = "SELECT * FROM {$table_name} WHERE num = 1"; + +// 1) ctor_params on a class with no constructor must throw ValueError +try { + pg_fetch_object(pg_query($db, $sql), null, 'NoCtor', [1, 2]); +} catch (ValueError $e) { + echo $e->getMessage(), "\n"; +} + +// 2) Constructor that throws: __destruct must NOT run on the partially constructed object +try { + pg_fetch_object(pg_query($db, $sql), null, 'ThrowingCtor'); +} catch (RuntimeException $e) { + echo "caught: ", $e->getMessage(), "\n"; +} + +// 3) Constructor sees row properties already merged onto $this +$obj = pg_fetch_object(pg_query($db, $sql), null, 'SeesProps'); +unset($obj); + +echo "Ok\n"; +?> +--CLEAN-- + +--EXPECT-- +pg_fetch_object(): Argument #4 ($constructor_args) must be empty when the specified class (NoCtor) does not have a constructor +caught: boom +ctor sees: num=1, str=hello +SeesProps::__destruct called +Ok From 0d9ff00394d9447992bb66ccb1cef3edf70576bd Mon Sep 17 00:00:00 2001 From: Calvin Buckley Date: Wed, 29 Apr 2026 10:00:01 -0400 Subject: [PATCH 019/213] ext/odbc: Get the exact length for quoted connection string components (#21892) * ext/odbc: get exact length for quoted connection strings strlen has to scan the string until the end of the null terminator, we might as well do the same but scan for end quotes that need escaping. * ext/odbc: rename function now that it gets the exact length rather than an estimate --- ext/odbc/odbc_utils.c | 2 +- ext/odbc/php_odbc.c | 12 ++++++------ ext/pdo_odbc/odbc_driver.c | 12 ++++++------ main/php_odbc_utils.c | 16 ++++++++++++---- main/php_odbc_utils.h | 2 +- 5 files changed, 26 insertions(+), 18 deletions(-) diff --git a/ext/odbc/odbc_utils.c b/ext/odbc/odbc_utils.c index 742bf54bb292..8468fa9a06c1 100644 --- a/ext/odbc/odbc_utils.c +++ b/ext/odbc/odbc_utils.c @@ -57,7 +57,7 @@ PHP_FUNCTION(odbc_connection_string_quote) Z_PARAM_STR(str) ZEND_PARSE_PARAMETERS_END(); - size_t new_size = php_odbc_connstr_estimate_quote_length(ZSTR_VAL(str)); + size_t new_size = php_odbc_connstr_get_quoted_length(ZSTR_VAL(str)); zend_string *new_string = zend_string_alloc(new_size, 0); php_odbc_connstr_quote(ZSTR_VAL(new_string), ZSTR_VAL(str), new_size); /* reset length */ diff --git a/ext/odbc/php_odbc.c b/ext/odbc/php_odbc.c index 2d6331b0f544..c9f1b3f2e147 100644 --- a/ext/odbc/php_odbc.c +++ b/ext/odbc/php_odbc.c @@ -1951,9 +1951,9 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool if (use_uid_arg) { should_quote_uid = !php_odbc_connstr_is_quoted(uid) && php_odbc_connstr_should_quote(uid); if (should_quote_uid) { - size_t estimated_length = php_odbc_connstr_estimate_quote_length(uid); - uid_quoted = emalloc(estimated_length); - php_odbc_connstr_quote(uid_quoted, uid, estimated_length); + size_t quoted_length = php_odbc_connstr_get_quoted_length(uid); + uid_quoted = emalloc(quoted_length); + php_odbc_connstr_quote(uid_quoted, uid, quoted_length); } else { uid_quoted = uid; } @@ -1966,9 +1966,9 @@ bool odbc_sqlconnect(zval *zv, char *db, char *uid, char *pwd, int cur_opt, bool if (use_pwd_arg) { should_quote_pwd = !php_odbc_connstr_is_quoted(pwd) && php_odbc_connstr_should_quote(pwd); if (should_quote_pwd) { - size_t estimated_length = php_odbc_connstr_estimate_quote_length(pwd); - pwd_quoted = emalloc(estimated_length); - php_odbc_connstr_quote(pwd_quoted, pwd, estimated_length); + size_t quoted_length = php_odbc_connstr_get_quoted_length(pwd); + pwd_quoted = emalloc(quoted_length); + php_odbc_connstr_quote(pwd_quoted, pwd, quoted_length); } else { pwd_quoted = pwd; } diff --git a/ext/pdo_odbc/odbc_driver.c b/ext/pdo_odbc/odbc_driver.c index 4c627419d18e..3c8afe2d4215 100644 --- a/ext/pdo_odbc/odbc_driver.c +++ b/ext/pdo_odbc/odbc_driver.c @@ -548,9 +548,9 @@ static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ if (use_uid_arg) { should_quote_uid = !php_odbc_connstr_is_quoted(dbh->username) && php_odbc_connstr_should_quote(dbh->username); if (should_quote_uid) { - size_t estimated_length = php_odbc_connstr_estimate_quote_length(dbh->username); - uid = emalloc(estimated_length); - php_odbc_connstr_quote(uid, dbh->username, estimated_length); + size_t quoted_length = php_odbc_connstr_get_quoted_length(dbh->username); + uid = emalloc(quoted_length); + php_odbc_connstr_quote(uid, dbh->username, quoted_length); } else { uid = dbh->username; } @@ -565,9 +565,9 @@ static int pdo_odbc_handle_factory(pdo_dbh_t *dbh, zval *driver_options) /* {{{ if (use_pwd_arg) { should_quote_pwd = !php_odbc_connstr_is_quoted(dbh->password) && php_odbc_connstr_should_quote(dbh->password); if (should_quote_pwd) { - size_t estimated_length = php_odbc_connstr_estimate_quote_length(dbh->password); - pwd = emalloc(estimated_length); - php_odbc_connstr_quote(pwd, dbh->password, estimated_length); + size_t quoted_length = php_odbc_connstr_get_quoted_length(dbh->password); + pwd = emalloc(quoted_length); + php_odbc_connstr_quote(pwd, dbh->password, quoted_length); } else { pwd = dbh->password; } diff --git a/main/php_odbc_utils.c b/main/php_odbc_utils.c index d3b18f2bd642..797a4ac04be1 100644 --- a/main/php_odbc_utils.c +++ b/main/php_odbc_utils.c @@ -71,12 +71,20 @@ PHPAPI bool php_odbc_connstr_should_quote(const char *str) } /** - * Estimates the worst-case scenario for a quoted version of a string's size. + * Gets the length of a string after it has been quoted. */ -PHPAPI size_t php_odbc_connstr_estimate_quote_length(const char *in_str) +PHPAPI size_t php_odbc_connstr_get_quoted_length(const char *in_str) { - /* Assume all '}'. Include '{,' '}', and the null terminator too */ - return (strlen(in_str) * 2) + 3; + /* Start with including the quotes ({}) and the null terminator */ + size_t size = 3; + /* Scan the string like strlen, doubling each } character. */ + while (*in_str) { + size++; + if (*in_str++ == '}') { + size++; + } + } + return size; } /** diff --git a/main/php_odbc_utils.h b/main/php_odbc_utils.h index 78353b49a814..f2bc46ebc5ba 100644 --- a/main/php_odbc_utils.h +++ b/main/php_odbc_utils.h @@ -16,5 +16,5 @@ PHPAPI bool php_odbc_connstr_is_quoted(const char *str); PHPAPI bool php_odbc_connstr_should_quote(const char *str); -PHPAPI size_t php_odbc_connstr_estimate_quote_length(const char *in_str); +PHPAPI size_t php_odbc_connstr_get_quoted_length(const char *in_str); PHPAPI size_t php_odbc_connstr_quote(char *out_str, const char *in_str, size_t out_str_size); From 3d7e970d0ada5d7d7b9caa00b707db0dc1dc4b30 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 30 Apr 2026 00:45:04 +0200 Subject: [PATCH 020/213] [skip ci] Remove redundant ext/dom/lexbor/patches from PHP-8.5 Those are the result of a bad upmerge. They were moved to ext/lexbor/patches, and were present twice in this branch. --- ...nd-column-information-for-use-in-PHP.patch | 188 ------------------ ...d-added-nodes-for-options-use-in-PHP.patch | 67 ------- ...and-data-structure-to-be-able-to-gen.patch | 97 --------- ...ve-unused-upper-case-tag-static-data.patch | 53 ----- ...nk-size-of-static-binary-search-tree.patch | 116 ----------- ...0006-Patch-out-unused-CSS-style-code.patch | 32 --- 6 files changed, 553 deletions(-) delete mode 100644 ext/dom/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch delete mode 100644 ext/dom/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch delete mode 100644 ext/dom/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch delete mode 100644 ext/dom/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch delete mode 100644 ext/dom/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch delete mode 100644 ext/dom/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch diff --git a/ext/dom/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch b/ext/dom/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch deleted file mode 100644 index 32d9d42d2bf1..000000000000 --- a/ext/dom/lexbor/patches/0001-Expose-line-and-column-information-for-use-in-PHP.patch +++ /dev/null @@ -1,188 +0,0 @@ -From 0cd2add6c46400b808329442f81451b369863983 Mon Sep 17 00:00:00 2001 -From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> -Date: Sat, 26 Aug 2023 15:08:59 +0200 -Subject: [PATCH 1/6] Expose line and column information for use in PHP - ---- - source/lexbor/dom/interfaces/node.h | 2 ++ - source/lexbor/html/token.h | 2 ++ - source/lexbor/html/tokenizer.c | 24 +++++++++++++++++++++++- - source/lexbor/html/tokenizer.h | 2 ++ - source/lexbor/html/tokenizer/state.h | 2 ++ - source/lexbor/html/tree.c | 11 +++++++++++ - source/lexbor/html/tree/error.c | 5 +++-- - source/lexbor/html/tree/error.h | 5 +++-- - 8 files changed, 48 insertions(+), 5 deletions(-) - -diff --git a/source/lexbor/dom/interfaces/node.h b/source/lexbor/dom/interfaces/node.h -index 6c74ac5..b95373c 100644 ---- a/source/lexbor/dom/interfaces/node.h -+++ b/source/lexbor/dom/interfaces/node.h -@@ -86,6 +86,8 @@ struct lxb_dom_node { - - lxb_dom_node_type_t type; - -+ size_t line; -+ - #ifdef LXB_DOM_NODE_USER_VARIABLES - LXB_DOM_NODE_USER_VARIABLES - #endif /* LXB_DOM_NODE_USER_VARIABLES */ -diff --git a/source/lexbor/html/token.h b/source/lexbor/html/token.h -index 79accd0..0b7f4fd 100644 ---- a/source/lexbor/html/token.h -+++ b/source/lexbor/html/token.h -@@ -33,6 +33,8 @@ enum lxb_html_token_type { - typedef struct { - const lxb_char_t *begin; - const lxb_char_t *end; -+ size_t line; -+ size_t column; - - const lxb_char_t *text_start; - const lxb_char_t *text_end; -diff --git a/source/lexbor/html/tokenizer.c b/source/lexbor/html/tokenizer.c -index 22b88ed..1d9f378 100644 ---- a/source/lexbor/html/tokenizer.c -+++ b/source/lexbor/html/tokenizer.c -@@ -92,6 +92,7 @@ lxb_html_tokenizer_init(lxb_html_tokenizer_t *tkz) - - tkz->pos = tkz->start; - tkz->end = tkz->start + LXB_HTML_TKZ_TEMP_SIZE; -+ /* current_line & current_column already initialized by calloc (zero-based) */ - - tkz->tree = NULL; - tkz->tags = NULL; -@@ -153,6 +154,8 @@ lxb_html_tokenizer_inherit(lxb_html_tokenizer_t *tkz_to, - tkz_to->start = tkz_from->start; - tkz_to->end = tkz_from->end; - tkz_to->pos = tkz_to->start; -+ tkz_to->current_line = tkz_from->current_line; -+ tkz_to->current_column = tkz_from->current_column; - - return LXB_STATUS_OK; - } -@@ -571,7 +574,26 @@ lxb_html_tokenizer_chunk(lxb_html_tokenizer_t *tkz, const lxb_char_t *data, - tkz->last = end; - - while (data < end) { -- data = tkz->state(tkz, data, end); -+ size_t current_column = tkz->current_column; -+ const lxb_char_t *new_data = tkz->state(tkz, data, end); -+ while (data < new_data) { -+ /* Codepoints < 0x80 are encoded the same as their ASCII counterpart, so '\n' will uniquely identify a newline. */ -+ if (*data == '\n') { -+ tkz->current_line++; -+ current_column = 0; -+ } else { -+ /* Other characters can be mapped back to the unicode codepoint offset because UTF-8 is a prefix code. -+ * Continuation bytes start with 0b10XXXXXX so we can skip those to only get the start of an encoded code point. */ -+ if ((*data & 0b11000000) == 0b10000000) { -+ /* Continuation byte, do nothing */ -+ } else { -+ /* First byte for a codepoint */ -+ current_column++; -+ } -+ } -+ data++; -+ } -+ tkz->current_column = current_column; - } - - return tkz->status; -diff --git a/source/lexbor/html/tokenizer.h b/source/lexbor/html/tokenizer.h -index 12b7c81..aa1ac37 100644 ---- a/source/lexbor/html/tokenizer.h -+++ b/source/lexbor/html/tokenizer.h -@@ -79,6 +79,8 @@ struct lxb_html_tokenizer { - const lxb_char_t *end; - const lxb_char_t *begin; - const lxb_char_t *last; -+ size_t current_line; -+ size_t current_column; - - /* Entities */ - const lexbor_sbst_entry_static_t *entity; -diff --git a/source/lexbor/html/tokenizer/state.h b/source/lexbor/html/tokenizer/state.h -index 5e91444..52eaa9a 100644 ---- a/source/lexbor/html/tokenizer/state.h -+++ b/source/lexbor/html/tokenizer/state.h -@@ -90,6 +90,8 @@ extern "C" { - do { \ - tkz->pos = tkz->start; \ - tkz->token->begin = v_begin; \ -+ tkz->token->line = tkz->current_line; \ -+ tkz->token->column = tkz->current_column; \ - } \ - while (0) - -diff --git a/source/lexbor/html/tree.c b/source/lexbor/html/tree.c -index 062ea56..3f4c18d 100644 ---- a/source/lexbor/html/tree.c -+++ b/source/lexbor/html/tree.c -@@ -431,6 +431,9 @@ lxb_html_tree_create_element_for_token(lxb_html_tree_t *tree, - return NULL; - } - -+ node->line = token->line; -+ /* We only expose line number in PHP DOM */ -+ - lxb_status_t status; - lxb_dom_element_t *element = lxb_dom_interface_element(node); - -@@ -767,6 +770,11 @@ lxb_html_tree_insert_character_for_data(lxb_html_tree_t *tree, - - lxb_dom_interface_text(text)->char_data.data = *str; - -+ if (tree->tkz_ref) { -+ text->line = tree->tkz_ref->token->line; -+ /* We only expose line number in PHP DOM */ -+ } -+ - if (ret_node != NULL) { - *ret_node = text; - } -@@ -806,6 +814,9 @@ lxb_html_tree_insert_comment(lxb_html_tree_t *tree, - return NULL; - } - -+ node->line = token->line; -+ /* We only expose line number in PHP DOM */ -+ - tree->status = lxb_html_token_make_text(token, &comment->char_data.data, - tree->document->dom_document.text); - if (tree->status != LXB_STATUS_OK) { -diff --git a/source/lexbor/html/tree/error.c b/source/lexbor/html/tree/error.c -index ffdc55c..ef36eab 100644 ---- a/source/lexbor/html/tree/error.c -+++ b/source/lexbor/html/tree/error.c -@@ -22,8 +22,9 @@ lxb_html_tree_error_add(lexbor_array_obj_t *parse_errors, - } - - entry->id = id; -- entry->begin = token->begin; -- entry->end = token->end; -+ entry->line = token->line; -+ entry->column = token->column; -+ entry->length = token->end - token->begin; - - return entry; - } -diff --git a/source/lexbor/html/tree/error.h b/source/lexbor/html/tree/error.h -index 7a212af..b186772 100644 ---- a/source/lexbor/html/tree/error.h -+++ b/source/lexbor/html/tree/error.h -@@ -109,8 +109,9 @@ lxb_html_tree_error_id_t; - - typedef struct { - lxb_html_tree_error_id_t id; -- const lxb_char_t *begin; -- const lxb_char_t *end; -+ size_t line; -+ size_t column; -+ size_t length; - } - lxb_html_tree_error_t; - --- -2.51.2 - diff --git a/ext/dom/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch b/ext/dom/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch deleted file mode 100644 index 1902abf96e3a..000000000000 --- a/ext/dom/lexbor/patches/0002-Track-implied-added-nodes-for-options-use-in-PHP.patch +++ /dev/null @@ -1,67 +0,0 @@ -From a4c29ba8d1ea1065ce6bd4a34382d53140cf1924 Mon Sep 17 00:00:00 2001 -From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> -Date: Mon, 14 Aug 2023 20:18:51 +0200 -Subject: [PATCH 2/6] Track implied added nodes for options use in PHP - ---- - source/lexbor/html/tree.h | 3 +++ - source/lexbor/html/tree/insertion_mode/after_head.c | 1 + - source/lexbor/html/tree/insertion_mode/before_head.c | 2 ++ - source/lexbor/html/tree/insertion_mode/before_html.c | 2 ++ - 4 files changed, 8 insertions(+) - -diff --git a/source/lexbor/html/tree.h b/source/lexbor/html/tree.h -index 4912efb..7b2c620 100644 ---- a/source/lexbor/html/tree.h -+++ b/source/lexbor/html/tree.h -@@ -55,6 +55,9 @@ struct lxb_html_tree { - bool foster_parenting; - bool frameset_ok; - bool scripting; -+ bool has_explicit_html_tag; -+ bool has_explicit_head_tag; -+ bool has_explicit_body_tag; - - lxb_html_tree_insertion_mode_f mode; - lxb_html_tree_insertion_mode_f original_mode; -diff --git a/source/lexbor/html/tree/insertion_mode/after_head.c b/source/lexbor/html/tree/insertion_mode/after_head.c -index ad551b5..1448654 100644 ---- a/source/lexbor/html/tree/insertion_mode/after_head.c -+++ b/source/lexbor/html/tree/insertion_mode/after_head.c -@@ -71,6 +71,7 @@ lxb_html_tree_insertion_mode_after_head_open(lxb_html_tree_t *tree, - return lxb_html_tree_process_abort(tree); - } - -+ tree->has_explicit_body_tag = true; - tree->frameset_ok = false; - tree->mode = lxb_html_tree_insertion_mode_in_body; - -diff --git a/source/lexbor/html/tree/insertion_mode/before_head.c b/source/lexbor/html/tree/insertion_mode/before_head.c -index 14621f2..cd2ac2a 100644 ---- a/source/lexbor/html/tree/insertion_mode/before_head.c -+++ b/source/lexbor/html/tree/insertion_mode/before_head.c -@@ -67,6 +67,8 @@ lxb_html_tree_insertion_mode_before_head_open(lxb_html_tree_t *tree, - return lxb_html_tree_process_abort(tree); - } - -+ tree->has_explicit_head_tag = true; -+ - tree->mode = lxb_html_tree_insertion_mode_in_head; - - break; -diff --git a/source/lexbor/html/tree/insertion_mode/before_html.c b/source/lexbor/html/tree/insertion_mode/before_html.c -index 05fe738..1e09cda 100644 ---- a/source/lexbor/html/tree/insertion_mode/before_html.c -+++ b/source/lexbor/html/tree/insertion_mode/before_html.c -@@ -78,6 +78,8 @@ lxb_html_tree_insertion_mode_before_html_open(lxb_html_tree_t *tree, - return lxb_html_tree_process_abort(tree); - } - -+ tree->has_explicit_html_tag = true; -+ - tree->mode = lxb_html_tree_insertion_mode_before_head; - - break; --- -2.51.2 - diff --git a/ext/dom/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch b/ext/dom/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch deleted file mode 100644 index 51f77483bc6e..000000000000 --- a/ext/dom/lexbor/patches/0003-Patch-utilities-and-data-structure-to-be-able-to-gen.patch +++ /dev/null @@ -1,97 +0,0 @@ -From 46fc776449252e74795569759a19d13857a59069 Mon Sep 17 00:00:00 2001 -From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> -Date: Thu, 24 Aug 2023 22:57:48 +0200 -Subject: [PATCH 3/6] Patch utilities and data structure to be able to generate - smaller lookup tables - -Changed the generation script to check if everything fits in 32-bits. -And change the actual field types to 32-bits. This decreases the hash -tables in size. ---- - source/lexbor/core/shs.h | 4 ++-- - utils/lexbor/encoding/single-byte.py | 4 ++-- - utils/lexbor/lexbor/LXB.py | 12 +++++++++--- - 3 files changed, 13 insertions(+), 7 deletions(-) - -diff --git a/source/lexbor/core/shs.h b/source/lexbor/core/shs.h -index 7a63a07..c84dfaa 100644 ---- a/source/lexbor/core/shs.h -+++ b/source/lexbor/core/shs.h -@@ -27,9 +27,9 @@ lexbor_shs_entry_t; - - typedef struct { - uint32_t key; -- void *value; -+ uint32_t value; - -- size_t next; -+ uint32_t next; - } - lexbor_shs_hash_t; - -diff --git a/utils/lexbor/encoding/single-byte.py b/utils/lexbor/encoding/single-byte.py -index d7d1bb2..5420c16 100755 ---- a/utils/lexbor/encoding/single-byte.py -+++ b/utils/lexbor/encoding/single-byte.py -@@ -128,7 +128,7 @@ class SingleByte: - entries = values[idx] - key_id = entries[1].decode('utf-8') - -- hash_key.append(key_id, '(void *) {}'.format(idx + 0x80)) -+ hash_key.append(key_id, idx + 0x80) - - return hash_key.create(rate = 1) - -@@ -161,7 +161,7 @@ def toHex(s): - lst = [] - - for ch in bytes(s, 'utf-8'): -- hv = hex(ch).replace('0x', '\\\\x') -+ hv = hex(ch).replace('0x', '\\x') - lst.append("'{}'".format(hv)) - - return ', '.join(lst) -diff --git a/utils/lexbor/lexbor/LXB.py b/utils/lexbor/lexbor/LXB.py -index 3e75812..2370c66 100755 ---- a/utils/lexbor/lexbor/LXB.py -+++ b/utils/lexbor/lexbor/LXB.py -@@ -94,7 +94,7 @@ class HashKey: - def append(self, key_id, value): - self.buffer.append([self.hash_id(int(key_id, 0)), value]) - -- def create(self, terminate_value = '{0, NULL, 0}', rate = 2, is_const = True, data_before = None): -+ def create(self, terminate_value = '{0, 0, 0}', rate = 2, is_const = True, data_before = None): - test = self.test(int(self.max_table_size / 1.2), int(self.max_table_size * 1.2)) - - rate_dn = rate - 1 -@@ -142,9 +142,12 @@ class HashKey: - entry = table[idx] - - if entry: -+ assert entry[0] < 2**32 -+ assert entry[1] < 2**32 -+ assert entry[2] < 2**32 - result.append("{{{}, {}, {}}},".format(entry[0], entry[1], entry[2])) - else: -- result.append("{0, NULL, 0},") -+ result.append("{0, 0, 0},") - - if int(idx) % rate == rate_dn: - result.append("\n ") -@@ -154,9 +157,12 @@ class HashKey: - if len(table): - entry = table[-1] - if entry: -+ assert entry[0] < 2**32 -+ assert entry[1] < 2**32 -+ assert entry[2] < 2**32 - result.append("{{{}, {}, {}}}\n".format(entry[0], entry[1], entry[2])) - else: -- result.append("{0, NULL, 0}\n") -+ result.append("{0, 0, 0}\n") - - result.append("};") - --- -2.51.2 - diff --git a/ext/dom/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch b/ext/dom/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch deleted file mode 100644 index 6cb6658a164b..000000000000 --- a/ext/dom/lexbor/patches/0004-Remove-unused-upper-case-tag-static-data.patch +++ /dev/null @@ -1,53 +0,0 @@ -From ae9d7254ac129cc3be34de6fd34af27baf3bb396 Mon Sep 17 00:00:00 2001 -From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> -Date: Wed, 29 Nov 2023 21:26:47 +0100 -Subject: [PATCH 4/6] Remove unused upper case tag static data - ---- - source/lexbor/tag/res.h | 2 ++ - source/lexbor/tag/tag.c | 2 ++ - 2 files changed, 4 insertions(+) - -diff --git a/source/lexbor/tag/res.h b/source/lexbor/tag/res.h -index 604757f..5672d4a 100644 ---- a/source/lexbor/tag/res.h -+++ b/source/lexbor/tag/res.h -@@ -226,6 +226,7 @@ static const lxb_tag_data_t lxb_tag_res_data_default[LXB_TAG__LAST_ENTRY] = - {{.u.short_str = "xmp", .length = 3, .next = NULL}, LXB_TAG_XMP, 1, true} - }; - -+#if 0 - static const lxb_tag_data_t lxb_tag_res_data_upper_default[LXB_TAG__LAST_ENTRY] = - { - {{.u.short_str = "#UNDEF", .length = 6, .next = NULL}, LXB_TAG__UNDEF, 1, true}, -@@ -427,6 +428,7 @@ static const lxb_tag_data_t lxb_tag_res_data_upper_default[LXB_TAG__LAST_ENTRY] - {{.u.short_str = "WBR", .length = 3, .next = NULL}, LXB_TAG_WBR, 1, true}, - {{.u.short_str = "XMP", .length = 3, .next = NULL}, LXB_TAG_XMP, 1, true} - }; -+#endif - - static const lexbor_shs_entry_t lxb_tag_res_shs_data_default[263] = - { -diff --git a/source/lexbor/tag/tag.c b/source/lexbor/tag/tag.c -index 780bc47..be5bb30 100644 ---- a/source/lexbor/tag/tag.c -+++ b/source/lexbor/tag/tag.c -@@ -92,6 +92,7 @@ lxb_tag_data_by_name(lexbor_hash_t *hash, const lxb_char_t *name, size_t len) - lexbor_hash_search_lower, name, len); - } - -+#if 0 - const lxb_tag_data_t * - lxb_tag_data_by_name_upper(lexbor_hash_t *hash, - const lxb_char_t *name, size_t len) -@@ -114,6 +115,7 @@ lxb_tag_data_by_name_upper(lexbor_hash_t *hash, - return (const lxb_tag_data_t *) lexbor_hash_search(hash, - lexbor_hash_search_upper, name, len); - } -+#endif - - /* - * No inline functions for ABI. --- -2.51.2 - diff --git a/ext/dom/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch b/ext/dom/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch deleted file mode 100644 index 9ef6e305e498..000000000000 --- a/ext/dom/lexbor/patches/0005-Shrink-size-of-static-binary-search-tree.patch +++ /dev/null @@ -1,116 +0,0 @@ -From 19cf6183813e013dfe0eb2303c15eaf6e01b9faf Mon Sep 17 00:00:00 2001 -From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> -Date: Wed, 29 Nov 2023 21:29:31 +0100 -Subject: [PATCH 5/6] Shrink size of static binary search tree - -This also makes it more efficient on the data cache. ---- - source/lexbor/core/sbst.h | 19 ++++++++++++++----- - source/lexbor/html/tokenizer/state.c | 2 +- - utils/lexbor/html/tokenizer_entities_bst.py | 8 ++++---- - utils/lexbor/lexbor/LXB.py | 2 +- - 4 files changed, 20 insertions(+), 11 deletions(-) - -diff --git a/source/lexbor/core/sbst.h b/source/lexbor/core/sbst.h -index b0fbc54..15a1d40 100644 ---- a/source/lexbor/core/sbst.h -+++ b/source/lexbor/core/sbst.h -@@ -15,16 +15,25 @@ extern "C" { - - #include "lexbor/core/base.h" - -+#ifdef __has_attribute -+# if __has_attribute(nonstring) && defined(__GNUC__) && !defined(__clang__) && __GNUC__ >= 15 -+# define LXB_NONSTRING __attribute__((nonstring)) -+# else -+# define LXB_NONSTRING -+# endif -+#else -+# define LXB_NONSTRING -+#endif - - typedef struct { - lxb_char_t key; - -- void *value; -- size_t value_len; -+ lxb_char_t value[6] LXB_NONSTRING; -+ unsigned char value_len; - -- size_t left; -- size_t right; -- size_t next; -+ unsigned short left; -+ unsigned short right; -+ unsigned short next; - } - lexbor_sbst_entry_static_t; - -diff --git a/source/lexbor/html/tokenizer/state.c b/source/lexbor/html/tokenizer/state.c -index db362c6..6c3cbeb 100644 ---- a/source/lexbor/html/tokenizer/state.c -+++ b/source/lexbor/html/tokenizer/state.c -@@ -1825,7 +1825,7 @@ lxb_html_tokenizer_state_char_ref_named(lxb_html_tokenizer_t *tkz, - goto done; - } - -- if (entry->value != NULL) { -+ if (entry->value[0] != 0) { - tkz->entity_end = (tkz->pos + (data - begin)) - tkz->start; - tkz->entity_match = entry; - } -diff --git a/utils/lexbor/html/tokenizer_entities_bst.py b/utils/lexbor/html/tokenizer_entities_bst.py -index b34bca1..2bfea81 100755 ---- a/utils/lexbor/html/tokenizer_entities_bst.py -+++ b/utils/lexbor/html/tokenizer_entities_bst.py -@@ -1,6 +1,6 @@ - - import json --import sys, re, os -+import sys, os - - # Find and append run script run dir to module search path - ABS_PATH = os.path.dirname(os.path.abspath(__file__)) -@@ -62,7 +62,7 @@ def entities_bst_create_layer(name, entry, index): - - def entities_bst_create(index): - bst = {} -- bst[0] = ["\0", 0, 0, 0, "NULL"] -+ bst[0] = ["\0", 0, 0, 0, "{0}"] - - begin = 1 - idx = end = entities_bst_create_tree(index, bst, begin) -@@ -114,7 +114,7 @@ def entities_bst_create_tree(index, bst, idx): - assert len(index[ split[0] ]['values']) < 2, 'Double values' - - if len(index[ split[0] ]['values']) == 0: -- value = "NULL" -+ value = "{0}" - else: - value = '"{}"'.format(toHex(index[ split[0] ]['values'][0]['characters'])) - -@@ -146,7 +146,7 @@ def toHex(s): - lst = [] - - for ch in bytes(s, 'utf-8'): -- hv = hex(ch).replace('0x', '\\\\x') -+ hv = hex(ch).replace('0x', '\\x') - lst.append(hv) - - return ''.join(lst) -diff --git a/utils/lexbor/lexbor/LXB.py b/utils/lexbor/lexbor/LXB.py -index 2370c66..c41e645 100755 ---- a/utils/lexbor/lexbor/LXB.py -+++ b/utils/lexbor/lexbor/LXB.py -@@ -27,7 +27,7 @@ class Temp: - - for line in fh: - for name in self.patterns: -- line = re.sub(name, '\n'.join(self.patterns[name]), line) -+ line = line.replace(name, '\n'.join(self.patterns[name])) - self.buffer.append(line) - fh.close() - --- -2.51.2 - diff --git a/ext/dom/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch b/ext/dom/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch deleted file mode 100644 index a643f9716488..000000000000 --- a/ext/dom/lexbor/patches/0006-Patch-out-unused-CSS-style-code.patch +++ /dev/null @@ -1,32 +0,0 @@ -From 54399ee441d922d89c32909e2028f899f6091cd6 Mon Sep 17 00:00:00 2001 -From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> -Date: Sun, 7 Jan 2024 21:59:28 +0100 -Subject: [PATCH 6/6] Patch out unused CSS style code - ---- - source/lexbor/css/rule.h | 2 ++ - 1 file changed, 2 insertions(+) - -diff --git a/source/lexbor/css/rule.h b/source/lexbor/css/rule.h -index 308dced..d192a01 100644 ---- a/source/lexbor/css/rule.h -+++ b/source/lexbor/css/rule.h -@@ -361,6 +361,7 @@ lxb_css_rule_ref_dec(lxb_css_rule_t *rule) - lxb_inline void - lxb_css_rule_ref_dec_destroy(lxb_css_rule_t *rule) - { -+#if 0 - if (rule->ref_count > 0) { - rule->ref_count--; - } -@@ -368,6 +369,7 @@ lxb_css_rule_ref_dec_destroy(lxb_css_rule_t *rule) - if (rule->ref_count == 0) { - (void) lxb_css_rule_destroy(rule, true); - } -+#endif - } - - lxb_inline void --- -2.51.2 - From ca08e0ff72215739b6ac959dd58a7ceb0b314b99 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Thu, 30 Apr 2026 00:29:13 +0200 Subject: [PATCH 021/213] Fix ext-dom shared build on Windows Fix ADD_SOURCES() target parameter for lexbor sources. This was the result of an incorrect upmerge from PHP 8.4 into 8.5. Fixes GH-21911 Closes GH-21912 Co-authored-by: nono303 --- ext/lexbor/config.w32 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ext/lexbor/config.w32 b/ext/lexbor/config.w32 index 44ddfe1ffae4..e75798e06187 100644 --- a/ext/lexbor/config.w32 +++ b/ext/lexbor/config.w32 @@ -11,10 +11,10 @@ ADD_SOURCES("ext/lexbor/lexbor/html/tree", "active_formatting.c open_elements.c ADD_SOURCES("ext/lexbor/lexbor/html/tree/insertion_mode", "after_after_body.c after_after_frameset.c after_body.c after_frameset.c after_head.c before_head.c before_html.c foreign_content.c in_body.c in_caption.c in_cell.c in_column_group.c in_frameset.c in_head.c in_head_noscript.c initial.c in_row.c in_table_body.c in_table.c in_table_text.c in_template.c text.c","lexbor"); ADD_SOURCES("ext/lexbor/lexbor/html", "encoding.c interface.c parser.c tag.c token.c token_attr.c tokenizer.c tree.c","lexbor"); ADD_SOURCES("ext/lexbor/lexbor/encoding", "decode.c encode.c encoding.c multi.c range.c res.c single.c","lexbor"); -ADD_SOURCES("ext/lexbor/lexbor/html/interfaces", "anchor_element.c area_element.c audio_element.c base_element.c body_element.c br_element.c button_element.c canvas_element.c data_element.c data_list_element.c details_element.c dialog_element.c directory_element.c div_element.c d_list_element.c document.c element.c embed_element.c field_set_element.c font_element.c form_element.c frame_element.c frame_set_element.c head_element.c heading_element.c hr_element.c html_element.c iframe_element.c image_element.c input_element.c label_element.c legend_element.c li_element.c link_element.c map_element.c marquee_element.c media_element.c menu_element.c meta_element.c meter_element.c mod_element.c object_element.c o_list_element.c opt_group_element.c option_element.c output_element.c paragraph_element.c param_element.c picture_element.c pre_element.c progress_element.c quote_element.c script_element.c search_element.c select_element.c selectedcontent_element.c slot_element.c source_element.c span_element.c style_element.c table_caption_element.c table_cell_element.c table_col_element.c table_element.c table_row_element.c table_section_element.c template_element.c text_area_element.c time_element.c title_element.c track_element.c u_list_element.c unknown_element.c video_element.c window.c", "dom"); -ADD_SOURCES("ext/lexbor/lexbor/css", "at_rule.c blank.c css.c declaration.c log.c parser.c property.c rule.c state.c stylesheet.c unit.c value.c", "dom"); -ADD_SOURCES("ext/lexbor/lexbor/css/at_rule", "state.c", "dom"); -ADD_SOURCES("ext/lexbor/lexbor/css/property", "state.c", "dom"); +ADD_SOURCES("ext/lexbor/lexbor/html/interfaces", "anchor_element.c area_element.c audio_element.c base_element.c body_element.c br_element.c button_element.c canvas_element.c data_element.c data_list_element.c details_element.c dialog_element.c directory_element.c div_element.c d_list_element.c document.c element.c embed_element.c field_set_element.c font_element.c form_element.c frame_element.c frame_set_element.c head_element.c heading_element.c hr_element.c html_element.c iframe_element.c image_element.c input_element.c label_element.c legend_element.c li_element.c link_element.c map_element.c marquee_element.c media_element.c menu_element.c meta_element.c meter_element.c mod_element.c object_element.c o_list_element.c opt_group_element.c option_element.c output_element.c paragraph_element.c param_element.c picture_element.c pre_element.c progress_element.c quote_element.c script_element.c search_element.c select_element.c selectedcontent_element.c slot_element.c source_element.c span_element.c style_element.c table_caption_element.c table_cell_element.c table_col_element.c table_element.c table_row_element.c table_section_element.c template_element.c text_area_element.c time_element.c title_element.c track_element.c u_list_element.c unknown_element.c video_element.c window.c", "lexbor"); +ADD_SOURCES("ext/lexbor/lexbor/css", "at_rule.c blank.c css.c declaration.c log.c parser.c property.c rule.c state.c stylesheet.c unit.c value.c", "lexbor"); +ADD_SOURCES("ext/lexbor/lexbor/css/at_rule", "state.c", "lexbor"); +ADD_SOURCES("ext/lexbor/lexbor/css/property", "state.c", "lexbor"); ADD_SOURCES("ext/lexbor/lexbor/css/selectors", "state.c selectors.c selector.c pseudo_state.c pseudo.c","lexbor"); ADD_SOURCES("ext/lexbor/lexbor/css/syntax", "state.c parser.c syntax.c anb.c tokenizer.c token.c","lexbor"); ADD_SOURCES("ext/lexbor/lexbor/css/syntax/tokenizer", "error.c","lexbor"); From 7a3d889ad8ef0f3425b83653f96e3649065e5930 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Thu, 30 Apr 2026 21:41:39 +0800 Subject: [PATCH 022/213] ext/zlib: Remove zval_get_long usage in inflate_init() (#21909) This is a follow-up on the removal of the silent casts in deflate_init(). --- NEWS | 2 ++ UPGRADING | 2 ++ .../tests/inflate_init_window_type_error.phpt | 16 ++++++++++++++++ ext/zlib/zlib.c | 8 +++----- 4 files changed, 23 insertions(+), 5 deletions(-) create mode 100644 ext/zlib/tests/inflate_init_window_type_error.phpt diff --git a/NEWS b/NEWS index 3144cdf88c59..9d0025319121 100644 --- a/NEWS +++ b/NEWS @@ -211,5 +211,7 @@ PHP NEWS . deflate_init() now raises a TypeError when the value for option "level", "memory", "window", or "strategy" is not of type int. (Weilin Du) + . inflate_init() now raises a TypeError when the value for option + "window" is not of type int. (Weilin Du) <<< NOTE: Insert NEWS from last stable release here prior to actual release! >>> diff --git a/UPGRADING b/UPGRADING index 6777820642f6..4942b6e88ed2 100644 --- a/UPGRADING +++ b/UPGRADING @@ -111,6 +111,8 @@ PHP 8.6 UPGRADE NOTES - Zlib: . deflate_init() now raises a TypeError when the value for option "level", "memory", "window", or "strategy" is not of type int. + . inflate_init() now raises a TypeError when the value for option + "window" is not of type int. ======================================== 2. New Features diff --git a/ext/zlib/tests/inflate_init_window_type_error.phpt b/ext/zlib/tests/inflate_init_window_type_error.phpt new file mode 100644 index 000000000000..fbca3129681e --- /dev/null +++ b/ext/zlib/tests/inflate_init_window_type_error.phpt @@ -0,0 +1,16 @@ +--TEST-- +inflate_init(): window option type validation +--EXTENSIONS-- +zlib +--FILE-- + []]); +} catch (TypeError $e) { + echo $e->getMessage(), PHP_EOL; +} + +?> +--EXPECT-- +inflate_init(): Argument #2 ($options) the value for option "window" must be of type int, array given diff --git a/ext/zlib/zlib.c b/ext/zlib/zlib.c index b1ee09635e5a..a57796b2c66a 100644 --- a/ext/zlib/zlib.c +++ b/ext/zlib/zlib.c @@ -885,16 +885,14 @@ PHP_FUNCTION(inflate_init) zend_long encoding, window = 15; char *dict = NULL; size_t dictlen = 0; - HashTable *options = NULL; - zval *option_buffer; + HashTable *options = (HashTable *) &zend_empty_array; if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS(), "l|H", &encoding, &options)) { RETURN_THROWS(); } - if (options && (option_buffer = zend_hash_str_find(options, ZEND_STRL("window"))) != NULL) { - ZVAL_DEINDIRECT(option_buffer); - window = zval_get_long(option_buffer); + if (!zlib_get_long_option(options, ZEND_STRL("window"), &window)) { + RETURN_THROWS(); } if (window < 8 || window > 15) { zend_value_error("zlib window size (logarithm) (" ZEND_LONG_FMT ") must be within 8..15", window); From f31e4e6068f0659f25c9be15da82a67e9c45a137 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 30 Apr 2026 15:35:18 +0100 Subject: [PATCH 023/213] ext/phar: convert phar_open_executed_filename() to use zend_string for alias (#21916) --- ext/phar/phar.c | 8 +++++--- ext/phar/phar_internal.h | 2 +- ext/phar/phar_object.c | 17 +++++++++-------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index cd363fbd88ee..d3b14b65504f 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -2252,7 +2252,7 @@ zend_string* phar_split_fname(const char *filename, size_t filename_len, zend_st * Invoked when a user calls Phar::mapPhar() from within an executing .phar * to set up its manifest directly */ -ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(const char *alias, size_t alias_len, char **error) /* {{{ */ +ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result phar_open_executed_filename(const zend_string *alias, char **error) /* {{{ */ { *error = NULL; @@ -2263,7 +2263,9 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(const cha return FAILURE; } - if (phar_open_parsed_phar(ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, false, REPORT_ERRORS, NULL, NULL) == SUCCESS) { + const char *alias_cstr = alias ? ZSTR_VAL(alias) : NULL; + size_t alias_len = alias ? ZSTR_LEN(alias) : 0; + if (phar_open_parsed_phar(ZSTR_VAL(fname), ZSTR_LEN(fname), alias_cstr, alias_len, false, REPORT_ERRORS, NULL, NULL) == SUCCESS) { return SUCCESS; } @@ -2292,7 +2294,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(const cha fname = actual; } - zend_result ret = phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, REPORT_ERRORS, NULL, error); + zend_result ret = phar_open_from_fp(fp, ZSTR_VAL(fname), ZSTR_LEN(fname), alias_cstr, alias_len, REPORT_ERRORS, NULL, error); if (actual) { zend_string_release_ex(actual, 0); diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 7a923fd15e18..30018986f1f6 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -409,7 +409,7 @@ ZEND_ATTRIBUTE_NONNULL zend_result phar_postprocess_file(phar_entry_data *idata, zend_result phar_open_from_filename(char *fname, size_t fname_len, const char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error); ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); -ZEND_ATTRIBUTE_NONNULL_ARGS(3) zend_result phar_open_executed_filename(const char *alias, size_t alias_len, char **error); +ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result phar_open_executed_filename(const zend_string *alias, char **error); zend_result phar_free_alias(const phar_archive_data *phar); phar_archive_data* phar_get_archive(const char *fname, size_t fname_len, const char *alias, size_t alias_len, char **error); zend_result phar_verify_signature(php_stream *fp, size_t end_of_phar, uint32_t sig_type, const char *sig, size_t sig_len, const char *fname, char **signature, size_t *signature_len, char **error); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 00a5ebf3058f..32c7d2b866c7 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -549,8 +549,8 @@ PHP_METHOD(Phar, webPhar) zval *mimeoverride = NULL; zend_fcall_info rewrite_fci = {0}; zend_fcall_info_cache rewrite_fcc; - char *alias = NULL, *error, *index_php = NULL, *ru = NULL; - size_t alias_len = 0, free_pathinfo = 0; + char *error, *index_php = NULL, *ru = NULL; + size_t free_pathinfo = 0; zend_string *f404 = NULL; size_t ru_len = 0; char *fname, *path_info, *mime_type = NULL, *entry, *pt; @@ -562,14 +562,15 @@ PHP_METHOD(Phar, webPhar) phar_entry_info *info = NULL; size_t sapi_mod_name_len = strlen(sapi_module.name); phar_action_status status = PHAR_ACT_DO_EXIT; + zend_string *alias = NULL; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!s!S!af!", &alias, &alias_len, &index_php, &index_php_len, &f404, &mimeoverride, &rewrite_fci, &rewrite_fcc) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!s!S!af!", &alias, &index_php, &index_php_len, &f404, &mimeoverride, &rewrite_fci, &rewrite_fcc) == FAILURE) { RETURN_THROWS(); } phar_request_initialize(); - if (phar_open_executed_filename(alias, alias_len, &error) != SUCCESS) { + if (phar_open_executed_filename(alias, &error) != SUCCESS) { if (error) { zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); efree(error); @@ -947,17 +948,17 @@ PHP_METHOD(Phar, createDefaultStub) /* {{{ Reads the currently executed file (a phar) and registers its manifest */ PHP_METHOD(Phar, mapPhar) { - char *alias = NULL, *error; - size_t alias_len = 0; + zend_string *alias = NULL; + char *error; zend_long dataoffset = 0; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "|s!l", &alias, &alias_len, &dataoffset) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "|S!l", &alias, &dataoffset) == FAILURE) { RETURN_THROWS(); } phar_request_initialize(); - RETVAL_BOOL(phar_open_executed_filename(alias, alias_len, &error) == SUCCESS); + RETVAL_BOOL(phar_open_executed_filename(alias, &error) == SUCCESS); if (error) { zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); From b04136ee71db97c358ceb49eb5347eb5a05e03f6 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Thu, 30 Apr 2026 15:35:51 +0100 Subject: [PATCH 024/213] ext/phar: convert phar_open_from_filename() to use zend_string for alias (#21917) --- ext/phar/phar.c | 12 +++++++----- ext/phar/phar_internal.h | 2 +- ext/phar/phar_object.c | 12 ++++++------ ext/phar/stream.c | 2 +- 4 files changed, 15 insertions(+), 13 deletions(-) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index d3b14b65504f..ef25e9c3192e 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -131,7 +131,7 @@ static void phar_split_cache_list(void) /* {{{ */ len = strlen(key); } - if (SUCCESS == phar_open_from_filename(key, len, NULL, 0, 0, &phar, NULL)) { + if (SUCCESS == phar_open_from_filename(key, len, NULL, 0, &phar, NULL)) { phar->phar_pos = i++; php_stream_close(phar->fp); phar->fp = NULL; @@ -1507,7 +1507,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(z * that the manifest is proper, then pass it to phar_parse_pharfile(). SUCCESS * or FAILURE is returned and pphar is set to a pointer to the phar's manifest */ -zend_result phar_open_from_filename(char *fname, size_t fname_len, const char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ +zend_result phar_open_from_filename(char *fname, size_t fname_len, const zend_string *alias, uint32_t options, phar_archive_data** pphar, char **error) /* {{{ */ { php_stream *fp; zend_string *actual; @@ -1521,7 +1521,9 @@ zend_result phar_open_from_filename(char *fname, size_t fname_len, const char *a is_data = true; } - if (phar_open_parsed_phar(fname, fname_len, alias, alias_len, is_data, options, pphar, error) == SUCCESS) { + const char *alias_cstr = alias ? ZSTR_VAL(alias) : NULL; + size_t alias_len = alias ? ZSTR_LEN(alias) : 0; + if (phar_open_parsed_phar(fname, fname_len, alias_cstr, alias_len, is_data, options, pphar, error) == SUCCESS) { return SUCCESS; } else if (error && *error) { return FAILURE; @@ -1549,7 +1551,7 @@ zend_result phar_open_from_filename(char *fname, size_t fname_len, const char *a fname_len = ZSTR_LEN(actual); } - zend_result ret = phar_open_from_fp(fp, fname, fname_len, alias, alias_len, options, pphar, error); + zend_result ret = phar_open_from_fp(fp, fname, fname_len, alias_cstr, alias_len, options, pphar, error); if (actual) { zend_string_release_ex(actual, 0); @@ -3158,7 +3160,7 @@ static zend_op_array *phar_compile_file(zend_file_handle *file_handle, int type) return phar_orig_compile_file(file_handle, type); } if (strstr(ZSTR_VAL(file_handle->filename), ".phar") && !strstr(ZSTR_VAL(file_handle->filename), "://")) { - if (SUCCESS == phar_open_from_filename(ZSTR_VAL(file_handle->filename), ZSTR_LEN(file_handle->filename), NULL, 0, 0, &phar, NULL)) { + if (SUCCESS == phar_open_from_filename(ZSTR_VAL(file_handle->filename), ZSTR_LEN(file_handle->filename), NULL, 0, &phar, NULL)) { if (phar->is_zip || phar->is_tar) { zend_file_handle f; diff --git a/ext/phar/phar_internal.h b/ext/phar/phar_internal.h index 30018986f1f6..5054699a8cbd 100644 --- a/ext/phar/phar_internal.h +++ b/ext/phar/phar_internal.h @@ -406,7 +406,7 @@ void phar_object_init(void); void phar_destroy_phar_data(phar_archive_data *phar); ZEND_ATTRIBUTE_NONNULL zend_result phar_postprocess_file(phar_entry_data *idata, uint32_t crc32, char **error, int process_zip); -zend_result phar_open_from_filename(char *fname, size_t fname_len, const char *alias, size_t alias_len, uint32_t options, phar_archive_data** pphar, char **error); +zend_result phar_open_from_filename(char *fname, size_t fname_len, const zend_string *alias, uint32_t options, phar_archive_data** pphar, char **error); ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_open_or_create_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); ZEND_ATTRIBUTE_NONNULL_ARGS(1, 6, 7) zend_result phar_create_or_parse_filename(zend_string *fname, const char *alias, size_t alias_len, bool is_data, uint32_t options, phar_archive_data** pphar, char **error); ZEND_ATTRIBUTE_NONNULL_ARGS(2) zend_result phar_open_executed_filename(const zend_string *alias, char **error); diff --git a/ext/phar/phar_object.c b/ext/phar/phar_object.c index 32c7d2b866c7..66d543732407 100644 --- a/ext/phar/phar_object.c +++ b/ext/phar/phar_object.c @@ -970,16 +970,16 @@ PHP_METHOD(Phar, mapPhar) PHP_METHOD(Phar, loadPhar) { zend_string *fname; - char *alias = NULL, *error; - size_t alias_len = 0; + zend_string *alias = NULL; + char *error; - if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|s!", &fname, &alias, &alias_len) == FAILURE) { + if (zend_parse_parameters(ZEND_NUM_ARGS(), "P|S!", &fname, &alias) == FAILURE) { RETURN_THROWS(); } phar_request_initialize(); - RETVAL_BOOL(phar_open_from_filename(ZSTR_VAL(fname), ZSTR_LEN(fname), alias, alias_len, REPORT_ERRORS, NULL, &error) == SUCCESS); + RETVAL_BOOL(phar_open_from_filename(ZSTR_VAL(fname), ZSTR_LEN(fname), alias, REPORT_ERRORS, NULL, &error) == SUCCESS); if (error) { zend_throw_exception_ex(phar_ce_PharException, 0, "%s", error); @@ -1266,7 +1266,7 @@ PHP_METHOD(Phar, unlinkArchive) RETURN_THROWS(); } - if (FAILURE == phar_open_from_filename(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, 0, REPORT_ERRORS, &phar, &error)) { + if (FAILURE == phar_open_from_filename(ZSTR_VAL(fname), ZSTR_LEN(fname), NULL, REPORT_ERRORS, &phar, &error)) { if (error) { zend_throw_exception_ex(phar_ce_PharException, 0, "Unknown phar archive \"%s\": %s", ZSTR_VAL(fname), error); efree(error); @@ -4416,7 +4416,7 @@ PHP_METHOD(PharFileInfo, __construct) RETURN_THROWS(); } - if (phar_open_from_filename(ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, 0, REPORT_ERRORS, &phar_data, &error) == FAILURE) { + if (phar_open_from_filename(ZSTR_VAL(arch), ZSTR_LEN(arch), NULL, REPORT_ERRORS, &phar_data, &error) == FAILURE) { zend_string_release_ex(arch, false); efree(entry); if (error) { diff --git a/ext/phar/stream.c b/ext/phar/stream.c index f9d19a04122a..29ce9ea9077d 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -137,7 +137,7 @@ php_url* phar_parse_url(php_stream_wrapper *wrapper, const char *filename, const return NULL; } } else { - if (phar_open_from_filename(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, options, NULL, &error) == FAILURE) + if (phar_open_from_filename(ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, options, NULL, &error) == FAILURE) { if (error) { if (!(options & PHP_STREAM_URL_STAT_QUIET)) { From ff1bb13315740a80c8072acb91d82ee3aed86c9d Mon Sep 17 00:00:00 2001 From: Remi Collet Date: Thu, 30 Apr 2026 15:52:19 +0200 Subject: [PATCH 025/213] ASN1_STRING has been made opaque in OpenSSL 4 --- ext/openssl/openssl_backend_common.c | 10 +++++----- ext/openssl/xp_ssl.c | 14 +++++++------- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/ext/openssl/openssl_backend_common.c b/ext/openssl/openssl_backend_common.c index 222053984916..5aa8d246177e 100644 --- a/ext/openssl/openssl_backend_common.c +++ b/ext/openssl/openssl_backend_common.c @@ -108,7 +108,7 @@ void php_openssl_add_assoc_name_entry(zval * val, char * key, X509_NAME * name, void php_openssl_add_assoc_asn1_string(zval * val, char * key, ASN1_STRING * str) { - add_assoc_stringl(val, key, (char *)str->data, str->length); + add_assoc_stringl(val, key, (const char *)ASN1_STRING_get0_data(str), ASN1_STRING_length(str)); } time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr) @@ -140,12 +140,12 @@ time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr) } if (timestr_len < 13) { - php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", timestr->data); + php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", ASN1_STRING_get0_data(timestr)); return (time_t)-1; } if (ASN1_STRING_type(timestr) == V_ASN1_GENERALIZEDTIME && timestr_len < 15) { - php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", timestr->data); + php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", ASN1_STRING_get0_data(timestr)); return (time_t)-1; } @@ -626,8 +626,8 @@ int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension) } extension_data = X509_EXTENSION_get_data(extension); - p = extension_data->data; - length = extension_data->length; + p = ASN1_STRING_get0_data(extension_data); + length = ASN1_STRING_length(extension_data); if (method->it) { names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, &p, length, ASN1_ITEM_ptr(method->it))); diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index eea758da4713..64f49ca4538d 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -492,12 +492,12 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) / } OPENSSL_free(cert_name); } else if (san->type == GEN_IPADD) { - if (san->d.iPAddress->length == 4) { + if (ASN1_STRING_length(san->d.iPAddress) == 4) { snprintf(ipbuffer, sizeof(ipbuffer), "%d.%d.%d.%d", - san->d.iPAddress->data[0], - san->d.iPAddress->data[1], - san->d.iPAddress->data[2], - san->d.iPAddress->data[3] + ASN1_STRING_get0_data(san->d.iPAddress)[0], + ASN1_STRING_get0_data(san->d.iPAddress)[1], + ASN1_STRING_get0_data(san->d.iPAddress)[2], + ASN1_STRING_get0_data(san->d.iPAddress)[3] ); if (strcasecmp(subject_name, (const char*)ipbuffer) == 0) { sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); @@ -506,9 +506,9 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) / } } #ifdef HAVE_IPV6_SAN - else if (san->d.ip->length == 16 && subject_name_is_ipv6) { + else if (ASN1_STRING_length(san->d.ip) == 16 && subject_name_is_ipv6) { ipbuffer[0] = 0; - EXPAND_IPV6_ADDRESS(ipbuffer, san->d.iPAddress->data); + EXPAND_IPV6_ADDRESS(ipbuffer, ASN1_STRING_get0_data(san->d.iPAddress)); if (strcasecmp((const char*)subject_name_ipv6_expanded, (const char*)ipbuffer) == 0) { sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); From 1f50b63369ab42bde33b2ad71be57736a689c459 Mon Sep 17 00:00:00 2001 From: Levi Morrison Date: Thu, 30 Apr 2026 15:53:47 -0400 Subject: [PATCH 026/213] Fix JIT vm_interrupt (#21910) * Add observer VM interrupt JIT regression test * Fix observer VM interrupt during tracing JIT calls --- NEWS | 4 ++ ext/opcache/jit/zend_jit_ir.c | 17 ++----- ext/zend_test/observer.c | 23 +++++++++ ext/zend_test/php_test.h | 1 + .../tests/observer_jit_vm_interrupt.inc | 8 +++ .../tests/observer_jit_vm_interrupt.phpt | 50 +++++++++++++++++++ 6 files changed, 90 insertions(+), 13 deletions(-) create mode 100644 ext/zend_test/tests/observer_jit_vm_interrupt.inc create mode 100644 ext/zend_test/tests/observer_jit_vm_interrupt.phpt diff --git a/NEWS b/NEWS index ef713ddd7255..a6fe8e2136a0 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,10 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.4.22 +- Opcache: + . Fixed tracing JIT crash when a VM interrupt is handled during an observed + user function call. (Levi Morrison) + - Standard: . Fixed bug GH-21689 (version_compare() incorrectly handles versions ending with a dot). (timwolla) diff --git a/ext/opcache/jit/zend_jit_ir.c b/ext/opcache/jit/zend_jit_ir.c index 4251d6b891c9..1346d141754f 100644 --- a/ext/opcache/jit/zend_jit_ir.c +++ b/ext/opcache/jit/zend_jit_ir.c @@ -10337,28 +10337,19 @@ static int zend_jit_do_fcall(zend_jit_ctx *jit, const zend_op *opline, const zen if (ZEND_OBSERVER_ENABLED && (!func || (func->common.fn_flags & (ZEND_ACC_CALL_VIA_TRAMPOLINE | ZEND_ACC_GENERATOR)) == 0)) { ir_ref observer_handler; ir_ref rx = jit_FP(jit); + const zend_op *observer_opline = NULL; struct jit_observer_fcall_is_unobserved_data unobserved_data = jit_observer_fcall_is_unobserved_start(jit, func, &observer_handler, rx, func_ref); if (trace && (trace->op != ZEND_JIT_TRACE_END || trace->stop != ZEND_JIT_TRACE_STOP_INTERPRETER)) { ZEND_ASSERT(trace[1].op == ZEND_JIT_TRACE_VM || trace[1].op == ZEND_JIT_TRACE_END); - jit_SET_EX_OPLINE(jit, trace[1].opline); + observer_opline = trace[1].opline; + jit_SET_EX_OPLINE(jit, observer_opline); } else if (GCC_GLOBAL_REGS) { // EX(opline) = opline ir_STORE(jit_EX(opline), jit_IP(jit)); } jit_observer_fcall_begin(jit, rx, observer_handler); - if (trace) { - int32_t exit_point = zend_jit_trace_get_exit_point(opline, ZEND_JIT_EXIT_TO_VM); - - exit_addr = zend_jit_trace_get_exit_addr(exit_point); - if (!exit_addr) { - return 0; - } - } else { - exit_addr = NULL; - } - - zend_jit_check_timeout(jit, NULL /* we're inside the called function */, exit_addr); + zend_jit_check_timeout(jit, observer_opline, NULL); jit_observer_fcall_is_unobserved_end(jit, &unobserved_data); } diff --git a/ext/zend_test/observer.c b/ext/zend_test/observer.c index 31052ec830f7..0dfb62723bc4 100644 --- a/ext/zend_test/observer.c +++ b/ext/zend_test/observer.c @@ -78,6 +78,10 @@ static void observer_begin(zend_execute_data *execute_data) { assert_observer_opline(execute_data); + if (ZT_G(observer_set_vm_interrupt_on_begin)) { + zend_atomic_bool_store_ex(&EG(vm_interrupt), true); + } + if (!ZT_G(observer_show_output)) { return; } @@ -146,6 +150,14 @@ static void observer_end(zend_execute_data *execute_data, zval *retval) } } +static void (*zend_test_prev_interrupt_function)(zend_execute_data *execute_data); +static void zend_test_interrupt_function(zend_execute_data *execute_data) +{ + if (zend_test_prev_interrupt_function) { + zend_test_prev_interrupt_function(execute_data); + } +} + static void observer_show_init(zend_function *fbc) { if (fbc->common.function_name) { @@ -361,6 +373,7 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("zend_test.observer.show_init_backtrace", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_init_backtrace, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.observer.show_opcode", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_show_opcode, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_ENTRY("zend_test.observer.show_opcode_in_user_handler", "", PHP_INI_SYSTEM, OnUpdateString, observer_show_opcode_in_user_handler, zend_zend_test_globals, zend_test_globals) + STD_PHP_INI_BOOLEAN("zend_test.observer.set_vm_interrupt_on_begin", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_set_vm_interrupt_on_begin, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.observer.fiber_init", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_fiber_init, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.observer.fiber_switch", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_fiber_switch, zend_zend_test_globals, zend_test_globals) STD_PHP_INI_BOOLEAN("zend_test.observer.fiber_destroy", "0", PHP_INI_SYSTEM, OnUpdateBool, observer_fiber_destroy, zend_zend_test_globals, zend_test_globals) @@ -398,10 +411,20 @@ void zend_test_observer_init(INIT_FUNC_ARGS) zend_test_prev_execute_internal = zend_execute_internal; zend_execute_internal = zend_test_execute_internal; } + + if (ZT_G(observer_set_vm_interrupt_on_begin)) { + zend_test_prev_interrupt_function = zend_interrupt_function; + zend_interrupt_function = zend_test_interrupt_function; + } } void zend_test_observer_shutdown(SHUTDOWN_FUNC_ARGS) { + if (zend_interrupt_function == zend_test_interrupt_function) { + zend_interrupt_function = zend_test_prev_interrupt_function; + zend_test_prev_interrupt_function = NULL; + } + if (type != MODULE_TEMPORARY) { UNREGISTER_INI_ENTRIES(); } diff --git a/ext/zend_test/php_test.h b/ext/zend_test/php_test.h index 7ec6f5431234..c1310db7bd70 100644 --- a/ext/zend_test/php_test.h +++ b/ext/zend_test/php_test.h @@ -45,6 +45,7 @@ ZEND_BEGIN_MODULE_GLOBALS(zend_test) int observer_show_init_backtrace; int observer_show_opcode; char *observer_show_opcode_in_user_handler; + int observer_set_vm_interrupt_on_begin; int observer_nesting_depth; int observer_fiber_init; int observer_fiber_switch; diff --git a/ext/zend_test/tests/observer_jit_vm_interrupt.inc b/ext/zend_test/tests/observer_jit_vm_interrupt.inc new file mode 100644 index 000000000000..426d9fdc2cb2 --- /dev/null +++ b/ext/zend_test/tests/observer_jit_vm_interrupt.inc @@ -0,0 +1,8 @@ + +--FILE-- + +--EXPECT-- +total=2438400 From c417deaf0f6e0a44da2315dd631b2f918a295782 Mon Sep 17 00:00:00 2001 From: Peter Kokot Date: Fri, 1 May 2026 17:46:40 +0200 Subject: [PATCH 027/213] ext/dom: Sync public headers (#21921) The ext/dom/lexbor/selectors-adapted/selectors.h isn't public header in current code (it isn't needed to use ext/dom in other extensions). And Autotools also doesn't install this header. --- ext/dom/config.w32 | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/ext/dom/config.w32 b/ext/dom/config.w32 index e045e29c6bab..e1cbccecf608 100644 --- a/ext/dom/config.w32 +++ b/ext/dom/config.w32 @@ -36,8 +36,7 @@ if (PHP_DOM == "yes") { "dom_ce.h " + "namespace_compat.h " + "xml_common.h " + - "xpath_callbacks.h " + - "lexbor/selectors-adapted/selectors.h " + "xpath_callbacks.h " ); } else { WARNING("dom support can't be enabled, libxml is not enabled") From 893bc0ad6e5a781d8b47fa42fb9f21623ea404b6 Mon Sep 17 00:00:00 2001 From: onthebed <1136664562@qq.com> Date: Wed, 29 Apr 2026 03:23:15 +0800 Subject: [PATCH 028/213] Fix stale getopt() optional value in CLI Technically this applies to other SAPIs, but CLI is currently the only one with a flag with an optional value. The PHP getopt() implementation already clears php_optarg by-hand. Fixes GH-21901 Closes GH-21902 Co-authored-by: Ilija Tovilo --- NEWS | 3 +++ main/getopt.c | 3 +++ sapi/cli/tests/gh21901.phpt | 13 +++++++++++++ 3 files changed, 19 insertions(+) create mode 100644 sapi/cli/tests/gh21901.phpt diff --git a/NEWS b/NEWS index 3553ae755173..326245a69568 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.5.7 +- CLI: + . Fixed bug GH-21901 (Stale getopt() optional value). (onthebed) + - Opcache: . Fixed tracing JIT crash when a VM interrupt is handled during an observed user function call. (Levi Morrison) diff --git a/main/getopt.c b/main/getopt.c index 65ce94ae9bb0..1d952555de58 100644 --- a/main/getopt.c +++ b/main/getopt.c @@ -59,6 +59,9 @@ PHPAPI int php_getopt(int argc, char* const *argv, const opt_struct opts[], char static char **prev_optarg = NULL; php_optidx = -1; + if (optarg) { + *optarg = NULL; + } if(prev_optarg && prev_optarg != optarg) { /* reset the state */ diff --git a/sapi/cli/tests/gh21901.phpt b/sapi/cli/tests/gh21901.phpt new file mode 100644 index 000000000000..d469df601377 --- /dev/null +++ b/sapi/cli/tests/gh21901.phpt @@ -0,0 +1,13 @@ +--TEST-- +Stale getopt() optional value in CLI +--FILE-- + +--EXPECTF-- +Configuration File (php.ini) Path: "%S" +Loaded Configuration File: "%S" +Scan for additional .ini files in: %s +Additional .ini files parsed: %s From b1242c32bcaff0b4766eaca7e1846c80687f7006 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Fri, 1 May 2026 19:23:03 +0200 Subject: [PATCH 029/213] Add OpenSSL TLS configurable session resumption support (#20296) This adds support for various session options to the stream SSL context. It allows setting a new session callback and session data on the client, and get and remove session callbacks on the server. The server also offers options to configure session cache parameters and the number of session tickets. A new Openssl\Session class is introduced for session import/export and introspection, along with Openssl\OpensslException as the base exception for the extension. RFC: https://wiki.php.net/rfc/tls_session_resumption_api Closes GH-20296 --- NEWS | 2 + UPGRADING | 14 + ext/openssl/openssl.c | 313 +++++++++ ext/openssl/openssl.stub.php | 43 +- ext/openssl/openssl_arginfo.h | 87 ++- ext/openssl/php_openssl.h | 26 +- ext/openssl/tests/ServerClientTestCase.inc | 3 + .../session_resumption_cache_disabled.phpt | 86 +++ .../session_resumption_client_basic.phpt | 89 +++ .../session_resumption_get_cb_no_ticket.phpt | 79 +++ ...esumption_get_cb_num_tickets_positive.phpt | 82 +++ ...on_resumption_get_cb_num_tickets_zero.phpt | 112 ++++ ...sion_resumption_import_export_session.phpt | 98 +++ .../session_resumption_invalid_callback.phpt | 60 ++ .../session_resumption_invalid_data.phpt | 66 ++ ...ion_resumption_invalid_session_import.phpt | 23 + .../session_resumption_new_cb_no_context.phpt | 78 +++ .../session_resumption_persistent_reject.phpt | 66 ++ .../session_resumption_require_new_cb.phpt | 73 +++ .../session_resumption_serialize_session.phpt | 84 +++ ...ption_server_external_with_context_id.phpt | 116 ++++ ...server_external_with_context_id_tls12.phpt | 116 ++++ ...mption_server_external_with_no_verify.phpt | 121 ++++ .../session_resumption_server_internal.phpt | 99 +++ ext/openssl/xp_ssl.c | 603 ++++++++++++++++-- 25 files changed, 2481 insertions(+), 58 deletions(-) create mode 100644 ext/openssl/tests/session_resumption_cache_disabled.phpt create mode 100644 ext/openssl/tests/session_resumption_client_basic.phpt create mode 100644 ext/openssl/tests/session_resumption_get_cb_no_ticket.phpt create mode 100644 ext/openssl/tests/session_resumption_get_cb_num_tickets_positive.phpt create mode 100644 ext/openssl/tests/session_resumption_get_cb_num_tickets_zero.phpt create mode 100644 ext/openssl/tests/session_resumption_import_export_session.phpt create mode 100644 ext/openssl/tests/session_resumption_invalid_callback.phpt create mode 100644 ext/openssl/tests/session_resumption_invalid_data.phpt create mode 100644 ext/openssl/tests/session_resumption_invalid_session_import.phpt create mode 100644 ext/openssl/tests/session_resumption_new_cb_no_context.phpt create mode 100644 ext/openssl/tests/session_resumption_persistent_reject.phpt create mode 100644 ext/openssl/tests/session_resumption_require_new_cb.phpt create mode 100644 ext/openssl/tests/session_resumption_serialize_session.phpt create mode 100644 ext/openssl/tests/session_resumption_server_external_with_context_id.phpt create mode 100644 ext/openssl/tests/session_resumption_server_external_with_context_id_tls12.phpt create mode 100644 ext/openssl/tests/session_resumption_server_external_with_no_verify.phpt create mode 100644 ext/openssl/tests/session_resumption_server_internal.phpt diff --git a/NEWS b/NEWS index 9d0025319121..5453a5fc094f 100644 --- a/NEWS +++ b/NEWS @@ -96,6 +96,8 @@ PHP NEWS . Added AES-SIV support. (jordikroon) . Implemented GH-20310 (No critical extension indication in openssl_x509_parse() output). (StephenWall) + . Added TLS session resumption support for streams with new context options + and Openssl\Session class. (Jakub Zelenka) - PDO_PGSQL: . Clear session-local state disconnect-equivalent processing. diff --git a/UPGRADING b/UPGRADING index 4942b6e88ed2..e55e03be48b9 100644 --- a/UPGRADING +++ b/UPGRADING @@ -141,6 +141,15 @@ PHP 8.6 UPGRADE NOTES . Added extra info about error location to the JSON error messages returned from json_last_error_msg() and JsonException message. +- OpenSSL: + . Added TLS session resumption support for streams with new stream context + options: session_data, session_new_cb, session_cache, session_cache_size, + session_timeout, session_id_context, session_get_cb, session_remove_cb, + and num_tickets. This allows saving and restoring client sessions across + requests, implementing custom server-side session storage, and controlling + session cache behavior. + RFC: https://wiki.php.net/rfc/tls_session_resumption + - Phar: . Overriding the getMTime() and getPathname() methods of SplFileInfo now influences the result of the phar buildFrom family of functions. @@ -232,6 +241,11 @@ PHP 8.6 UPGRADE NOTES 7. New Classes and Interfaces ======================================== +- OpenSSL: + . Openssl\OpensslException + . Openssl\Session + RFC: https://wiki.php.net/rfc/tls_session_resumption + - Standard: . enum SortDirection RFC: https://wiki.php.net/rfc/sort_direction_enum diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 09440b2660af..c85ca073f446 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -56,6 +56,10 @@ ZEND_DECLARE_MODULE_GLOBALS(openssl) #include "openssl_arginfo.h" +/* OpenSSLException class */ + +zend_class_entry *php_openssl_exception_ce; + /* OpenSSLCertificate class */ zend_class_entry *php_openssl_certificate_ce; @@ -165,6 +169,302 @@ static void php_openssl_pkey_free_obj(zend_object *object) zend_object_std_dtor(&key_object->std); } +/* OpenSSLSession class */ + +zend_class_entry *php_openssl_session_ce; + +static zend_object_handlers php_openssl_session_object_handlers; + +bool php_openssl_is_session_ce(zval *val) +{ + return Z_TYPE_P(val) == IS_OBJECT && Z_OBJCE_P(val) == php_openssl_session_ce; +} + +SSL_SESSION *php_openssl_session_from_zval(zval *zv) +{ + if (!php_openssl_is_session_ce(zv)) { + return NULL; + } + return Z_OPENSSL_SESSION_P(zv)->session; +} + +void php_openssl_session_object_init(zval *zv, SSL_SESSION *session) +{ + object_init_ex(zv, php_openssl_session_ce); + php_openssl_session_object *obj = Z_OPENSSL_SESSION_P(zv); + obj->session = session; + + unsigned int id_len = 0; + const unsigned char *id = SSL_SESSION_get_id(session, &id_len); + zend_update_property_stringl(php_openssl_session_ce, Z_OBJ_P(zv), + ZEND_STRL("id"), (char *)id, id_len); +} + +static zend_object *php_openssl_session_create_object(zend_class_entry *class_type) +{ + php_openssl_session_object *intern = zend_object_alloc(sizeof(php_openssl_session_object), class_type); + + zend_object_std_init(&intern->std, class_type); + object_properties_init(&intern->std, class_type); + + return &intern->std; +} + +static zend_function *php_openssl_session_get_constructor(zend_object *object) +{ + zend_throw_error(NULL, + "Cannot directly construct OpenSSLSession, use OpenSSLSession::import() or TLS session callbacks"); + return NULL; +} + +static void php_openssl_session_free_obj(zend_object *object) +{ + php_openssl_session_object *session_object = php_openssl_session_from_obj(object); + + if (session_object->session) { + SSL_SESSION_free(session_object->session); + session_object->session = NULL; + } + zend_object_std_dtor(&session_object->std); +} + +#define PHP_OPENSSL_SESSION_CHECK() \ + php_openssl_session_object *obj = Z_OPENSSL_SESSION_P(ZEND_THIS); \ + if (!obj->session) { \ + zend_throw_exception(php_openssl_exception_ce, "Session is not valid", 0); \ + RETURN_THROWS(); \ + } + +PHP_METHOD(Openssl_Session, export) +{ + zend_long format = ENCODING_PEM; + + ZEND_PARSE_PARAMETERS_START(0, 1) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(format) + ZEND_PARSE_PARAMETERS_END(); + + PHP_OPENSSL_SESSION_CHECK(); + + if (format == ENCODING_DER) { + int len = i2d_SSL_SESSION(obj->session, NULL); + if (len <= 0) { + zend_throw_exception(php_openssl_exception_ce, "Failed to export session", 0); + RETURN_THROWS(); + } + + zend_string *result = zend_string_alloc(len, 0); + unsigned char *p = (unsigned char *)ZSTR_VAL(result); + i2d_SSL_SESSION(obj->session, &p); + ZSTR_VAL(result)[len] = '\0'; + + RETURN_NEW_STR(result); + } + + if (format == ENCODING_PEM) { + BIO *bio = BIO_new(BIO_s_mem()); + if (!bio) { + zend_throw_exception(php_openssl_exception_ce, "Failed to create BIO", 0); + RETURN_THROWS(); + } + + if (!PEM_write_bio_SSL_SESSION(bio, obj->session)) { + BIO_free(bio); + zend_throw_exception(php_openssl_exception_ce, "Failed to export session as PEM", 0); + RETURN_THROWS(); + } + + char *data; + long len = BIO_get_mem_data(bio, &data); + zend_string *result = zend_string_init(data, len, 0); + BIO_free(bio); + + RETURN_NEW_STR(result); + } + + zend_argument_value_error(1, "must be OPENSSL_ENCODING_DER or OPENSSL_ENCODING_PEM"); + RETURN_THROWS(); +} + +PHP_METHOD(Openssl_Session, import) +{ + zend_string *data; + zend_long format = ENCODING_PEM; + + ZEND_PARSE_PARAMETERS_START(1, 2) + Z_PARAM_STR(data) + Z_PARAM_OPTIONAL + Z_PARAM_LONG(format) + ZEND_PARSE_PARAMETERS_END(); + + SSL_SESSION *session = NULL; + + if (format == ENCODING_DER) { + const unsigned char *p = (const unsigned char *)ZSTR_VAL(data); + session = d2i_SSL_SESSION(NULL, &p, ZSTR_LEN(data)); + } else if (format == ENCODING_PEM) { + BIO *bio = BIO_new_mem_buf(ZSTR_VAL(data), ZSTR_LEN(data)); + if (bio) { + session = PEM_read_bio_SSL_SESSION(bio, NULL, NULL, NULL); + BIO_free(bio); + } + } else { + zend_argument_value_error(2, "must be OPENSSL_ENCODING_DER or OPENSSL_ENCODING_PEM"); + RETURN_THROWS(); + } + + if (!session) { + zend_throw_exception(php_openssl_exception_ce, "Failed to import session data", 0); + RETURN_THROWS(); + } + + php_openssl_session_object_init(return_value, session); +} + +PHP_METHOD(Openssl_Session, isResumable) +{ + ZEND_PARSE_PARAMETERS_NONE(); + PHP_OPENSSL_SESSION_CHECK(); + + RETURN_BOOL(SSL_SESSION_is_resumable(obj->session)); +} + +PHP_METHOD(Openssl_Session, getTimeout) +{ + ZEND_PARSE_PARAMETERS_NONE(); + PHP_OPENSSL_SESSION_CHECK(); + RETURN_LONG((zend_long)SSL_SESSION_get_timeout(obj->session)); +} + +PHP_METHOD(Openssl_Session, getCreatedAt) +{ + ZEND_PARSE_PARAMETERS_NONE(); + PHP_OPENSSL_SESSION_CHECK(); +#if PHP_OPENSSL_API_VERSION >= 0x30300 + RETURN_LONG((zend_long)SSL_SESSION_get_time_ex(obj->session)); +#else + RETURN_LONG((zend_long)SSL_SESSION_get_time(obj->session)); +#endif +} + +PHP_METHOD(Openssl_Session, getProtocol) +{ + ZEND_PARSE_PARAMETERS_NONE(); + PHP_OPENSSL_SESSION_CHECK(); + + int version = SSL_SESSION_get_protocol_version(obj->session); + + switch (version) { + case TLS1_3_VERSION: + RETURN_STRING("TLSv1.3"); + case TLS1_2_VERSION: + RETURN_STRING("TLSv1.2"); + case TLS1_1_VERSION: + RETURN_STRING("TLSv1.1"); + case TLS1_VERSION: + RETURN_STRING("TLSv1.0"); + default: + RETURN_NULL(); + } +} + +PHP_METHOD(Openssl_Session, getCipher) +{ + ZEND_PARSE_PARAMETERS_NONE(); + PHP_OPENSSL_SESSION_CHECK(); + + const SSL_CIPHER *cipher = SSL_SESSION_get0_cipher(obj->session); + if (!cipher) { + RETURN_NULL(); + } + + RETURN_STRING(SSL_CIPHER_get_name(cipher)); +} + +PHP_METHOD(Openssl_Session, hasTicket) +{ + ZEND_PARSE_PARAMETERS_NONE(); + PHP_OPENSSL_SESSION_CHECK(); + + RETURN_BOOL(SSL_SESSION_has_ticket(obj->session)); +} + +PHP_METHOD(Openssl_Session, getTicketLifetimeHint) +{ + ZEND_PARSE_PARAMETERS_NONE(); + PHP_OPENSSL_SESSION_CHECK(); + + if (!SSL_SESSION_has_ticket(obj->session)) { + RETURN_NULL(); + } + + RETURN_LONG((zend_long)SSL_SESSION_get_ticket_lifetime_hint(obj->session)); +} +PHP_METHOD(Openssl_Session, __serialize) +{ + ZEND_PARSE_PARAMETERS_NONE(); + + PHP_OPENSSL_SESSION_CHECK(); + + BIO *bio = BIO_new(BIO_s_mem()); + if (!bio) { + zend_throw_exception(php_openssl_exception_ce, "Failed to serialize session", 0); + RETURN_THROWS(); + } + + if (!PEM_write_bio_SSL_SESSION(bio, obj->session)) { + BIO_free(bio); + zend_throw_exception(php_openssl_exception_ce, "Failed to serialize session", 0); + RETURN_THROWS(); + } + + char *data; + long len = BIO_get_mem_data(bio, &data); + zend_string *pem = zend_string_init(data, len, 0); + BIO_free(bio); + + array_init(return_value); + add_assoc_str(return_value, "pem", pem); +} + +PHP_METHOD(Openssl_Session, __unserialize) +{ + HashTable *data; + + ZEND_PARSE_PARAMETERS_START(1, 1) + Z_PARAM_ARRAY_HT(data) + ZEND_PARSE_PARAMETERS_END(); + + zval *pem_zv = zend_hash_str_find(data, ZEND_STRL("pem")); + if (!pem_zv || Z_TYPE_P(pem_zv) != IS_STRING) { + zend_throw_exception(php_openssl_exception_ce, "Invalid serialization data", 0); + RETURN_THROWS(); + } + + BIO *bio = BIO_new_mem_buf(Z_STRVAL_P(pem_zv), Z_STRLEN_P(pem_zv)); + if (!bio) { + zend_throw_exception(php_openssl_exception_ce, "Failed to unserialize session", 0); + RETURN_THROWS(); + } + + SSL_SESSION *session = PEM_read_bio_SSL_SESSION(bio, NULL, NULL, NULL); + BIO_free(bio); + + if (!session) { + zend_throw_exception(php_openssl_exception_ce, "Failed to unserialize session", 0); + RETURN_THROWS(); + } + + php_openssl_session_object *obj = Z_OPENSSL_SESSION_P(ZEND_THIS); + obj->session = session; + + /* Populate id property */ + unsigned int id_len = 0; + const unsigned char *id = SSL_SESSION_get_id(session, &id_len); + zend_update_property_stringl(php_openssl_session_ce, Z_OBJ_P(ZEND_THIS), + ZEND_STRL("id"), (char *)id, id_len); +} + #if defined(HAVE_OPENSSL_ARGON2) static const zend_module_dep openssl_deps[] = { ZEND_MOD_REQUIRED("standard") @@ -381,6 +681,8 @@ PHP_INI_END() /* {{{ PHP_MINIT_FUNCTION */ PHP_MINIT_FUNCTION(openssl) { + php_openssl_exception_ce = register_class_Openssl_OpensslException(zend_ce_exception); + php_openssl_certificate_ce = register_class_OpenSSLCertificate(); php_openssl_certificate_ce->create_object = php_openssl_certificate_create_object; php_openssl_certificate_ce->default_object_handlers = &php_openssl_certificate_object_handlers; @@ -414,6 +716,17 @@ PHP_MINIT_FUNCTION(openssl) php_openssl_pkey_object_handlers.clone_obj = NULL; php_openssl_pkey_object_handlers.compare = zend_objects_not_comparable; + php_openssl_session_ce = register_class_Openssl_Session(); + php_openssl_session_ce->create_object = php_openssl_session_create_object; + php_openssl_session_ce->default_object_handlers = &php_openssl_session_object_handlers; + + memcpy(&php_openssl_session_object_handlers, &std_object_handlers, sizeof(zend_object_handlers)); + php_openssl_session_object_handlers.offset = offsetof(php_openssl_session_object, std); + php_openssl_session_object_handlers.free_obj = php_openssl_session_free_obj; + php_openssl_session_object_handlers.get_constructor = php_openssl_session_get_constructor; + php_openssl_session_object_handlers.clone_obj = NULL; + php_openssl_session_object_handlers.compare = zend_objects_not_comparable; + register_openssl_symbols(module_number); php_openssl_backend_init(); diff --git a/ext/openssl/openssl.stub.php b/ext/openssl/openssl.stub.php index 0111cc0cc7bc..86dcc8f4f556 100644 --- a/ext/openssl/openssl.stub.php +++ b/ext/openssl/openssl.stub.php @@ -2,6 +2,46 @@ /** @generate-class-entries */ +namespace Openssl { + + class OpensslException extends Exception + { + } + + /** + * @strict-properties + */ + final class Session + { + public readonly string $id; + + public function export(int $format = OPENSSL_ENCODING_PEM): string {} + + public static function import(string $data, int $format = OPENSSL_ENCODING_PEM): Session {} + + public function isResumable(): bool {} + + public function getTimeout(): int {} + + public function getCreatedAt(): int {} + + public function getProtocol(): ?string {} + + public function getCipher(): ?string {} + + public function hasTicket(): bool {} + + public function getTicketLifetimeHint(): ?int {} + + public function __serialize(): array {} + + public function __unserialize(array $data): void {} + } + +} + +namespace { + /** * @var string * @cvalue OPENSSL_VERSION_TEXT @@ -409,7 +449,6 @@ */ const OPENSSL_ENCODING_PEM = UNKNOWN; - /** * @strict-properties * @not-serializable @@ -699,3 +738,5 @@ function openssl_get_cert_locations(): array {} function openssl_password_hash(string $algo, #[\SensitiveParameter] string $password, array $options = []): string {} function openssl_password_verify(string $algo, #[\SensitiveParameter] string $password, string $hash): bool {} #endif + +} diff --git a/ext/openssl/openssl_arginfo.h b/ext/openssl/openssl_arginfo.h index 32002cd81d5a..851ba2e913ba 100644 --- a/ext/openssl/openssl_arginfo.h +++ b/ext/openssl/openssl_arginfo.h @@ -1,5 +1,5 @@ /* This is a generated file, edit openssl.stub.php instead. - * Stub hash: a571945d38a3460de017405454b61609811fe1b1 */ + * Stub hash: c0b746f3a9fff06533a7682a35f44f5df951d12f */ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_x509_export_to_file, 0, 2, _IS_BOOL, 0) ZEND_ARG_OBJ_TYPE_MASK(0, certificate, OpenSSLCertificate, MAY_BE_STRING, NULL) @@ -406,6 +406,39 @@ ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_openssl_password_verify, 0, 3, _ ZEND_END_ARG_INFO() #endif +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Openssl_Session_export, 0, 0, IS_STRING, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, format, IS_LONG, 0, "OPENSSL_ENCODING_PEM") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_OBJ_INFO_EX(arginfo_class_Openssl_Session_import, 0, 1, Openssl\\Session, 0) + ZEND_ARG_TYPE_INFO(0, data, IS_STRING, 0) + ZEND_ARG_TYPE_INFO_WITH_DEFAULT_VALUE(0, format, IS_LONG, 0, "OPENSSL_ENCODING_PEM") +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Openssl_Session_isResumable, 0, 0, _IS_BOOL, 0) +ZEND_END_ARG_INFO() + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Openssl_Session_getTimeout, 0, 0, IS_LONG, 0) +ZEND_END_ARG_INFO() + +#define arginfo_class_Openssl_Session_getCreatedAt arginfo_class_Openssl_Session_getTimeout + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Openssl_Session_getProtocol, 0, 0, IS_STRING, 1) +ZEND_END_ARG_INFO() + +#define arginfo_class_Openssl_Session_getCipher arginfo_class_Openssl_Session_getProtocol + +#define arginfo_class_Openssl_Session_hasTicket arginfo_class_Openssl_Session_isResumable + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Openssl_Session_getTicketLifetimeHint, 0, 0, IS_LONG, 1) +ZEND_END_ARG_INFO() + +#define arginfo_class_Openssl_Session___serialize arginfo_openssl_get_cert_locations + +ZEND_BEGIN_ARG_WITH_RETURN_TYPE_INFO_EX(arginfo_class_Openssl_Session___unserialize, 0, 1, IS_VOID, 0) + ZEND_ARG_TYPE_INFO(0, data, IS_ARRAY, 0) +ZEND_END_ARG_INFO() + ZEND_FUNCTION(openssl_x509_export_to_file); ZEND_FUNCTION(openssl_x509_export); ZEND_FUNCTION(openssl_x509_fingerprint); @@ -473,6 +506,17 @@ ZEND_FUNCTION(openssl_get_cert_locations); ZEND_FUNCTION(openssl_password_hash); ZEND_FUNCTION(openssl_password_verify); #endif +ZEND_METHOD(Openssl_Session, export); +ZEND_METHOD(Openssl_Session, import); +ZEND_METHOD(Openssl_Session, isResumable); +ZEND_METHOD(Openssl_Session, getTimeout); +ZEND_METHOD(Openssl_Session, getCreatedAt); +ZEND_METHOD(Openssl_Session, getProtocol); +ZEND_METHOD(Openssl_Session, getCipher); +ZEND_METHOD(Openssl_Session, hasTicket); +ZEND_METHOD(Openssl_Session, getTicketLifetimeHint); +ZEND_METHOD(Openssl_Session, __serialize); +ZEND_METHOD(Openssl_Session, __unserialize); static const zend_function_entry ext_functions[] = { ZEND_FE(openssl_x509_export_to_file, arginfo_openssl_x509_export_to_file) @@ -548,6 +592,21 @@ static const zend_function_entry ext_functions[] = { ZEND_FE_END }; +static const zend_function_entry class_Openssl_Session_methods[] = { + ZEND_ME(Openssl_Session, export, arginfo_class_Openssl_Session_export, ZEND_ACC_PUBLIC) + ZEND_ME(Openssl_Session, import, arginfo_class_Openssl_Session_import, ZEND_ACC_PUBLIC|ZEND_ACC_STATIC) + ZEND_ME(Openssl_Session, isResumable, arginfo_class_Openssl_Session_isResumable, ZEND_ACC_PUBLIC) + ZEND_ME(Openssl_Session, getTimeout, arginfo_class_Openssl_Session_getTimeout, ZEND_ACC_PUBLIC) + ZEND_ME(Openssl_Session, getCreatedAt, arginfo_class_Openssl_Session_getCreatedAt, ZEND_ACC_PUBLIC) + ZEND_ME(Openssl_Session, getProtocol, arginfo_class_Openssl_Session_getProtocol, ZEND_ACC_PUBLIC) + ZEND_ME(Openssl_Session, getCipher, arginfo_class_Openssl_Session_getCipher, ZEND_ACC_PUBLIC) + ZEND_ME(Openssl_Session, hasTicket, arginfo_class_Openssl_Session_hasTicket, ZEND_ACC_PUBLIC) + ZEND_ME(Openssl_Session, getTicketLifetimeHint, arginfo_class_Openssl_Session_getTicketLifetimeHint, ZEND_ACC_PUBLIC) + ZEND_ME(Openssl_Session, __serialize, arginfo_class_Openssl_Session___serialize, ZEND_ACC_PUBLIC) + ZEND_ME(Openssl_Session, __unserialize, arginfo_class_Openssl_Session___unserialize, ZEND_ACC_PUBLIC) + ZEND_FE_END +}; + static void register_openssl_symbols(int module_number) { REGISTER_STRING_CONSTANT("OPENSSL_VERSION_TEXT", OPENSSL_VERSION_TEXT, CONST_PERSISTENT); @@ -751,6 +810,32 @@ static void register_openssl_symbols(int module_number) #endif } +static zend_class_entry *register_class_Openssl_OpensslException(zend_class_entry *class_entry_Openssl_Exception) +{ + zend_class_entry ce, *class_entry; + + INIT_NS_CLASS_ENTRY(ce, "Openssl", "OpensslException", NULL); + class_entry = zend_register_internal_class_with_flags(&ce, class_entry_Openssl_Exception, 0); + + return class_entry; +} + +static zend_class_entry *register_class_Openssl_Session(void) +{ + zend_class_entry ce, *class_entry; + + INIT_NS_CLASS_ENTRY(ce, "Openssl", "Session", class_Openssl_Session_methods); + class_entry = zend_register_internal_class_with_flags(&ce, NULL, ZEND_ACC_FINAL|ZEND_ACC_NO_DYNAMIC_PROPERTIES); + + zval property_id_default_value; + ZVAL_UNDEF(&property_id_default_value); + zend_string *property_id_name = zend_string_init("id", sizeof("id") - 1, true); + zend_declare_typed_property(class_entry, property_id_name, &property_id_default_value, ZEND_ACC_PUBLIC|ZEND_ACC_READONLY, NULL, (zend_type) ZEND_TYPE_INIT_MASK(MAY_BE_STRING)); + zend_string_release_ex(property_id_name, true); + + return class_entry; +} + static zend_class_entry *register_class_OpenSSLCertificate(void) { zend_class_entry ce, *class_entry; diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index df5ee3f7cd68..72fd98745e14 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -30,8 +30,10 @@ extern zend_module_entry openssl_module_entry; #define PHP_OPENSSL_API_VERSION 0x10100 #elif OPENSSL_VERSION_NUMBER < 0x30200000L #define PHP_OPENSSL_API_VERSION 0x30000 -#else +#elif OPENSSL_VERSION_NUMBER < 0x30300000L #define PHP_OPENSSL_API_VERSION 0x30200 +#else +#define PHP_OPENSSL_API_VERSION 0x30300 #endif #define PHP_OPENSSL_ERR_BUFFER_SIZE 16 @@ -201,6 +203,28 @@ static inline php_openssl_pkey_object *php_openssl_pkey_from_obj(zend_object *ob bool php_openssl_is_pkey_ce(zval *val); void php_openssl_pkey_object_init(zval *zv, EVP_PKEY *pkey, bool is_private); +/* OpenSSLSession class */ + +#include + +typedef struct _php_openssl_session_object { + SSL_SESSION *session; + zend_object std; +} php_openssl_session_object; + +static inline php_openssl_session_object *php_openssl_session_from_obj(zend_object *obj) { + return (php_openssl_session_object *)((char *)(obj) - offsetof(php_openssl_session_object, std)); +} + +#define Z_OPENSSL_SESSION_P(zv) php_openssl_session_from_obj(Z_OBJ_P(zv)) + +/* Extern declarations for xp_ssl.c */ +extern zend_class_entry *php_openssl_session_ce; + +void php_openssl_session_object_init(zval *zv, SSL_SESSION *session); +bool php_openssl_is_session_ce(zval *val); +SSL_SESSION *php_openssl_session_from_zval(zval *zv); + #if defined(HAVE_OPENSSL_ARGON2) /** diff --git a/ext/openssl/tests/ServerClientTestCase.inc b/ext/openssl/tests/ServerClientTestCase.inc index 8eedbfdebee8..f0336fdd3921 100644 --- a/ext/openssl/tests/ServerClientTestCase.inc +++ b/ext/openssl/tests/ServerClientTestCase.inc @@ -179,6 +179,9 @@ class ServerClientTestCase if (empty($addr)) { throw new \Exception("Failed server start"); } + if (strpos($addr, 'SERVER_EXCEPTION') !== false) { + echo $addr; + } if ($code === false) { $clientCode = preg_replace('/{{\s*ADDR\s*}}/', $addr, $clientCode); } else { diff --git a/ext/openssl/tests/session_resumption_cache_disabled.phpt b/ext/openssl/tests/session_resumption_cache_disabled.phpt new file mode 100644 index 000000000000..9e0e8a82f399 --- /dev/null +++ b/ext/openssl/tests/session_resumption_cache_disabled.phpt @@ -0,0 +1,86 @@ +--TEST-- +TLS session resumption - server with cache disabled +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'session_cache' => false, /* Disable session caching */ + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + /* Accept two connections */ + for ($i = 0; $i < 2; $i++) { + $client = @stream_socket_accept($server, 30); + if ($client) { + fwrite($client, "No cache connection " . ($i + 1) . "\n"); + fclose($client); + } + } +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $globalSession = null; + + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_new_cb' => function($stream, $session) use (&$globalSession) { + $globalSession = $session; + } + ]]); + + /* First connection */ + $client1 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + if ($client1) { + echo trim(fgets($client1)) . "\n"; + $meta1 = stream_get_meta_data($client1); + echo "First connection resumed: " . ($meta1['crypto']['session_reused'] ? "yes" : "no") . "\n"; + fclose($client1); + } + + /* Second connection - server won't use cached session */ + $ctx2 = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_data' => $globalSession, + ]]); + + $client2 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx2); + if ($client2) { + echo trim(fgets($client2)) . "\n"; + $meta2 = stream_get_meta_data($client2); + echo "Second connection resumed: " . ($meta2['crypto']['session_reused'] ? "yes" : "no") . "\n"; + fclose($client2); + } +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_disabled_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECT-- +No cache connection 1 +First connection resumed: no +No cache connection 2 +Second connection resumed: no diff --git a/ext/openssl/tests/session_resumption_client_basic.phpt b/ext/openssl/tests/session_resumption_client_basic.phpt new file mode 100644 index 000000000000..ee1d126a6d9f --- /dev/null +++ b/ext/openssl/tests/session_resumption_client_basic.phpt @@ -0,0 +1,89 @@ +--TEST-- +TLS session resumption - client basic resumption +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'session_cache' => true, + 'session_id_context' => 'test-basic', + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + /* Accept two connections */ + for ($i = 0; $i < 2; $i++) { + $client = @stream_socket_accept($server, 30); + if ($client) { + fwrite($client, "Hello from server\n"); + fclose($client); + } + } +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $sessionData = ''; + + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_new_cb' => function($stream, $session) use (&$sessionData) { + $sessionData = $session; + } + ]]); + + /* First connection - full handshake */ + $client1 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + if ($client1) { + echo trim(fgets($client1)) . "\n"; + $meta1 = stream_get_meta_data($client1); + echo "First connection resumed: " . ($meta1['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo "Session data received: " . (!empty($sessionData) ? "yes" : "no") . "\n"; + fclose($client1); + } + + /* Second connection - resumed session */ + $ctx2 = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_data' => $sessionData, + ]]); + + $client2 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx2); + if ($client2) { + echo trim(fgets($client2)) . "\n"; + $meta2 = stream_get_meta_data($client2); + echo "Second connection resumed: " . ($meta2['crypto']['session_reused'] ? "yes" : "no") . "\n"; + fclose($client2); + } +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_resumption_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECT-- +Hello from server +First connection resumed: no +Session data received: yes +Hello from server +Second connection resumed: yes diff --git a/ext/openssl/tests/session_resumption_get_cb_no_ticket.phpt b/ext/openssl/tests/session_resumption_get_cb_no_ticket.phpt new file mode 100644 index 000000000000..f87f831a7859 --- /dev/null +++ b/ext/openssl/tests/session_resumption_get_cb_no_ticket.phpt @@ -0,0 +1,79 @@ +--TEST-- +TLS session resumption - warning when trying to enable tickets with session_get_cb +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'session_id_context' => 'test-app', + 'no_ticket' => false, // Explicitly trying to enable tickets + 'session_new_cb' => function($stream, $sessionData) { + // Store session + }, + 'session_get_cb' => function($stream, $sessionId) { + return null; + } + ]]); + + try { + $server = @stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + $client = @stream_socket_accept($server, 30); + if ($client === false) { + phpt_notify(message: "SERVER_FAILED_UNEXPECTEDLY"); + } else { + phpt_notify(message: "SERVER_CREATED_UNEXPECTEDLY"); + fclose($server); + } + } catch (\Throwable $e) { + phpt_notify(message: "SERVER_EXCEPTION: " . $e->getMessage()); + } +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $flags = STREAM_CLIENT_CONNECT; + + /* Try to use corrupted session data */ + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_data' => 'this_is_invalid_session_data', + ]]); + + $client = @stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + + if ($client === false) { + echo "Connection failed as expected\n"; + } + + $result = phpt_wait(); + echo trim($result) . "\n"; +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_no_ticket_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECT-- +SERVER_EXCEPTION: Session tickets cannot be enabled when session_get_cb is setConnection failed as expected + diff --git a/ext/openssl/tests/session_resumption_get_cb_num_tickets_positive.phpt b/ext/openssl/tests/session_resumption_get_cb_num_tickets_positive.phpt new file mode 100644 index 000000000000..5563b0c22cf8 --- /dev/null +++ b/ext/openssl/tests/session_resumption_get_cb_num_tickets_positive.phpt @@ -0,0 +1,82 @@ +--TEST-- +TLS session resumption - num_tickets controls ticket generation (TLS 1.3) +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_3_SERVER, + 'num_tickets' => 3, // Issue 3 tickets per connection + ]]); + + $server = stream_socket_server('tlsv1.3://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + // Accept one connection + $client = @stream_socket_accept($server, 30); + if ($client) { + fwrite($client, "Ticket test\n"); + // Keep connection open briefly to allow tickets to be sent + usleep(100000); // 100ms + fclose($client); + } + + phpt_notify(message: "SERVER_DONE"); +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $ticketCount = 0; + + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'crypto_method' => STREAM_CRYPTO_METHOD_TLSv1_3_CLIENT, + 'session_new_cb' => function($stream, $session) use (&$ticketCount) { + $ticketCount++; + } + ]]); + + $client = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + if ($client) { + $response = fgets($client); + echo trim($response) . "\n"; + + // Keep connection open briefly to receive all tickets + usleep(150000); // 150ms + fclose($client); + } + + echo "Tickets received: $ticketCount\n"; + + $result = phpt_wait(); + echo trim($result) . "\n"; +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_num_tickets_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECTF-- +Ticket test +Tickets received: 3 +SERVER_DONE diff --git a/ext/openssl/tests/session_resumption_get_cb_num_tickets_zero.phpt b/ext/openssl/tests/session_resumption_get_cb_num_tickets_zero.phpt new file mode 100644 index 000000000000..13654cd451e9 --- /dev/null +++ b/ext/openssl/tests/session_resumption_get_cb_num_tickets_zero.phpt @@ -0,0 +1,112 @@ +--TEST-- +TLS session resumption - num_tickets = 0 disables tickets, forces session IDs +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'session_id_context' => 'test-no-tickets', + 'num_tickets' => 0, // Disable ticket issuance + 'session_new_cb' => function($stream, $session) use (&$sessionStore, &$newCbCalled) { + $key = bin2hex($session->id); + $sessionStore[$key] = $session; + $newCbCalled++; + }, + 'session_get_cb' => function($stream, $sessionId) use (&$sessionStore) { + $key = bin2hex($sessionId); + return $sessionStore[$key] ?? null; + }, + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + // Accept two connections + for ($i = 0; $i < 2; $i++) { + $client = @stream_socket_accept($server, 30); + if ($client) { + fwrite($client, "Response " . ($i + 1) . "\n"); + usleep(50000); // Allow session storage + fclose($client); + } + } + + phpt_notify(message: "NEW_CB_CALLS:$newCbCalled"); +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $sessionData = null; + $clientTickets = 0; + + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_new_cb' => function($stream, $session) use (&$sessionData, &$clientTickets) { + $sessionData = $session; + $clientTickets++; + } + ]]); + + // First connection + $client1 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + if ($client1) { + $meta1 = stream_get_meta_data($client1); + echo "Client first connection resumed: " . ($meta1['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo trim(fgets($client1)) . "\n"; + usleep(100000); // Wait for session storage + fclose($client1); + } + + echo "Client received tickets on first connection: $clientTickets\n"; + + // Second connection with resumption + $ctx2 = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_data' => $sessionData, + ]]); + + $client2 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx2); + if ($client2) { + $meta2 = stream_get_meta_data($client2); + echo "Client second connection resumed: " . ($meta2['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo trim(fgets($client2)) . "\n"; + fclose($client2); + } + + $result = phpt_wait(); + echo "Server: " . trim($result) . "\n"; +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_no_tickets_zero_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECT-- +Client first connection resumed: no +Response 1 +Client received tickets on first connection: 0 +Client second connection resumed: no +Response 2 +Server: NEW_CB_CALLS:0 diff --git a/ext/openssl/tests/session_resumption_import_export_session.phpt b/ext/openssl/tests/session_resumption_import_export_session.phpt new file mode 100644 index 000000000000..0d9a3274b113 --- /dev/null +++ b/ext/openssl/tests/session_resumption_import_export_session.phpt @@ -0,0 +1,98 @@ +--TEST-- +TLS session resumption - import and export session +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'session_cache' => true, + 'session_id_context' => 'test-basic', + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + /* Accept single connections */ + $client = @stream_socket_accept($server, 30); + if ($client) { + fwrite($client, "Hello from server\n"); + fclose($client); + } +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $sessionData = ''; + + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_new_cb' => function($stream, $session) use (&$sessionData) { + if (empty($sessionData)) { + // default should be pem + $pemSessionData = $session->export(); + var_dump($pemSessionData); + $session = Openssl\Session::import($pemSessionData); + $pemSessionData = $session->export(OPENSSL_ENCODING_PEM); + var_dump($pemSessionData); + $session = Openssl\Session::import($pemSessionData, OPENSSL_ENCODING_PEM); + $derSessionData = $session->export(OPENSSL_ENCODING_DER); + var_dump(strlen($derSessionData) > 0); + var_dump(strpos($derSessionData, 'BEGIN SSL SESSION PARAMETERS') === false); + $session = Openssl\Session::import($derSessionData, OPENSSL_ENCODING_DER); + var_dump($session); + } + $sessionData = $session; + } + ]]); + + /* First connection - full handshake */ + $client1 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + if ($client1) { + echo trim(fgets($client1)) . "\n"; + $meta1 = stream_get_meta_data($client1); + echo "First connection resumed: " . ($meta1['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo "Session data received: " . (!empty($sessionData) ? "yes" : "no") . "\n"; + fclose($client1); + } +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_resumption_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECTF-- +string(%d) "-----BEGIN SSL SESSION PARAMETERS----- +%a +-----END SSL SESSION PARAMETERS----- +" +string(%d) "-----BEGIN SSL SESSION PARAMETERS----- +%a +-----END SSL SESSION PARAMETERS----- +" +bool(true) +bool(true) +object(Openssl\Session)#%d (1) { + ["id"]=> + string(32) "%a" +} +Hello from server +First connection resumed: no +Session data received: yes diff --git a/ext/openssl/tests/session_resumption_invalid_callback.phpt b/ext/openssl/tests/session_resumption_invalid_callback.phpt new file mode 100644 index 000000000000..b6cfc90a0554 --- /dev/null +++ b/ext/openssl/tests/session_resumption_invalid_callback.phpt @@ -0,0 +1,60 @@ +--TEST-- +TLS session resumption - invalid callback throws TypeError +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + $client = @stream_socket_accept($server, 30); + if ($client) { + fclose($client); + } +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $flags = STREAM_CLIENT_CONNECT; + + /* Try to use invalid callback */ + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_new_cb' => 'not_a_valid_function', + ]]); + + try { + $client = @stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + echo "Should not reach here\n"; + } catch (TypeError $e) { + echo "TypeError caught: " . (strpos($e->getMessage(), 'session_new_cb must be a valid callback') !== false ? "YES" : "NO"); + echo "\n"; + } +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_invalid_cb_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECTF-- +TypeError caught: YES diff --git a/ext/openssl/tests/session_resumption_invalid_data.phpt b/ext/openssl/tests/session_resumption_invalid_data.phpt new file mode 100644 index 000000000000..7e50b9235a2b --- /dev/null +++ b/ext/openssl/tests/session_resumption_invalid_data.phpt @@ -0,0 +1,66 @@ +--TEST-- +TLS session resumption - invalid session data is fatal +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + $client = @stream_socket_accept($server, 30); + if ($client) { + fclose($client); + } +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $flags = STREAM_CLIENT_CONNECT; + + /* Try to use corrupted session data */ + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_data' => 'this_is_invalid_session_data', + ]]); + + try { + $client = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + + if ($client === false) { + echo "Connection failed unexpectedlyd\n"; + } + } catch (\Throwable $e) { + echo "Type error thrown: " . $e->getMessage() . "\n"; + } +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_invalid_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECTF-- + +Warning: stream_socket_client(): Failed to enable crypto in %s on line %d + +Warning: stream_socket_client(): Unable to connect to %s in %s on line %d +Type error thrown: session_data must be an OpenSSLSession instance diff --git a/ext/openssl/tests/session_resumption_invalid_session_import.phpt b/ext/openssl/tests/session_resumption_invalid_session_import.phpt new file mode 100644 index 000000000000..a9c5b65f2051 --- /dev/null +++ b/ext/openssl/tests/session_resumption_invalid_session_import.phpt @@ -0,0 +1,23 @@ +--TEST-- +TLS session resumption - invalid session import +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- +getMessage() . "\n"; +} +?> +--CLEAN-- + +--EXPECT-- +Failed to import session data diff --git a/ext/openssl/tests/session_resumption_new_cb_no_context.phpt b/ext/openssl/tests/session_resumption_new_cb_no_context.phpt new file mode 100644 index 000000000000..ee2852c54ad7 --- /dev/null +++ b/ext/openssl/tests/session_resumption_new_cb_no_context.phpt @@ -0,0 +1,78 @@ +--TEST-- +TLS session resumption - warning when session_new_cb without session_id_context and verify_peer enabled +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'verify_peer' => true, + 'cafile' => '%s', + 'session_new_cb' => function($stream, $session) { + echo "not called new_cb\n"; + }, + 'session_get_cb' => function($stream, $sessionId) { + echo "not called new_cb\n"; + return null; + } + /* Missing: 'session_id_context' => 'myapp' */ + ]]); + + try { + $server = @stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + $client = @stream_socket_accept($server, 30); + if ($client === false) { + phpt_notify(message: "SERVER_FAILED_UNEXPECTEDLY"); + } else { + phpt_notify(message: "SERVER_CREATED_UNEXPECTEDLY"); + fclose($server); + } + } catch (\Throwable $e) { + phpt_notify(message: "SERVER_EXCEPTION: " . $e->getMessage()); + } +CODE; +$serverCode = sprintf($serverCode, $certFile, $caCertFile); + +$clientCode = <<<'CODE' + $flags = STREAM_CLIENT_CONNECT; + + /* Try to use corrupted session data */ + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false + ]]); + + $client = @stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + + $result = phpt_wait(); + echo trim($result) . "\n"; +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveCaCert($caCertFile); +$certificateGenerator->saveNewCertAsFileWithKey('session_verify_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECT-- +SERVER_EXCEPTION: session_id_context must be set if session_new_cb is set diff --git a/ext/openssl/tests/session_resumption_persistent_reject.phpt b/ext/openssl/tests/session_resumption_persistent_reject.phpt new file mode 100644 index 000000000000..835e9bb51648 --- /dev/null +++ b/ext/openssl/tests/session_resumption_persistent_reject.phpt @@ -0,0 +1,66 @@ +--TEST-- +TLS session resumption - callbacks rejected on persistent streams +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + $client = @stream_socket_accept($server, 30); + if ($client) { + fclose($client); + } +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $flags = STREAM_CLIENT_CONNECT | STREAM_CLIENT_PERSISTENT; + + /* Try to use callback with persistent stream */ + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_new_cb' => function($stream, $session) { + echo "This should never be called\n"; + } + ]]); + + $client = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + + if ($client === false) { + echo "Connection failed as expected with persistent stream\n"; + } +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_persistent_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECTF-- + +Warning: stream_socket_client(): session_new_cb is not supported for persistent streams in %s on line %d + +Warning: stream_socket_client(): Failed to enable crypto in %s on line %d + +Warning: stream_socket_client(): Unable to connect to %s in %s on line %d +Connection failed as expected with persistent stream diff --git a/ext/openssl/tests/session_resumption_require_new_cb.phpt b/ext/openssl/tests/session_resumption_require_new_cb.phpt new file mode 100644 index 000000000000..a08408e2d90b --- /dev/null +++ b/ext/openssl/tests/session_resumption_require_new_cb.phpt @@ -0,0 +1,73 @@ +--TEST-- +TLS session resumption - server requires session_new_cb with session_get_cb +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'session_get_cb' => function($stream, $sessionId) { + return null; + } + ]]); + + try { + $server = @stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + $client = @stream_socket_accept($server, 30); + if ($client === false) { + phpt_notify(message: "SERVER_FAILED_UNEXPECTEDLY"); + } else { + phpt_notify(message: "SERVER_CREATED_UNEXPECTEDLY"); + fclose($server); + } + } catch (\Throwable $e) { + phpt_notify(message: "SERVER_EXCEPTION: " . $e->getMessage()); + } +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $flags = STREAM_CLIENT_CONNECT; + + /* Try to use corrupted session data */ + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_data' => 'this_is_invalid_session_data', + ]]); + + $client = @stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + + if ($client === false) { + echo "Connection failed as expected\n"; + } + + $result = phpt_wait(); + echo trim($result) . "\n"; +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_require_cb_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECT-- +SERVER_EXCEPTION: session_new_cb is required when session_get_cb is providedConnection failed as expected diff --git a/ext/openssl/tests/session_resumption_serialize_session.phpt b/ext/openssl/tests/session_resumption_serialize_session.phpt new file mode 100644 index 000000000000..f2f3c98e5e5b --- /dev/null +++ b/ext/openssl/tests/session_resumption_serialize_session.phpt @@ -0,0 +1,84 @@ +--TEST-- +TLS session resumption - serialize session +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'session_cache' => true, + 'session_id_context' => 'test-basic', + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + /* Accept single connections */ + $client = @stream_socket_accept($server, 30); + if ($client) { + fwrite($client, "Hello from server\n"); + fclose($client); + } +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $sessionData = ''; + + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_new_cb' => function($stream, $session) use (&$sessionData) { + if (empty($sessionData)) { + $serializedSessionData = serialize($session); + var_dump($serializedSessionData); + $session = unserialize($serializedSessionData); + var_dump($session); + } + $sessionData = $session; + } + ]]); + + /* First connection - full handshake */ + $client1 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + if ($client1) { + echo trim(fgets($client1)) . "\n"; + $meta1 = stream_get_meta_data($client1); + echo "First connection resumed: " . ($meta1['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo "Session data received: " . (!empty($sessionData) ? "yes" : "no") . "\n"; + fclose($client1); + } +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_resumption_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECTF-- +string(%d) "O:15:"Openssl\Session":1:{s:3:"pem";s:%d:"-----BEGIN SSL SESSION PARAMETERS----- +%a +-----END SSL SESSION PARAMETERS----- +";}" +object(Openssl\Session)#9 (1) { + ["id"]=> +%a +} +Hello from server +First connection resumed: no +Session data received: yes diff --git a/ext/openssl/tests/session_resumption_server_external_with_context_id.phpt b/ext/openssl/tests/session_resumption_server_external_with_context_id.phpt new file mode 100644 index 000000000000..02c6a7dcfdc7 --- /dev/null +++ b/ext/openssl/tests/session_resumption_server_external_with_context_id.phpt @@ -0,0 +1,116 @@ +--TEST-- +TLS session resumption - server external cache callbacks with context id +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'session_id_context' => 'test-server', + 'session_new_cb' => function($stream, $session) use (&$sessionStore, &$newCbCalled) { + $key = bin2hex($session->id); + $sessionStore[$key] = $session; + $newCbCalled = true; + }, + 'session_get_cb' => function($stream, $sessionId) use (&$sessionStore, &$getCbCalled) { + $key = bin2hex($sessionId); + $getCbCalled = true; + return $sessionStore[$key] ?? null; + }, + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + /* Accept two connections */ + for ($i = 0; $i < 2; $i++) { + $client = @stream_socket_accept($server, 30); + if ($client) { + fwrite($client, "Response " . ($i + 1) . "\n"); + fclose($client); + } + } + + /* Report results */ + $result = []; + if ($newCbCalled) $result[] = "NEW_CB_CALLED"; + if ($getCbCalled) $result[] = "GET_CB_CALLED"; + $result[] = "SESSIONS:" . count($sessionStore); + + phpt_notify(message: implode(",", $result)); +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $sessionData = null; + + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_new_cb' => function($stream, $session) use (&$sessionData) { + $sessionData = $session; + } + ]]); + + /* First connection */ + $client1 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + if ($client1) { + $meta1 = stream_get_meta_data($client1); + echo "Client first connection resumed: " . ($meta1['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo trim(fgets($client1)) . "\n"; + fclose($client1); + } + + echo "Session captured: " . ($sessionData !== null ? "YES" : "NO") . "\n"; + + /* Second connection with session resumption */ + $ctx2 = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_data' => $sessionData, + ]]); + + $client2 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx2); + if ($client2) { + $meta2 = stream_get_meta_data($client2); + echo "Client second connection resumed: " . ($meta2['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo trim(fgets($client2)) . "\n"; + fclose($client2); + } + + /* Get server callback results */ + $result = phpt_wait(); + echo "Server: " . trim($result) . "\n"; +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_external_proper_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECTF-- +Client first connection resumed: no +Response 1 +Session captured: YES +Client second connection resumed: yes +Response 2 +Server: NEW_CB_CALLED,GET_CB_CALLED,SESSIONS:3 diff --git a/ext/openssl/tests/session_resumption_server_external_with_context_id_tls12.phpt b/ext/openssl/tests/session_resumption_server_external_with_context_id_tls12.phpt new file mode 100644 index 000000000000..bdc3d2ce1bf6 --- /dev/null +++ b/ext/openssl/tests/session_resumption_server_external_with_context_id_tls12.phpt @@ -0,0 +1,116 @@ +--TEST-- +TLS session resumption - server external cache callbacks with context id for TLS 1.2 +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'session_id_context' => 'test-server', // Proper configuration + 'session_new_cb' => function($stream, $session) use (&$sessionStore, &$newCbCalled) { + $key = bin2hex($session->id); + $sessionStore[$key] = $session; + $newCbCalled = true; + }, + 'session_get_cb' => function($stream, $sessionId) use (&$sessionStore, &$getCbCalled) { + $key = bin2hex($sessionId); + $getCbCalled = true; + return $sessionStore[$key] ?? null; + }, + ]]); + + $server = stream_socket_server('tlsv1.2://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + /* Accept two connections */ + for ($i = 0; $i < 2; $i++) { + $client = @stream_socket_accept($server, 30); + if ($client) { + fwrite($client, "Response " . ($i + 1) . "\n"); + fclose($client); + } + } + + /* Report results */ + $result = []; + if ($newCbCalled) $result[] = "NEW_CB_CALLED"; + if ($getCbCalled) $result[] = "GET_CB_CALLED"; + $result[] = "SESSIONS:" . count($sessionStore); + + phpt_notify(message: implode(",", $result)); +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $sessionData = null; + + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_new_cb' => function($stream, $session) use (&$sessionData) { + $sessionData = $session; + } + ]]); + + /* First connection */ + $client1 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + if ($client1) { + $meta1 = stream_get_meta_data($client1); + echo "Client first connection resumed: " . ($meta1['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo trim(fgets($client1)) . "\n"; + fclose($client1); + } + + echo "Session captured: " . ($sessionData !== null ? "YES" : "NO") . "\n"; + + /* Second connection with session resumption */ + $ctx2 = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_data' => $sessionData, + ]]); + + $client2 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx2); + if ($client2) { + $meta2 = stream_get_meta_data($client2); + echo "Client second connection resumed: " . ($meta2['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo trim(fgets($client2)) . "\n"; + fclose($client2); + } + + /* Get server callback results */ + $result = phpt_wait(); + echo "Server: " . trim($result) . "\n"; +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_external_proper_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECTF-- +Client first connection resumed: no +Response 1 +Session captured: YES +Client second connection resumed: yes +Response 2 +Server: NEW_CB_CALLED,GET_CB_CALLED,SESSIONS:1 diff --git a/ext/openssl/tests/session_resumption_server_external_with_no_verify.phpt b/ext/openssl/tests/session_resumption_server_external_with_no_verify.phpt new file mode 100644 index 000000000000..28bb97faff28 --- /dev/null +++ b/ext/openssl/tests/session_resumption_server_external_with_no_verify.phpt @@ -0,0 +1,121 @@ +--TEST-- +TLS session resumption - server external cache callbacks with no verify +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'verify_peer' => false, + 'no_ticket' => true, + 'session_cache' => true, + 'session_new_cb' => function($stream, $session) use (&$sessionStore, &$newCbCalled) { + $key = bin2hex($session->id); + $sessionStore[$key] = $session; + $newCbCalled = true; + }, + 'session_get_cb' => function($stream, $sessionId) use (&$sessionStore, &$getCbCalled) { + $key = bin2hex($sessionId); + $getCbCalled = true; + return $sessionStore[$key] ?? null; + }, + 'session_remove_cb' => function($stream, $sessionId) use (&$sessionStore, &$removeCbCalled) { + $key = bin2hex($sessionId); + unset($sessionStore[$key]); + $removeCbCalled = true; + } + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + /* Accept two connections */ + for ($i = 0; $i < 2; $i++) { + $client = @stream_socket_accept($server, 30); + if ($client) { + fwrite($client, "Response " . ($i + 1) . "\n"); + fclose($client); + } + } + + /* Notify client about callback invocations */ + $result = []; + if ($newCbCalled) $result[] = "NEW_CB_CALLED"; + if ($getCbCalled) $result[] = "GET_CB_CALLED"; + if ($removeCbCalled) $result[] = "REMOVE_CB_CALLED"; + + phpt_notify(message: implode(",", $result)); +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $sessionData = null; + + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_new_cb' => function($stream, $session) use (&$sessionData) { + $sessionData = $session; + } + ]]); + + /* First connection */ + $client1 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + if ($client1) { + $meta1 = stream_get_meta_data($client1); + echo "Client first connection resumed: " . ($meta1['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo trim(fgets($client1)) . "\n"; + fclose($client1); + } + + /* Second connection with session resumption */ + $ctx2 = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_data' => $sessionData, + ]]); + + $client2 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx2); + if ($client2) { + $meta2 = stream_get_meta_data($client2); + echo "Client second connection resumed: " . ($meta2['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo trim(fgets($client2)) . "\n"; + fclose($client2); + } + + /* Get server callback results */ + $result = phpt_wait(); + echo "Server callbacks: " . trim($result) . "\n"; +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_server_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECTF-- +Client first connection resumed: no +Response 1 +Client second connection resumed: yes +Response 2 +Server callbacks: NEW_CB_CALLED,GET_CB_CALLED diff --git a/ext/openssl/tests/session_resumption_server_internal.phpt b/ext/openssl/tests/session_resumption_server_internal.phpt new file mode 100644 index 000000000000..d7c2633601e8 --- /dev/null +++ b/ext/openssl/tests/session_resumption_server_internal.phpt @@ -0,0 +1,99 @@ +--TEST-- +TLS session resumption - server internal cache +--EXTENSIONS-- +openssl +--SKIPIF-- + +--FILE-- + [ + 'local_cert' => '%s', + 'session_id_context' => 'test-server', + 'session_cache' => true, + 'session_cache_size' => 1024, + 'session_timeout' => 300, + ]]); + + $server = stream_socket_server('tls://127.0.0.1:0', $errno, $errstr, $flags, $ctx); + phpt_notify_server_start($server); + + /* Accept two connections */ + for ($i = 0; $i < 2; $i++) { + $client = @stream_socket_accept($server, 30); + if ($client) { + fwrite($client, "Connection " . ($i + 1) . "\n"); + fclose($client); + } + } + + phpt_notify(message: "SERVER_DONE"); +CODE; +$serverCode = sprintf($serverCode, $certFile); + +$clientCode = <<<'CODE' + $sessionData = null; + + $flags = STREAM_CLIENT_CONNECT; + $ctx = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_new_cb' => function($stream, $session) use (&$sessionData) { + $sessionData = $session; + } + ]]); + + /* First connection */ + $client1 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx); + if ($client1) { + $meta1 = stream_get_meta_data($client1); + echo "Client first connection resumed: " . ($meta1['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo trim(fgets($client1)) . "\n"; + fclose($client1); + } + + echo "Session data received: " . ($sessionData !== null ? "YES" : "NO") . "\n"; + + /* Second connection with session resumption */ + $ctx2 = stream_context_create(['ssl' => [ + 'verify_peer' => false, + 'verify_peer_name' => false, + 'session_data' => $sessionData, + ]]); + + $client2 = stream_socket_client("tls://{{ ADDR }}", $errno, $errstr, 30, $flags, $ctx2); + if ($client2) { + $meta2 = stream_get_meta_data($client2); + echo "Client second connection resumed: " . ($meta2['crypto']['session_reused'] ? "yes" : "no") . "\n"; + echo trim(fgets($client2)) . "\n"; + fclose($client2); + } + + /* Wait for server */ + $result = phpt_wait(); + echo trim($result) . "\n"; +CODE; + +include 'CertificateGenerator.inc'; +$certificateGenerator = new CertificateGenerator(); +$certificateGenerator->saveNewCertAsFileWithKey('session_internal_cache_test', $certFile); + +include 'ServerClientTestCase.inc'; +ServerClientTestCase::getInstance()->run($clientCode, $serverCode); +?> +--CLEAN-- + +--EXPECTF-- +Client first connection resumed: no +Connection 1 +Session data received: YES +Client second connection resumed: yes +Connection 2 +SERVER_DONE diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index 64f49ca4538d..ed72ca49677f 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -176,6 +176,14 @@ typedef struct _php_openssl_alpn_ctx_t { } php_openssl_alpn_ctx; #endif +/* Holds session callback */ +typedef struct _php_openssl_session_callbacks_t { + int refcount; + zval new_cb; + zval get_cb; + zval remove_cb; +} php_openssl_session_callbacks_t; + /* This implementation is very closely tied to the that of the native * sockets implemented in the core. * Don't try this technique in other extensions! @@ -195,6 +203,7 @@ typedef struct _php_openssl_netstream_data_t { #ifdef HAVE_TLS_ALPN php_openssl_alpn_ctx alpn_ctx; #endif + php_openssl_session_callbacks_t *session_callbacks; char *url_name; unsigned state_set:1; unsigned _spare:31; @@ -1547,37 +1556,404 @@ static int php_openssl_server_alpn_callback(SSL *ssl_handle, #endif -static zend_result php_openssl_setup_crypto(php_stream *stream, - php_openssl_netstream_data_t *sslsock, - php_stream_xport_crypto_param *cparam) /* {{{ */ +static int php_openssl_get_ctx_stream_data_index(void) +{ + static int ctx_data_index = -1; + if (ctx_data_index < 0) { + ctx_data_index = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL); + } + return ctx_data_index; +} + +/** + * OpenSSL new session callback - called when a new session is established + */ +static int php_openssl_session_new_cb(SSL *ssl, SSL_SESSION *session) +{ + php_stream *stream = (php_stream *)SSL_get_ex_data(ssl, php_openssl_get_ssl_stream_data_index()); + if (!stream) { + return 0; + } + + php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t *)stream->abstract; + if (!sslsock || !sslsock->session_callbacks) { + return 0; + } + + /* Increment reference - we're giving ownership to the PHP object */ + SSL_SESSION_up_ref(session); + + zval args[2]; + zval retval; + + ZVAL_RES(&args[0], stream->res); + php_openssl_session_object_init(&args[1], session); + + if (call_user_function(EG(function_table), NULL, &sslsock->session_callbacks->new_cb, + &retval, 2, args) == SUCCESS) { + zval_ptr_dtor(&retval); + } + + zval_ptr_dtor(&args[1]); + + return 0; +} + +/** + * OpenSSL get session callback - called when server needs to retrieve a session + */ +static SSL_SESSION *php_openssl_session_get_cb(SSL *ssl, const unsigned char *session_id, + int session_id_len, int *copy) +{ + php_stream *stream = (php_stream *)SSL_get_ex_data(ssl, php_openssl_get_ssl_stream_data_index()); + if (!stream) { + *copy = 0; + return NULL; + } + + php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t *)stream->abstract; + if (!sslsock || !sslsock->session_callbacks) { + *copy = 0; + return NULL; + } + + zval args[2]; + zval retval; + + ZVAL_RES(&args[0], stream->res); + ZVAL_STRINGL(&args[1], (char *)session_id, session_id_len); + + SSL_SESSION *session = NULL; + + if (call_user_function(EG(function_table), NULL, &sslsock->session_callbacks->get_cb, + &retval, 2, args) == SUCCESS) { + if (php_openssl_is_session_ce(&retval)) { + /* Get session from object and increment ref since OpenSSL will own it */ + php_openssl_session_object *obj = Z_OPENSSL_SESSION_P(&retval); + if (obj->session) { + SSL_SESSION_up_ref(obj->session); + session = obj->session; + } + zval_ptr_dtor(&retval); + } else if (Z_TYPE(retval) != IS_NULL) { + zend_type_error("session_get_cb return type must be null or OpenSSLSession"); + return NULL; + } + } + + zval_ptr_dtor(&args[1]); + + *copy = 0; + return session; +} + +/** + * OpenSSL remove session callback - called when a session is evicted from cache + */ +static void php_openssl_session_remove_cb(SSL_CTX *ctx, SSL_SESSION *session) +{ + php_stream *stream = (php_stream *)SSL_CTX_get_ex_data(ctx, php_openssl_get_ctx_stream_data_index()); + if (!stream) { + return; + } + + php_openssl_netstream_data_t *sslsock = (php_openssl_netstream_data_t *)stream->abstract; + if (!sslsock || !sslsock->session_callbacks) { + return; + } + + unsigned int session_id_len = 0; + const unsigned char *session_id = SSL_SESSION_get_id(session, &session_id_len); + + zval args[2]; + zval retval; + + ZVAL_RES(&args[0], stream->res); + ZVAL_STRINGL(&args[1], (char *)session_id, session_id_len); + + if (call_user_function(EG(function_table), NULL, &sslsock->session_callbacks->remove_cb, + &retval, 2, args) == SUCCESS) { + zval_ptr_dtor(&retval); + } + + zval_ptr_dtor(&args[1]); +} + +/** + * Validate callable and allocate callback structure if needed. + */ +static zend_result php_openssl_validate_and_allocate_callback( + php_openssl_netstream_data_t *sslsock, zval *callable, + const char *callback_name, bool is_persistent) +{ + zend_fcall_info_cache fcc; + char *is_callable_error = NULL; + + /* Callbacks not supported for persistent streams */ + if (is_persistent) { + php_error_docref(NULL, E_WARNING, + "%s is not supported for persistent streams", callback_name); + return FAILURE; + } + + /* Validate callable */ + if (!zend_is_callable_ex(callable, NULL, 0, NULL, &fcc, &is_callable_error)) { + if (is_callable_error) { + zend_type_error("%s must be a valid callback, %s", callback_name, is_callable_error); + efree(is_callable_error); + } else { + zend_type_error("%s must be a valid callback", callback_name); + } + return FAILURE; + } + + /* Allocate callback structure if not already allocated */ + if (!sslsock->session_callbacks) { + sslsock->session_callbacks = (php_openssl_session_callbacks_t *)pemalloc( + sizeof(php_openssl_session_callbacks_t), is_persistent); + ZVAL_UNDEF(&sslsock->session_callbacks->new_cb); + ZVAL_UNDEF(&sslsock->session_callbacks->get_cb); + ZVAL_UNDEF(&sslsock->session_callbacks->remove_cb); + sslsock->session_callbacks->refcount = 1; + } + + return SUCCESS; +} + +/** + * Configure session resumption options for client connections + */ +static zend_result php_openssl_setup_client_session(php_stream *stream, + php_openssl_netstream_data_t *sslsock) { - const SSL_METHOD *method; - int ssl_ctx_options; - int method_flags; - zend_long min_version = 0; - zend_long max_version = 0; - char *cipherlist = NULL; - char *alpn_protocols = NULL; zval *val; - bool verify_peer = false; + bool enable_client_cache = false; + bool is_persistent = php_stream_is_persistent(stream); + + if (GET_VER_OPT("session_data")) { + if (php_openssl_is_session_ce(val)) { + enable_client_cache = true; + } else if (Z_TYPE_P(val) != IS_NULL) { + zend_type_error("session_data must be an OpenSSLSession instance"); + return FAILURE; + } + } - if (sslsock->ssl_handle) { - if (sslsock->s.is_blocked) { - php_error_docref(NULL, E_WARNING, "SSL/TLS already set-up for this stream"); + if (GET_VER_OPT("session_new_cb")) { + if (FAILURE == php_openssl_validate_and_allocate_callback( + sslsock, val, "session_new_cb", is_persistent)) { + return FAILURE; + } + + ZVAL_COPY(&sslsock->session_callbacks->new_cb, val); + SSL_CTX_sess_set_new_cb(sslsock->ctx, php_openssl_session_new_cb); + enable_client_cache = true; + } + + if (enable_client_cache) { + SSL_CTX_set_session_cache_mode(sslsock->ctx, + SSL_SESS_CACHE_CLIENT | SSL_SESS_CACHE_NO_INTERNAL); + } + + return SUCCESS; +} + +static bool php_openssl_is_session_cache_enabled(php_stream *stream, bool internal_only) +{ + zval *val; + + if (GET_VER_OPT("session_cache")) { + return zend_is_true(val); + } + + if (internal_only) { + return false; + } + + return GET_VER_OPT("session_get_cb"); +} + +/** + * Configure session resumption options for server connections + */ +static zend_result php_openssl_setup_server_session(php_stream *stream, + php_openssl_netstream_data_t *sslsock) +{ + zval *val; + bool has_get_cb = false; + bool has_new_cb = false; + bool has_remove_cb = false; + bool has_session_id_context = false; + bool is_persistent = php_stream_is_persistent(stream); + + /* Check for session_get_cb first (determines cache mode) */ + if (GET_VER_OPT("session_get_cb")) { + if (FAILURE == php_openssl_validate_and_allocate_callback( + sslsock, val, "session_new_cb", is_persistent)) { return FAILURE; + } + ZVAL_COPY(&sslsock->session_callbacks->get_cb, val); + has_get_cb = true; + } + + if (GET_VER_OPT("session_id_context")) { + if (Z_TYPE_P(val) != IS_STRING || Z_STRLEN_P(val) == 0) { + zend_type_error("session_id_context must be a non empty string"); + return FAILURE; + } + SSL_CTX_set_session_id_context(sslsock->ctx, (const unsigned char *) Z_STRVAL_P(val), + Z_STRLEN_P(val)); + has_session_id_context = true; + } + + /* Check for session_new_cb */ + if (GET_VER_OPT("session_new_cb")) { + if (FAILURE == php_openssl_validate_and_allocate_callback( + sslsock, val, "session_new_cb", is_persistent)) { + return FAILURE; + } + ZVAL_COPY(&sslsock->session_callbacks->new_cb, val); + has_new_cb = true; + + if (!has_session_id_context && + (SSL_CTX_get_verify_mode(sslsock->ctx) & SSL_VERIFY_PEER) != 0) { + zend_value_error("session_id_context must be set if session_new_cb is set"); + return FAILURE; + } + } + + /* Validate: if session_get_cb is provided, session_new_cb is required */ + if (has_get_cb && !has_new_cb) { + zend_value_error("session_new_cb is required when session_get_cb is provided"); + return FAILURE; + } + + /* Check for session_remove_cb (optional) */ + if (GET_VER_OPT("session_remove_cb")) { + if (FAILURE == php_openssl_validate_and_allocate_callback( + sslsock, val, "session_remove_cb", is_persistent)) { + return FAILURE; + } + + ZVAL_COPY(&sslsock->session_callbacks->remove_cb, val); + has_remove_cb = true; + } + + /* Configure cache mode based on whether external callbacks are provided */ + if (has_get_cb) { + /* External cache mode - disable internal cache */ + SSL_CTX_set_session_cache_mode(sslsock->ctx, + SSL_SESS_CACHE_SERVER | SSL_SESS_CACHE_NO_INTERNAL); + + /* Set callbacks */ + SSL_CTX_sess_set_new_cb(sslsock->ctx, php_openssl_session_new_cb); + SSL_CTX_sess_set_get_cb(sslsock->ctx, php_openssl_session_get_cb); + + if (has_remove_cb) { + SSL_CTX_sess_set_remove_cb(sslsock->ctx, php_openssl_session_remove_cb); + } + + // Disable tickets (they won't work anyway) and warn if explicity enabled + SSL_CTX_set_options(sslsock->ctx, SSL_OP_NO_TICKET); + if (GET_VER_OPT("no_ticket") && !zend_is_true(val)) { + zend_value_error("Session tickets cannot be enabled when session_get_cb is set"); + } + } else if (php_openssl_is_session_cache_enabled(stream, true)) { + if (!has_session_id_context && + (SSL_CTX_get_verify_mode(sslsock->ctx) & SSL_VERIFY_PEER) != 0) { + zend_value_error("session_id_context must be set for internal session cache"); + } + + /* Internal cache mode */ + SSL_CTX_set_session_cache_mode(sslsock->ctx, SSL_SESS_CACHE_SERVER); + + /* Handle session_cache_size */ + if (GET_VER_OPT("session_cache_size")) { + zend_long cache_size = zval_get_long(val); + if (cache_size > 0) { + SSL_CTX_sess_set_cache_size(sslsock->ctx, cache_size); + } else { + zend_value_error("session_cache_size must be positive"); + } } else { - return SUCCESS; + /* Default cache size from RFC */ + SSL_CTX_sess_set_cache_size(sslsock->ctx, 20480); + } + + /* Handle session_timeout */ + if (GET_VER_OPT("session_timeout")) { + zend_long timeout = zval_get_long(val); + if (timeout > 0) { + SSL_CTX_set_timeout(sslsock->ctx, timeout); + } else { + zend_value_error("session_timeout must be positive"); + } + } else { + /* Default timeout from RFC */ + SSL_CTX_set_timeout(sslsock->ctx, 300); + } + + /* Optional notification callback for internal cache */ + if (has_new_cb) { + SSL_CTX_sess_set_new_cb(sslsock->ctx, php_openssl_session_new_cb); } + } else { + /* Session caching disabled */ + SSL_CTX_set_session_cache_mode(sslsock->ctx, SSL_SESS_CACHE_OFF); } - ERR_clear_error(); + return SUCCESS; +} - /* We need to do slightly different things based on client/server method - * so let's remember which method was selected */ - sslsock->is_client = cparam->inputs.method & STREAM_CRYPTO_IS_CLIENT; - method_flags = cparam->inputs.method & ~STREAM_CRYPTO_IS_CLIENT; +static zend_result php_openssl_apply_client_session_data(php_stream *stream, + php_openssl_netstream_data_t *sslsock) +{ + zval *val; + + if (GET_VER_OPT("session_data")) { + SSL_SESSION *session = NULL; + bool needs_free = false; + + if (php_openssl_is_session_ce(val)) { + session = php_openssl_session_from_zval(val); + if (!session) { + php_error_docref(NULL, E_WARNING, + "Invalid OpenSSLSession object, falling back to full handshake"); + return FAILURE; + } + /* Object owns the session, we just borrow it */ + needs_free = false; + } else if (Z_TYPE_P(val) != IS_NULL) { + zend_type_error("session_data must be an OpenSSLSession instance"); + return FAILURE; + } + + if (session) { + if (SSL_set_session(sslsock->ssl_handle, session) != 1) { + php_error_docref(NULL, E_WARNING, + "Failed to set session for resumption, falling back to full handshake"); + if (needs_free) { + SSL_SESSION_free(session); + } + ERR_clear_error(); + return FAILURE; + } + + if (needs_free) { + SSL_SESSION_free(session); + } + } + } + + return SUCCESS; +} + +static zend_result php_openssl_create_server_ctx(php_stream *stream, + php_openssl_netstream_data_t *sslsock, int method_flags) +{ + zval *val; - method = sslsock->is_client ? SSLv23_client_method() : SSLv23_server_method(); + const SSL_METHOD *method = sslsock->is_client ? SSLv23_client_method() : SSLv23_server_method(); sslsock->ctx = SSL_CTX_new(method); if (sslsock->ctx == NULL) { @@ -1585,14 +1961,24 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, return FAILURE; } + SSL_CTX_set_ex_data(sslsock->ctx, php_openssl_get_ctx_stream_data_index(), stream); + + zend_long min_version = 0; + zend_long max_version = 0; GET_VER_OPT_LONG("min_proto_version", min_version); GET_VER_OPT_LONG("max_proto_version", max_version); method_flags = php_openssl_get_proto_version_flags(method_flags, min_version, max_version); - ssl_ctx_options = SSL_OP_ALL; + int ssl_ctx_options = SSL_OP_ALL; if (GET_VER_OPT("no_ticket") && zend_is_true(val)) { ssl_ctx_options |= SSL_OP_NO_TICKET; } + if (GET_VER_OPT("num_tickets")) { + zend_long num_tickets = zval_get_long(val); + if (num_tickets >= 0) { + SSL_CTX_set_num_tickets(sslsock->ctx, num_tickets); + } + } ssl_ctx_options &= ~SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS; @@ -1605,6 +1991,7 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, ssl_ctx_options |= SSL_OP_NO_COMPRESSION; } + bool verify_peer = false; if (GET_VER_OPT("verify_peer") && !zend_is_true(val)) { php_openssl_disable_peer_verification(sslsock->ctx, stream); } else { @@ -1620,6 +2007,7 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, SSL_CTX_set_default_passwd_cb(sslsock->ctx, php_openssl_passwd_callback); } + char *cipherlist = NULL; GET_VER_OPT_STRING("ciphers", cipherlist); #ifndef USE_OPENSSL_SYSTEM_CIPHERS if (!cipherlist) { @@ -1642,6 +2030,7 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, #endif } + char *alpn_protocols = NULL; GET_VER_OPT_STRING("alpn_protocols", alpn_protocols); if (alpn_protocols) { #ifdef HAVE_TLS_ALPN @@ -1680,10 +2069,96 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, SSL_CTX_set_min_proto_version(sslsock->ctx, php_openssl_get_min_proto_version(method_flags)); SSL_CTX_set_max_proto_version(sslsock->ctx, php_openssl_get_max_proto_version(method_flags)); - if (sslsock->is_client == 0 && - PHP_STREAM_CONTEXT(stream) && - FAILURE == php_openssl_set_server_specific_opts(stream, sslsock->ctx) - ) { + if (sslsock->is_client) { + /* Setup client session resumption */ + if (FAILURE == php_openssl_setup_client_session(stream, sslsock)) { + return FAILURE; + } + } else if (PHP_STREAM_CONTEXT(stream)) { + if (FAILURE == php_openssl_setup_server_session(stream, sslsock)) { + return FAILURE; + } + /* Original server-specific setup */ + if (FAILURE == php_openssl_set_server_specific_opts(stream, sslsock->ctx)) { + return FAILURE; + } + } + +#ifdef HAVE_TLS_SNI + /* Enable server-side SNI */ + if (!sslsock->is_client && php_openssl_enable_server_sni(stream, sslsock, verify_peer) == FAILURE) { + return FAILURE; + } +#endif + + return SUCCESS; +} + +static zend_result php_openssl_setup_crypto(php_stream *stream, + php_openssl_netstream_data_t *sslsock, + php_stream_xport_crypto_param *cparam) /* {{{ */ +{ + if (sslsock->ssl_handle) { + if (sslsock->s.is_blocked) { + php_error_docref(NULL, E_WARNING, "SSL/TLS already set-up for this stream"); + return FAILURE; + } else { + return SUCCESS; + } + } + + ERR_clear_error(); + + /* We need to do slightly different things based on client/server method + * so let's remember which method was selected */ + sslsock->is_client = cparam->inputs.method & STREAM_CRYPTO_IS_CLIENT; + int method_flags = cparam->inputs.method & ~STREAM_CRYPTO_IS_CLIENT; + + /* Re-use SSL_CTX if session is set */ + if (cparam->inputs.session) { + php_openssl_netstream_data_t *parent_sslsock; + + if (cparam->inputs.session->ops != &php_openssl_socket_ops) { + php_error_docref(NULL, E_WARNING, "Supplied session stream must be an SSL enabled stream"); + } else if ((parent_sslsock = cparam->inputs.session->abstract)->ctx == NULL) { + php_error_docref(NULL, E_WARNING, "Supplied SSL session stream is not set up"); + } else if (sslsock->is_client && parent_sslsock->ssl_handle == NULL) { + php_error_docref(NULL, E_WARNING, "Supplied SSL session stream is not initialized"); + } else { + SSL_CTX_up_ref(parent_sslsock->ctx); + sslsock->ctx = parent_sslsock->ctx; + if (parent_sslsock->session_callbacks) { + parent_sslsock->session_callbacks->refcount++; + sslsock->session_callbacks = parent_sslsock->session_callbacks; + } + + sslsock->ssl_handle = SSL_new(sslsock->ctx); + if (!sslsock->ssl_handle) { + php_error_docref(NULL, E_WARNING, "SSL handle creation failure"); + SSL_CTX_free(sslsock->ctx); + sslsock->ctx = NULL; + return FAILURE; + } + + SSL_set_ex_data(sslsock->ssl_handle, php_openssl_get_ssl_stream_data_index(), stream); + + if (!SSL_set_fd(sslsock->ssl_handle, sslsock->s.socket)) { + php_openssl_handle_ssl_error(stream, 0, true); + } + + if (sslsock->is_client) { + if (SSL_copy_session_id(sslsock->ssl_handle, parent_sslsock->ssl_handle)) { + SSL_CTX_set_session_cache_mode(sslsock->ctx, SSL_SESS_CACHE_CLIENT); + } else { + php_error_docref(NULL, E_WARNING, "SSL session copying failed creation failure"); + } + } + + return SUCCESS; + } + } + + if (php_openssl_create_server_ctx(stream, sslsock, method_flags) == FAILURE) { return FAILURE; } @@ -1707,32 +2182,6 @@ static zend_result php_openssl_setup_crypto(php_stream *stream, php_openssl_handle_ssl_error(stream, 0, true); } -#ifdef HAVE_TLS_SNI - /* Enable server-side SNI */ - if (!sslsock->is_client && php_openssl_enable_server_sni(stream, sslsock, verify_peer) == FAILURE) { - return FAILURE; - } -#endif - - /* Enable server-side handshake renegotiation rate-limiting */ - if (!sslsock->is_client) { - php_openssl_init_server_reneg_limit(stream, sslsock); - } - -#ifdef SSL_MODE_RELEASE_BUFFERS - SSL_set_mode(sslsock->ssl_handle, SSL_MODE_RELEASE_BUFFERS); -#endif - - if (cparam->inputs.session) { - if (cparam->inputs.session->ops != &php_openssl_socket_ops) { - php_error_docref(NULL, E_WARNING, "Supplied session stream must be an SSL enabled stream"); - } else if (((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle == NULL) { - php_error_docref(NULL, E_WARNING, "Supplied SSL session stream is not initialized"); - } else { - SSL_copy_session_id(sslsock->ssl_handle, ((php_openssl_netstream_data_t*)cparam->inputs.session->abstract)->ssl_handle); - } - } - return SUCCESS; } /* }}} */ @@ -1813,10 +2262,22 @@ static int php_openssl_enable_crypto(php_stream *stream, struct timeval start_time, *timeout; bool blocked = sslsock->s.is_blocked, has_timeout = false; -#ifdef HAVE_TLS_SNI if (sslsock->is_client) { + /* Set session data for client */ + if ( php_openssl_apply_client_session_data(stream, sslsock)) { + return FAILURE; + } +#ifdef HAVE_TLS_SNI php_openssl_enable_client_sni(stream, sslsock); +#endif + } else { + php_openssl_init_server_reneg_limit(stream, sslsock); } + +#ifdef PHP_OPENSSL_TLS_DEBUG + BIO *b_out = BIO_new_fp(stdout, BIO_NOCLOSE | BIO_FP_TEXT); + SSL_set_msg_callback(sslsock->ssl_handle, SSL_trace); + SSL_set_msg_callback_arg(sslsock->ssl_handle, b_out); #endif if (!sslsock->state_set) { @@ -1828,6 +2289,8 @@ static int php_openssl_enable_crypto(php_stream *stream, sslsock->state_set = 1; } + SSL_set_mode(sslsock->ssl_handle, SSL_MODE_RELEASE_BUFFERS); + if (SUCCESS == php_openssl_set_blocking(sslsock, 0)) { /* The following mode are added only if we are able to change socket * to non blocking mode which is also used for read and write */ @@ -2201,6 +2664,13 @@ static int php_openssl_sockop_close(php_stream *stream, int close_handle) /* {{{ pefree(sslsock->reneg, php_stream_is_persistent(stream)); } + if (sslsock->session_callbacks && --sslsock->session_callbacks->refcount == 0) { + zval_ptr_dtor(&sslsock->session_callbacks->new_cb); + zval_ptr_dtor(&sslsock->session_callbacks->get_cb); + zval_ptr_dtor(&sslsock->session_callbacks->remove_cb); + pefree(sslsock->session_callbacks, php_stream_is_persistent(stream)); + } + pefree(sslsock, php_stream_is_persistent(stream)); return 0; @@ -2277,7 +2747,7 @@ static inline int php_openssl_tcp_sockop_accept(php_stream *stream, php_openssl_ clisockdata->method = sock->method; if (php_stream_xport_crypto_setup(xparam->outputs.client, clisockdata->method, - NULL) < 0 || php_stream_xport_crypto_enable( + sock->ctx ? stream : NULL) < 0 || php_stream_xport_crypto_enable( xparam->outputs.client, 1) < 0) { php_error_docref(NULL, E_WARNING, "Failed to enable crypto"); @@ -2336,6 +2806,7 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val add_assoc_string(&tmp, "cipher_name", (char *) SSL_CIPHER_get_name(cipher)); add_assoc_long(&tmp, "cipher_bits", SSL_CIPHER_get_bits(cipher, NULL)); add_assoc_string(&tmp, "cipher_version", SSL_CIPHER_get_version(cipher)); + add_assoc_bool(&tmp, "session_reused", SSL_session_reused(sslsock->ssl_handle)); #ifdef HAVE_TLS_ALPN { @@ -2536,7 +3007,14 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val (xparam->op == STREAM_XPORT_OP_CONNECT_ASYNC && xparam->outputs.returncode == 1 && xparam->outputs.error_code == EINPROGRESS))) { - if (php_stream_xport_crypto_setup(stream, sslsock->method, NULL) < 0 || + zval *val; + php_stream *session_stream = NULL; + + if (GET_VER_OPT("session_stream")) { + php_stream_from_zval_no_verify(session_stream, val); + } + + if (php_stream_xport_crypto_setup(stream, sslsock->method, session_stream) < 0 || php_stream_xport_crypto_enable(stream, 1) < 0) { php_error_docref(NULL, E_WARNING, "Failed to enable crypto"); xparam->outputs.returncode = -1; @@ -2544,6 +3022,21 @@ static int php_openssl_sockop_set_option(php_stream *stream, int option, int val } return PHP_STREAM_OPTION_RETURN_OK; + case STREAM_XPORT_OP_LISTEN: + /* Do normal listen first */ + xparam->outputs.returncode = php_stream_socket_ops.set_option( + stream, option, value, ptrparam); + + if (xparam->outputs.returncode == 0 && sslsock->enable_on_connect) { + /* Check if we should create SSL_CTX early for session resumption */ + if (php_openssl_is_session_cache_enabled(stream, false)) { + if (FAILURE == php_openssl_create_server_ctx(stream, sslsock, sslsock->method)) { + xparam->outputs.returncode = -1; + } + } + } + return PHP_STREAM_OPTION_RETURN_OK; + case STREAM_XPORT_OP_ACCEPT: /* we need to copy the additional fields that the underlying tcp transport * doesn't know about */ From e3845851d3d2e80dd1dd5931eb2b369b2352198a Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Fri, 1 May 2026 19:21:54 +0200 Subject: [PATCH 030/213] Fix gh21901.phpt expected output when no ini file is loaded --- sapi/cli/tests/gh21901.phpt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sapi/cli/tests/gh21901.phpt b/sapi/cli/tests/gh21901.phpt index d469df601377..39c76913d1f8 100644 --- a/sapi/cli/tests/gh21901.phpt +++ b/sapi/cli/tests/gh21901.phpt @@ -7,7 +7,7 @@ $cmd = $php_escaped . ' -n -d foo=bar --ini'; echo shell_exec($cmd); ?> --EXPECTF-- -Configuration File (php.ini) Path: "%S" -Loaded Configuration File: "%S" +Configuration File (php.ini) Path: %s +Loaded Configuration File: %s Scan for additional .ini files in: %s Additional .ini files parsed: %s From 19255f4b784cedf6dd4bb21e97def348d335dd69 Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sat, 2 May 2026 01:49:34 +0200 Subject: [PATCH 031/213] Backport compatibility changes for OpenSSL 4.0 This backports: - 266f85f4e89957a02142f5fc9baea723d57bd90b - ff1bb13315740a80c8072acb91d82ee3aed86c9d --- NEWS | 3 +++ ext/openssl/openssl.c | 16 ++++++++-------- ext/openssl/php_openssl.h | 4 +++- ext/openssl/xp_ssl.c | 14 +++++++------- 4 files changed, 21 insertions(+), 16 deletions(-) diff --git a/NEWS b/NEWS index aa91603d8723..c9b334b1645a 100644 --- a/NEWS +++ b/NEWS @@ -5,6 +5,9 @@ PHP NEWS - Curl: . Add support for brotli and zstd on Windows. (Shivam Mathur) +- OpenSSL: + . Fix compatibility issues with OpenSSL 4.0. (jordikroon, Remi) + 18 Dec 2025, PHP 8.2.30 - Curl: diff --git a/ext/openssl/openssl.c b/ext/openssl/openssl.c index 9e703f758636..1d467f5b50af 100644 --- a/ext/openssl/openssl.c +++ b/ext/openssl/openssl.c @@ -469,9 +469,9 @@ void php_openssl_store_errors() errors = OPENSSL_G(errors); do { - errors->top = (errors->top + 1) % ERR_NUM_ERRORS; + errors->top = (errors->top + 1) % PHP_OPENSSL_ERR_BUFFER_SIZE; if (errors->top == errors->bottom) { - errors->bottom = (errors->bottom + 1) % ERR_NUM_ERRORS; + errors->bottom = (errors->bottom + 1) % PHP_OPENSSL_ERR_BUFFER_SIZE; } errors->buffer[errors->top] = error_code; } while ((error_code = ERR_get_error())); @@ -685,7 +685,7 @@ static void php_openssl_add_assoc_name_entry(zval * val, char * key, X509_NAME * static void php_openssl_add_assoc_asn1_string(zval * val, char * key, ASN1_STRING * str) /* {{{ */ { - add_assoc_stringl(val, key, (char *)str->data, str->length); + add_assoc_stringl(val, key, (const char *)ASN1_STRING_get0_data(str), ASN1_STRING_length(str)); } /* }}} */ @@ -718,12 +718,12 @@ static time_t php_openssl_asn1_time_to_time_t(ASN1_UTCTIME * timestr) /* {{{ */ } if (timestr_len < 13 && timestr_len != 11) { - php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", timestr->data); + php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", ASN1_STRING_get0_data(timestr)); return (time_t)-1; } if (ASN1_STRING_type(timestr) == V_ASN1_GENERALIZEDTIME && timestr_len < 15) { - php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", timestr->data); + php_error_docref(NULL, E_WARNING, "Unable to parse time string %s correctly", ASN1_STRING_get0_data(timestr)); return (time_t)-1; } @@ -1982,8 +1982,8 @@ static int openssl_x509v3_subjectAltName(BIO *bio, X509_EXTENSION *extension) } extension_data = X509_EXTENSION_get_data(extension); - p = extension_data->data; - length = extension_data->length; + p = ASN1_STRING_get0_data(extension_data); + length = ASN1_STRING_length(extension_data); if (method->it) { names = (GENERAL_NAMES*) (ASN1_item_d2i(NULL, &p, length, ASN1_ITEM_ptr(method->it))); @@ -6709,7 +6709,7 @@ PHP_FUNCTION(openssl_error_string) RETURN_FALSE; } - OPENSSL_G(errors)->bottom = (OPENSSL_G(errors)->bottom + 1) % ERR_NUM_ERRORS; + OPENSSL_G(errors)->bottom = (OPENSSL_G(errors)->bottom + 1) % PHP_OPENSSL_ERR_BUFFER_SIZE; val = OPENSSL_G(errors)->buffer[OPENSSL_G(errors)->bottom]; if (val) { diff --git a/ext/openssl/php_openssl.h b/ext/openssl/php_openssl.h index 5cfadbedc982..fd7f818d30bd 100644 --- a/ext/openssl/php_openssl.h +++ b/ext/openssl/php_openssl.h @@ -44,6 +44,8 @@ extern zend_module_entry openssl_module_entry; #endif #endif +#define PHP_OPENSSL_ERR_BUFFER_SIZE 16 + #define OPENSSL_RAW_DATA 1 #define OPENSSL_ZERO_PADDING 2 #define OPENSSL_DONT_ZERO_PAD_KEY 4 @@ -73,7 +75,7 @@ extern zend_module_entry openssl_module_entry; #endif struct php_openssl_errors { - int buffer[ERR_NUM_ERRORS]; + int buffer[PHP_OPENSSL_ERR_BUFFER_SIZE]; int top; int bottom; }; diff --git a/ext/openssl/xp_ssl.c b/ext/openssl/xp_ssl.c index a0db38c20bc0..46b4de67ee7d 100644 --- a/ext/openssl/xp_ssl.c +++ b/ext/openssl/xp_ssl.c @@ -497,12 +497,12 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) / } OPENSSL_free(cert_name); } else if (san->type == GEN_IPADD) { - if (san->d.iPAddress->length == 4) { + if (ASN1_STRING_length(san->d.iPAddress) == 4) { sprintf(ipbuffer, "%d.%d.%d.%d", - san->d.iPAddress->data[0], - san->d.iPAddress->data[1], - san->d.iPAddress->data[2], - san->d.iPAddress->data[3] + ASN1_STRING_get0_data(san->d.iPAddress)[0], + ASN1_STRING_get0_data(san->d.iPAddress)[1], + ASN1_STRING_get0_data(san->d.iPAddress)[2], + ASN1_STRING_get0_data(san->d.iPAddress)[3] ); if (strcasecmp(subject_name, (const char*)ipbuffer) == 0) { sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); @@ -511,9 +511,9 @@ static bool php_openssl_matches_san_list(X509 *peer, const char *subject_name) / } } #ifdef HAVE_IPV6_SAN - else if (san->d.ip->length == 16 && subject_name_is_ipv6) { + else if (ASN1_STRING_length(san->d.ip) == 16 && subject_name_is_ipv6) { ipbuffer[0] = 0; - EXPAND_IPV6_ADDRESS(ipbuffer, san->d.iPAddress->data); + EXPAND_IPV6_ADDRESS(ipbuffer, ASN1_STRING_get0_data(san->d.iPAddress)); if (strcasecmp((const char*)subject_name_ipv6_expanded, (const char*)ipbuffer) == 0) { sk_GENERAL_NAME_pop_free(alt_names, GENERAL_NAME_free); From d4c195c41c26115413fa96097827910b4c549025 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Fri, 1 May 2026 18:36:28 -0700 Subject: [PATCH 032/213] Zend/Optimizer/block_pass.c: remove code disabled with `#if 0` (#21791) It has been that way since the initial public release of the optimizer in 528006a3b49fd45d6b2803c7b7843b2e7d6929d6 and survived through the merging as ext/opcache (34d3202edac0a56b91eb8a305fc1801bbd9b7653) and then moving it into core (#6642). If it hasn't been needed in the last 13 years, should be safe to drop. --- Zend/Optimizer/block_pass.c | 53 ------------------------------------- 1 file changed, 53 deletions(-) diff --git a/Zend/Optimizer/block_pass.c b/Zend/Optimizer/block_pass.c index c85b444640a8..02c28ead33e1 100644 --- a/Zend/Optimizer/block_pass.c +++ b/Zend/Optimizer/block_pass.c @@ -344,59 +344,6 @@ static void zend_optimize_block(zend_basic_block *block, zend_op_array *op_array } break; -#if 0 - /* pre-evaluate functions: - constant(x) - function_exists(x) - extension_loaded(x) - BAD: interacts badly with Accelerator - */ - if((opline->op1_type & IS_VAR) && - VAR_SOURCE(opline->op1) && VAR_SOURCE(opline->op1)->opcode == ZEND_DO_CF_FCALL && - VAR_SOURCE(opline->op1)->extended_value == 1) { - zend_op *fcall = VAR_SOURCE(opline->op1); - zend_op *sv = fcall-1; - if(sv >= block->start_opline && sv->opcode == ZEND_SEND_VAL && - sv->op1_type == IS_CONST && Z_TYPE(OPLINE_OP1_LITERAL(sv)) == IS_STRING && - Z_LVAL(OPLINE_OP2_LITERAL(sv)) == 1 - ) { - zval *arg = &OPLINE_OP1_LITERAL(sv); - char *fname = FUNCTION_CACHE->funcs[Z_LVAL(ZEND_OP1_LITERAL(fcall))].function_name; - size_t flen = FUNCTION_CACHE->funcs[Z_LVAL(ZEND_OP1_LITERAL(fcall))].name_len; - if((flen == sizeof("function_exists")-1 && zend_binary_strcasecmp(fname, flen, "function_exists", sizeof("function_exists")-1) == 0) || - (flen == sizeof("is_callable")-1 && zend_binary_strcasecmp(fname, flen, "is_callable", sizeof("is_callable")-1) == 0) - ) { - zend_function *function; - if((function = zend_hash_find_ptr(EG(function_table), Z_STR_P(arg))) != NULL) { - literal_dtor(arg); - MAKE_NOP(sv); - MAKE_NOP(fcall); - LITERAL_BOOL(opline->op1, 1); - opline->op1_type = IS_CONST; - } - } else if(flen == sizeof("constant")-1 && zend_binary_strcasecmp(fname, flen, "constant", sizeof("constant")-1) == 0) { - zval c; - if (zend_optimizer_get_persistent_constant(Z_STR_P(arg), &c, true ELS_CC)) { - literal_dtor(arg); - MAKE_NOP(sv); - MAKE_NOP(fcall); - ZEND_OP1_LITERAL(opline) = zend_optimizer_add_literal(op_array, &c); - /* no copy ctor - get already copied it */ - opline->op1_type = IS_CONST; - } - } else if(flen == sizeof("extension_loaded")-1 && zend_binary_strcasecmp(fname, flen, "extension_loaded", sizeof("extension_loaded")-1) == 0) { - if(zend_hash_exists(&module_registry, Z_STR_P(arg))) { - literal_dtor(arg); - MAKE_NOP(sv); - MAKE_NOP(fcall); - LITERAL_BOOL(opline->op1, 1); - opline->op1_type = IS_CONST; - } - } - } - } -#endif - case ZEND_FETCH_LIST_R: case ZEND_FETCH_LIST_W: if (opline->op1_type & (IS_TMP_VAR|IS_VAR)) { From d71eadc0359338c5ff9d7cc269fca5aa2211cecd Mon Sep 17 00:00:00 2001 From: Daniel Wolfe Date: Fri, 1 May 2026 23:24:50 -0600 Subject: [PATCH 033/213] ext/xsl: Update gh21496.phpt (#21928) Skip test if simplexml extension is disabled. --- ext/xsl/tests/gh21496.phpt | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/xsl/tests/gh21496.phpt b/ext/xsl/tests/gh21496.phpt index 7a5cea37937d..12ff202aed17 100644 --- a/ext/xsl/tests/gh21496.phpt +++ b/ext/xsl/tests/gh21496.phpt @@ -3,6 +3,7 @@ GH-21496 (UAF in dom_objects_free_storage when importing non-document node as st --EXTENSIONS-- dom xsl +simplexml --CREDITS-- YuanchengJiang --FILE-- From b9f64f7afa4ee592b24ea7ec91fd1f72c1f5b344 Mon Sep 17 00:00:00 2001 From: Gina Peter Banyard Date: Sat, 2 May 2026 15:37:10 +0100 Subject: [PATCH 034/213] Improve ZPP weak parsing by returning value directly when possible These changes are based on a previous PR by @ndossche to reduce codebloat: https://github.com/php/php-src/pull/18436 For zend_parse_arg_str_weak() we can return a `zend_string*` directly, as errors can be indicated by a NULL pointer return. For zend_parse_arg_double_weak() we can return a `double` directly, as we can represent ZPP errors via `NAN` as booleans and integers never coerce to NAN. One might think that the string `'NAN'` can be coerced to double `NAN`, however PHP doesn't allow this coercion. And an explicit cast to double via `(float)` of such a string results in 0. For zend_parse_arg_bool_weak() we instead create a new enum zpp_parse_bool_status that represents a tri-state which we return. Allowing us to return the boolean value via the return type instead of using an out pointer. --- Zend/zend_API.c | 82 +++++++++++++++++----------------- Zend/zend_API.h | 44 +++++++++++------- Zend/zend_execute.c | 27 ++++++----- Zend/zend_frameless_function.h | 2 +- Zend/zend_vm_def.h | 2 +- Zend/zend_vm_execute.h | 12 ++--- 6 files changed, 93 insertions(+), 76 deletions(-) diff --git a/Zend/zend_API.c b/Zend/zend_API.c index c97d9308e208..c04217983b5d 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -509,35 +509,33 @@ static ZEND_COLD bool zend_null_arg_deprecated(const char *fallback_type, uint32 return !EG(exception); } -ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_weak(const zval *arg, bool *dest, uint32_t arg_num) /* {{{ */ +ZEND_API zpp_parse_bool_status ZEND_FASTCALL zend_parse_arg_bool_weak(const zval *arg, uint32_t arg_num) /* {{{ */ { if (EXPECTED(Z_TYPE_P(arg) <= IS_STRING)) { if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("bool", arg_num)) { - return 0; + return ZPP_PARSE_BOOL_STATUS_ERROR; } - *dest = zend_is_true(arg); - } else { - return 0; + return zend_is_true(arg); } - return 1; + return ZPP_PARSE_BOOL_STATUS_ERROR; } /* }}} */ -ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_slow(const zval *arg, bool *dest, uint32_t arg_num) /* {{{ */ +ZEND_API zpp_parse_bool_status ZEND_FASTCALL zend_parse_arg_bool_slow(const zval *arg, uint32_t arg_num) /* {{{ */ { if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) { - return 0; + return ZPP_PARSE_BOOL_STATUS_ERROR; } - return zend_parse_arg_bool_weak(arg, dest, arg_num); + return zend_parse_arg_bool_weak(arg, arg_num); } /* }}} */ -ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_bool_slow(const zval *arg, bool *dest, uint32_t arg_num) +ZEND_API zpp_parse_bool_status ZEND_FASTCALL zend_flf_parse_arg_bool_slow(const zval *arg, uint32_t arg_num) { if (UNEXPECTED(ZEND_FLF_ARG_USES_STRICT_TYPES())) { - return 0; + return ZPP_PARSE_BOOL_STATUS_ERROR; } - return zend_parse_arg_bool_weak(arg, dest, arg_num); + return zend_parse_arg_bool_weak(arg, arg_num); } ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_weak(const zval *arg, zend_long *dest, uint32_t arg_num) /* {{{ */ @@ -624,44 +622,46 @@ ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_long_slow(const zval *arg, zend_l return zend_parse_arg_long_weak(arg, dest, arg_num); } -ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, double *dest, uint32_t arg_num) /* {{{ */ +ZEND_API double ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, uint32_t arg_num) /* {{{ */ { if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) { - *dest = (double)Z_LVAL_P(arg); + return (double)Z_LVAL_P(arg); } else if (EXPECTED(Z_TYPE_P(arg) == IS_STRING)) { zend_long l; + double dval; uint8_t type; - if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, dest)) != IS_DOUBLE)) { + if (UNEXPECTED((type = is_numeric_str_function(Z_STR_P(arg), &l, &dval)) != IS_DOUBLE)) { if (EXPECTED(type != 0)) { - *dest = (double)(l); + return (double)(l); } else { - return 0; + return NAN; } + } else { + return dval; } } else if (EXPECTED(Z_TYPE_P(arg) < IS_TRUE)) { if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("float", arg_num)) { - return 0; + return NAN; } - *dest = 0.0; + return 0.0; } else if (EXPECTED(Z_TYPE_P(arg) == IS_TRUE)) { - *dest = 1.0; + return 1.0; } else { - return 0; + return NAN; } - return 1; } /* }}} */ -ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_slow(const zval *arg, double *dest, uint32_t arg_num) /* {{{ */ +ZEND_API double ZEND_FASTCALL zend_parse_arg_double_slow(const zval *arg, uint32_t arg_num) /* {{{ */ { if (EXPECTED(Z_TYPE_P(arg) == IS_LONG)) { /* SSTH Exception: IS_LONG may be accepted instead as IS_DOUBLE */ - *dest = (double)Z_LVAL_P(arg); + return (double)Z_LVAL_P(arg); } else if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) { - return 0; + return NAN; } - return zend_parse_arg_double_weak(arg, dest, arg_num); + return zend_parse_arg_double_weak(arg, arg_num); } /* }}} */ @@ -728,58 +728,58 @@ ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_or_str_slow(zval *arg, zval ** return true; } -ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest, uint32_t arg_num) /* {{{ */ +ZEND_API zend_string* ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, uint32_t arg_num) /* {{{ */ { if (EXPECTED(Z_TYPE_P(arg) < IS_STRING)) { if (UNEXPECTED(Z_TYPE_P(arg) == IS_NULL) && !zend_null_arg_deprecated("string", arg_num)) { - return 0; + return NULL; } convert_to_string(arg); - *dest = Z_STR_P(arg); + return Z_STR_P(arg); } else if (UNEXPECTED(Z_TYPE_P(arg) == IS_OBJECT)) { zend_object *zobj = Z_OBJ_P(arg); zval obj; if (zobj->handlers->cast_object(zobj, &obj, IS_STRING) == SUCCESS) { OBJ_RELEASE(zobj); ZVAL_COPY_VALUE(arg, &obj); - *dest = Z_STR_P(arg); - return 1; + return Z_STR_P(arg); } - return 0; + return NULL; } else { - return 0; + return NULL; } - return 1; } /* }}} */ -ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num) /* {{{ */ +ZEND_API zend_string* ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, uint32_t arg_num) /* {{{ */ { if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) { - return 0; + return NULL; } - return zend_parse_arg_str_weak(arg, dest, arg_num); + return zend_parse_arg_str_weak(arg, arg_num); } /* }}} */ -ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num) +ZEND_API zend_string* ZEND_FASTCALL zend_flf_parse_arg_str_slow(zval *arg, uint32_t arg_num) { if (UNEXPECTED(ZEND_FLF_ARG_USES_STRICT_TYPES())) { - return 0; + return NULL; } - return zend_parse_arg_str_weak(arg, dest, arg_num); + return zend_parse_arg_str_weak(arg, arg_num); } ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_or_long_slow(zval *arg, zend_string **dest_str, zend_long *dest_long, uint32_t arg_num) /* {{{ */ { + zend_string *str; if (UNEXPECTED(ZEND_ARG_USES_STRICT_TYPES())) { return 0; } if (zend_parse_arg_long_weak(arg, dest_long, arg_num)) { *dest_str = NULL; return 1; - } else if (zend_parse_arg_str_weak(arg, dest_str, arg_num)) { + } else if ((str = zend_parse_arg_str_weak(arg, arg_num)) != NULL) { *dest_long = 0; + *dest_str = str; return 1; } else { return 0; diff --git a/Zend/zend_API.h b/Zend/zend_API.h index 7cc9b6ff38dd..01a9202be1c3 100644 --- a/Zend/zend_API.h +++ b/Zend/zend_API.h @@ -2179,21 +2179,27 @@ ZEND_API ZEND_COLD void zend_class_redeclaration_error_ex(int type, zend_string /* Inlined implementations shared by new and old parameter parsing APIs */ +typedef enum zpp_parse_bool_status { + ZPP_PARSE_BOOL_STATUS_FALSE = 0, + ZPP_PARSE_BOOL_STATUS_TRUE = 1, + ZPP_PARSE_BOOL_STATUS_ERROR = 2, +} zpp_parse_bool_status; + ZEND_API bool ZEND_FASTCALL zend_parse_arg_class(zval *arg, zend_class_entry **pce, uint32_t num, bool check_null); -ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_slow(const zval *arg, bool *dest, uint32_t arg_num); -ZEND_API bool ZEND_FASTCALL zend_parse_arg_bool_weak(const zval *arg, bool *dest, uint32_t arg_num); +ZEND_API zpp_parse_bool_status ZEND_FASTCALL zend_parse_arg_bool_slow(const zval *arg, uint32_t arg_num); +ZEND_API zpp_parse_bool_status ZEND_FASTCALL zend_parse_arg_bool_weak(const zval *arg, uint32_t arg_num); ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_slow(const zval *arg, zend_long *dest, uint32_t arg_num); ZEND_API bool ZEND_FASTCALL zend_parse_arg_long_weak(const zval *arg, zend_long *dest, uint32_t arg_num); -ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_slow(const zval *arg, double *dest, uint32_t arg_num); -ZEND_API bool ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, double *dest, uint32_t arg_num); -ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num); -ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, zend_string **dest, uint32_t arg_num); +ZEND_API double ZEND_FASTCALL zend_parse_arg_double_slow(const zval *arg, uint32_t arg_num); +ZEND_API double ZEND_FASTCALL zend_parse_arg_double_weak(const zval *arg, uint32_t arg_num); +ZEND_API zend_string* ZEND_FASTCALL zend_parse_arg_str_slow(zval *arg, uint32_t arg_num); +ZEND_API zend_string* ZEND_FASTCALL zend_parse_arg_str_weak(zval *arg, uint32_t arg_num); ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_slow(zval *arg, zval **dest, uint32_t arg_num); ZEND_API bool ZEND_FASTCALL zend_parse_arg_number_or_str_slow(zval *arg, zval **dest, uint32_t arg_num); ZEND_API bool ZEND_FASTCALL zend_parse_arg_str_or_long_slow(zval *arg, zend_string **dest_str, zend_long *dest_long, uint32_t arg_num); -ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_bool_slow(const zval *arg, bool *dest, uint32_t arg_num); -ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_str_slow(zval *arg, zend_string **dest, uint32_t arg_num); +ZEND_API zpp_parse_bool_status ZEND_FASTCALL zend_flf_parse_arg_bool_slow(const zval *arg, uint32_t arg_num); +ZEND_API zend_string* ZEND_FASTCALL zend_flf_parse_arg_str_slow(zval *arg, uint32_t arg_num); ZEND_API bool ZEND_FASTCALL zend_flf_parse_arg_long_slow(const zval *arg, zend_long *dest, uint32_t arg_num); static zend_always_inline bool zend_parse_arg_bool_ex(const zval *arg, bool *dest, bool *is_null, bool check_null, uint32_t arg_num, bool frameless) @@ -2209,11 +2215,16 @@ static zend_always_inline bool zend_parse_arg_bool_ex(const zval *arg, bool *des *is_null = 1; *dest = 0; } else { + zpp_parse_bool_status result; if (frameless) { - return zend_flf_parse_arg_bool_slow(arg, dest, arg_num); + result = zend_flf_parse_arg_bool_slow(arg, arg_num); } else { - return zend_parse_arg_bool_slow(arg, dest, arg_num); + result = zend_parse_arg_bool_slow(arg, arg_num); + } + if (UNEXPECTED(result == ZPP_PARSE_BOOL_STATUS_ERROR)) { + return false; } + *dest = result; } return 1; } @@ -2259,7 +2270,8 @@ static zend_always_inline bool zend_parse_arg_double(const zval *arg, double *de *is_null = 1; *dest = 0.0; } else { - return zend_parse_arg_double_slow(arg, dest, arg_num); + *dest = zend_parse_arg_double_slow(arg, arg_num); + return !zend_isnan(*dest); } return 1; } @@ -2296,12 +2308,13 @@ static zend_always_inline bool zend_parse_arg_str_ex(zval *arg, zend_string **de *dest = NULL; } else { if (frameless) { - return zend_flf_parse_arg_str_slow(arg, dest, arg_num); + *dest = zend_flf_parse_arg_str_slow(arg, arg_num); } else { - return zend_parse_arg_str_slow(arg, dest, arg_num); + *dest = zend_parse_arg_str_slow(arg, arg_num); } + return *dest != NULL; } - return 1; + return true; } static zend_always_inline bool zend_parse_arg_str(zval *arg, zend_string **dest, bool check_null, uint32_t arg_num) @@ -2532,7 +2545,8 @@ static zend_always_inline bool zend_parse_arg_array_ht_or_str( *dest_str = NULL; } else { *dest_ht = NULL; - return zend_parse_arg_str_slow(arg, dest_str, arg_num); + *dest_str = zend_parse_arg_str_slow(arg, arg_num); + return *dest_str != NULL; } return 1; } diff --git a/Zend/zend_execute.c b/Zend/zend_execute.c index 85461eaa1569..4253037fda52 100644 --- a/Zend/zend_execute.c +++ b/Zend/zend_execute.c @@ -733,8 +733,6 @@ static bool zend_verify_weak_scalar_type_hint(uint32_t type_mask, zval *arg) { zend_long lval; double dval; - zend_string *str; - bool bval; /* Type preference order: int -> float -> string -> bool */ if (type_mask & MAY_BE_LONG) { @@ -760,16 +758,23 @@ static bool zend_verify_weak_scalar_type_hint(uint32_t type_mask, zval *arg) return false; } } - if ((type_mask & MAY_BE_DOUBLE) && zend_parse_arg_double_weak(arg, &dval, 0)) { - zval_ptr_dtor(arg); - ZVAL_DOUBLE(arg, dval); - return true; + if (type_mask & MAY_BE_DOUBLE) { + dval = zend_parse_arg_double_weak(arg, 0); + if (EXPECTED(!zend_isnan(dval))) { + zval_ptr_dtor(arg); + ZVAL_DOUBLE(arg, dval); + return true; + } } - if ((type_mask & MAY_BE_STRING) && zend_parse_arg_str_weak(arg, &str, 0)) { + if ((type_mask & MAY_BE_STRING) && zend_parse_arg_str_weak(arg, 0)) { /* on success "arg" is converted to IS_STRING */ return true; } - if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL && zend_parse_arg_bool_weak(arg, &bval, 0)) { + if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL) { + zpp_parse_bool_status bval = zend_parse_arg_bool_weak(arg, 0); + if (UNEXPECTED(bval == ZPP_PARSE_BOOL_STATUS_ERROR)) { + return false; + } zval_ptr_dtor(arg); ZVAL_BOOL(arg, bval); return true; @@ -793,21 +798,19 @@ static bool can_convert_to_string(const zval *zv) { static bool zend_verify_weak_scalar_type_hint_no_sideeffect(uint32_t type_mask, const zval *arg) { zend_long lval; - double dval; - bool bval; /* Pass (uint32_t)-1 as arg_num to indicate to ZPP not to emit any deprecation notice, * this is needed because the version with side effects also uses 0 (e.g. for typed properties) */ if ((type_mask & MAY_BE_LONG) && zend_parse_arg_long_weak(arg, &lval, (uint32_t)-1)) { return true; } - if ((type_mask & MAY_BE_DOUBLE) && zend_parse_arg_double_weak(arg, &dval, (uint32_t)-1)) { + if ((type_mask & MAY_BE_DOUBLE) && !zend_isnan(zend_parse_arg_double_weak(arg, (uint32_t)-1))) { return true; } if ((type_mask & MAY_BE_STRING) && can_convert_to_string(arg)) { return true; } - if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL && zend_parse_arg_bool_weak(arg, &bval, (uint32_t)-1)) { + if ((type_mask & MAY_BE_BOOL) == MAY_BE_BOOL && zend_parse_arg_bool_weak(arg, (uint32_t)-1) != ZPP_PARSE_BOOL_STATUS_ERROR) { return true; } return false; diff --git a/Zend/zend_frameless_function.h b/Zend/zend_frameless_function.h index 241507aa99e7..b6f361f104b0 100644 --- a/Zend/zend_frameless_function.h +++ b/Zend/zend_frameless_function.h @@ -64,7 +64,7 @@ dest_ht = NULL; \ ZVAL_COPY(&str_tmp, arg ## arg_num); \ arg ## arg_num = &str_tmp; \ - if (!zend_flf_parse_arg_str_slow(arg ## arg_num, &dest_str, arg_num)) { \ + if (!(dest_str = zend_flf_parse_arg_str_slow(arg ## arg_num, arg_num))) { \ zend_wrong_parameter_type_error(arg_num, Z_EXPECTED_ARRAY_OR_STRING, arg ## arg_num); \ goto flf_clean; \ } \ diff --git a/Zend/zend_vm_def.h b/Zend/zend_vm_def.h index 1f7e09d1be35..05923bbc2b61 100644 --- a/Zend/zend_vm_def.h +++ b/Zend/zend_vm_def.h @@ -8843,7 +8843,7 @@ ZEND_VM_COLD_CONST_HANDLER(121, ZEND_STRLEN, CONST|TMP|CV, ANY) } ZVAL_COPY(&tmp, value); - if (zend_parse_arg_str_weak(&tmp, &str, 1)) { + if ((str = zend_parse_arg_str_weak(&tmp, 1)) != NULL) { ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str)); zval_ptr_dtor(&tmp); break; diff --git a/Zend/zend_vm_execute.h b/Zend/zend_vm_execute.h index d5860da23b4c..2b5b9e5fcd47 100644 --- a/Zend/zend_vm_execute.h +++ b/Zend/zend_vm_execute.h @@ -6083,7 +6083,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_ } ZVAL_COPY(&tmp, value); - if (zend_parse_arg_str_weak(&tmp, &str, 1)) { + if ((str = zend_parse_arg_str_weak(&tmp, 1)) != NULL) { ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str)); zval_ptr_dtor(&tmp); break; @@ -18167,7 +18167,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_STRLEN_SPEC_T } ZVAL_COPY(&tmp, value); - if (zend_parse_arg_str_weak(&tmp, &str, 1)) { + if ((str = zend_parse_arg_str_weak(&tmp, 1)) != NULL) { ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str)); zval_ptr_dtor(&tmp); break; @@ -40758,7 +40758,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_FUNC_CCONV ZEND_STRLEN_SPEC_C } ZVAL_COPY(&tmp, value); - if (zend_parse_arg_str_weak(&tmp, &str, 1)) { + if ((str = zend_parse_arg_str_weak(&tmp, 1)) != NULL) { ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str)); zval_ptr_dtor(&tmp); break; @@ -58741,7 +58741,7 @@ static ZEND_VM_COLD ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_STRLE } ZVAL_COPY(&tmp, value); - if (zend_parse_arg_str_weak(&tmp, &str, 1)) { + if ((str = zend_parse_arg_str_weak(&tmp, 1)) != NULL) { ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str)); zval_ptr_dtor(&tmp); break; @@ -70723,7 +70723,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_STRLEN_SPEC_TMP_TA } ZVAL_COPY(&tmp, value); - if (zend_parse_arg_str_weak(&tmp, &str, 1)) { + if ((str = zend_parse_arg_str_weak(&tmp, 1)) != NULL) { ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str)); zval_ptr_dtor(&tmp); break; @@ -93214,7 +93214,7 @@ static ZEND_OPCODE_HANDLER_RET ZEND_OPCODE_HANDLER_CCONV ZEND_STRLEN_SPEC_CV_TAI } ZVAL_COPY(&tmp, value); - if (zend_parse_arg_str_weak(&tmp, &str, 1)) { + if ((str = zend_parse_arg_str_weak(&tmp, 1)) != NULL) { ZVAL_LONG(EX_VAR(opline->result.var), ZSTR_LEN(str)); zval_ptr_dtor(&tmp); break; From c130d42be4ede3e2c530e43d4212a8b26c3e0533 Mon Sep 17 00:00:00 2001 From: Jorg Adam Sowa Date: Sat, 2 May 2026 16:51:02 +0200 Subject: [PATCH 035/213] Validate SameSite cookie attribute against allowed values (#21670) Extract php_is_valid_samesite_value() in ext/standard/head.c as a shared validation function that enforces the SameSite whitelist (Strict, Lax, None, or empty string) with case-insensitive matching. Apply validation in both setcookie()/setrawcookie() (replacing the existing TODO comment) and the session.cookie_samesite INI handler. Previously arbitrary strings including CRLF sequences were accepted and appended verbatim into the Set-Cookie header. --- ext/session/session.c | 16 +++++- .../session_get_cookie_params_basic.phpt | 6 +-- .../session_get_cookie_params_variation1.phpt | 6 +-- ...session_set_cookie_params_invalid_ini.phpt | 22 ++++++++ .../session_set_cookie_params_variation6.phpt | 54 +++++++++++++------ .../session_set_cookie_params_variation7.phpt | 4 +- ext/standard/head.c | 13 ++++- ext/standard/head.h | 2 + .../tests/setcookie_samesite_validation.phpt | 52 ++++++++++++++++++ 9 files changed, 148 insertions(+), 27 deletions(-) create mode 100644 ext/session/tests/session_set_cookie_params_invalid_ini.phpt create mode 100644 ext/standard/tests/setcookie_samesite_validation.phpt diff --git a/ext/session/session.c b/ext/session/session.c index 96e32ea7043f..0a6ad38e5581 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -739,6 +739,20 @@ static PHP_INI_MH(OnUpdateSessionStr) return OnUpdateStr(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); } +static PHP_INI_MH(OnUpdateSessionSameSite) +{ + SESSION_CHECK_ACTIVE_STATE; + SESSION_CHECK_OUTPUT_STATE; + + if (new_value && ZSTR_LEN(new_value) > 0 && !php_is_valid_samesite_value(new_value)) { + php_error_docref(NULL, E_WARNING, + "session.cookie_samesite must be \"Strict\", \"Lax\", \"None\", or \"\""); + return FAILURE; + } + + return OnUpdateStr(entry, new_value, mh_arg1, mh_arg2, mh_arg3, stage); +} + static PHP_INI_MH(OnUpdateSessionBool) { SESSION_CHECK_ACTIVE_STATE; @@ -910,7 +924,7 @@ PHP_INI_BEGIN() STD_PHP_INI_BOOLEAN("session.cookie_secure", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_secure, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.cookie_partitioned", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_partitioned, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.cookie_httponly", "0", PHP_INI_ALL, OnUpdateSessionBool, cookie_httponly, php_ps_globals, ps_globals) - STD_PHP_INI_ENTRY("session.cookie_samesite", "", PHP_INI_ALL, OnUpdateSessionStr, cookie_samesite, php_ps_globals, ps_globals) + STD_PHP_INI_ENTRY("session.cookie_samesite", "", PHP_INI_ALL, OnUpdateSessionSameSite, cookie_samesite, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.use_cookies", "1", PHP_INI_ALL, OnUpdateSessionBool, use_cookies, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.use_only_cookies", "1", PHP_INI_ALL, OnUpdateUseOnlyCookies, use_only_cookies, php_ps_globals, ps_globals) STD_PHP_INI_BOOLEAN("session.use_strict_mode", "0", PHP_INI_ALL, OnUpdateSessionBool, use_strict_mode, php_ps_globals, ps_globals) diff --git a/ext/session/tests/session_get_cookie_params_basic.phpt b/ext/session/tests/session_get_cookie_params_basic.phpt index 73ffd4c94d1e..8e7f8da4e3fb 100644 --- a/ext/session/tests/session_get_cookie_params_basic.phpt +++ b/ext/session/tests/session_get_cookie_params_basic.phpt @@ -30,7 +30,7 @@ var_dump(session_set_cookie_params([ "domain" => "baz", "secure" => FALSE, "httponly" => FALSE, - "samesite" => "please"])); + "samesite" => "Strict"])); var_dump(session_get_cookie_params()); var_dump(session_set_cookie_params([ "secure" => TRUE, @@ -107,7 +107,7 @@ array(7) { ["httponly"]=> bool(false) ["samesite"]=> - string(6) "please" + string(6) "Strict" } bool(true) array(7) { @@ -124,6 +124,6 @@ array(7) { ["httponly"]=> bool(false) ["samesite"]=> - string(6) "please" + string(6) "Strict" } Done diff --git a/ext/session/tests/session_get_cookie_params_variation1.phpt b/ext/session/tests/session_get_cookie_params_variation1.phpt index 7ce112c9b94d..0ab0f233530b 100644 --- a/ext/session/tests/session_get_cookie_params_variation1.phpt +++ b/ext/session/tests/session_get_cookie_params_variation1.phpt @@ -30,7 +30,7 @@ ini_set("session.cookie_secure", TRUE); var_dump(session_get_cookie_params()); ini_set("session.cookie_httponly", TRUE); var_dump(session_get_cookie_params()); -ini_set("session.cookie_samesite", "foo"); +ini_set("session.cookie_samesite", "Lax"); var_dump(session_get_cookie_params()); ini_set("session.cookie_partitioned", TRUE); var_dump(session_get_cookie_params()); @@ -150,7 +150,7 @@ array(7) { ["httponly"]=> bool(true) ["samesite"]=> - string(3) "foo" + string(3) "Lax" } array(7) { ["lifetime"]=> @@ -166,6 +166,6 @@ array(7) { ["httponly"]=> bool(true) ["samesite"]=> - string(3) "foo" + string(3) "Lax" } Done diff --git a/ext/session/tests/session_set_cookie_params_invalid_ini.phpt b/ext/session/tests/session_set_cookie_params_invalid_ini.phpt new file mode 100644 index 000000000000..61728c342ea2 --- /dev/null +++ b/ext/session/tests/session_set_cookie_params_invalid_ini.phpt @@ -0,0 +1,22 @@ +--TEST-- +Test session.cookie_samesite with invalid INI value +--INI-- +session.cookie_samesite=Invalid +--EXTENSIONS-- +session +--SKIPIF-- + +--FILE-- + +--EXPECTF-- +Warning: PHP Startup: session.cookie_samesite must be "Strict", "Lax", "None", or "" in Unknown on line 0 +string(0) "" +Done diff --git a/ext/session/tests/session_set_cookie_params_variation6.phpt b/ext/session/tests/session_set_cookie_params_variation6.phpt index 61243f82751e..fbf958a0be07 100644 --- a/ext/session/tests/session_set_cookie_params_variation6.phpt +++ b/ext/session/tests/session_set_cookie_params_variation6.phpt @@ -1,7 +1,7 @@ --TEST-- -Test session_set_cookie_params() function : variation +Test session_set_cookie_params() samesite validation --INI-- -session.cookie_samesite=test +session.cookie_samesite=Lax --EXTENSIONS-- session --SKIPIF-- @@ -11,36 +11,56 @@ session ob_start(); -echo "*** Testing session_set_cookie_params() : variation ***\n"; - +echo "-- Valid values --\n"; var_dump(ini_get("session.cookie_samesite")); -var_dump(session_set_cookie_params(["samesite" => "nothing"])); +var_dump(session_set_cookie_params(["samesite" => "Strict"])); var_dump(ini_get("session.cookie_samesite")); -var_dump(session_start()); +var_dump(session_set_cookie_params(["samesite" => "None"])); var_dump(ini_get("session.cookie_samesite")); -var_dump(session_set_cookie_params(["samesite" => "test"])); +var_dump(session_set_cookie_params(["samesite" => ""])); var_dump(ini_get("session.cookie_samesite")); -var_dump(session_destroy()); + +echo "-- Invalid value via session_set_cookie_params --\n"; +var_dump(session_set_cookie_params(["samesite" => "Invalid"])); var_dump(ini_get("session.cookie_samesite")); -var_dump(session_set_cookie_params(["samesite" => "other"])); + +echo "-- Invalid value via ini_set --\n"; +var_dump(ini_set("session.cookie_samesite", "Invalid")); var_dump(ini_get("session.cookie_samesite")); +echo "-- Cannot change while session is active --\n"; +var_dump(session_set_cookie_params(["samesite" => "Lax"])); +var_dump(session_start()); +var_dump(session_set_cookie_params(["samesite" => "Strict"])); +var_dump(session_destroy()); + echo "Done"; ob_end_flush(); ?> --EXPECTF-- -*** Testing session_set_cookie_params() : variation *** -string(4) "test" +-- Valid values -- +string(3) "Lax" bool(true) -string(7) "nothing" +string(6) "Strict" bool(true) -string(7) "nothing" +string(4) "None" +bool(true) +string(0) "" +-- Invalid value via session_set_cookie_params -- -Warning: session_set_cookie_params(): Session cookie parameters cannot be changed when a session is active (started from %s on line %d) in %s on line %d +Warning: session_set_cookie_params(): session.cookie_samesite must be "Strict", "Lax", "None", or "" in %s on line %d +bool(false) +string(0) "" +-- Invalid value via ini_set -- + +Warning: ini_set(): session.cookie_samesite must be "Strict", "Lax", "None", or "" in %s on line %d bool(false) -string(7) "nothing" +string(0) "" +-- Cannot change while session is active -- bool(true) -string(7) "nothing" bool(true) -string(5) "other" + +Warning: session_set_cookie_params(): Session cookie parameters cannot be changed when a session is active (started from %s on line %d) in %s on line %d +bool(false) +bool(true) Done diff --git a/ext/session/tests/session_set_cookie_params_variation7.phpt b/ext/session/tests/session_set_cookie_params_variation7.phpt index 430c6efc36e9..3780fc0222f1 100644 --- a/ext/session/tests/session_set_cookie_params_variation7.phpt +++ b/ext/session/tests/session_set_cookie_params_variation7.phpt @@ -33,7 +33,7 @@ try { var_dump(ini_get("session.cookie_secure")); var_dump(ini_get("session.cookie_samesite")); -var_dump(session_set_cookie_params(["secure" => true, "samesite" => "please"])); +var_dump(session_set_cookie_params(["secure" => true, "samesite" => "Strict"])); var_dump(ini_get("session.cookie_secure")); var_dump(ini_get("session.cookie_samesite")); @@ -66,7 +66,7 @@ string(1) "0" string(0) "" bool(true) string(1) "1" -string(6) "please" +string(6) "Strict" string(1) "0" bool(true) string(2) "42" diff --git a/ext/standard/head.c b/ext/standard/head.c index 69e8d1f794ff..03f2e6189ee5 100644 --- a/ext/standard/head.c +++ b/ext/standard/head.c @@ -74,6 +74,13 @@ PHPAPI bool php_header(void) } } +PHPAPI bool php_is_valid_samesite_value(zend_string *value) +{ + return zend_string_equals_literal_ci(value, "Strict") + || zend_string_equals_literal_ci(value, "Lax") + || zend_string_equals_literal_ci(value, "None"); +} + #define ILLEGAL_COOKIE_CHARACTER "\",\", \";\", \" \", \"\\t\", \"\\r\", \"\\n\", \"\\013\", or \"\\014\"" PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t expires, zend_string *path, zend_string *domain, bool secure, bool httponly, @@ -121,7 +128,11 @@ PHPAPI zend_result php_setcookie(zend_string *name, zend_string *value, time_t e return FAILURE; } - /* Should check value of SameSite? */ + if (samesite && ZSTR_LEN(samesite) > 0 && !php_is_valid_samesite_value(samesite)) { + zend_value_error("%s(): \"samesite\" option must be \"Strict\", \"Lax\", \"None\", or \"\"", + get_active_function_name()); + return FAILURE; + } if (value == NULL || ZSTR_LEN(value) == 0) { /* diff --git a/ext/standard/head.h b/ext/standard/head.h index 07c947f8ad0b..8b91371a46e2 100644 --- a/ext/standard/head.h +++ b/ext/standard/head.h @@ -24,6 +24,8 @@ #define COOKIE_SAMESITE "; SameSite=" #define COOKIE_PARTITIONED "; Partitioned" +PHPAPI bool php_is_valid_samesite_value(zend_string *value); + extern PHP_RINIT_FUNCTION(head); PHPAPI bool php_header(void); diff --git a/ext/standard/tests/setcookie_samesite_validation.phpt b/ext/standard/tests/setcookie_samesite_validation.phpt new file mode 100644 index 000000000000..3827f04fe8d4 --- /dev/null +++ b/ext/standard/tests/setcookie_samesite_validation.phpt @@ -0,0 +1,52 @@ +--TEST-- +setcookie() and setrawcookie() validate samesite option +--FILE-- + 'Strict'])); +var_dump(setcookie('test', 'value', ['samesite' => 'Lax'])); +var_dump(setcookie('test', 'value', ['samesite' => 'None'])); +var_dump(setcookie('test', 'value', ['samesite' => ''])); + +// Case-insensitive +var_dump(setcookie('test', 'value', ['samesite' => 'strict'])); +var_dump(setcookie('test', 'value', ['samesite' => 'LAX'])); +var_dump(setcookie('test', 'value', ['samesite' => 'NONE'])); + +// setrawcookie uses the same validation +var_dump(setrawcookie('test', 'value', ['samesite' => 'Lax'])); + +// Invalid values +try { + setcookie('test', 'value', ['samesite' => 'Invalid']); +} catch (ValueError $e) { + echo $e->getMessage() . "\n"; +} + +try { + setcookie('test', 'value', ['samesite' => "Strict\r\nX-Injected: evil"]); +} catch (ValueError $e) { + echo $e->getMessage() . "\n"; +} + +try { + setrawcookie('test', 'value', ['samesite' => 'Invalid']); +} catch (ValueError $e) { + echo $e->getMessage() . "\n"; +} + +?> +--EXPECTF-- +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +bool(true) +setcookie(): "samesite" option must be "Strict", "Lax", "None", or "" +setcookie(): "samesite" option must be "Strict", "Lax", "None", or "" +setrawcookie(): "samesite" option must be "Strict", "Lax", "None", or "" From 28f668d88fec2bcfac590ddc273dcd6c8c3fda54 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Sun, 3 May 2026 02:08:10 +0800 Subject: [PATCH 036/213] ext/standard: Reject null bytes in proc_open() $cwd (#21871) --- NEWS | 2 ++ UPGRADING | 2 ++ ext/standard/proc_open.c | 2 +- .../proc_open_cwd_null_bytes.phpt | 18 ++++++++++++++++++ 4 files changed, 23 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/general_functions/proc_open_cwd_null_bytes.phpt diff --git a/NEWS b/NEWS index 5453a5fc094f..fd17715973a8 100644 --- a/NEWS +++ b/NEWS @@ -186,6 +186,8 @@ PHP NEWS (Weilin Du) . getenv() and putenv() now raises a ValueError when the first argument contains null bytes. (Weilin Du) + . proc_open() now raises a ValueError when the $cwd argument contains + null bytes. (Weilin Du) - Streams: . Added so_keepalive, tcp_keepidle, tcp_keepintvl and tcp_keepcnt stream diff --git a/UPGRADING b/UPGRADING index e55e03be48b9..088f5b620bd4 100644 --- a/UPGRADING +++ b/UPGRADING @@ -102,6 +102,8 @@ PHP 8.6 UPGRADE NOTES argument value is passed. . scandir() now raises a ValueError when an invalid $sorting_order argument value is passed. + . proc_open() now raises a ValueError when the $cwd argument contains + null bytes. - Zip: . ZipArchive::extractTo now raises a TypeError for the diff --git a/ext/standard/proc_open.c b/ext/standard/proc_open.c index edccbeae5646..111111406799 100644 --- a/ext/standard/proc_open.c +++ b/ext/standard/proc_open.c @@ -1240,7 +1240,7 @@ PHP_FUNCTION(proc_open) Z_PARAM_ARRAY_HT(descriptorspec) Z_PARAM_ZVAL(pipes) Z_PARAM_OPTIONAL - Z_PARAM_STRING_OR_NULL(cwd, cwd_len) + Z_PARAM_PATH_OR_NULL(cwd, cwd_len) Z_PARAM_ARRAY_HT_OR_NULL(environment) Z_PARAM_ARRAY_OR_NULL(other_options) ZEND_PARSE_PARAMETERS_END(); diff --git a/ext/standard/tests/general_functions/proc_open_cwd_null_bytes.phpt b/ext/standard/tests/general_functions/proc_open_cwd_null_bytes.phpt new file mode 100644 index 000000000000..faa86c824177 --- /dev/null +++ b/ext/standard/tests/general_functions/proc_open_cwd_null_bytes.phpt @@ -0,0 +1,18 @@ +--TEST-- +proc_open() rejects null bytes in cwd +--SKIPIF-- + +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +proc_open(): Argument #4 ($cwd) must not contain any null bytes From cb3dc62fd90dc2660296d9261c022cd7de52253f Mon Sep 17 00:00:00 2001 From: David Carlier Date: Thu, 30 Apr 2026 19:17:42 +0100 Subject: [PATCH 037/213] ext/spl: Fix SplFixedArray::setSize leak when destructor grows during clear. close GH-21920 --- NEWS | 4 +++ ext/spl/spl_fixedarray.c | 12 ++++---- ...ay_setSize_destruct_grow_during_clear.phpt | 28 +++++++++++++++++++ 3 files changed, 38 insertions(+), 6 deletions(-) create mode 100644 ext/spl/tests/SplFixedArray_setSize_destruct_grow_during_clear.phpt diff --git a/NEWS b/NEWS index 3dbfb2724956..35f34920e626 100644 --- a/NEWS +++ b/NEWS @@ -9,6 +9,10 @@ PHP NEWS - OpenSSL: . Fix compatibility issues with OpenSSL 4.0. (jordikroon, Remi) +- SPL: + . Fix SplFixedArray::setSize leak when destructor grows during clear. + (David Carlier) + - Standard: . Fixed bug GH-21689 (version_compare() incorrectly handles versions ending with a dot). (timwolla) diff --git a/ext/spl/spl_fixedarray.c b/ext/spl/spl_fixedarray.c index 84adbe2233b1..8f8108e2f90b 100644 --- a/ext/spl/spl_fixedarray.c +++ b/ext/spl/spl_fixedarray.c @@ -172,18 +172,18 @@ static void spl_fixedarray_resize(spl_fixedarray *array, zend_long size) return; } - /* first initialization */ - if (array->size == 0) { - spl_fixedarray_init(array, size); - return; - } - if (UNEXPECTED(array->cached_resize >= 0)) { /* We're already resizing, so just remember the desired size. * The resize will happen later. */ array->cached_resize = size; return; } + /* first initialization */ + if (array->size == 0) { + spl_fixedarray_init(array, size); + return; + } + array->cached_resize = size; /* clearing the array */ diff --git a/ext/spl/tests/SplFixedArray_setSize_destruct_grow_during_clear.phpt b/ext/spl/tests/SplFixedArray_setSize_destruct_grow_during_clear.phpt new file mode 100644 index 000000000000..f0982364afa8 --- /dev/null +++ b/ext/spl/tests/SplFixedArray_setSize_destruct_grow_during_clear.phpt @@ -0,0 +1,28 @@ +--TEST-- +SplFixedArray::setSize: grow re-entrantly during clear (setSize(0)) +--FILE-- +arr !== null) { + $this->arr->setSize(5); + } + } +} + +$arr = new SplFixedArray(2); +$r = new Reentrant(); +$r->arr = $arr; +$arr[0] = $r; +unset($r); +$arr[1] = "tail"; + +$arr->setSize(0); +echo "size: ", $arr->getSize(), "\n"; +$arr[0] = "ok"; +var_dump($arr[0]); +?> +--EXPECT-- +size: 5 +string(2) "ok" From a0d743ca174fe5e0b64ecae27682acf03bd96eae Mon Sep 17 00:00:00 2001 From: Frediano Ziglio Date: Thu, 9 Apr 2026 03:34:04 +0100 Subject: [PATCH 038/213] ext/pdo_dblib: Added dblib_handle_check_liveness handler (#21681) Closes #21681 In case of persistent connection it was not checked if the connection was still alive always assuming it was. If the connection was broken this caused PHP to reuse the broken connection over and over. dbdead function is supported by all dblib implementation (MS, Sybase, FreeTDS). Change tested manually, see https://github.com/FreeTDS/freetds/issues/711#issuecomment-4211772091 Signed-off-by: Frediano Ziglio --- NEWS | 3 +++ UPGRADING | 4 ++++ ext/pdo_dblib/dblib_driver.c | 13 ++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/NEWS b/NEWS index fd17715973a8..45524b382c73 100644 --- a/NEWS +++ b/NEWS @@ -99,6 +99,9 @@ PHP NEWS . Added TLS session resumption support for streams with new context options and Openssl\Session class. (Jakub Zelenka) +- PDO_DBLIB; + . Added dblib_handle_check_liveness handler. (freddy77) + - PDO_PGSQL: . Clear session-local state disconnect-equivalent processing. (KentarouTakeda) diff --git a/UPGRADING b/UPGRADING index 088f5b620bd4..fa10bd149f08 100644 --- a/UPGRADING +++ b/UPGRADING @@ -204,6 +204,10 @@ PHP 8.6 UPGRADE NOTES . Output of openssl_x509_parse() contains criticalExtensions listing all critical certificate extensions. +- PDO_DBLIB: + . When using persistent connections, there is now a liveness check in the + constructor. + - Phar: . Phar::mungServer() now supports reference values. diff --git a/ext/pdo_dblib/dblib_driver.c b/ext/pdo_dblib/dblib_driver.c index 42ba72b40ede..9f590c9071b6 100644 --- a/ext/pdo_dblib/dblib_driver.c +++ b/ext/pdo_dblib/dblib_driver.c @@ -420,6 +420,17 @@ static int dblib_get_attribute(pdo_dbh_t *dbh, zend_long attr, zval *return_valu return 1; } +static zend_result dblib_handle_check_liveness(pdo_dbh_t *dbh) +{ + pdo_dblib_db_handle *H = (pdo_dblib_db_handle *)dbh->driver_data; + + if (dbdead(H->link)) { + return FAILURE; + } + + return SUCCESS; +} + static const struct pdo_dbh_methods dblib_methods = { dblib_handle_closer, dblib_handle_preparer, @@ -432,7 +443,7 @@ static const struct pdo_dbh_methods dblib_methods = { dblib_handle_last_id, /* last insert id */ dblib_fetch_error, /* fetch error */ dblib_get_attribute, /* get attr */ - NULL, /* check liveness */ + dblib_handle_check_liveness, /* check_liveness */ NULL, /* get driver methods */ NULL, /* request shutdown */ NULL, /* in transaction, use PDO's internal tracking mechanism */ From 334287d18fe0a74a1280aa13a1f20fa79d6e34c1 Mon Sep 17 00:00:00 2001 From: Saki Takamachi Date: Sun, 3 May 2026 16:27:41 +0900 Subject: [PATCH 039/213] Fix indentation in UPGRADING related #21681 --- UPGRADING | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/UPGRADING b/UPGRADING index fa10bd149f08..4cbe4a981052 100644 --- a/UPGRADING +++ b/UPGRADING @@ -206,7 +206,7 @@ PHP 8.6 UPGRADE NOTES - PDO_DBLIB: . When using persistent connections, there is now a liveness check in the - constructor. + constructor. - Phar: . Phar::mungServer() now supports reference values. From e228395787a13f2f9f5b474d6484c85e7ffa03c7 Mon Sep 17 00:00:00 2001 From: Ilia Alshanetsky Date: Fri, 3 Apr 2026 11:27:52 -0400 Subject: [PATCH 040/213] Use pemalloc/perealloc for persistent allocations Replace direct malloc/realloc calls with OOM-safe pemalloc/perealloc (persistent: true) counterparts. Fixes GH-19200 Fixes GH-17013 Closes GH-21625 --- Zend/zend.c | 2 +- Zend/zend_API.c | 20 ++++++++++---------- Zend/zend_inheritance.c | 12 ++---------- ext/opcache/zend_accelerator_blacklist.c | 2 +- main/network.c | 12 ++++++------ main/php_ini.c | 2 +- main/php_ini_builder.h | 2 +- sapi/phpdbg/phpdbg.c | 4 ++-- sapi/phpdbg/phpdbg_prompt.c | 4 ++-- 9 files changed, 26 insertions(+), 34 deletions(-) diff --git a/Zend/zend.c b/Zend/zend.c index f4236053af3d..f83389a96a6e 100644 --- a/Zend/zend.c +++ b/Zend/zend.c @@ -1303,7 +1303,7 @@ ZEND_API void zend_append_version_info(const zend_extension *extension) /* {{{ * snprintf(new_info, new_info_length, " with %s v%s, %s, by %s\n", extension->name, extension->version, extension->copyright, extension->author); - zend_version_info = (char *) realloc(zend_version_info, zend_version_info_length+new_info_length + 1); + zend_version_info = (char *) perealloc(zend_version_info, zend_version_info_length+new_info_length + 1, true); strncat(zend_version_info, new_info, new_info_length); zend_version_info_length += new_info_length; free(new_info); diff --git a/Zend/zend_API.c b/Zend/zend_API.c index c04217983b5d..ccb770a9963b 100644 --- a/Zend/zend_API.c +++ b/Zend/zend_API.c @@ -2504,19 +2504,19 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */ dl_loaded_count++; } } ZEND_HASH_FOREACH_END(); - module_request_startup_handlers = (zend_module_entry**)realloc( + module_request_startup_handlers = (zend_module_entry**)perealloc( module_request_startup_handlers, sizeof(zend_module_entry*) * (startup_count + 1 + shutdown_count + 1 + - post_deactivate_count + 1)); + post_deactivate_count + 1), true); module_request_startup_handlers[startup_count] = NULL; module_request_shutdown_handlers = module_request_startup_handlers + startup_count + 1; module_request_shutdown_handlers[shutdown_count] = NULL; module_post_deactivate_handlers = module_request_shutdown_handlers + shutdown_count + 1; module_post_deactivate_handlers[post_deactivate_count] = NULL; /* Cannot reuse module_request_startup_handlers because it is freed in zend_destroy_modules, which happens before zend_unload_modules. */ - modules_dl_loaded = realloc(modules_dl_loaded, sizeof(zend_module_entry*) * (dl_loaded_count + 1)); + modules_dl_loaded = perealloc(modules_dl_loaded, sizeof(zend_module_entry*) * (dl_loaded_count + 1), true); modules_dl_loaded[dl_loaded_count] = NULL; startup_count = 0; @@ -2543,10 +2543,10 @@ ZEND_API void zend_collect_module_handlers(void) /* {{{ */ } } ZEND_HASH_FOREACH_END(); - class_cleanup_handlers = (zend_class_entry**)realloc( + class_cleanup_handlers = (zend_class_entry**)perealloc( class_cleanup_handlers, sizeof(zend_class_entry*) * - (class_count + 1)); + (class_count + 1), true); class_cleanup_handlers[class_count] = NULL; if (class_count) { @@ -3143,7 +3143,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend } lowercase_name = zend_string_tolower_ex(internal_function->function_name, type == MODULE_PERSISTENT); lowercase_name = zend_new_interned_string(lowercase_name); - reg_function = malloc(sizeof(zend_internal_function)); + reg_function = pemalloc(sizeof(zend_internal_function), true); memcpy(reg_function, &function, sizeof(zend_internal_function)); if (zend_hash_add_ptr(target_function_table, lowercase_name, reg_function) == NULL) { unload=1; @@ -3161,8 +3161,8 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend zend_flf_capacity *= 2; } /* +1 for NULL terminator */ - zend_flf_handlers = realloc(zend_flf_handlers, (zend_flf_capacity + 1) * sizeof(void *)); - zend_flf_functions = realloc(zend_flf_functions, (zend_flf_capacity + 1) * sizeof(zend_function *)); + zend_flf_handlers = perealloc(zend_flf_handlers, (zend_flf_capacity + 1) * sizeof(void *), true); + zend_flf_functions = perealloc(zend_flf_functions, (zend_flf_capacity + 1) * sizeof(zend_function *), true); } zend_flf_handlers[zend_flf_count] = flf_info->handler; zend_flf_functions[zend_flf_count] = (zend_function *)reg_function; @@ -3208,7 +3208,7 @@ ZEND_API zend_result zend_register_functions(zend_class_entry *scope, const zend /* Treat return type as an extra argument */ num_args++; - new_arg_info = malloc(sizeof(zend_arg_info) * num_args); + new_arg_info = pemalloc(sizeof(zend_arg_info) * num_args, true); reg_function->arg_info = new_arg_info + 1; for (i = 0; i < num_args; i++) { zend_convert_internal_arg_info(&new_arg_info[i], &arg_info[i], @@ -3493,7 +3493,7 @@ ZEND_API int zend_next_free_module(void) /* {{{ */ static zend_class_entry *do_register_internal_class(const zend_class_entry *orig_class_entry, uint32_t ce_flags) /* {{{ */ { - zend_class_entry *class_entry = malloc(sizeof(zend_class_entry)); + zend_class_entry *class_entry = pemalloc(sizeof(zend_class_entry), true); zend_string *lowercase_name; *class_entry = *orig_class_entry; diff --git a/Zend/zend_inheritance.c b/Zend/zend_inheritance.c index bf4c84404a67..d70d08f5f1c4 100644 --- a/Zend/zend_inheritance.c +++ b/Zend/zend_inheritance.c @@ -1595,11 +1595,7 @@ static void zend_do_inherit_interfaces(zend_class_entry *ce, const zend_class_en ce_num = ce->num_interfaces; - if (ce->type == ZEND_INTERNAL_CLASS) { - ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num)); - } else { - ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num)); - } + ce->interfaces = (zend_class_entry **) perealloc(ce->interfaces, sizeof(zend_class_entry *) * (ce_num + if_num), ce->type == ZEND_INTERNAL_CLASS); /* Inherit the interfaces, only if they're not already inherited by the class */ while (if_num--) { @@ -2234,11 +2230,7 @@ ZEND_API void zend_do_implement_interface(zend_class_entry *ce, zend_class_entry } ZEND_HASH_FOREACH_END(); } else { if (ce->num_interfaces >= current_iface_num) { - if (ce->type == ZEND_INTERNAL_CLASS) { - ce->interfaces = (zend_class_entry **) realloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num)); - } else { - ce->interfaces = (zend_class_entry **) erealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num)); - } + ce->interfaces = (zend_class_entry **) perealloc(ce->interfaces, sizeof(zend_class_entry *) * (++current_iface_num), ce->type == ZEND_INTERNAL_CLASS); } ce->interfaces[ce->num_interfaces++] = iface; diff --git a/ext/opcache/zend_accelerator_blacklist.c b/ext/opcache/zend_accelerator_blacklist.c index 56a4ceb4dc4d..ed03a82e9f3f 100644 --- a/ext/opcache/zend_accelerator_blacklist.c +++ b/ext/opcache/zend_accelerator_blacklist.c @@ -225,7 +225,7 @@ static inline void zend_accel_blacklist_allocate(zend_blacklist *blacklist) { if (blacklist->pos == blacklist->size) { blacklist->size += ZEND_BLACKLIST_BLOCK_SIZE; - blacklist->entries = (zend_blacklist_entry *) realloc(blacklist->entries, sizeof(zend_blacklist_entry)*blacklist->size); + blacklist->entries = (zend_blacklist_entry *) perealloc(blacklist->entries, sizeof(zend_blacklist_entry)*blacklist->size, true); } } diff --git a/main/network.c b/main/network.c index f652cf555ffb..90d1716b5582 100644 --- a/main/network.c +++ b/main/network.c @@ -1459,7 +1459,7 @@ static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf if (*hstbuflen == 0) { *hstbuflen = 1024; - *tmphstbuf = (char *)malloc (*hstbuflen); + *tmphstbuf = (char *)pemalloc(*hstbuflen, true); } while (( res = @@ -1467,7 +1467,7 @@ static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf && (errno == ERANGE)) { /* Enlarge the buffer. */ *hstbuflen *= 2; - *tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen); + *tmphstbuf = (char *)perealloc(*tmphstbuf, *hstbuflen, true); } if (res != 0) { @@ -1485,7 +1485,7 @@ static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf if (*hstbuflen == 0) { *hstbuflen = 1024; - *tmphstbuf = (char *)malloc (*hstbuflen); + *tmphstbuf = (char *)pemalloc(*hstbuflen, true); } while ((NULL == ( hp = @@ -1493,7 +1493,7 @@ static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf && (errno == ERANGE)) { /* Enlarge the buffer. */ *hstbuflen *= 2; - *tmphstbuf = (char *)realloc (*tmphstbuf,*hstbuflen); + *tmphstbuf = (char *)perealloc(*tmphstbuf, *hstbuflen, true); } return hp; } @@ -1503,11 +1503,11 @@ static struct hostent * gethostname_re (const char *host,struct hostent *hostbuf { if (*hstbuflen == 0) { *hstbuflen = sizeof(struct hostent_data); - *tmphstbuf = (char *)malloc (*hstbuflen); + *tmphstbuf = (char *)pemalloc(*hstbuflen, true); } else { if (*hstbuflen < sizeof(struct hostent_data)) { *hstbuflen = sizeof(struct hostent_data); - *tmphstbuf = (char *)realloc(*tmphstbuf, *hstbuflen); + *tmphstbuf = (char *)perealloc(*tmphstbuf, *hstbuflen, true); } } memset((void *)(*tmphstbuf),0,*hstbuflen); diff --git a/main/php_ini.c b/main/php_ini.c index 9925eafad1fd..43e1c115e6ea 100644 --- a/main/php_ini.c +++ b/main/php_ini.c @@ -694,7 +694,7 @@ void php_init_config(void) if (total_l) { size_t php_ini_scanned_files_len = (php_ini_scanned_files) ? strlen(php_ini_scanned_files) + 1 : 0; - php_ini_scanned_files = (char *) realloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1); + php_ini_scanned_files = (char *) perealloc(php_ini_scanned_files, php_ini_scanned_files_len + total_l + 1, true); if (!php_ini_scanned_files_len) { *php_ini_scanned_files = '\0'; } diff --git a/main/php_ini_builder.h b/main/php_ini_builder.h index 0ad70b6f68a7..9f73cba13cb7 100644 --- a/main/php_ini_builder.h +++ b/main/php_ini_builder.h @@ -60,7 +60,7 @@ static inline char *php_ini_builder_finish(struct php_ini_builder *b) static inline void php_ini_builder_realloc(struct php_ini_builder *b, size_t delta) { /* reserve enough space for the null terminator */ - b->value = realloc(b->value, b->length + delta + 1); + b->value = perealloc(b->value, b->length + delta + 1, true); } /** diff --git a/sapi/phpdbg/phpdbg.c b/sapi/phpdbg/phpdbg.c index 278e2657862f..3c0d5e836dd0 100644 --- a/sapi/phpdbg/phpdbg.c +++ b/sapi/phpdbg/phpdbg.c @@ -1199,9 +1199,9 @@ int main(int argc, char **argv) /* {{{ */ case 'z': zend_extensions_len++; if (zend_extensions_list) { - zend_extensions_list = realloc(zend_extensions_list, sizeof(char*) * zend_extensions_len); + zend_extensions_list = perealloc(zend_extensions_list, sizeof(char*) * zend_extensions_len, true); } else { - zend_extensions_list = malloc(sizeof(char*) * zend_extensions_len); + zend_extensions_list = pemalloc(sizeof(char*) * zend_extensions_len, true); } zend_extensions_list[zend_extensions_len-1] = strdup(php_optarg); break; diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c index 9435e25ca00b..692cda32c7ea 100644 --- a/sapi/phpdbg/phpdbg_prompt.c +++ b/sapi/phpdbg/phpdbg_prompt.c @@ -215,9 +215,9 @@ static void phpdbg_line_init(char *cmd, struct phpdbg_init_state *state) { if (state->in_code) { if (state->code == NULL) { - state->code = malloc(cmd_len + 1); + state->code = pemalloc(cmd_len + 1, true); } else { - state->code = realloc(state->code, state->code_len + cmd_len + 1); + state->code = perealloc(state->code, state->code_len + cmd_len + 1, true); } if (state->code) { From 87258eb2676e3847573b0f02277d6b7dc46415b8 Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Mon, 4 May 2026 02:36:50 +0200 Subject: [PATCH 041/213] ext/phar: Fix path overread from recent refactoring (#21943) This is from unrelased refactoring: e1c5049#diff-04979daf330cd412502ec8ebf4a363d608a73f034687a0dd07328fd0969f2813L2070-R2069 . It was a clear mistake that can lead to the over-read. --- ext/phar/phar.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index ef25e9c3192e..38c4bb26ff89 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -2074,7 +2074,7 @@ zend_string* phar_fix_filepath(const char *path, size_t path_length, bool use_cw size_t ptr_length; if (use_cwd && PHAR_G(cwd_len) && path_length > 2 && path[0] == '.' && path[1] == '/') { - new_path = zend_string_alloc(path_length + path_length + 1, false); + new_path = zend_string_alloc(path_length + PHAR_G(cwd_len) + 1, false); new_path_len = PHAR_G(cwd_len); memcpy(ZSTR_VAL(new_path), PHAR_G(cwd), PHAR_G(cwd_len)); } else { From d694135da0504b8dffab29157482695614d69cf2 Mon Sep 17 00:00:00 2001 From: Pratik Bhujel Date: Mon, 4 May 2026 18:28:41 +0545 Subject: [PATCH 042/213] Fix GH-21831: Disallow SplObjectStorage mutation during getHash() (#21835) Fixes GH-21831. `getHash()` runs while `SplObjectStorage` is looking up an object. Letting it mutate a storage from there is unsafe, because the caller may still be iterating the table that just changed underneath it. This makes that fail immediately with an `Error` instead of trying to handle it one caller at a time. The existing concurrent deletion tests now cover the new rule, and GH-21831 has a direct regression test. This targets master, so the behavior change is also noted in `UPGRADING`. --- NEWS | 2 + UPGRADING | 2 + ext/spl/spl_observer.c | 108 ++++++++++++++++-- .../SplObjectStorage/concurrent_deletion.phpt | 54 ++++++--- .../concurrent_deletion_addall.phpt | 33 ++---- .../concurrent_deletion_removeexcept.phpt | 25 ++-- ext/spl/tests/SplObjectStorage/gh21831.phpt | 36 ++++++ 7 files changed, 198 insertions(+), 62 deletions(-) create mode 100644 ext/spl/tests/SplObjectStorage/gh21831.phpt diff --git a/NEWS b/NEWS index 45524b382c73..34fbfc5bb385 100644 --- a/NEWS +++ b/NEWS @@ -160,6 +160,8 @@ PHP NEWS - SPL: . DirectoryIterator key can now work better with filesystem supporting larger directory indexing. (David Carlier) + . Fixed bug GH-21831 (SplObjectStorage::removeAllExcept() use-after-free + with re-entrant getHash()). (Pratik Bhujel) . Fix bugs GH-8561, GH-8562, GH-8563, and GH-8564 (Fixing various SplFileObject iterator desync bugs). (iliaal) diff --git a/UPGRADING b/UPGRADING index 4cbe4a981052..3540aee482d9 100644 --- a/UPGRADING +++ b/UPGRADING @@ -77,6 +77,8 @@ PHP 8.6 UPGRADE NOTES logic in their updateTimestamp() method. - SPL: + . SplObjectStorage::getHash() implementations may no longer mutate any + SplObjectStorage instance. Attempting to do so now throws an Error. . SplFileObject::next() now advances the stream when no prior current() call has cached a line. A subsequent current() call returns the new line rather than the previous one. diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index a25cf3cd1bb7..1c6156f6bbfc 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -45,6 +45,8 @@ static zend_object_handlers spl_handler_MultipleIterator; #define SOS_OVERRIDDEN_WRITE_DIMENSION 2 #define SOS_OVERRIDDEN_UNSET_DIMENSION 4 +ZEND_TLS uint32_t spl_object_storage_get_hash_depth; + typedef struct _spl_SplObjectStorage { /* {{{ */ HashTable storage; zend_long index; @@ -69,6 +71,16 @@ static inline spl_SplObjectStorage *spl_object_storage_from_obj(zend_object *obj #define Z_SPLOBJSTORAGE_P(zv) spl_object_storage_from_obj(Z_OBJ_P((zv))) +static zend_always_inline bool spl_object_storage_is_mutating_within_get_hash_call(void) +{ + if (UNEXPECTED(spl_object_storage_get_hash_depth)) { + zend_throw_error(NULL, "Modification of SplObjectStorage during getHash() is prohibited"); + return true; + } + + return false; +} + static void spl_SplObjectStorage_free_storage(zend_object *object) /* {{{ */ { spl_SplObjectStorage *intern = spl_object_storage_from_obj(object); @@ -83,7 +95,10 @@ static zend_result spl_object_storage_get_hash(zend_hash_key *key, spl_SplObject zval param; zval rv; ZVAL_OBJ(¶m, obj); + ZVAL_UNDEF(&rv); + spl_object_storage_get_hash_depth++; zend_call_method_with_1_params(&intern->std, intern->std.ce, &intern->fptr_get_hash, "getHash", &rv, ¶m); + spl_object_storage_get_hash_depth--; if (UNEXPECTED(Z_ISUNDEF(rv))) { /* An exception has occurred */ return FAILURE; @@ -176,6 +191,10 @@ static spl_SplObjectStorageElement *spl_object_storage_attach_handle(spl_SplObje static spl_SplObjectStorageElement *spl_object_storage_attach(spl_SplObjectStorage *intern, zend_object *obj, zval *inf) /* {{{ */ { + if (UNEXPECTED(spl_object_storage_is_mutating_within_get_hash_call())) { + return NULL; + } + if (EXPECTED(!(intern->flags & SOS_OVERRIDDEN_WRITE_DIMENSION))) { return spl_object_storage_attach_handle(intern, obj, inf); } @@ -221,6 +240,10 @@ static spl_SplObjectStorageElement *spl_object_storage_attach(spl_SplObjectStora static zend_result spl_object_storage_detach(spl_SplObjectStorage *intern, zend_object *obj) /* {{{ */ { + if (UNEXPECTED(spl_object_storage_is_mutating_within_get_hash_call())) { + return FAILURE; + } + if (EXPECTED(!(intern->flags & SOS_OVERRIDDEN_UNSET_DIMENSION))) { return zend_hash_index_del(&intern->storage, obj->handle); } @@ -247,7 +270,7 @@ static zend_result spl_object_storage_detach(spl_SplObjectStorage *intern, zend_ if (UNEXPECTED(Z_ISUNDEF_P(_z))) continue; \ _ptr = Z_PTR_P(_z); -static void spl_object_storage_addall(spl_SplObjectStorage *intern, spl_SplObjectStorage *other) { /* {{{ */ +static zend_result spl_object_storage_addall(spl_SplObjectStorage *intern, spl_SplObjectStorage *other) { /* {{{ */ spl_SplObjectStorageElement *element; SPL_SAFE_HASH_FOREACH_PTR(&other->storage, element) { @@ -255,12 +278,16 @@ static void spl_object_storage_addall(spl_SplObjectStorage *intern, spl_SplObjec zend_object *obj = element->obj; GC_ADDREF(obj); ZVAL_COPY(&zv, &element->inf); - spl_object_storage_attach(intern, obj, &zv); + spl_SplObjectStorageElement *attached = spl_object_storage_attach(intern, obj, &zv); zval_ptr_dtor(&zv); OBJ_RELEASE(obj); + if (UNEXPECTED(!attached)) { + return FAILURE; + } } ZEND_HASH_FOREACH_END(); intern->index = 0; + return SUCCESS; } /* }}} */ #define SPL_OBJECT_STORAGE_CLASS_HAS_OVERRIDE(class_type, zstr_method) \ @@ -446,6 +473,9 @@ PHP_METHOD(SplObjectStorage, attach) Z_PARAM_ZVAL(inf) ZEND_PARSE_PARAMETERS_END(); spl_object_storage_attach(intern, obj, inf); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } } /* }}} */ // todo: make spl_object_storage_has_dimension return bool as well @@ -494,6 +524,10 @@ static zval *spl_object_storage_read_dimension(zend_object *object, zval *offset static void spl_object_storage_write_dimension(zend_object *object, zval *offset, zval *inf) { spl_SplObjectStorage *intern = spl_object_storage_from_obj(object); + if (UNEXPECTED(spl_object_storage_is_mutating_within_get_hash_call())) { + return; + } + if (UNEXPECTED(offset == NULL || Z_TYPE_P(offset) != IS_OBJECT || (intern->flags & SOS_OVERRIDDEN_WRITE_DIMENSION))) { zend_std_write_dimension(object, offset, inf); return; @@ -504,6 +538,10 @@ static void spl_object_storage_write_dimension(zend_object *object, zval *offset static void spl_multiple_iterator_write_dimension(zend_object *object, zval *offset, zval *inf) { spl_SplObjectStorage *intern = spl_object_storage_from_obj(object); + if (UNEXPECTED(spl_object_storage_is_mutating_within_get_hash_call())) { + return; + } + if (UNEXPECTED(offset == NULL || Z_TYPE_P(offset) != IS_OBJECT || (intern->flags & SOS_OVERRIDDEN_WRITE_DIMENSION))) { zend_std_write_dimension(object, offset, inf); return; @@ -518,6 +556,10 @@ static void spl_multiple_iterator_write_dimension(zend_object *object, zval *off static void spl_object_storage_unset_dimension(zend_object *object, zval *offset) { spl_SplObjectStorage *intern = spl_object_storage_from_obj(object); + if (UNEXPECTED(spl_object_storage_is_mutating_within_get_hash_call())) { + return; + } + if (UNEXPECTED(Z_TYPE_P(offset) != IS_OBJECT || (intern->flags & SOS_OVERRIDDEN_UNSET_DIMENSION))) { zend_std_unset_dimension(object, offset); return; @@ -535,6 +577,9 @@ PHP_METHOD(SplObjectStorage, detach) Z_PARAM_OBJ(obj) ZEND_PARSE_PARAMETERS_END(); spl_object_storage_detach(intern, obj); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); intern->index = 0; @@ -566,6 +611,7 @@ PHP_METHOD(SplObjectStorage, offsetGet) ZEND_PARSE_PARAMETERS_END(); if (spl_object_storage_get_hash(&key, intern, obj) == FAILURE) { + /* This may be the old NULL fallback, or an exception thrown by getHash(). */ RETURN_NULL(); } @@ -592,7 +638,9 @@ PHP_METHOD(SplObjectStorage, addAll) other = Z_SPLOBJSTORAGE_P(obj); - spl_object_storage_addall(intern, other); + if (UNEXPECTED(spl_object_storage_addall(intern, other) == FAILURE)) { + RETURN_THROWS(); + } RETURN_LONG(zend_hash_num_elements(&intern->storage)); } /* }}} */ @@ -614,6 +662,9 @@ PHP_METHOD(SplObjectStorage, removeAll) zend_hash_internal_pointer_reset(&other->storage); while ((element = zend_hash_get_current_data_ptr(&other->storage)) != NULL) { if (spl_object_storage_detach(intern, element->obj) == FAILURE) { + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } zend_hash_move_forward(&other->storage); } } @@ -641,8 +692,19 @@ PHP_METHOD(SplObjectStorage, removeAllExcept) SPL_SAFE_HASH_FOREACH_PTR(&intern->storage, element) { zend_object *elem_obj = element->obj; GC_ADDREF(elem_obj); - if (!spl_object_storage_contains(other, elem_obj)) { - spl_object_storage_detach(intern, elem_obj); + bool contains = spl_object_storage_contains(other, elem_obj); + if (UNEXPECTED(EG(exception))) { + OBJ_RELEASE(elem_obj); + RETURN_THROWS(); + } + if (!contains) { + if (spl_object_storage_detach(intern, elem_obj) == FAILURE) { + OBJ_RELEASE(elem_obj); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } + continue; + } } OBJ_RELEASE(elem_obj); } ZEND_HASH_FOREACH_END(); @@ -663,7 +725,13 @@ PHP_METHOD(SplObjectStorage, contains) ZEND_PARSE_PARAMETERS_START(1, 1) Z_PARAM_OBJ(obj) ZEND_PARSE_PARAMETERS_END(); - RETURN_BOOL(spl_object_storage_contains(intern, obj)); + + bool contains = spl_object_storage_contains(intern, obj); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } + + RETURN_BOOL(contains); } /* }}} */ /* {{{ Determine number of objects in storage */ @@ -753,6 +821,9 @@ PHP_METHOD(SplObjectStorage, setInfo) if (zend_parse_parameters(ZEND_NUM_ARGS(), "z", &inf) == FAILURE) { RETURN_THROWS(); } + if (UNEXPECTED(spl_object_storage_is_mutating_within_get_hash_call())) { + RETURN_THROWS(); + } if ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) == NULL) { RETURN_NULL(); @@ -947,6 +1018,10 @@ PHP_METHOD(SplObjectStorage, unserialize) if (spl_object_storage_get_hash(&key, intern, Z_OBJ_P(entry)) == FAILURE) { zval_ptr_dtor(&inf); + if (EG(exception)) { + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + RETURN_THROWS(); + } goto outexcept; } pelement = spl_object_storage_get(intern, &key); @@ -960,6 +1035,14 @@ PHP_METHOD(SplObjectStorage, unserialize) var_push_dtor(&var_hash, &obj); } element = spl_object_storage_attach(intern, Z_OBJ_P(entry), Z_ISUNDEF(inf)?NULL:&inf); + if (UNEXPECTED(!element)) { + zval_ptr_dtor(&inf); + if (EG(exception)) { + PHP_VAR_UNSERIALIZE_DESTROY(var_hash); + RETURN_THROWS(); + } + goto outexcept; + } var_replace(&var_hash, &inf, &element->inf); zval_ptr_dtor(&inf); } @@ -1055,7 +1138,9 @@ PHP_METHOD(SplObjectStorage, __unserialize) } ZVAL_DEREF(val); - spl_object_storage_attach(intern, Z_OBJ_P(key), val); + if (UNEXPECTED(!spl_object_storage_attach(intern, Z_OBJ_P(key), val))) { + RETURN_THROWS(); + } key = NULL; } else { key = val; @@ -1151,8 +1236,14 @@ PHP_METHOD(MultipleIterator, attachIterator) } spl_object_storage_attach(intern, iterator, &zinfo); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } } else { spl_object_storage_attach(intern, iterator, NULL); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } } } /* }}} */ @@ -1167,6 +1258,9 @@ PHP_METHOD(MultipleIterator, detachIterator) RETURN_THROWS(); } spl_object_storage_detach(intern, Z_OBJ_P(iterator)); + if (UNEXPECTED(EG(exception))) { + RETURN_THROWS(); + } zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); intern->index = 0; diff --git a/ext/spl/tests/SplObjectStorage/concurrent_deletion.phpt b/ext/spl/tests/SplObjectStorage/concurrent_deletion.phpt index ae063f1c9b03..9da6270b6d7d 100644 --- a/ext/spl/tests/SplObjectStorage/concurrent_deletion.phpt +++ b/ext/spl/tests/SplObjectStorage/concurrent_deletion.phpt @@ -1,46 +1,62 @@ --TEST-- -SplObjectStorage: Concurrent deletion during iteration +SplObjectStorage: Mutation during getHash is prohibited --CREDITS-- cnitlrt --FILE-- mutate) { + $victim[new stdClass()] = null; } return spl_object_hash($obj); } } +function populate(SplObjectStorage $victim, SplObjectStorage $other): void { + for ($i = 0; $i < 1024; $i++) { + $o = new stdClass(); + $victim[$o] = null; + $other[$o] = null; + } +} + $victim = new SplObjectStorage(); $other = new EvilStorage(); -for ($i = 0; $i < 1024; $i++) { - $o = new stdClass(); - $victim[$o] = null; - $other[$o] = null; +populate($victim, $other); +$other->mutate = true; + +try { + $victim->removeAllExcept($other); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } -var_dump($victim->removeAllExcept($other)); +var_dump(count($victim), count($other)); unset($victim, $other); $victim = new SplObjectStorage(); $other = new EvilStorage(); -for ($i = 0; $i < 1024; $i++) { - $o = new stdClass(); - $victim[$o] = null; - $other[$o] = null; +populate($victim, $other); +$other->mutate = true; + +try { + $other->addAll($victim); +} catch (Error $e) { + echo $e->getMessage(), "\n"; } -var_dump($other->addAll($victim)); +var_dump(count($victim), count($other)); ?> ---EXPECTF-- -int(%d) +--EXPECT-- +Modification of SplObjectStorage during getHash() is prohibited +int(1024) +int(1024) +Modification of SplObjectStorage during getHash() is prohibited +int(1024) int(1024) diff --git a/ext/spl/tests/SplObjectStorage/concurrent_deletion_addall.phpt b/ext/spl/tests/SplObjectStorage/concurrent_deletion_addall.phpt index af3fc381b562..aadbe2acba27 100644 --- a/ext/spl/tests/SplObjectStorage/concurrent_deletion_addall.phpt +++ b/ext/spl/tests/SplObjectStorage/concurrent_deletion_addall.phpt @@ -1,5 +1,5 @@ --TEST-- -SplObjectStorage: Concurrent deletion during addAll +SplObjectStorage: Mutation during getHash is prohibited during addAll --CREDITS-- cnitlrt --FILE-- @@ -17,27 +17,16 @@ $storage = new SplObjectStorage(); $storage[new stdClass] = 'foo'; $evil = new EvilStorage(); -$evil->addAll($storage); +try { + $evil->addAll($storage); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -var_dump($evil, $storage); +var_dump(count($evil), count($storage)); ?> ---EXPECTF-- -object(EvilStorage)#%d (1) { - ["storage":"SplObjectStorage":private]=> - array(1) { - [0]=> - array(2) { - ["obj"]=> - object(stdClass)#%d (0) { - } - ["inf"]=> - string(3) "foo" - } - } -} -object(SplObjectStorage)#%d (1) { - ["storage":"SplObjectStorage":private]=> - array(0) { - } -} +--EXPECT-- +Modification of SplObjectStorage during getHash() is prohibited +int(0) +int(1) diff --git a/ext/spl/tests/SplObjectStorage/concurrent_deletion_removeexcept.phpt b/ext/spl/tests/SplObjectStorage/concurrent_deletion_removeexcept.phpt index b2ed211b304a..2602bc9e1f03 100644 --- a/ext/spl/tests/SplObjectStorage/concurrent_deletion_removeexcept.phpt +++ b/ext/spl/tests/SplObjectStorage/concurrent_deletion_removeexcept.phpt @@ -1,5 +1,5 @@ --TEST-- -SplObjectStorage: Concurrent deletion during removeAllExcept +SplObjectStorage: Mutation during getHash is prohibited during removeAllExcept --CREDITS-- cnitlrt --FILE-- @@ -17,19 +17,16 @@ $storage = new SplObjectStorage(); $storage[new stdClass] = 'foo'; $evil = new EvilStorage(); -$storage->removeAllExcept($evil); +try { + $storage->removeAllExcept($evil); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} -var_dump($evil, $storage); +var_dump(count($evil), count($storage)); ?> ---EXPECTF-- -object(EvilStorage)#%d (1) { - ["storage":"SplObjectStorage":private]=> - array(0) { - } -} -object(SplObjectStorage)#%d (1) { - ["storage":"SplObjectStorage":private]=> - array(0) { - } -} +--EXPECT-- +Modification of SplObjectStorage during getHash() is prohibited +int(0) +int(1) diff --git a/ext/spl/tests/SplObjectStorage/gh21831.phpt b/ext/spl/tests/SplObjectStorage/gh21831.phpt new file mode 100644 index 000000000000..581012d86a4f --- /dev/null +++ b/ext/spl/tests/SplObjectStorage/gh21831.phpt @@ -0,0 +1,36 @@ +--TEST-- +GH-21831: SplObjectStorage::getHash() cannot mutate storage during removeAllExcept() +--FILE-- +other) { + $this->other->offsetUnset($obj); + $this->other = null; + } + + return 'x'; + } +} + +$storage = new SplObjectStorage(); +$storage[new stdClass()] = null; + +$filter = new FilterStorage(); +$filter->other = $storage; + +try { + $storage->removeAllExcept($filter); +} catch (Error $e) { + echo $e->getMessage(), "\n"; +} + +var_dump(count($storage)); + +?> +--EXPECT-- +Modification of SplObjectStorage during getHash() is prohibited +int(1) From 241767cc54b38bc0f7753ecc5e3b87db01a22e1d Mon Sep 17 00:00:00 2001 From: Jorg Adam Sowa Date: Mon, 4 May 2026 14:55:40 +0200 Subject: [PATCH 043/213] ext/session: remove dead condition in session.c (#21939) --- ext/session/session.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/ext/session/session.c b/ext/session/session.c index 0a6ad38e5581..3985925ca2bc 100644 --- a/ext/session/session.c +++ b/ext/session/session.c @@ -446,9 +446,7 @@ static zend_result php_session_initialize(void) } else if (PS(use_strict_mode) && PS(mod)->s_validate_sid && PS(mod)->s_validate_sid(&PS(mod_data), PS(id)) == FAILURE ) { - if (PS(id)) { - zend_string_release_ex(PS(id), false); - } + zend_string_release_ex(PS(id), false); PS(id) = PS(mod)->s_create_sid(&PS(mod_data)); if (!PS(id)) { PS(id) = php_session_create_id(NULL); From 71926644bbb7f671a9378c0a83989a811f5b288f Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 2 May 2026 16:27:25 +0100 Subject: [PATCH 044/213] Fix GH-21927: Use-after-free of self-freeing MultipleIterator children. Add a refcount on the child iterator across rewind/next/valid/current/key calls so user methods can detach themselves without freeing the object mid-call. close GH-21933 --- NEWS | 2 + ext/spl/spl_observer.c | 23 +++++- ext/spl/tests/gh21927.phpt | 151 +++++++++++++++++++++++++++++++++++++ 3 files changed, 173 insertions(+), 3 deletions(-) create mode 100644 ext/spl/tests/gh21927.phpt diff --git a/NEWS b/NEWS index 35f34920e626..073a6a9acd44 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,8 @@ PHP NEWS - SPL: . Fix SplFixedArray::setSize leak when destructor grows during clear. (David Carlier) + . Fixed bug GH-21933 (use after free of self-freeing MultipleIterator + children). (David Carlier) - Standard: . Fixed bug GH-21689 (version_compare() incorrectly handles versions ending diff --git a/ext/spl/spl_observer.c b/ext/spl/spl_observer.c index e653d1173b24..56cdbdd4b5f3 100644 --- a/ext/spl/spl_observer.c +++ b/ext/spl/spl_observer.c @@ -1232,7 +1232,9 @@ PHP_METHOD(MultipleIterator, rewind) zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { zend_object *it = element->obj; + GC_ADDREF(it); zend_call_known_instance_method_with_0_params(it->ce->iterator_funcs_ptr->zf_rewind, it, NULL); + OBJ_RELEASE(it); zend_hash_move_forward_ex(&intern->storage, &intern->pos); } } @@ -1253,7 +1255,9 @@ PHP_METHOD(MultipleIterator, next) zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { zend_object *it = element->obj; + GC_ADDREF(it); zend_call_known_instance_method_with_0_params(it->ce->iterator_funcs_ptr->zf_next, it, NULL); + OBJ_RELEASE(it); zend_hash_move_forward_ex(&intern->storage, &intern->pos); } } @@ -1282,7 +1286,9 @@ PHP_METHOD(MultipleIterator, valid) zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { zend_object *it = element->obj; + GC_ADDREF(it); zend_call_known_instance_method_with_0_params(it->ce->iterator_funcs_ptr->zf_valid, it, &retval); + OBJ_RELEASE(it); if (!Z_ISUNDEF(retval)) { valid = (Z_TYPE(retval) == IS_TRUE); @@ -1320,6 +1326,9 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ zend_hash_internal_pointer_reset_ex(&intern->storage, &intern->pos); while ((element = zend_hash_get_current_data_ptr_ex(&intern->storage, &intern->pos)) != NULL && !EG(exception)) { zend_object *it = element->obj; + zval inf; + GC_ADDREF(it); + ZVAL_COPY(&inf, &element->inf); zend_call_known_instance_method_with_0_params(it->ce->iterator_funcs_ptr->zf_valid, it, &retval); if (!Z_ISUNDEF(retval)) { @@ -1336,10 +1345,14 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ zend_call_known_instance_method_with_0_params(it->ce->iterator_funcs_ptr->zf_key, it, &retval); } if (Z_ISUNDEF(retval)) { + OBJ_RELEASE(it); + zval_ptr_dtor(&inf); zend_throw_exception(spl_ce_RuntimeException, "Failed to call sub iterator method", 0); return; } } else if (intern->flags & MIT_NEED_ALL) { + OBJ_RELEASE(it); + zval_ptr_dtor(&inf); if (SPL_MULTIPLE_ITERATOR_GET_ALL_CURRENT == get_type) { zend_throw_exception(spl_ce_RuntimeException, "Called current() with non valid sub iterator", 0); } else { @@ -1351,15 +1364,17 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ } if (intern->flags & MIT_KEYS_ASSOC) { - switch (Z_TYPE(element->inf)) { + switch (Z_TYPE(inf)) { case IS_LONG: - add_index_zval(return_value, Z_LVAL(element->inf), &retval); + add_index_zval(return_value, Z_LVAL(inf), &retval); break; case IS_STRING: - zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR(element->inf), &retval); + zend_symtable_update(Z_ARRVAL_P(return_value), Z_STR(inf), &retval); break; default: zval_ptr_dtor(&retval); + OBJ_RELEASE(it); + zval_ptr_dtor(&inf); zend_throw_exception(spl_ce_InvalidArgumentException, "Sub-Iterator is associated with NULL", 0); return; } @@ -1367,6 +1382,8 @@ static void spl_multiple_iterator_get_all(spl_SplObjectStorage *intern, int get_ add_next_index_zval(return_value, &retval); } + OBJ_RELEASE(it); + zval_ptr_dtor(&inf); zend_hash_move_forward_ex(&intern->storage, &intern->pos); } } diff --git a/ext/spl/tests/gh21927.phpt b/ext/spl/tests/gh21927.phpt new file mode 100644 index 000000000000..a60ea5ca1025 --- /dev/null +++ b/ext/spl/tests/gh21927.phpt @@ -0,0 +1,151 @@ +--TEST-- +GH-21927: Use-after-free of self-freeing MultipleIterator children +--FILE-- +parent->detachIterator($this); + echo "rewind: still alive\n"; + } + public function next(): void {} + public function current(): mixed { return 0; } + public function key(): mixed { return 0; } + public function valid(): bool { return false; } +} + +class DetachOnNext implements Iterator { + public function __construct(private MultipleIterator $parent) {} + public function rewind(): void {} + public function next(): void { + $this->parent->detachIterator($this); + echo "next: still alive\n"; + } + public function current(): mixed { return 0; } + public function key(): mixed { return 0; } + public function valid(): bool { return true; } +} + +class DetachOnValid implements Iterator { + public function __construct(private MultipleIterator $parent) {} + public function rewind(): void {} + public function next(): void {} + public function current(): mixed { return 0; } + public function key(): mixed { return 0; } + public function valid(): bool { + $this->parent->detachIterator($this); + echo "valid: still alive\n"; + return true; + } +} + +class DetachOnCurrent implements Iterator { + public function __construct(private MultipleIterator $parent) {} + public function rewind(): void {} + public function next(): void {} + public function current(): mixed { + $this->parent->detachIterator($this); + echo "current: still alive\n"; + return 'C'; + } + public function key(): mixed { return 'k'; } + public function valid(): bool { return true; } +} + +class DetachOnKey implements Iterator { + public function __construct(private MultipleIterator $parent) {} + public function rewind(): void {} + public function next(): void {} + public function current(): mixed { return 'C'; } + public function key(): mixed { + $this->parent->detachIterator($this); + echo "key: still alive\n"; + return 'K'; + } + public function valid(): bool { return true; } +} + +echo "-- detach inside rewind --\n"; +$mi = new MultipleIterator(); +$mi->attachIterator(new DetachOnRewind($mi)); +$mi->rewind(); +var_dump($mi->countIterators()); + +echo "-- detach inside next --\n"; +$mi = new MultipleIterator(); +$mi->attachIterator(new DetachOnNext($mi)); +$mi->rewind(); +$mi->next(); +var_dump($mi->countIterators()); + +echo "-- detach inside valid --\n"; +$mi = new MultipleIterator(); +$mi->attachIterator(new DetachOnValid($mi)); +var_dump($mi->valid()); +var_dump($mi->countIterators()); + +echo "-- detach inside current (numeric keys) --\n"; +$mi = new MultipleIterator(); +$mi->attachIterator(new DetachOnCurrent($mi)); +var_dump($mi->current()); +var_dump($mi->countIterators()); + +echo "-- detach inside key (numeric keys) --\n"; +$mi = new MultipleIterator(); +$mi->attachIterator(new DetachOnKey($mi)); +var_dump($mi->key()); +var_dump($mi->countIterators()); + +echo "-- detach inside current (assoc keys, refcounted inf) --\n"; +$mi = new MultipleIterator(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_ASSOC); +$mi->attachIterator(new DetachOnCurrent($mi), 'cur_info_string'); +var_dump($mi->current()); +var_dump($mi->countIterators()); + +echo "-- detach inside key (assoc keys, refcounted inf) --\n"; +$mi = new MultipleIterator(MultipleIterator::MIT_NEED_ALL | MultipleIterator::MIT_KEYS_ASSOC); +$mi->attachIterator(new DetachOnKey($mi), 'key_info_string'); +var_dump($mi->key()); +var_dump($mi->countIterators()); + +?> +--EXPECT-- +-- detach inside rewind -- +rewind: still alive +int(0) +-- detach inside next -- +next: still alive +int(0) +-- detach inside valid -- +valid: still alive +bool(true) +int(0) +-- detach inside current (numeric keys) -- +current: still alive +array(1) { + [0]=> + string(1) "C" +} +int(0) +-- detach inside key (numeric keys) -- +key: still alive +array(1) { + [0]=> + string(1) "K" +} +int(0) +-- detach inside current (assoc keys, refcounted inf) -- +current: still alive +array(1) { + ["cur_info_string"]=> + string(1) "C" +} +int(0) +-- detach inside key (assoc keys, refcounted inf) -- +key: still alive +array(1) { + ["key_info_string"]=> + string(1) "K" +} +int(0) From eba954db2b495de517c66de5e008d7bf5f3619ad Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Tue, 5 May 2026 01:12:30 +0800 Subject: [PATCH 045/213] ext/phar: Readability Improvements in phar_fancy_stat() (#21865) --- ext/phar/func_interceptors.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/ext/phar/func_interceptors.c b/ext/phar/func_interceptors.c index e2b45ac2a0ae..8f5d1ab068f1 100644 --- a/ext/phar/func_interceptors.c +++ b/ext/phar/func_interceptors.c @@ -323,10 +323,6 @@ static void phar_fancy_stat(zend_stat_t *stat_sb, int type, zval *return_value) zval stat_dev, stat_ino, stat_mode, stat_nlink, stat_uid, stat_gid, stat_rdev, stat_size, stat_atime, stat_mtime, stat_ctime, stat_blksize, stat_blocks; int rmask=S_IROTH, wmask=S_IWOTH, xmask=S_IXOTH; /* access rights defaults to other */ - char *stat_sb_names[13] = { - "dev", "ino", "mode", "nlink", "uid", "gid", "rdev", - "size", "atime", "mtime", "ctime", "blksize", "blocks" - }; if (type >= FS_IS_W && type <= FS_IS_X) { if(stat_sb->st_uid==getuid()) { @@ -443,19 +439,19 @@ static void phar_fancy_stat(zend_stat_t *stat_sb, int type, zval *return_value) zend_hash_next_index_insert(Z_ARRVAL_P(return_value), &stat_blocks); /* Store string indexes referencing the same zval*/ - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[0], strlen(stat_sb_names[0]), &stat_dev); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[1], strlen(stat_sb_names[1]), &stat_ino); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[2], strlen(stat_sb_names[2]), &stat_mode); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[3], strlen(stat_sb_names[3]), &stat_nlink); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[4], strlen(stat_sb_names[4]), &stat_uid); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[5], strlen(stat_sb_names[5]), &stat_gid); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[6], strlen(stat_sb_names[6]), &stat_rdev); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[7], strlen(stat_sb_names[7]), &stat_size); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[8], strlen(stat_sb_names[8]), &stat_atime); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[9], strlen(stat_sb_names[9]), &stat_mtime); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[10], strlen(stat_sb_names[10]), &stat_ctime); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[11], strlen(stat_sb_names[11]), &stat_blksize); - zend_hash_str_update(Z_ARRVAL_P(return_value), stat_sb_names[12], strlen(stat_sb_names[12]), &stat_blocks); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("dev"), &stat_dev); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("ino"), &stat_ino); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("mode"), &stat_mode); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("nlink"), &stat_nlink); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("uid"), &stat_uid); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("gid"), &stat_gid); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("rdev"), &stat_rdev); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("size"), &stat_size); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("atime"), &stat_atime); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("mtime"), &stat_mtime); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("ctime"), &stat_ctime); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("blksize"), &stat_blksize); + zend_hash_str_update(Z_ARRVAL_P(return_value), ZEND_STRL("blocks"), &stat_blocks); return; } From 2f4a214e5dde0a58b0bd12ffe0b8c66a0d47db96 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Tue, 5 May 2026 01:19:07 +0800 Subject: [PATCH 046/213] ext/standard: Reject null bytes in parse_str() (#21942) --- NEWS | 2 ++ UPGRADING | 2 ++ ext/standard/string.c | 2 +- .../tests/strings/parse_str_null_bytes.phpt | 14 ++++++++++++++ 4 files changed, 19 insertions(+), 1 deletion(-) create mode 100644 ext/standard/tests/strings/parse_str_null_bytes.phpt diff --git a/NEWS b/NEWS index 34fbfc5bb385..fe70343e8398 100644 --- a/NEWS +++ b/NEWS @@ -191,6 +191,8 @@ PHP NEWS (Weilin Du) . getenv() and putenv() now raises a ValueError when the first argument contains null bytes. (Weilin Du) + . parse_str() now raises a ValueError when the $string argument contains + null bytes. (Weilin Du) . proc_open() now raises a ValueError when the $cwd argument contains null bytes. (Weilin Du) diff --git a/UPGRADING b/UPGRADING index 3540aee482d9..fe44036383d0 100644 --- a/UPGRADING +++ b/UPGRADING @@ -99,6 +99,8 @@ PHP 8.6 UPGRADE NOTES argument value is passed. . getenv() and putenv() now raises a ValueError when the first argument contains null bytes. + . parse_str() now raises a ValueError when the $string argument contains + null bytes. . linkinfo() now raises a ValueError when the $path argument is empty. . pathinfo() now raises a ValueError when an invalid $flag argument value is passed. diff --git a/ext/standard/string.c b/ext/standard/string.c index ef9e66ab53f8..89b4e51e6c2c 100644 --- a/ext/standard/string.c +++ b/ext/standard/string.c @@ -5012,7 +5012,7 @@ PHP_FUNCTION(parse_str) size_t arglen; ZEND_PARSE_PARAMETERS_START(2, 2) - Z_PARAM_STRING(arg, arglen) + Z_PARAM_PATH(arg, arglen) Z_PARAM_ZVAL(arrayArg) ZEND_PARSE_PARAMETERS_END(); diff --git a/ext/standard/tests/strings/parse_str_null_bytes.phpt b/ext/standard/tests/strings/parse_str_null_bytes.phpt new file mode 100644 index 000000000000..fd0d94bb0fc8 --- /dev/null +++ b/ext/standard/tests/strings/parse_str_null_bytes.phpt @@ -0,0 +1,14 @@ +--TEST-- +parse_str() rejects null bytes +--FILE-- +getMessage(), "\n"; +} + +?> +--EXPECT-- +parse_str(): Argument #1 ($string) must not contain any null bytes From 6e871075758de4016e72913fbcef226ab6ea7ef1 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 2 May 2026 05:35:29 +0100 Subject: [PATCH 047/213] ext/mysqlnd: Fix persistent free of non-persistent connect_attr key. set_client_option_2d() built the temporary key string with the connection's persistent flag but always released it with persistent=1. On a duplicate-key update of the connect_attr hash, zend_hash_update() does not retain the passed key, so the caller-owned non-persistent string was freed via free() instead of efree(), tripping the IS_STR_PERSISTENT assertion in debug builds and mismatching allocators in release. Reachable by retrying mysqli_real_connect() on a handle whose first connect failed, since mysqlnd re-adds _client_name and _server_host on every connect attempt. close GH-21931 --- NEWS | 3 +++ .../tests/mysqli_real_connect_retry_attr.phpt | 26 +++++++++++++++++++ ext/mysqlnd/mysqlnd_connection.c | 9 +++---- 3 files changed, 32 insertions(+), 6 deletions(-) create mode 100644 ext/mysqli/tests/mysqli_real_connect_retry_attr.phpt diff --git a/NEWS b/NEWS index 073a6a9acd44..eb0336f62933 100644 --- a/NEWS +++ b/NEWS @@ -2,6 +2,9 @@ PHP NEWS ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ?? ??? ????, PHP 8.4.22 +- MySQLnd: + . Fix persistent free of non-persistent connect_attr key (David Carlier). + - Opcache: . Fixed tracing JIT crash when a VM interrupt is handled during an observed user function call. (Levi Morrison) diff --git a/ext/mysqli/tests/mysqli_real_connect_retry_attr.phpt b/ext/mysqli/tests/mysqli_real_connect_retry_attr.phpt new file mode 100644 index 000000000000..7f7731807428 --- /dev/null +++ b/ext/mysqli/tests/mysqli_real_connect_retry_attr.phpt @@ -0,0 +1,26 @@ +--TEST-- +mysqli_real_connect() retry on same handle does not corrupt mysqlnd connect_attr +--EXTENSIONS-- +mysqli +--SKIPIF-- + +--FILE-- + +--EXPECT-- +done! diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c index 2f09ac5ee837..2402ad6fc8f4 100644 --- a/ext/mysqlnd/mysqlnd_connection.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -1572,17 +1572,14 @@ MYSQLND_METHOD(mysqlnd_conn_data, set_client_option_2d)(MYSQLND_CONN_DATA * cons zval attrz; zend_string *str; + str = zend_string_init(key, strlen(key), conn->persistent); + ZVAL_NEW_STR(&attrz, zend_string_init(value, strlen(value), conn->persistent)); if (conn->persistent) { - str = zend_string_init(key, strlen(key), 1); GC_MAKE_PERSISTENT_LOCAL(str); - ZVAL_NEW_STR(&attrz, zend_string_init(value, strlen(value), 1)); GC_MAKE_PERSISTENT_LOCAL(Z_COUNTED(attrz)); - } else { - str = zend_string_init(key, strlen(key), 0); - ZVAL_NEW_STR(&attrz, zend_string_init(value, strlen(value), 0)); } zend_hash_update(conn->options->connect_attr, str, &attrz); - zend_string_release_ex(str, 1); + zend_string_release_ex(str, conn->persistent); } break; default: From c94cb026670d423d0fe388c4cc58d40727d38ac5 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 27 Feb 2026 06:39:25 +0000 Subject: [PATCH 048/213] ext/pcre: simplify pattern info error handling - use zend_hash_str_lookup for locale char table management - replace the separate zend_hash_find_ptr + zend_string_init + zend_hash_add_ptr + zend_string_release sequence with a single zend_hash_str_lookup() call which handles find-or-insert in one hash traversal and manages persistent key creation internally. close GH-21312 --- ext/pcre/php_pcre.c | 31 +++++++++++-------------------- 1 file changed, 11 insertions(+), 20 deletions(-) diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c index 161cdf852c1e..8a3eef28b034 100644 --- a/ext/pcre/php_pcre.c +++ b/ext/pcre/php_pcre.c @@ -748,21 +748,23 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, bo } if (key != regex) { - tables = (uint8_t *)zend_hash_find_ptr(&char_tables, BG(ctype_string)); - if (!tables) { - zend_string *_k; + zv = zend_hash_str_lookup(&char_tables, ZSTR_VAL(BG(ctype_string)), ZSTR_LEN(BG(ctype_string))); + if (Z_ISNULL_P(zv)) { tables = pcre2_maketables(gctx); if (UNEXPECTED(!tables)) { + /* Remove the placeholder entry created by zend_hash_str_lookup(), + * set ptr to NULL first so the destructor (pefree) is safe. */ + ZVAL_PTR(zv, NULL); + zend_hash_str_del(&char_tables, ZSTR_VAL(BG(ctype_string)), ZSTR_LEN(BG(ctype_string))); php_error_docref(NULL,E_WARNING, "Failed to generate locale character tables"); pcre_handle_exec_error(PCRE2_ERROR_NOMEMORY); zend_string_release_ex(key, 0); efree(pattern); return NULL; } - _k = zend_string_init(ZSTR_VAL(BG(ctype_string)), ZSTR_LEN(BG(ctype_string)), 1); - GC_MAKE_PERSISTENT_LOCAL(_k); - zend_hash_add_ptr(&char_tables, _k, (void *)tables); - zend_string_release(_k); + ZVAL_PTR(zv, (void *)tables); + } else { + tables = Z_PTR_P(zv); } } pcre2_set_character_tables(cctx, tables); @@ -824,19 +826,8 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, bo new_entry.refcount = 0; new_entry.subpats_table = NULL; - rc = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, &new_entry.capture_count); - if (rc < 0) { - if (key != regex) { - zend_string_release_ex(key, 0); - } - pcre2_code_free(new_entry.re); - php_error_docref(NULL, E_WARNING, "Internal pcre2_pattern_info() error %d", rc); - pcre_handle_exec_error(PCRE2_ERROR_INTERNAL); - return NULL; - } - - rc = pcre2_pattern_info(re, PCRE2_INFO_NAMECOUNT, &new_entry.name_count); - if (rc < 0) { + if ((rc = pcre2_pattern_info(re, PCRE2_INFO_CAPTURECOUNT, &new_entry.capture_count)) < 0 || + (rc = pcre2_pattern_info(re, PCRE2_INFO_NAMECOUNT, &new_entry.name_count)) < 0) { if (key != regex) { zend_string_release_ex(key, 0); } From de90598b4d399702264d2b1e5c0b0c506cc40208 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Tue, 5 May 2026 09:12:35 +0200 Subject: [PATCH 049/213] zend_types: Remove deprecated `Z_*()` macros (#21946) * zend_types: Remove deprecated `Z_COPYABLE()` * zend_types: Remove deprecated `Z_OPT_IMMUTABLE()` and `Z_IMMUTABLE()` --- UPGRADING.INTERNALS | 5 +++++ Zend/zend_types.h | 14 -------------- 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/UPGRADING.INTERNALS b/UPGRADING.INTERNALS index c0815a781d78..a4297eec5870 100644 --- a/UPGRADING.INTERNALS +++ b/UPGRADING.INTERNALS @@ -98,6 +98,11 @@ PHP 8.6 INTERNALS UPGRADE NOTES the non-throw versions. . The XtOffsetOf() alias of C’s offsetof() macro has been removed. Use offsetof() directly. + . The deprecated Z_COPYABLE(), Z_COPYABLE_P(), Z_OPT_COPYABLE(), and + Z_OPT_COPYABLE_P() macros have been removed. Check for IS_ARRAY directly. + . The deprecated Z_IMMUTABLE(), Z_IMMUTABLE_P(), Z_OPT_IMMUTABLE(), and + Z_OPT_IMMUTABLE_P() macros have been removed. Check for + IS_ARRAY && !REFCOUNTED directly. ======================== 2. Build system changes diff --git a/Zend/zend_types.h b/Zend/zend_types.h index 30d77da67323..cfff3b942c4b 100644 --- a/Zend/zend_types.h +++ b/Zend/zend_types.h @@ -944,16 +944,6 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) { #define Z_COLLECTABLE(zval) ((Z_TYPE_FLAGS(zval) & IS_TYPE_COLLECTABLE) != 0) #define Z_COLLECTABLE_P(zval_p) Z_COLLECTABLE(*(zval_p)) -/* deprecated: (COPYABLE is the same as IS_ARRAY) */ -#define Z_COPYABLE(zval) (Z_TYPE(zval) == IS_ARRAY) -#define Z_COPYABLE_P(zval_p) Z_COPYABLE(*(zval_p)) - -/* deprecated: (IMMUTABLE is the same as IS_ARRAY && !REFCOUNTED) */ -#define Z_IMMUTABLE(zval) (Z_TYPE_INFO(zval) == IS_ARRAY) -#define Z_IMMUTABLE_P(zval_p) Z_IMMUTABLE(*(zval_p)) -#define Z_OPT_IMMUTABLE(zval) Z_IMMUTABLE(zval_p) -#define Z_OPT_IMMUTABLE_P(zval_p) Z_IMMUTABLE(*(zval_p)) - /* the following Z_OPT_* macros make better code when Z_TYPE_INFO accessed before */ #define Z_OPT_TYPE(zval) (Z_TYPE_INFO(zval) & Z_TYPE_MASK) #define Z_OPT_TYPE_P(zval_p) Z_OPT_TYPE(*(zval_p)) @@ -967,10 +957,6 @@ static zend_always_inline uint32_t zval_gc_info(uint32_t gc_type_info) { #define Z_OPT_COLLECTABLE(zval) ((Z_TYPE_INFO(zval) & (IS_TYPE_COLLECTABLE << Z_TYPE_FLAGS_SHIFT)) != 0) #define Z_OPT_COLLECTABLE_P(zval_p) Z_OPT_COLLECTABLE(*(zval_p)) -/* deprecated: (COPYABLE is the same as IS_ARRAY) */ -#define Z_OPT_COPYABLE(zval) (Z_OPT_TYPE(zval) == IS_ARRAY) -#define Z_OPT_COPYABLE_P(zval_p) Z_OPT_COPYABLE(*(zval_p)) - #define Z_OPT_ISREF(zval) (Z_OPT_TYPE(zval) == IS_REFERENCE) #define Z_OPT_ISREF_P(zval_p) Z_OPT_ISREF(*(zval_p)) From ac86e1046852c0882a4a0c3f4083a5fdf801aac5 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 5 May 2026 11:20:26 +0200 Subject: [PATCH 050/213] Fix compiler warning with GCC 16: variable 'offset' set but not used [-Werror=unused-but-set-variable=] --- ext/mysqlnd/mysqlnd_result.c | 6 ++---- ext/opcache/zend_persist.c | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index ae8dc77b4cd9..f43b1d7f59d3 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -994,8 +994,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, const unsigned int array_init_size(return_value, array_size); HashTable *row_ht = Z_ARRVAL_P(return_value); - MYSQLND_FIELD *field = meta->fields; - for (unsigned i = 0; i < meta->field_count; i++, field++) { + for (unsigned i = 0; i < meta->field_count; i++) { zval *data = &row_data[i]; if (flags & MYSQLND_FETCH_NUM) { @@ -1038,10 +1037,9 @@ MYSQLND_METHOD(mysqlnd_res, fetch_row_c)(MYSQLND_RES * result) mysqlnd_result_free_prev_data(result); if (result->m.fetch_row(result, &row_data, 0, &fetched_anything) == PASS && fetched_anything) { unsigned field_count = result->field_count; - MYSQLND_FIELD *field = result->meta->fields; ret = mnd_emalloc(field_count * sizeof(char *)); - for (unsigned i = 0; i < field_count; i++, field++) { + for (unsigned i = 0; i < field_count; i++) { zval *data = &row_data[i]; if (Z_TYPE_P(data) != IS_NULL) { convert_to_string(data); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index f8e11e4d01ec..3f80b7d65d99 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -525,9 +525,8 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc zend_op *new_opcodes = zend_shared_memdup_put(op_array->opcodes, sizeof(zend_op) * op_array->last); zend_op *opline = new_opcodes; zend_op *end = new_opcodes + op_array->last; - int offset = 0; - for (; opline < end ; opline++, offset++) { + for (; opline < end ; opline++) { #if ZEND_USE_ABS_CONST_ADDR if (opline->op1_type == IS_CONST) { opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals)); From efc42033d54d0c3eeefd1c5ce8b197783846e635 Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Tue, 5 May 2026 19:21:44 +0800 Subject: [PATCH 051/213] ext/pcntl: Ensure `$array` is a list array in `pcntl_exec` (#21951) --- NEWS | 4 ++++ UPGRADING | 2 ++ ext/pcntl/pcntl.c | 6 +++++- ext/pcntl/tests/pcntl_exec_list_args.phpt | 14 ++++++++++++++ 4 files changed, 25 insertions(+), 1 deletion(-) create mode 100644 ext/pcntl/tests/pcntl_exec_list_args.phpt diff --git a/NEWS b/NEWS index fe70343e8398..5f0c155a3f7b 100644 --- a/NEWS +++ b/NEWS @@ -85,6 +85,10 @@ PHP NEWS list of candidate encodings (with 200,000+ entries). (Jordi Kroon) . mbregex has been deprecated. (youkidearitai) +- PCNTL: + . pcntl_exec() now throws a ValueError if the $args array is not a list + array. (Weilin Du) + - Mysqli: . Added mysqli_quote_string() and mysqli::quote_string(). (Kamil Tekiela) diff --git a/UPGRADING b/UPGRADING index fe44036383d0..d271eb47f7d1 100644 --- a/UPGRADING +++ b/UPGRADING @@ -37,6 +37,8 @@ PHP 8.6 UPGRADE NOTES - PCNTL: . pcntl_alarm() now raises a ValueError if the seconds argument is lower than zero or greater than platform's UINT_MAX. + . pcntl_exec() now raises a ValueError if the $args argument is not a list + array. - PCRE: . preg_grep() now returns false instead of a partial array when a PCRE diff --git a/ext/pcntl/pcntl.c b/ext/pcntl/pcntl.c index e9453b21329e..2ba732c4540e 100644 --- a/ext/pcntl/pcntl.c +++ b/ext/pcntl/pcntl.c @@ -675,7 +675,11 @@ PHP_FUNCTION(pcntl_exec) ZEND_PARSE_PARAMETERS_END(); if (args != NULL) { - // TODO Check array is a list? + if (!zend_array_is_list(Z_ARRVAL_P(args))) { + zend_argument_value_error(2, "must be a list array"); + RETURN_THROWS(); + } + /* Build argument list */ SEPARATE_ARRAY(args); const HashTable *args_ht = Z_ARRVAL_P(args); diff --git a/ext/pcntl/tests/pcntl_exec_list_args.phpt b/ext/pcntl/tests/pcntl_exec_list_args.phpt new file mode 100644 index 000000000000..5cd8c0fbe228 --- /dev/null +++ b/ext/pcntl/tests/pcntl_exec_list_args.phpt @@ -0,0 +1,14 @@ +--TEST-- +pcntl_exec(): Argument array must be a list +--EXTENSIONS-- +pcntl +--FILE-- + '-n']); +} catch (Throwable $e) { + echo $e::class, ': ', $e->getMessage(), "\n"; +} +?> +--EXPECT-- +ValueError: pcntl_exec(): Argument #2 ($args) must be a list array From 631c366f9f58c8ba4078a48d1f56187cfbf8e549 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 5 May 2026 12:54:25 +0100 Subject: [PATCH 052/213] [ci skip] fix NEWS last entry --- NEWS | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/NEWS b/NEWS index 5f0c155a3f7b..4ace7d3dc462 100644 --- a/NEWS +++ b/NEWS @@ -85,10 +85,6 @@ PHP NEWS list of candidate encodings (with 200,000+ entries). (Jordi Kroon) . mbregex has been deprecated. (youkidearitai) -- PCNTL: - . pcntl_exec() now throws a ValueError if the $args array is not a list - array. (Weilin Du) - - Mysqli: . Added mysqli_quote_string() and mysqli::quote_string(). (Kamil Tekiela) @@ -103,6 +99,10 @@ PHP NEWS . Added TLS session resumption support for streams with new context options and Openssl\Session class. (Jakub Zelenka) +- PCNTL: + . pcntl_exec() now throws a ValueError if the $args array is not a list + array. (Weilin Du) + - PDO_DBLIB; . Added dblib_handle_check_liveness handler. (freddy77) From 6872432adf1a8ddd09a06385512003b1e1a0c916 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Mon, 27 Apr 2026 17:39:42 +0200 Subject: [PATCH 053/213] Fix incorrect trace stop type Restores 79aaeea, which was likely lost in the rebase of 76d7c61 Fixes GH-21746 Closes GH-21891 --- NEWS | 1 + ext/opcache/jit/zend_jit_vm_helpers.c | 2 + ext/opcache/tests/jit/gh21746.inc | 16 ++++ ext/opcache/tests/jit/gh21746.phpt | 112 ++++++++++++++++++++++++++ 4 files changed, 131 insertions(+) create mode 100644 ext/opcache/tests/jit/gh21746.inc create mode 100644 ext/opcache/tests/jit/gh21746.phpt diff --git a/NEWS b/NEWS index 64c9f13cc57c..abd76d8555fe 100644 --- a/NEWS +++ b/NEWS @@ -8,6 +8,7 @@ PHP NEWS - Opcache: . Fixed tracing JIT crash when a VM interrupt is handled during an observed user function call. (Levi Morrison) + . Fixed bug GH-21746 (Segfault with tracing JIT). (Arnaud) - OpenSSL: . Fix compatibility issues with OpenSSL 4.0. (jordikroon, Remi) diff --git a/ext/opcache/jit/zend_jit_vm_helpers.c b/ext/opcache/jit/zend_jit_vm_helpers.c index cb896c0cd8c6..44f46feb5f69 100644 --- a/ext/opcache/jit/zend_jit_vm_helpers.c +++ b/ext/opcache/jit/zend_jit_vm_helpers.c @@ -1097,6 +1097,8 @@ zend_jit_trace_stop ZEND_FASTCALL zend_jit_trace_execute(zend_execute_data *ex, if (UNEXPECTED(!jit_extension) || UNEXPECTED(!(jit_extension->func_info.flags & ZEND_FUNC_JIT_ON_HOT_TRACE))) { if (execute_data->prev_execute_data != prev_execute_data) { + stop = ZEND_JIT_TRACE_STOP_RETURN; + } else { stop = ZEND_JIT_TRACE_STOP_INTERPRETER; } break; diff --git a/ext/opcache/tests/jit/gh21746.inc b/ext/opcache/tests/jit/gh21746.inc new file mode 100644 index 000000000000..b118625484d0 --- /dev/null +++ b/ext/opcache/tests/jit/gh21746.inc @@ -0,0 +1,16 @@ + ''; + $e = fn() => ''; + $f = fn() => ''; + $g = fn() => ''; + return '' + .LR::p(null, '', null, [], '') + .LR::hbbch([null], $d) + .LR::hbbch([null], $e) + .LR::hbbch([null], $f) + .LR::hbbch([null], $g); +}; diff --git a/ext/opcache/tests/jit/gh21746.phpt b/ext/opcache/tests/jit/gh21746.phpt new file mode 100644 index 000000000000..29b3be778be7 --- /dev/null +++ b/ext/opcache/tests/jit/gh21746.phpt @@ -0,0 +1,112 @@ +--TEST-- +GH-21746: Segfault with tracing JIT on 2nd call of eval'd closure +--CREDITS-- +theodorejb +--EXTENSIONS-- +opcache +--INI-- +opcache.jit=tracing +--FILE-- + $_) { if ($i === 0) break; } + return $result; + } + public static function hbbch(array $positional, ?\Closure $cb): string { + if ($cb && is_array($positional[0] ?? null)) foreach ($positional[0] as $v) $cb($v); + return ''; + } +} + +$renderFile = __DIR__ . '/gh21746.inc'; + +// prevent JITing $renderFile +ini_set('opcache.file_update_protection', 100); +touch($renderFile); + +$renderer = require $renderFile; + +for ($r = 0; $r < 70; $r++) { + echo "Render $r..."; + $renderer(); + echo "OK\n"; +} + +?> +==DONE== +--EXPECT-- +Render 0...OK +Render 1...OK +Render 2...OK +Render 3...OK +Render 4...OK +Render 5...OK +Render 6...OK +Render 7...OK +Render 8...OK +Render 9...OK +Render 10...OK +Render 11...OK +Render 12...OK +Render 13...OK +Render 14...OK +Render 15...OK +Render 16...OK +Render 17...OK +Render 18...OK +Render 19...OK +Render 20...OK +Render 21...OK +Render 22...OK +Render 23...OK +Render 24...OK +Render 25...OK +Render 26...OK +Render 27...OK +Render 28...OK +Render 29...OK +Render 30...OK +Render 31...OK +Render 32...OK +Render 33...OK +Render 34...OK +Render 35...OK +Render 36...OK +Render 37...OK +Render 38...OK +Render 39...OK +Render 40...OK +Render 41...OK +Render 42...OK +Render 43...OK +Render 44...OK +Render 45...OK +Render 46...OK +Render 47...OK +Render 48...OK +Render 49...OK +Render 50...OK +Render 51...OK +Render 52...OK +Render 53...OK +Render 54...OK +Render 55...OK +Render 56...OK +Render 57...OK +Render 58...OK +Render 59...OK +Render 60...OK +Render 61...OK +Render 62...OK +Render 63...OK +Render 64...OK +Render 65...OK +Render 66...OK +Render 67...OK +Render 68...OK +Render 69...OK +==DONE== From 608c3edc05f2422cd33ca343c5932670e7834a5d Mon Sep 17 00:00:00 2001 From: Weilin Du <108666168+LamentXU123@users.noreply.github.com> Date: Wed, 6 May 2026 02:38:29 +0800 Subject: [PATCH 054/213] ext/intl: Use ICU U16_APPEND_UNSAFE macro for UTF-16 surrogate pair encoding (#21954) --- ext/intl/converter/converter.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/ext/intl/converter/converter.cpp b/ext/intl/converter/converter.cpp index 051f3ca8bd3a..430d58c8f025 100644 --- a/ext/intl/converter/converter.cpp +++ b/ext/intl/converter/converter.cpp @@ -167,9 +167,9 @@ static void php_converter_append_toUnicode_target(zval *val, UConverterToUnicode if (lval > 0xFFFF) { /* Supplemental planes U+010000 - U+10FFFF */ if (TARGET_CHECK(args, 2)) { - /* TODO: Find the ICU call which does this properly */ - *(args->target++) = (UChar)(((lval - 0x10000) >> 10) | 0xD800); - *(args->target++) = (UChar)(((lval - 0x10000) & 0x3FF) | 0xDC00); + int32_t offset = 0; + U16_APPEND_UNSAFE(args->target, offset, lval); + args->target += offset; } return; } From e5fa4ec36a55b2da83d04e600de9dc8dc38b8951 Mon Sep 17 00:00:00 2001 From: Kamil Tekiela Date: Tue, 5 May 2026 21:02:02 +0100 Subject: [PATCH 055/213] ext/mysqlnd: Use iterated struct and remove dulicate SET_AFFECTED_ROWS (#21713) --- ext/mysqlnd/mysqlnd_result.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 1d43946f41d3..bce57b0ab052 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -720,9 +720,6 @@ MYSQLND_METHOD(mysqlnd_res, store_result_fetch_data)(MYSQLND_CONN_DATA * const c if (ret == FAIL) { COPY_CLIENT_ERROR(&set->error_info, row_packet.error_info); - } else { - /* libmysql's documentation says it should be so for SELECT statements */ - UPSERT_STATUS_SET_AFFECTED_ROWS(conn->upsert_status, set->row_count); } DBG_INF_FMT("ret=%s row_count=%u warnings=%u server_status=%u", ret == PASS? "PASS":"FAIL", @@ -1002,18 +999,11 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, const unsigned int } } if (flags & MYSQLND_FETCH_ASSOC) { - /* zend_hash_quick_update needs length + trailing zero */ - /* QQ: Error handling ? */ - /* - zend_hash_quick_update does not check, as add_assoc_zval_ex do, whether - the index is a numeric and convert it to it. This however means constant - hashing of the column name, which is not needed as it can be precomputed. - */ Z_TRY_ADDREF_P(data); - if (meta->fields[i].is_numeric == FALSE) { - zend_hash_update(row_ht, meta->fields[i].sname, data); + if (field->is_numeric == FALSE) { + zend_hash_update(row_ht, field->sname, data); } else { - zend_hash_index_update(row_ht, meta->fields[i].num_key, data); + zend_hash_index_update(row_ht, field->num_key, data); } } From 6a2751450930e111ec960f5fb76754db21b9d919 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 5 May 2026 11:22:09 +0200 Subject: [PATCH 056/213] Fix compiler warning with glibc 2.43 support of C23 const-preserving standard library macros: assignment discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers] See https://sourceware.org/cgit/glibc/commit/?id=cd748a63ab1 Closes GH-21950 --- ext/mysqlnd/mysqlnd_alloc.c | 10 +++++----- ext/mysqlnd/mysqlnd_connection.c | 2 +- ext/mysqlnd/mysqlnd_wireprotocol.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_alloc.c b/ext/mysqlnd/mysqlnd_alloc.c index 06971b3487dd..3c059f327ac9 100644 --- a/ext/mysqlnd/mysqlnd_alloc.c +++ b/ext/mysqlnd/mysqlnd_alloc.c @@ -201,7 +201,7 @@ static void _mysqlnd_efree(void *ptr MYSQLND_MEM_D) #if PHP_DEBUG { - char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); + const char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno); } #endif @@ -232,7 +232,7 @@ static void _mysqlnd_pefree(void *ptr, bool persistent MYSQLND_MEM_D) #if PHP_DEBUG { - char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); + const char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno); } #endif @@ -264,7 +264,7 @@ static char * _mysqlnd_pememdup(const char * const ptr, size_t length, bool pers #if PHP_DEBUG { - char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); + const char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno); } #endif @@ -295,7 +295,7 @@ static char * _mysqlnd_pestrndup(const char * const ptr, size_t length, bool per #if PHP_DEBUG { - char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); + const char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno); } #endif @@ -336,7 +336,7 @@ static char * _mysqlnd_pestrdup(const char * const ptr, bool persistent MYSQLND_ TRACE_ALLOC_ENTER(mysqlnd_pestrdup_name); #if PHP_DEBUG { - char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); + const char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno); } #endif diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c index 2402ad6fc8f4..2d7d97b237e5 100644 --- a/ext/mysqlnd/mysqlnd_connection.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -557,7 +557,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_ /* IPv6 without square brackets so without port */ transport.l = mnd_sprintf(&transport.s, 0, "tcp://[%s]:%u", hostname.s, port); } else { - char *p; + const char *p; /* IPv6 addresses are in the format [address]:port */ if (hostname.s[0] == '[') { /* IPv6 */ diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 36fd53233737..64c2c7969619 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -461,7 +461,7 @@ php_mysqlnd_greet_read(MYSQLND_CONN_DATA * conn, void * _packet) packet->auth_protocol = estrdup(""); } else { /* Check if NUL present */ - char *null_terminator = memchr(p, '\0', remaining_size); + const char *null_terminator = memchr(p, '\0', remaining_size); size_t auth_protocol_len; if (null_terminator) { /* If present, do basically estrdup */ From 178a5e79971bebe58cd0f578a1ede0e8dbf90690 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 5 May 2026 11:20:26 +0200 Subject: [PATCH 057/213] Fix compiler warning with GCC 16: variable 'offset' set but not used [-Werror=unused-but-set-variable=] --- ext/mysqlnd/mysqlnd_result.c | 6 ++---- ext/opcache/zend_persist.c | 3 +-- 2 files changed, 3 insertions(+), 6 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index ae8dc77b4cd9..f43b1d7f59d3 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -994,8 +994,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, const unsigned int array_init_size(return_value, array_size); HashTable *row_ht = Z_ARRVAL_P(return_value); - MYSQLND_FIELD *field = meta->fields; - for (unsigned i = 0; i < meta->field_count; i++, field++) { + for (unsigned i = 0; i < meta->field_count; i++) { zval *data = &row_data[i]; if (flags & MYSQLND_FETCH_NUM) { @@ -1038,10 +1037,9 @@ MYSQLND_METHOD(mysqlnd_res, fetch_row_c)(MYSQLND_RES * result) mysqlnd_result_free_prev_data(result); if (result->m.fetch_row(result, &row_data, 0, &fetched_anything) == PASS && fetched_anything) { unsigned field_count = result->field_count; - MYSQLND_FIELD *field = result->meta->fields; ret = mnd_emalloc(field_count * sizeof(char *)); - for (unsigned i = 0; i < field_count; i++, field++) { + for (unsigned i = 0; i < field_count; i++) { zval *data = &row_data[i]; if (Z_TYPE_P(data) != IS_NULL) { convert_to_string(data); diff --git a/ext/opcache/zend_persist.c b/ext/opcache/zend_persist.c index 38e58d5a1663..29b6c2f7a6b2 100644 --- a/ext/opcache/zend_persist.c +++ b/ext/opcache/zend_persist.c @@ -543,9 +543,8 @@ static void zend_persist_op_array_ex(zend_op_array *op_array, zend_persistent_sc zend_op *new_opcodes = zend_shared_memdup_put(op_array->opcodes, sizeof(zend_op) * op_array->last); zend_op *opline = new_opcodes; zend_op *end = new_opcodes + op_array->last; - int offset = 0; - for (; opline < end ; opline++, offset++) { + for (; opline < end ; opline++) { #if ZEND_USE_ABS_CONST_ADDR if (opline->op1_type == IS_CONST) { opline->op1.zv = (zval*)((char*)opline->op1.zv + ((char*)op_array->literals - (char*)orig_literals)); From ac1390f60ebc03b92e0a14343ff5aea67d4cd6d2 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Tue, 5 May 2026 11:22:09 +0200 Subject: [PATCH 058/213] Fix compiler warning with glibc 2.43 support of C23 const-preserving standard library macros: assignment discards 'const' qualifier from pointer target type [-Werror=discarded-qualifiers] See https://sourceware.org/cgit/glibc/commit/?id=cd748a63ab1 Closes GH-21950 --- ext/mysqlnd/mysqlnd_alloc.c | 10 +++++----- ext/mysqlnd/mysqlnd_connection.c | 2 +- ext/mysqlnd/mysqlnd_wireprotocol.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ext/mysqlnd/mysqlnd_alloc.c b/ext/mysqlnd/mysqlnd_alloc.c index 06971b3487dd..3c059f327ac9 100644 --- a/ext/mysqlnd/mysqlnd_alloc.c +++ b/ext/mysqlnd/mysqlnd_alloc.c @@ -201,7 +201,7 @@ static void _mysqlnd_efree(void *ptr MYSQLND_MEM_D) #if PHP_DEBUG { - char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); + const char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno); } #endif @@ -232,7 +232,7 @@ static void _mysqlnd_pefree(void *ptr, bool persistent MYSQLND_MEM_D) #if PHP_DEBUG { - char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); + const char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno); } #endif @@ -264,7 +264,7 @@ static char * _mysqlnd_pememdup(const char * const ptr, size_t length, bool pers #if PHP_DEBUG { - char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); + const char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno); } #endif @@ -295,7 +295,7 @@ static char * _mysqlnd_pestrndup(const char * const ptr, size_t length, bool per #if PHP_DEBUG { - char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); + const char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno); } #endif @@ -336,7 +336,7 @@ static char * _mysqlnd_pestrdup(const char * const ptr, bool persistent MYSQLND_ TRACE_ALLOC_ENTER(mysqlnd_pestrdup_name); #if PHP_DEBUG { - char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); + const char * fn = strrchr(__zend_filename, PHP_DIR_SEPARATOR); TRACE_ALLOC_INF_FMT("file=%-15s line=%4d", fn? fn + 1:__zend_filename, __zend_lineno); } #endif diff --git a/ext/mysqlnd/mysqlnd_connection.c b/ext/mysqlnd/mysqlnd_connection.c index 9c379448f63e..3b51ee665542 100644 --- a/ext/mysqlnd/mysqlnd_connection.c +++ b/ext/mysqlnd/mysqlnd_connection.c @@ -552,7 +552,7 @@ MYSQLND_METHOD(mysqlnd_conn_data, get_scheme)(MYSQLND_CONN_DATA * conn, MYSQLND_ /* IPv6 without square brackets so without port */ transport.l = mnd_sprintf(&transport.s, 0, "tcp://[%s]:%u", hostname.s, port); } else { - char *p; + const char *p; /* IPv6 addresses are in the format [address]:port */ if (hostname.s[0] == '[') { /* IPv6 */ diff --git a/ext/mysqlnd/mysqlnd_wireprotocol.c b/ext/mysqlnd/mysqlnd_wireprotocol.c index 36fd53233737..64c2c7969619 100644 --- a/ext/mysqlnd/mysqlnd_wireprotocol.c +++ b/ext/mysqlnd/mysqlnd_wireprotocol.c @@ -461,7 +461,7 @@ php_mysqlnd_greet_read(MYSQLND_CONN_DATA * conn, void * _packet) packet->auth_protocol = estrdup(""); } else { /* Check if NUL present */ - char *null_terminator = memchr(p, '\0', remaining_size); + const char *null_terminator = memchr(p, '\0', remaining_size); size_t auth_protocol_len; if (null_terminator) { /* If present, do basically estrdup */ From 33caad78f044bbe3137f26b164e233ef6b634e81 Mon Sep 17 00:00:00 2001 From: Arnaud Le Blanc Date: Wed, 6 May 2026 12:39:47 +0200 Subject: [PATCH 059/213] Fix bad merge --- ext/mysqlnd/mysqlnd_result.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/mysqlnd/mysqlnd_result.c b/ext/mysqlnd/mysqlnd_result.c index 1f811c8795df..b4d0bdbd8d2c 100644 --- a/ext/mysqlnd/mysqlnd_result.c +++ b/ext/mysqlnd/mysqlnd_result.c @@ -990,7 +990,7 @@ MYSQLND_METHOD(mysqlnd_res, fetch_into)(MYSQLND_RES * result, const unsigned int HashTable *row_ht = Z_ARRVAL_P(return_value); MYSQLND_FIELD *field = meta->fields; - for (unsigned i = 0; i < meta->field_count; i++) { + for (unsigned i = 0; i < meta->field_count; i++, field++) { zval *data = &row_data[i]; if (flags & MYSQLND_FETCH_NUM) { From aee3b3ac9b816b0def1c462695b483b49a83148e Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 3 May 2026 19:56:53 +0200 Subject: [PATCH 060/213] GHSA-85c2-q967-79q5: [soap] Fix stale SOAP_GLOBAL(ref_map) pointer with Apache Map Fixes GHSA-85c2-q967-79q5 Fixes CVE-2026-6722 --- ext/soap/php_encoding.c | 3 +- ext/soap/tests/GHSA-85c2-q967-79q5.phpt | 61 +++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 ext/soap/tests/GHSA-85c2-q967-79q5.phpt diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index a685dbcd228a..725c279d8d42 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -365,6 +365,7 @@ static bool soap_check_xml_ref(zval *data, xmlNodePtr node) static void soap_add_xml_ref(zval *data, xmlNodePtr node) { if (SOAP_GLOBAL(ref_map)) { + Z_TRY_ADDREF_P(data); zend_hash_index_update(SOAP_GLOBAL(ref_map), (zend_ulong)node, data); } } @@ -3448,7 +3449,7 @@ void encode_reset_ns() } else { SOAP_GLOBAL(ref_map) = emalloc(sizeof(HashTable)); } - zend_hash_init(SOAP_GLOBAL(ref_map), 0, NULL, NULL, 0); + zend_hash_init(SOAP_GLOBAL(ref_map), 0, NULL, ZVAL_PTR_DTOR, 0); } void encode_finish() diff --git a/ext/soap/tests/GHSA-85c2-q967-79q5.phpt b/ext/soap/tests/GHSA-85c2-q967-79q5.phpt new file mode 100644 index 000000000000..8bcac26ad187 --- /dev/null +++ b/ext/soap/tests/GHSA-85c2-q967-79q5.phpt @@ -0,0 +1,61 @@ +--TEST-- +GHSA-85c2-q967-79q5: Stale SOAP_GLOBAL(ref_map) pointer with Apache Map +--CREDITS-- +brettgervasoni +--EXTENSIONS-- +soap +--FILE-- + + + + + + + + foo + bar + + + foo + baz + + + + + + +XML; + +$s = new SoapServer(null, ['uri' => 'urn:a']); +$s->setClass(Handler::class); +$s->handle($envelope); +var_dump($result); + +?> +--EXPECTF-- + + +array(2) { + [0]=> + array(1) { + ["foo"]=> + string(3) "baz" + } + [1]=> + object(stdClass)#%d (1) { + ["object"]=> + string(3) "bar" + } +} From db2a7f9348fd5dda5fd162061786a664c417bf5b Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sun, 3 May 2026 19:57:16 +0200 Subject: [PATCH 061/213] GHSA-m33r-qmcv-p97q: [soap] Fix use-after-free after header parsing failure with SOAP_PERSISTENCE_SESSION Fixes GHSA-m33r-qmcv-p97q Fixes CVE-2026-7261 --- ext/soap/soap.c | 12 ++++- ext/soap/tests/GHSA-m33r-qmcv-p97q.phpt | 58 +++++++++++++++++++++++++ 2 files changed, 68 insertions(+), 2 deletions(-) create mode 100644 ext/soap/tests/GHSA-m33r-qmcv-p97q.phpt diff --git a/ext/soap/soap.c b/ext/soap/soap.c index 1350c0c0a344..02501b8d73ff 100644 --- a/ext/soap/soap.c +++ b/ext/soap/soap.c @@ -1438,12 +1438,20 @@ PHP_METHOD(SoapServer, handle) instanceof_function(Z_OBJCE(h->retval), soap_fault_class_entry)) { php_output_discard(); soap_server_fault_ex(function, &h->retval, h); - if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);} + if (service->type == SOAP_CLASS && soap_obj) { + if (service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) { + zval_ptr_dtor(soap_obj); + } + } goto fail; } else if (EG(exception)) { php_output_discard(); _soap_server_exception(service, function, ZEND_THIS); - if (service->type == SOAP_CLASS && soap_obj) {zval_ptr_dtor(soap_obj);} + if (service->type == SOAP_CLASS && soap_obj) { + if (service->soap_class.persistence != SOAP_PERSISTENCE_SESSION) { + zval_ptr_dtor(soap_obj); + } + } goto fail; } } else if (h->mustUnderstand) { diff --git a/ext/soap/tests/GHSA-m33r-qmcv-p97q.phpt b/ext/soap/tests/GHSA-m33r-qmcv-p97q.phpt new file mode 100644 index 000000000000..bcf441ccd18a --- /dev/null +++ b/ext/soap/tests/GHSA-m33r-qmcv-p97q.phpt @@ -0,0 +1,58 @@ +--TEST-- +GHSA-m33r-qmcv-p97q: Use-after-free after header parsing failure with SOAP_PERSISTENCE_SESSION +--CREDITS-- +Ilia Alshanetsky (iliaal) +--EXTENSIONS-- +soap +session +--FILE-- + 'urn:a']); +$srv->setClass(Handler::class); +$srv->setPersistence(SOAP_PERSISTENCE_SESSION); + +$srv->handle(<< + + + + + + + + +XML); + +$srv->handle(<< + + + + + + + + +XML); + +?> +--EXPECT-- + +SOAP-ENV:Serverdenied + +SOAP-ENV:Serverdenied From 79551ab8b1a97760c739e372f9bc359619f3554d Mon Sep 17 00:00:00 2001 From: Ilija Tovilo Date: Sat, 25 Apr 2026 00:44:37 +0200 Subject: [PATCH 062/213] GHSA-hmxp-6pc4-f3vv: [soap] Fix broken Apache map value NULL check Fixes GHSA-hmxp-6pc4-f3vv Fixes CVE-2026-7262 --- ext/soap/php_encoding.c | 2 +- ext/soap/tests/GHSA-hmxp-6pc4-f3vv.phpt | 39 +++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 ext/soap/tests/GHSA-hmxp-6pc4-f3vv.phpt diff --git a/ext/soap/php_encoding.c b/ext/soap/php_encoding.c index 725c279d8d42..0865726ceb9b 100644 --- a/ext/soap/php_encoding.c +++ b/ext/soap/php_encoding.c @@ -2722,7 +2722,7 @@ static zval *to_zval_map(zval *ret, encodeTypePtr type, xmlNodePtr data) } xmlValue = get_node(item->children, "value"); - if (!xmlKey) { + if (!xmlValue) { soap_error0(E_ERROR, "Encoding: Can't decode apache map, missing value"); } diff --git a/ext/soap/tests/GHSA-hmxp-6pc4-f3vv.phpt b/ext/soap/tests/GHSA-hmxp-6pc4-f3vv.phpt new file mode 100644 index 000000000000..e46ab2e4607d --- /dev/null +++ b/ext/soap/tests/GHSA-hmxp-6pc4-f3vv.phpt @@ -0,0 +1,39 @@ +--TEST-- +GHSA-hmxp-6pc4-f3vv: Null pointer dereference on missing Apache map value +--CREDITS-- +Ilia Alshanetsky (iliaal) +--EXTENSIONS-- +soap +--FILE-- + + + + + + + hello + + + + +XML; + +$server = new SoapServer(null, [ + 'uri' => 'urn:test', + 'typemap' => [['type_name' => 'anything']], +]); +$server->addFunction('test'); +function test($m) { return null; } +$server->handle($request); + +?> +--EXPECT-- + +SOAP-ENV:ServerSOAP-ERROR: Encoding: Can't decode apache map, missing value From 99a5ad7441de9914246c7863adb6997396008b9d Mon Sep 17 00:00:00 2001 From: Jakub Zelenka Date: Sun, 3 May 2026 20:01:41 +0200 Subject: [PATCH 063/213] GHSA-7qg2-v9fj-4mwv: [fpm] XSS within status endpoint Fixes GHSA-7qg2-v9fj-4mwv Fixes CVE-2026-6735 --- sapi/fpm/fpm/fpm_status.c | 34 +++++++++++-- .../tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt | 48 +++++++++++++++++++ 2 files changed, 78 insertions(+), 4 deletions(-) create mode 100644 sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt diff --git a/sapi/fpm/fpm/fpm_status.c b/sapi/fpm/fpm/fpm_status.c index cebaa18c964b..0339b75a1449 100644 --- a/sapi/fpm/fpm/fpm_status.c +++ b/sapi/fpm/fpm/fpm_status.c @@ -528,8 +528,8 @@ int fpm_status_handle_request(void) /* {{{ */ if (full_syntax) { unsigned int i; int first; - zend_string *tmp_query_string; - char *query_string; + zend_string *tmp_query_string, *tmp_request_uri_string; + char *query_string, *request_uri_string; struct timeval duration, now; float cpu; @@ -554,13 +554,36 @@ int fpm_status_handle_request(void) /* {{{ */ } } + request_uri_string = NULL; + tmp_request_uri_string = NULL; + if (proc->request_uri[0] != '\0') { + if (encode_html) { + tmp_request_uri_string = php_escape_html_entities_ex( + (const unsigned char *) proc->request_uri, + strlen(proc->request_uri), 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT, + NULL, /* double_encode */ 1, /* quiet */ 0); + request_uri_string = ZSTR_VAL(tmp_request_uri_string); + } else if (encode_json) { + tmp_request_uri_string = php_json_encode_string(proc->request_uri, + strlen(proc->request_uri), PHP_JSON_INVALID_UTF8_IGNORE); + request_uri_string = ZSTR_VAL(tmp_request_uri_string); + /* remove quotes around the string */ + if (ZSTR_LEN(tmp_request_uri_string) >= 2) { + request_uri_string[ZSTR_LEN(tmp_request_uri_string) - 1] = '\0'; + ++request_uri_string; + } + } else { + request_uri_string = proc->request_uri; + } + } + query_string = NULL; tmp_query_string = NULL; if (proc->query_string[0] != '\0') { if (encode_html) { tmp_query_string = php_escape_html_entities_ex( (const unsigned char *) proc->query_string, - strlen(proc->query_string), 1, ENT_HTML_IGNORE_ERRORS & ENT_COMPAT, + strlen(proc->query_string), 1, ENT_DISALLOWED | ENT_HTML_DOC_XML1 | ENT_COMPAT, NULL, /* double_encode */ 1, /* quiet */ 0); } else if (encode_json) { tmp_query_string = php_json_encode_string(proc->query_string, @@ -599,7 +622,7 @@ int fpm_status_handle_request(void) /* {{{ */ proc->requests, duration.tv_sec * 1000000UL + duration.tv_usec, proc->request_method[0] != '\0' ? proc->request_method : "-", - proc->request_uri[0] != '\0' ? proc->request_uri : "-", + request_uri_string ? request_uri_string : "-", query_string ? "?" : "", query_string ? query_string : "", proc->content_length, @@ -610,6 +633,9 @@ int fpm_status_handle_request(void) /* {{{ */ PUTS(buffer); efree(buffer); + if (tmp_request_uri_string) { + zend_string_free(tmp_request_uri_string); + } if (tmp_query_string) { zend_string_free(tmp_query_string); } diff --git a/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt b/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt new file mode 100644 index 000000000000..475bc130a42b --- /dev/null +++ b/sapi/fpm/tests/ghsa-7qg2-v9fj-4mwv-status-xss.phpt @@ -0,0 +1,48 @@ +--TEST-- +FPM: GHSA-7qg2-v9fj-4mwv - status xss +--SKIPIF-- + +--FILE-- +start(); +$tester->expectLogStartNotices(); +$responses = $tester + ->multiRequest([ + ['uri' => '/', 'query' => ''], + ['uri' => '/status', 'query' => 'full&html', 'delay' => 100000], + ]); +var_dump(strpos($responses[1]->getBody(), '