From ebbb1b42958f9c793cd10bf55d31837946905277 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 19 Oct 2025 20:52:19 +0200 Subject: [PATCH 1/3] Fix GH-19021: improve tidyOptGetCategory detection We now check both this symbol and TidyInternalCategory presence. Co-authored-by: Peter Kokot --- NEWS | 4 ++++ ext/tidy/config.m4 | 30 +++++++++++++++++++++++------- 2 files changed, 27 insertions(+), 7 deletions(-) diff --git a/NEWS b/NEWS index 537673e64fa99..4b2a4777fef50 100644 --- a/NEWS +++ b/NEWS @@ -64,6 +64,10 @@ PHP NEWS - Standard: . Fix shm corruption with coercion in options of unserialize(). (nielsdos) +- Tidy: + . Fixed GH-19021 (improved tidyOptGetCategory detection). + (arjendekorte, David Carlier, Peter Kokot) + - XMLReader: . Fix arginfo/zpp violations when LIBXML_SCHEMAS_ENABLED is not available. (nielsdos) diff --git a/ext/tidy/config.m4 b/ext/tidy/config.m4 index 802e12fc367c0..ff80a2cde30f9 100644 --- a/ext/tidy/config.m4 +++ b/ext/tidy/config.m4 @@ -62,16 +62,32 @@ if test "$PHP_TIDY" != "no"; then AC_DEFINE(HAVE_TIDYRELEASEDATE,1,[ ]) ], [], []) - dnl The tidyOptGetCategory function (added in libtidy 5.4.0) if only useable - dnl if TidyInternalCategory (added in libtidy 5.6.0) is also present. - PHP_CHECK_LIBRARY($TIDY_LIB_NAME,TidyInternalCategory, - [ - AC_DEFINE(HAVE_TIDYOPTGETCATEGORY,1,[ ]) - ], [], []) - PHP_ADD_LIBRARY_WITH_PATH($TIDY_LIB_NAME, $TIDY_LIBDIR, TIDY_SHARED_LIBADD) PHP_ADD_INCLUDE($TIDY_INCDIR) + old_CPPFLAGS=$CPPFLAGS + CPPFLAGS=-I$TIDY_INCDIR + + dnl The tidyOptGetCategory function (added in tidy-html5 5.4.0) is only + dnl useable if TidyInternalCategory (added in tidy-html5 5.6.0) is also + dnl present. + AC_CACHE_CHECK([for tidyOptGetCategory], [php_ac_cv_have_tidyoptgetcategory], + [AC_COMPILE_IFELSE([AC_LANG_PROGRAM([#include ],[ + TidyDoc doc = tidyCreate(); + TidyOption badopt = tidyGetOptionByName(doc, ""); + Bool v = (tidyOptGetCategory(badopt) == TidyInternalCategory); + (void)v; + tidyRelease(doc); + ])], + [php_ac_cv_have_tidyoptgetcategory=yes], + [php_ac_cv_have_tidyoptgetcategory=no]) + ]) + AS_VAR_IF([php_ac_cv_have_tidyoptgetcategory], [yes], + [AC_DEFINE([HAVE_TIDYOPTGETCATEGORY], [1], + [Define to 1 if tidyOptGetCategory is available.])]) + + CPPFLAGS=$old_CPPFLAGS + dnl Add -Wno-ignored-qualifiers as this is an issue upstream TIDY_COMPILER_FLAGS="$TIDY_CFLAGS -Wno-ignored-qualifiers -DZEND_ENABLE_STATIC_TSRMLS_CACHE=1" PHP_NEW_EXTENSION(tidy, tidy.c, $ext_shared,, $TIDY_COMPILER_FLAGS) From a29c5d6928c28f656c6348c2371a7cd4d4add2e2 Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 19 Oct 2025 23:03:18 +0200 Subject: [PATCH 2/3] phar: Simplify phar_wrapper_stat() (#20222) We can pass NULL instead of the error pointer, as we never use the value of the error pointer anyway. --- ext/phar/stream.c | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/ext/phar/stream.c b/ext/phar/stream.c index d7bcc78fd8a8d..77ca7137fdf50 100644 --- a/ext/phar/stream.c +++ b/ext/phar/stream.c @@ -558,7 +558,7 @@ static int phar_wrapper_stat(php_stream_wrapper *wrapper, const char *url, int f php_stream_statbuf *ssb, php_stream_context *context) /* {{{ */ { php_url *resource = NULL; - char *internal_file, *error; + char *internal_file; phar_archive_data *phar; phar_entry_info *entry; size_t internal_file_len; @@ -582,16 +582,10 @@ 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, &error)) { + if (FAILURE == phar_get_archive(&phar, ZSTR_VAL(resource->host), ZSTR_LEN(resource->host), NULL, 0, NULL)) { php_url_free(resource); - if (error) { - efree(error); - } return FAILURE; } - if (error) { - efree(error); - } if (*internal_file == '\0') { /* root directory requested */ phar_dostat(phar, NULL, ssb, true); From 63e534d7cae5c50c306382e0b12e64470bd3f66a Mon Sep 17 00:00:00 2001 From: Niels Dossche <7771979+nielsdos@users.noreply.github.com> Date: Sun, 19 Oct 2025 23:29:08 +0200 Subject: [PATCH 3/3] phar: Remove no-op bool casts (#20227) The field in this struct is already a bool. --- ext/phar/phar.c | 8 ++++---- ext/phar/tar.c | 6 +++--- ext/phar/zip.c | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/ext/phar/phar.c b/ext/phar/phar.c index f31a4f841225f..8a41ae99199fd 100644 --- a/ext/phar/phar.c +++ b/ext/phar/phar.c @@ -1108,11 +1108,11 @@ static zend_result phar_parse_pharfile(php_stream *fp, char *fname, size_t fname /* set up our manifest */ zend_hash_init(&mydata->manifest, manifest_count, - zend_get_hash_value, destroy_phar_manifest_entry, (bool)mydata->is_persistent); + zend_get_hash_value, destroy_phar_manifest_entry, mydata->is_persistent); zend_hash_init(&mydata->mounted_dirs, 5, - zend_get_hash_value, NULL, (bool)mydata->is_persistent); + zend_get_hash_value, NULL, mydata->is_persistent); zend_hash_init(&mydata->virtual_dirs, manifest_count * 2, - zend_get_hash_value, NULL, (bool)mydata->is_persistent); + zend_get_hash_value, NULL, mydata->is_persistent); mydata->fname = pestrndup(fname, fname_len, mydata->is_persistent); #ifdef PHP_WIN32 phar_unixify_path_separators(mydata->fname, fname_len); @@ -1451,7 +1451,7 @@ ZEND_ATTRIBUTE_NONNULL_ARGS(1, 7, 8) zend_result phar_create_or_parse_filename(c zend_hash_init(&mydata->mounted_dirs, sizeof(char *), zend_get_hash_value, NULL, 0); zend_hash_init(&mydata->virtual_dirs, sizeof(char *), - zend_get_hash_value, NULL, (bool)mydata->is_persistent); + zend_get_hash_value, NULL, mydata->is_persistent); mydata->fname_len = fname_len; snprintf(mydata->version, sizeof(mydata->version), "%s", PHP_PHAR_API_VERSION); mydata->is_temporary_alias = alias ? 0 : 1; diff --git a/ext/phar/tar.c b/ext/phar/tar.c index 550183746a2c8..8a5df4f443dc3 100644 --- a/ext/phar/tar.c +++ b/ext/phar/tar.c @@ -233,11 +233,11 @@ zend_result phar_parse_tarfile(php_stream* fp, char *fname, size_t fname_len, ch myphar->is_persistent = PHAR_G(persist); /* estimate number of entries, can't be certain with tar files */ zend_hash_init(&myphar->manifest, 2 + (totalsize >> 12), - zend_get_hash_value, destroy_phar_manifest_entry, (bool)myphar->is_persistent); + zend_get_hash_value, destroy_phar_manifest_entry, myphar->is_persistent); zend_hash_init(&myphar->mounted_dirs, 5, - zend_get_hash_value, NULL, (bool)myphar->is_persistent); + zend_get_hash_value, NULL, myphar->is_persistent); zend_hash_init(&myphar->virtual_dirs, 4 + (totalsize >> 11), - zend_get_hash_value, NULL, (bool)myphar->is_persistent); + zend_get_hash_value, NULL, myphar->is_persistent); myphar->is_tar = 1; /* remember whether this entire phar was compressed with gz/bzip2 */ myphar->flags = compression; diff --git a/ext/phar/zip.c b/ext/phar/zip.c index e8ffecec57147..dff893c221b94 100644 --- a/ext/phar/zip.c +++ b/ext/phar/zip.c @@ -336,11 +336,11 @@ zend_result phar_parse_zipfile(php_stream *fp, char *fname, size_t fname_len, ch php_stream_seek(fp, PHAR_GET_32(locator.cdir_offset), SEEK_SET); /* read in central directory */ zend_hash_init(&mydata->manifest, PHAR_GET_16(locator.count), - zend_get_hash_value, destroy_phar_manifest_entry, (bool)mydata->is_persistent); + zend_get_hash_value, destroy_phar_manifest_entry, mydata->is_persistent); zend_hash_init(&mydata->mounted_dirs, 5, - zend_get_hash_value, NULL, (bool)mydata->is_persistent); + zend_get_hash_value, NULL, mydata->is_persistent); zend_hash_init(&mydata->virtual_dirs, PHAR_GET_16(locator.count) * 2, - zend_get_hash_value, NULL, (bool)mydata->is_persistent); + zend_get_hash_value, NULL, mydata->is_persistent); entry.phar = mydata; entry.is_zip = 1; entry.fp_type = PHAR_FP;