[packages/php-pecl-expect] And more fixes
arekm
arekm at pld-linux.org
Thu Feb 19 21:06:18 CET 2026
commit 0c1a5cfd7f39cac816fd4ff9e8fbd16a6fda4288
Author: Arkadiusz Miśkiewicz <arekm at maven.pl>
Date: Thu Feb 19 21:06:13 2026 +0100
And more fixes
build.patch | 152 ++++++++++++++++++++++++++++++++++++++++++++++++++-
php-pecl-expect.spec | 4 +-
2 files changed, 153 insertions(+), 3 deletions(-)
---
diff --git a/php-pecl-expect.spec b/php-pecl-expect.spec
index 0cd4bc5..10bd146 100644
--- a/php-pecl-expect.spec
+++ b/php-pecl-expect.spec
@@ -19,7 +19,7 @@ BuildRequires: %{php_name}-devel >= 3:5.0.4
BuildRequires: expect-devel
BuildRequires: rpmbuild(macros) >= 1.650
%if %{with tests}
-BuildRequires: %{php_name}-cgi
+BuildRequires: %{php_name}-cli
%endif
%{?requires_php_extension}
Provides: php(%{modname}) = %{version}
@@ -53,7 +53,7 @@ phpize
%if %{with tests}
export NO_INTERACTION=1
%{__make} test \
- PHP_EXECUTABLE=%{_bindir}/%{php_name}.cgi
+ PHP_EXECUTABLE=%{_bindir}/%{php_name}
%endif
%install
diff --git a/build.patch b/build.patch
index 815ec52..bb4b061 100644
--- a/build.patch
+++ b/build.patch
@@ -58,4 +58,154 @@
if ((fp = exp_popen((char*)command)) != NULL) {
#else
if ((fp = exp_popen(command)) != NULL) {
-=======
+
+ Fix segfaults on PHP 8.5 (three distinct bugs)
+
+ 1. OPcache immutable arrays: PHP 8.5 with opcache.protect_memory=1
+ stores literal arrays in read-only shared memory. Calls to
+ zend_hash_internal_pointer_reset() and zend_hash_move_forward()
+ wrote to ht->nInternalPointer in that protected memory, causing
+ SIGSEGV. Fix: use _ex variants with a local HashPosition variable
+ so no write touches the HashTable struct itself.
+
+ 2. Dead stream validation: !&(stream->wrapperdata) is always false in
+ PHP 7+ because wrapperdata is an embedded zval (not a pointer).
+ Non-expect streams (e.g. from popen()) bypassed the check and
+ crashed inside libexpect. Fix: check Z_TYPE(stream->wrapperdata)
+ != IS_LONG instead.
+
+ 3. php_stream_open_wrapper() during MINIT: OnSetExpectLogFile called
+ php_stream_open_wrapper() at PHP_INI_STAGE_STARTUP before
+ EG(regular_list) is initialized, crashing in zend_hash_rehash.
+ Fix: skip stream opening during STARTUP/SHUTDOWN stages and add
+ PHP_RINIT_FUNCTION to open the logfile once the request context
+ is available.
+
+diff --git a/expect.c b/expect.c
+index cc735a8..ca2b4a1 100644
+--- a/expect.c
++++ b/expect.c
+@@ -53,7 +53,7 @@ zend_module_entry expect_module_entry = {
+ expect_functions,
+ PHP_MINIT(expect),
+ PHP_MSHUTDOWN(expect),
+- NULL,
++ PHP_RINIT(expect),
+ NULL,
+ PHP_MINFO(expect),
+ PHP_EXPECT_VERSION,
+@@ -151,8 +151,18 @@ static PHP_INI_MH(OnSetExpectLogUser)
+ * */
+ static PHP_INI_MH(OnSetExpectLogFile)
+ {
++ /* PHP streams cannot be opened during module startup because the resource
++ * list (EG(regular_list)) is not yet initialized. The logfile will be
++ * opened in RINIT once the request context is available. */
++ if (stage == PHP_INI_STAGE_STARTUP || stage == PHP_INI_STAGE_SHUTDOWN) {
++ return SUCCESS;
++ }
++
+ if (EXPECT_G(logfile_stream)) {
+ php_stream_close(EXPECT_G(logfile_stream));
++ EXPECT_G(logfile_stream) = NULL;
++ exp_logfile = NULL;
++ exp_logfile_all = 0;
+ }
+ #if PHP_MAJOR_VERSION >= 7
+ if (ZSTR_LEN(new_value) > 0) {
+@@ -232,6 +242,28 @@ PHP_MSHUTDOWN_FUNCTION(expect)
+ /* }}} */
+
+
++/* {{{ PHP_RINIT_FUNCTION
++ * Apply ini settings that require PHP streams, skipped during MINIT. */
++PHP_RINIT_FUNCTION(expect)
++{
++ if (!EXPECT_G(logfile_stream)) {
++ char *logfile = zend_ini_string("expect.logfile", sizeof("expect.logfile") - 1, 0);
++ if (logfile && strlen(logfile) > 0) {
++ php_stream *stream = php_stream_open_wrapper(logfile, "a", 0, NULL);
++ if (stream) {
++ stream->flags |= PHP_STREAM_FLAG_NO_SEEK;
++ if (php_stream_cast(stream, PHP_STREAM_AS_STDIO, (void **) &exp_logfile, REPORT_ERRORS) == SUCCESS) {
++ EXPECT_G(logfile_stream) = stream;
++ exp_logfile_all = 1;
++ }
++ }
++ }
++ }
++ return SUCCESS;
++}
++/* }}} */
++
++
+ /* {{{ PHP_MINFO_FUNCTION */
+ PHP_MINFO_FUNCTION(expect)
+ {
+@@ -316,7 +348,10 @@ PHP_FUNCTION(expect_expectl)
+ #endif
+ php_stream *stream;
+ int fd, argc;
+-
++#if PHP_MAJOR_VERSION >= 7
++ HashPosition pos;
++#endif
++
+ if (ZEND_NUM_ARGS() < 2 || ZEND_NUM_ARGS() > 3) { WRONG_PARAM_COUNT; }
+
+ if (zend_parse_parameters (ZEND_NUM_ARGS() TSRMLS_CC, "ra|z/", &z_stream, &z_cases, &z_match) == FAILURE) {
+@@ -330,7 +365,7 @@ PHP_FUNCTION(expect_expectl)
+ #endif
+
+ #if PHP_MAJOR_VERSION >= 7
+- if (!&(stream->wrapperdata)) {
++ if (Z_TYPE(stream->wrapperdata) != IS_LONG) {
+ #else
+ if (!stream->wrapperdata) {
+ #endif
+@@ -346,16 +381,17 @@ PHP_FUNCTION(expect_expectl)
+ ecases = (struct exp_case*) safe_emalloc (argc + 1, sizeof(struct exp_case), 0);
+ ecases_ptr = ecases;
+
+- zend_hash_internal_pointer_reset (Z_ARRVAL_P(z_cases));
+-
+ #if PHP_MAJOR_VERSION >= 7
+- while ((z_case = zend_hash_get_current_data (Z_ARRVAL_P(z_cases))) != NULL)
++ zend_hash_internal_pointer_reset_ex (Z_ARRVAL_P(z_cases), &pos);
++
++ while ((z_case = zend_hash_get_current_data_ex (Z_ARRVAL_P(z_cases), &pos)) != NULL)
+ {
+ zval *z_pattern, *z_exp_type;
+- zend_hash_get_current_key(Z_ARRVAL_P(z_cases), NULL, &key);
++ zend_hash_get_current_key_ex(Z_ARRVAL_P(z_cases), NULL, &key, &pos);
+
+ if (Z_TYPE_P(z_case) != IS_ARRAY) {
+ #else
++ zend_hash_internal_pointer_reset (Z_ARRVAL_P(z_cases));
+ while (zend_hash_get_current_data (Z_ARRVAL_P(z_cases), (void **)&z_case) == SUCCESS)
+ {
+ zval **z_pattern, **z_exp_type;
+@@ -437,7 +473,11 @@ PHP_FUNCTION(expect_expectl)
+ }
+
+ ecases_ptr++;
++#if PHP_MAJOR_VERSION >= 7
++ zend_hash_move_forward_ex(Z_ARRVAL_P(z_cases), &pos);
++#else
+ zend_hash_move_forward(Z_ARRVAL_P(z_cases));
++#endif
+ }
+ ecases_ptr->pattern = NULL;
+ ecases_ptr->re = NULL;
+diff --git a/php_expect.h b/php_expect.h
+index a8ce93d..856ff85 100644
+--- a/php_expect.h
++++ b/php_expect.h
+@@ -47,6 +47,7 @@ extern zend_module_entry expect_module_entry;
+
+ PHP_MINIT_FUNCTION(expect);
+ PHP_MSHUTDOWN_FUNCTION(expect);
++PHP_RINIT_FUNCTION(expect);
+ PHP_MINFO_FUNCTION(expect);
+
+ PHP_FUNCTION(expect_popen);
================================================================
---- gitweb:
http://git.pld-linux.org/gitweb.cgi/packages/php-pecl-expect.git/commitdiff/0c1a5cfd7f39cac816fd4ff9e8fbd16a6fda4288
More information about the pld-cvs-commit
mailing list