diff options
| -rw-r--r-- | failed.txt | 29 | ||||
| -rw-r--r-- | php-cve-2026-14179.patch | 274 | ||||
| -rw-r--r-- | php-cve-2026-6722.patch | 107 | ||||
| -rw-r--r-- | php-cve-2026-6735.patch | 144 | ||||
| -rw-r--r-- | php-cve-2026-7258.patch | 1719 | ||||
| -rw-r--r-- | php-cve-2026-7259.patch | 66 | ||||
| -rw-r--r-- | php-cve-2026-7261.patch | 111 | ||||
| -rw-r--r-- | php-cve-2026-7262.patch | 77 | ||||
| -rw-r--r-- | php-cve-2026-7568.patch | 101 | ||||
| -rw-r--r-- | php81.spec | 51 |
10 files changed, 2664 insertions, 15 deletions
@@ -1,25 +1,28 @@ -===== 8.1.34 (2025-12-18) +===== 8.1.34-2 (2026-05-07) $ grep -ar 'Tests failed' /var/lib/mock/*/build.log -/var/lib/mock/el8a81/build.log:Tests failed : 0 -/var/lib/mock/el8x81/build.log:Tests failed : 0 -/var/lib/mock/el9a81/build.log:Tests failed : 2 -/var/lib/mock/el9x81/build.log:Tests failed : 2 -/var/lib/mock/el10a81/build.log:Tests failed : 2 -/var/lib/mock/el10x81/build.log:Tests failed : 2 -/var/lib/mock/fc41a81/build.log:Tests failed : 1 -/var/lib/mock/fc41x81/build.log:Tests failed : 1 -/var/lib/mock/fc42a81/build.log:Tests failed : 1 -/var/lib/mock/fc42x81/build.log:Tests failed : 1 -/var/lib/mock/fc43a81/build.log:Tests failed : 2 -/var/lib/mock/fc43x81/build.log:Tests failed : 2 +/var/lib/mock/el8a81/build.log:Tests failed : 2 +/var/lib/mock/el8x81/build.log:Tests failed : 2 +/var/lib/mock/el9a81/build.log:Tests failed : 4 +/var/lib/mock/el9x81/build.log:Tests failed : 4 +/var/lib/mock/el10a81/build.log:Tests failed : 4 +/var/lib/mock/el10x81/build.log:Tests failed : 4 +/var/lib/mock/fc42a81/build.log:Tests failed : 3 +/var/lib/mock/fc42x81/build.log:Tests failed : 3 +/var/lib/mock/fc43a81/build.log:Tests failed : 4 +/var/lib/mock/fc43x81/build.log:Tests failed : 4 +/var/lib/mock/fc44a81/build.log:Tests failed : 4 +/var/lib/mock/fc44x81/build.log:Tests failed : 4 fc*, el10: 3 openssl_x509_parse() tests [ext/openssl/tests/openssl_x509_parse_basic.phpt] fc43, el9, el10: 3 Bug #74341 (openssl_x509_parse fails to parse ASN.1 UTCTime without seconds) [ext/openssl/tests/bug74341.phpt] +all + 3 sni_server [ext/openssl/tests/sni_server.phpt] + 3 sni_server with separate pk and cert [ext/openssl/tests/sni_server_key_cert.phpt] 1 proc_open give erratic test results :( diff --git a/php-cve-2026-14179.patch b/php-cve-2026-14179.patch new file mode 100644 index 0000000..71e15cd --- /dev/null +++ b/php-cve-2026-14179.patch @@ -0,0 +1,274 @@ +From 4b0dd469bbba7bf5f25f1a4f694aeb15c3515be4 Mon Sep 17 00:00:00 2001 +From: Saki Takamachi <saki@sakiot.com> +Date: Sun, 3 May 2026 19:56:30 +0200 +Subject: [PATCH 07/10] GHSA-w476-322c-wpvm: [pdo_firebird] Fix SQL injection + via NUL bytes in quoted strings + +Fixes GHSA-w476-322c-wpvm +Fixes CVE-2025-14179 + +(cherry picked from commit 3f40b65323dd1b85e9bab6878237d3867e449d5c) +--- + ext/pdo_firebird/firebird_driver.c | 69 ++++++++++++------- + .../tests/ghsa-w476-322c-wpvm.phpt | 44 ++++++++++++ + 2 files changed, 88 insertions(+), 25 deletions(-) + create mode 100644 ext/pdo_firebird/tests/ghsa-w476-322c-wpvm.phpt + +diff --git a/ext/pdo_firebird/firebird_driver.c b/ext/pdo_firebird/firebird_driver.c +index a446622c90e..25882919f86 100644 +--- a/ext/pdo_firebird/firebird_driver.c ++++ b/ext/pdo_firebird/firebird_driver.c +@@ -291,7 +291,7 @@ static FbTokenType getToken(const char** begin, const char* end) + return ret; + } + +-int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) ++int preprocess(const zend_string* sql, char* sql_out, size_t* sql_out_len, HashTable* named_params) + { + bool passAsIs = 1, execBlock = 0; + zend_long pindex = -1; +@@ -322,7 +322,7 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) + if (l > 252) { + return 0; + } +- strncpy(ident, i, l); ++ memcpy(ident, i, l); + ident[l] = '\0'; + if (!strcasecmp(ident, "EXECUTE")) + { +@@ -347,7 +347,7 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) + if (l > 252) { + return 0; + } +- strncpy(ident2, i2, l); ++ memcpy(ident2, i2, l); + ident2[l] = '\0'; + execBlock = !strcasecmp(ident2, "BLOCK"); + passAsIs = 0; +@@ -363,11 +363,15 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) + + if (passAsIs) + { +- strcpy(sql_out, ZSTR_VAL(sql)); ++ memcpy(sql_out, ZSTR_VAL(sql), ZSTR_LEN(sql)); ++ sql_out[ZSTR_LEN(sql)] = '\0'; ++ *sql_out_len = ZSTR_LEN(sql); + return 1; + } + +- strncat(sql_out, start, p - start); ++ char *sql_out_p = sql_out; ++ memcpy(sql_out_p, start, p - start); ++ sql_out_p += p - start; + + while (p < end) + { +@@ -375,10 +379,12 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) + tok = getToken(&p, end); + switch (tok) + { +- case ttParamMark: +- tok = getToken(&p, end); ++ case ttParamMark: { ++ const char* p_peek = p; ++ tok = getToken(&p_peek, end); + if (tok == ttIdent /*|| tok == ttString*/) + { ++ p = p_peek; + ++pindex; + l = p - start; + /* check the length of the identifier */ +@@ -387,7 +393,7 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) + if (l > 253) { + return 0; + } +- strncpy(pname, start, l); ++ memcpy(pname, start, l); + pname[l] = '\0'; + + if (named_params) { +@@ -396,7 +402,7 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) + zend_hash_str_update(named_params, pname, l, &tmp); + } + +- strcat(sql_out, "?"); ++ *sql_out_p++ = '?'; + } + else + { +@@ -406,10 +412,11 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) + return 0; + } + ++pindex; +- strncat(sql_out, start, p - start); ++ memcpy(sql_out_p, start, p - start); ++ sql_out_p += p - start; + } + break; +- ++ } + case ttIdent: + if (execBlock) + { +@@ -421,11 +428,14 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) + if (l > 252) { + return 0; + } +- strncpy(ident, start, l); ++ memcpy(ident, start, l); + ident[l] = '\0'; + if (!strcasecmp(ident, "AS")) + { +- strncat(sql_out, start, end - start); ++ memcpy(sql_out_p, start, end - start); ++ sql_out_p += end - start; ++ *sql_out_p = '\0'; ++ *sql_out_len = sql_out_p - sql_out; + return 1; + } + } +@@ -436,7 +446,8 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) + case ttComment: + case ttString: + case ttOther: +- strncat(sql_out, start, p - start); ++ memcpy(sql_out_p, start, p - start); ++ sql_out_p += p - start; + break; + + case ttBrokenComment: +@@ -454,6 +465,8 @@ int preprocess(const zend_string* sql, char* sql_out, HashTable* named_params) + break; + } + } ++ *sql_out_p = '\0'; ++ *sql_out_len = sql_out_p - sql_out; + return 1; + } + +@@ -663,7 +676,7 @@ free_statement: + static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *unquoted, enum pdo_param_type paramtype) + { + size_t qcount = 0; +- char const *co, *l, *r; ++ char const *co, *l; + char *c; + size_t quotedlen; + zend_string *quoted_str; +@@ -672,9 +685,15 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un + return zend_string_init("''", 2, 0); + } + ++ const char * const end = ZSTR_VAL(unquoted) + ZSTR_LEN(unquoted); ++ + /* Firebird only requires single quotes to be doubled if string lengths are used */ + /* count the number of ' characters */ +- for (co = ZSTR_VAL(unquoted); (co = strchr(co,'\'')); qcount++, co++); ++ for (co = ZSTR_VAL(unquoted); co < end; co++) { ++ if (*co == '\'') { ++ qcount++; ++ } ++ } + + if (UNEXPECTED(ZSTR_LEN(unquoted) + 2 > ZSTR_MAX_LEN - qcount)) { + return NULL; +@@ -686,15 +705,14 @@ static zend_string* firebird_handle_quoter(pdo_dbh_t *dbh, const zend_string *un + *c++ = '\''; + + /* foreach (chunk that ends in a quote) */ +- for (l = ZSTR_VAL(unquoted); (r = strchr(l,'\'')); l = r+1) { +- strncpy(c, l, r-l+1); +- c += (r-l+1); +- /* add the second quote */ +- *c++ = '\''; ++ for (l = ZSTR_VAL(unquoted); l < end; l++) { ++ *c++ = *l; ++ if (*l == '\'') { ++ /* add the second quote */ ++ *c++ = '\''; ++ } + } + +- /* copy the remainder */ +- strncpy(c, l, quotedlen-(c-ZSTR_VAL(quoted_str))-1); + ZSTR_VAL(quoted_str)[quotedlen-1] = '\''; + ZSTR_VAL(quoted_str)[quotedlen] = '\0'; + +@@ -787,6 +805,7 @@ static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sql, + { + pdo_firebird_db_handle *H = (pdo_firebird_db_handle *)dbh->driver_data; + char *new_sql; ++ size_t new_sql_len; + + /* Firebird allows SQL statements up to 64k, so bail if it doesn't fit */ + if (ZSTR_LEN(sql) > 65536) { +@@ -814,14 +833,14 @@ static int firebird_alloc_prepare_stmt(pdo_dbh_t *dbh, const zend_string *sql, + we need to replace :foo by ?, and store the name we just replaced */ + new_sql = emalloc(ZSTR_LEN(sql)+1); + new_sql[0] = '\0'; +- if (!preprocess(sql, new_sql, named_params)) { ++ if (!preprocess(sql, new_sql, &new_sql_len, named_params)) { + strcpy(dbh->error_code, "07000"); + efree(new_sql); + return 0; + } + + /* prepare the statement */ +- if (isc_dsql_prepare(H->isc_status, &H->tr, s, 0, new_sql, H->sql_dialect, out_sqlda)) { ++ if (isc_dsql_prepare(H->isc_status, &H->tr, s, new_sql_len, new_sql, H->sql_dialect, out_sqlda)) { + RECORD_ERROR(dbh); + efree(new_sql); + return 0; +diff --git a/ext/pdo_firebird/tests/ghsa-w476-322c-wpvm.phpt b/ext/pdo_firebird/tests/ghsa-w476-322c-wpvm.phpt +new file mode 100644 +index 00000000000..41c1125e9b9 +--- /dev/null ++++ b/ext/pdo_firebird/tests/ghsa-w476-322c-wpvm.phpt +@@ -0,0 +1,44 @@ ++--TEST-- ++GHSA-w476-322c-wpvm: SQL injection in pdo_firebird via NUL bytes in quoted strings ++--EXTENSIONS-- ++pdo_firebird ++--SKIPIF-- ++<?php require('skipif.inc'); ?> ++--XLEAK-- ++A bug in firebird causes a memory leak when calling `isc_attach_database()`. ++See https://github.com/FirebirdSQL/firebird/issues/7849 ++--FILE-- ++<?php ++ ++require("testdb.inc"); ++ ++$dbh->exec('CREATE TABLE ghsa_w476_322c_wpvm (name VARCHAR(255))'); ++ ++$param = $dbh->quote("\0"); ++$param2 = $dbh->quote('or 1=1--'); ++var_export($param); ++echo("\n"); ++ ++echo "prepare: "; ++$stmt = $dbh->prepare("SELECT * FROM ghsa_w476_322c_wpvm WHERE name = {$param} AND name = {$param2}"); ++$stmt->execute(); ++echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC)) . "\n"; ++ ++echo "query: "; ++$stmt = $dbh->query("SELECT * FROM ghsa_w476_322c_wpvm WHERE name = {$param} AND name = {$param2}"); ++echo json_encode($stmt->fetchAll(PDO::FETCH_ASSOC)) . "\n"; ++ ++echo "exec: "; ++$affectedRows = $dbh->exec("UPDATE ghsa_w476_322c_wpvm SET name = 'updated' WHERE name = {$param} AND name = {$param2}"); ++echo $affectedRows . "\n"; ++?> ++--CLEAN-- ++<?php ++require 'testdb.inc'; ++$dbh->exec("DROP TABLE ghsa_w476_322c_wpvm"); ++?> ++--EXPECT-- ++'\'' . "\0" . '\'' ++prepare: [] ++query: [] ++exec: 0 +-- +2.54.0 + diff --git a/php-cve-2026-6722.patch b/php-cve-2026-6722.patch new file mode 100644 index 0000000..3365479 --- /dev/null +++ b/php-cve-2026-6722.patch @@ -0,0 +1,107 @@ +From 15064460d6682766f91c1a841d27cdfbc38907e8 Mon Sep 17 00:00:00 2001 +From: Ilija Tovilo <ilija.tovilo@me.com> +Date: Sun, 3 May 2026 19:56:53 +0200 +Subject: [PATCH 01/10] GHSA-85c2-q967-79q5: [soap] Fix stale + SOAP_GLOBAL(ref_map) pointer with Apache Map + +Fixes GHSA-85c2-q967-79q5 +Fixes CVE-2026-6722 + +(cherry picked from commit aee3b3ac9b816b0def1c462695b483b49a83148e) +--- + 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 4d389a8c585..bf394f7ea92 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); + } + } +@@ -3437,7 +3438,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 00000000000..8bcac26ad18 +--- /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-- ++<?php ++ ++class Handler { ++ public function test(...$args) { ++ $GLOBALS['result'] = $args; ++ } ++} ++ ++$envelope = <<<'XML' ++<?xml version="1.0" encoding="UTF-8"?> ++<soapenv:Envelope ++ xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" ++ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ++ xmlns:xsd="http://www.w3.org/2001/XMLSchema"> ++ ++ <soapenv:Body> ++ <test> ++ <map xsi:type="apache:Map" xmlns:apache="http://xml.apache.org/xml-soap"> ++ <item> ++ <key>foo</key> ++ <value id="stale"><object>bar</object></value> ++ </item> ++ <item> ++ <key>foo</key> ++ <value>baz</value> ++ </item> ++ </map> ++ <stale href="#stale"/> ++ </test> ++ </soapenv:Body> ++</soapenv:Envelope> ++XML; ++ ++$s = new SoapServer(null, ['uri' => 'urn:a']); ++$s->setClass(Handler::class); ++$s->handle($envelope); ++var_dump($result); ++ ++?> ++--EXPECTF-- ++<?xml version="1.0" encoding="UTF-8"?> ++<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/" xmlns:ns1="urn:a" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:SOAP-ENC="http://schemas.xmlsoap.org/soap/encoding/" SOAP-ENV:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"><SOAP-ENV:Body><ns1:testResponse><return xsi:nil="true"/></ns1:testResponse></SOAP-ENV:Body></SOAP-ENV:Envelope> ++array(2) { ++ [0]=> ++ array(1) { ++ ["foo"]=> ++ string(3) "baz" ++ } ++ [1]=> ++ object(stdClass)#%d (1) { ++ ["object"]=> ++ string(3) "bar" ++ } ++} +-- +2.54.0 + diff --git a/php-cve-2026-6735.patch b/php-cve-2026-6735.patch new file mode 100644 index 0000000..9f287dd --- /dev/null +++ b/php-cve-2026-6735.patch @@ -0,0 +1,144 @@ +From cc2960e782eb5cc262d7bd572a7d18979a811954 Mon Sep 17 00:00:00 2001 +From: Jakub Zelenka <bukka@php.net> +Date: Sun, 3 May 2026 20:01:41 +0200 +Subject: [PATCH 04/10] GHSA-7qg2-v9fj-4mwv: [fpm] XSS within status endpoint + +Fixes GHSA-7qg2-v9fj-4mwv +Fixes CVE-2026-6735 + +(cherry picked from commit 99a5ad7441de9914246c7863adb6997396008b9d) +--- + 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 f698753cf4c..81292aa3bf8 100644 +--- a/sapi/fpm/fpm/fpm_status.c ++++ b/sapi/fpm/fpm/fpm_status.c +@@ -525,8 +525,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; + +@@ -551,13 +551,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, +@@ -596,7 +619,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, +@@ -607,6 +630,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 00000000000..475bc130a42 +--- /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-- ++<?php include "skipif.inc"; ?> ++--FILE-- ++<?php ++ ++require_once "tester.inc"; ++ ++$cfg = <<<EOT ++[global] ++error_log = {{FILE:LOG}} ++[unconfined] ++listen = {{ADDR}} ++pm = static ++pm.max_children = 2 ++pm.status_path = /status ++catch_workers_output = yes ++EOT; ++ ++$code = <<<EOT ++<?php ++usleep(200000); ++EOT; ++ ++$tester = new FPM\Tester($cfg, $code); ++$tester->start(); ++$tester->expectLogStartNotices(); ++$responses = $tester ++ ->multiRequest([ ++ ['uri' => '/<script>alert(1)</script>', 'query' => '<script>alert(2)</script>'], ++ ['uri' => '/status', 'query' => 'full&html', 'delay' => 100000], ++ ]); ++var_dump(strpos($responses[1]->getBody(), '<script>')); ++$tester->terminate(); ++$tester->expectLogTerminatingNotices(); ++$tester->close(); ++ ++?> ++Done ++--EXPECT-- ++bool(false) ++Done ++--CLEAN-- ++<?php ++require_once "tester.inc"; ++FPM\Tester::clean(); ++?> +-- +2.54.0 + diff --git a/php-cve-2026-7258.patch b/php-cve-2026-7258.patch new file mode 100644 index 0000000..b9c8180 --- /dev/null +++ b/php-cve-2026-7258.patch @@ -0,0 +1,1719 @@ +From 07e5a9263314fd9a2a4479661353704e00dd8d0c Mon Sep 17 00:00:00 2001 +From: Ilija Tovilo <ilija.tovilo@me.com> +Date: Sun, 3 May 2026 20:03:18 +0200 +Subject: [PATCH 08/10] GHSA-m8rr-4c36-8gq4: Consistently pass unsigned char to + ctype.h functions + +Fixes GHSA-m8rr-4c36-8gq4 +Fixes CVE-2026-7258 + +(cherry picked from commit a38418777f65780d9d622197677e90567690fc07) +--- + Zend/zend_compile.c | 2 +- + Zend/zend_operators.c | 8 ++++---- + Zend/zend_virtual_cwd.c | 10 +++++----- + Zend/zend_virtual_cwd.h | 2 +- + ext/com_dotnet/com_extension.c | 4 ++-- + ext/date/lib/parse_date.c | 10 +++++----- + ext/date/lib/parse_date.re | 10 +++++----- + ext/date/lib/parse_iso_intervals.c | 4 ++-- + ext/date/lib/parse_iso_intervals.re | 4 ++-- + ext/date/lib/timelib.c | 2 +- + ext/filter/logical_filters.c | 10 +++++----- + ext/ftp/ftp.c | 10 +++++----- + ext/gd/libgd/gd_xbm.c | 2 +- + ext/imap/php_imap.c | 2 +- + ext/intl/locale/locale_methods.c | 2 +- + ext/mbstring/mbstring.c | 4 ++-- + ext/mbstring/php_mbregex.c | 2 +- + ext/pcre/php_pcre.c | 4 ++-- + ext/pdo/pdo.c | 2 +- + ext/pdo/pdo_sql_parser.re | 2 +- + ext/pdo/pdo_stmt.c | 2 +- + ext/standard/dl.c | 2 +- + ext/standard/exec.c | 2 +- + ext/standard/file.c | 2 +- + ext/standard/filters.c | 2 +- + ext/standard/formatted_print.c | 8 ++++---- + ext/standard/ftp_fopen_wrapper.c | 12 ++++++------ + ext/standard/html.c | 4 ++-- + ext/standard/math.c | 6 +++--- + ext/standard/metaphone.c | 18 ++++++++--------- + ext/standard/quot_print.c | 8 ++++---- + ext/standard/scanf.c | 10 +++++----- + ext/standard/soundex.c | 2 +- + ext/standard/string.c | 14 +++++++------- + ext/standard/strnatcmp.c | 30 ++++++++++++++--------------- + ext/standard/type.c | 2 +- + ext/standard/url.c | 20 +++++++++---------- + ext/standard/url_scanner_ex.re | 6 +++--- + ext/standard/versioning.c | 16 +++++++-------- + main/SAPI.c | 6 +++--- + main/fopen_wrappers.c | 6 +++--- + main/php_ini.c | 2 +- + main/php_variables.c | 4 ++-- + main/rfc1867.c | 12 ++++++------ + main/snprintf.c | 14 +++++++------- + main/spprintf.c | 14 +++++++------- + main/streams/streams.c | 4 ++-- + main/streams/transports.c | 2 +- + sapi/cli/php_cli_server.c | 2 +- + sapi/fpm/fpm/fpm_conf.c | 4 ++-- + sapi/litespeed/lsapi_main.c | 4 ++-- + sapi/litespeed/lsapilib.c | 6 +++--- + sapi/phpdbg/phpdbg_cmd.c | 4 ++-- + sapi/phpdbg/phpdbg_prompt.c | 2 +- + sapi/phpdbg/phpdbg_utils.c | 10 +++++----- + win32/sendmail.c | 6 +++--- + 56 files changed, 182 insertions(+), 182 deletions(-) + +diff --git a/Zend/zend_compile.c b/Zend/zend_compile.c +index c0cd3c97341..856e81ace7f 100644 +--- a/Zend/zend_compile.c ++++ b/Zend/zend_compile.c +@@ -2006,7 +2006,7 @@ ZEND_API size_t zend_dirname(char *path, size_t len) + /* Note that on Win32 CWD is per drive (heritage from CP/M). + * This means dirname("c:foo") maps to "c:." or "c:" - which means CWD on C: drive. + */ +- if ((2 <= len) && isalpha((int)((unsigned char *)path)[0]) && (':' == path[1])) { ++ if ((2 <= len) && isalpha((unsigned char)path[0]) && (':' == path[1])) { + /* Skip over the drive spec (if any) so as not to change */ + path += 2; + len_adjust += 2; +diff --git a/Zend/zend_operators.c b/Zend/zend_operators.c +index ef5c50c4336..1c4abc9ede5 100644 +--- a/Zend/zend_operators.c ++++ b/Zend/zend_operators.c +@@ -2883,8 +2883,8 @@ ZEND_API int ZEND_FASTCALL zend_binary_strcasecmp_l(const char *s1, size_t len1, + + len = MIN(len1, len2); + while (len--) { +- c1 = zend_tolower((int)*(unsigned char *)s1++); +- c2 = zend_tolower((int)*(unsigned char *)s2++); ++ c1 = zend_tolower((unsigned char)*(s1++)); ++ c2 = zend_tolower((unsigned char)*(s2++)); + if (c1 != c2) { + return c1 - c2; + } +@@ -2904,8 +2904,8 @@ ZEND_API int ZEND_FASTCALL zend_binary_strncasecmp_l(const char *s1, size_t len1 + } + len = MIN(length, MIN(len1, len2)); + while (len--) { +- c1 = zend_tolower((int)*(unsigned char *)s1++); +- c2 = zend_tolower((int)*(unsigned char *)s2++); ++ c1 = zend_tolower((unsigned char)*(s1++)); ++ c2 = zend_tolower((unsigned char)*(s2++)); + if (c1 != c2) { + return c1 - c2; + } +diff --git a/Zend/zend_virtual_cwd.c b/Zend/zend_virtual_cwd.c +index d8a9046d04d..ca5f79d9933 100644 +--- a/Zend/zend_virtual_cwd.c ++++ b/Zend/zend_virtual_cwd.c +@@ -195,7 +195,7 @@ void virtual_cwd_main_cwd_init(uint8_t reinit) /* {{{ */ + main_cwd_state.cwd_length = strlen(cwd); + #ifdef ZEND_WIN32 + if (main_cwd_state.cwd_length >= 2 && cwd[1] == ':') { +- cwd[0] = toupper(cwd[0]); ++ cwd[0] = toupper((unsigned char)cwd[0]); + } + #endif + main_cwd_state.cwd = strdup(cwd); +@@ -273,7 +273,7 @@ CWD_API char *virtual_getcwd_ex(size_t *length) /* {{{ */ + *length = state->cwd_length+1; + retval = (char *) emalloc(*length+1); + memcpy(retval, state->cwd, *length); +- retval[0] = toupper(retval[0]); ++ retval[0] = toupper((unsigned char)retval[0]); + retval[*length-1] = DEFAULT_SLASH; + retval[*length] = '\0'; + return retval; +@@ -1114,7 +1114,7 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func + if (resolved_path[start] == 0) { + goto verify; + } +- resolved_path[start] = toupper(resolved_path[start]); ++ resolved_path[start] = toupper((unsigned char)resolved_path[start]); + start++; + } + resolved_path[start++] = DEFAULT_SLASH; +@@ -1122,13 +1122,13 @@ CWD_API int virtual_file_ex(cwd_state *state, const char *path, verify_path_func + if (resolved_path[start] == 0) { + goto verify; + } +- resolved_path[start] = toupper(resolved_path[start]); ++ resolved_path[start] = toupper((unsigned char)resolved_path[start]); + start++; + } + resolved_path[start++] = DEFAULT_SLASH; + } else if (IS_ABSOLUTE_PATH(resolved_path, path_length)) { + /* skip DRIVE name */ +- resolved_path[0] = toupper(resolved_path[0]); ++ resolved_path[0] = toupper((unsigned char)resolved_path[0]); + resolved_path[2] = DEFAULT_SLASH; + start = 3; + } +diff --git a/Zend/zend_virtual_cwd.h b/Zend/zend_virtual_cwd.h +index 728e3ba69d8..d15c8e28d5d 100644 +--- a/Zend/zend_virtual_cwd.h ++++ b/Zend/zend_virtual_cwd.h +@@ -82,7 +82,7 @@ typedef unsigned short mode_t; + #define IS_UNC_PATH(path, len) \ + (len >= 2 && IS_SLASH(path[0]) && IS_SLASH(path[1])) + #define IS_ABSOLUTE_PATH(path, len) \ +- (len >= 2 && (/* is local */isalpha(path[0]) && path[1] == ':' || /* is UNC */IS_SLASH(path[0]) && IS_SLASH(path[1]))) ++ (len >= 2 && (/* is local */isalpha((unsigned char)(path)[0]) && path[1] == ':' || /* is UNC */IS_SLASH(path[0]) && IS_SLASH(path[1]))) + + #else + #ifdef HAVE_DIRENT_H +diff --git a/ext/com_dotnet/com_extension.c b/ext/com_dotnet/com_extension.c +index 55b3c282aee..380ca0791e8 100644 +--- a/ext/com_dotnet/com_extension.c ++++ b/ext/com_dotnet/com_extension.c +@@ -104,11 +104,11 @@ static PHP_INI_MH(OnTypeLibFileUpdate) + } + + /* Remove leading/training white spaces on search_string */ +- while (isspace(*typelib_name)) {/* Ends on '\0' in worst case */ ++ while (isspace((unsigned char)*typelib_name)) {/* Ends on '\0' in worst case */ + typelib_name ++; + } + ptr = typelib_name + strlen(typelib_name) - 1; +- while ((ptr != typelib_name) && isspace(*ptr)) { ++ while ((ptr != typelib_name) && isspace((unsigned char)*ptr)) { + *ptr = '\0'; + ptr--; + } +diff --git a/ext/date/lib/parse_date.c b/ext/date/lib/parse_date.c +index 78feb742081..9c5c9d602a1 100644 +--- a/ext/date/lib/parse_date.c ++++ b/ext/date/lib/parse_date.c +@@ -509,7 +509,7 @@ static timelib_sll timelib_get_nr(const char **ptr, int max_length) + + static void timelib_skip_day_suffix(const char **ptr) + { +- if (isspace(**ptr)) { ++ if (isspace((unsigned char)**ptr)) { + return; + } + if (!timelib_strncasecmp(*ptr, "nd", 2) || !timelib_strncasecmp(*ptr, "rd", 2) ||!timelib_strncasecmp(*ptr, "st", 2) || !timelib_strncasecmp(*ptr, "th", 2)) { +@@ -792,7 +792,7 @@ static timelib_long timelib_parse_tz_cor(const char **ptr, int *tz_not_found) + + *tz_not_found = 1; + +- while (isdigit(**ptr) || **ptr == ':') { ++ while (isdigit((unsigned char)**ptr) || **ptr == ':') { + ++*ptr; + } + end = *ptr; +@@ -857,7 +857,7 @@ static timelib_long timelib_parse_tz_minutes(const char **ptr, timelib_time *t) + } + + ++*ptr; +- while (isdigit(**ptr)) { ++ while (isdigit((unsigned char)**ptr)) { + ++*ptr; + } + +@@ -25936,10 +25936,10 @@ timelib_time *timelib_strtotime(const char *s, size_t len, timelib_error_contain + in.errors->error_messages = NULL; + + if (len > 0) { +- while (isspace(*s) && s < e) { ++ while (isspace((unsigned char)*s) && s < e) { + s++; + } +- while (isspace(*e) && e > s) { ++ while (isspace((unsigned char)*e) && e > s) { + e--; + } + } +diff --git a/ext/date/lib/parse_date.re b/ext/date/lib/parse_date.re +index f0db34d302b..a2d12361df9 100644 +--- a/ext/date/lib/parse_date.re ++++ b/ext/date/lib/parse_date.re +@@ -507,7 +507,7 @@ static timelib_sll timelib_get_nr(const char **ptr, int max_length) + + static void timelib_skip_day_suffix(const char **ptr) + { +- if (isspace(**ptr)) { ++ if (isspace((unsigned char)**ptr)) { + return; + } + if (!timelib_strncasecmp(*ptr, "nd", 2) || !timelib_strncasecmp(*ptr, "rd", 2) ||!timelib_strncasecmp(*ptr, "st", 2) || !timelib_strncasecmp(*ptr, "th", 2)) { +@@ -790,7 +790,7 @@ static timelib_long timelib_parse_tz_cor(const char **ptr, int *tz_not_found) + + *tz_not_found = 1; + +- while (isdigit(**ptr) || **ptr == ':') { ++ while (isdigit((unsigned char)**ptr) || **ptr == ':') { + ++*ptr; + } + end = *ptr; +@@ -855,7 +855,7 @@ static timelib_long timelib_parse_tz_minutes(const char **ptr, timelib_time *t) + } + + ++*ptr; +- while (isdigit(**ptr)) { ++ while (isdigit((unsigned char)**ptr)) { + ++*ptr; + } + +@@ -1938,10 +1938,10 @@ timelib_time *timelib_strtotime(const char *s, size_t len, timelib_error_contain + in.errors->error_messages = NULL; + + if (len > 0) { +- while (isspace(*s) && s < e) { ++ while (isspace((unsigned char)*s) && s < e) { + s++; + } +- while (isspace(*e) && e > s) { ++ while (isspace((unsigned char)*e) && e > s) { + e--; + } + } +diff --git a/ext/date/lib/parse_iso_intervals.c b/ext/date/lib/parse_iso_intervals.c +index a467da3471f..113343f5615 100644 +--- a/ext/date/lib/parse_iso_intervals.c ++++ b/ext/date/lib/parse_iso_intervals.c +@@ -948,10 +948,10 @@ void timelib_strtointerval(const char *s, size_t len, + in.errors->error_messages = NULL; + + if (len > 0) { +- while (isspace(*s) && s < e) { ++ while (isspace((unsigned char)*s) && s < e) { + s++; + } +- while (isspace(*e) && e > s) { ++ while (isspace((unsigned char)*e) && e > s) { + e--; + } + } +diff --git a/ext/date/lib/parse_iso_intervals.re b/ext/date/lib/parse_iso_intervals.re +index 2a394156f98..00942007751 100644 +--- a/ext/date/lib/parse_iso_intervals.re ++++ b/ext/date/lib/parse_iso_intervals.re +@@ -343,10 +343,10 @@ void timelib_strtointerval(const char *s, size_t len, + in.errors->error_messages = NULL; + + if (len > 0) { +- while (isspace(*s) && s < e) { ++ while (isspace((unsigned char)*s) && s < e) { + s++; + } +- while (isspace(*e) && e > s) { ++ while (isspace((unsigned char)*e) && e > s) { + e--; + } + } +diff --git a/ext/date/lib/timelib.c b/ext/date/lib/timelib.c +index d42c69bbd6f..9949225df7e 100644 +--- a/ext/date/lib/timelib.c ++++ b/ext/date/lib/timelib.c +@@ -126,7 +126,7 @@ void timelib_time_tz_abbr_update(timelib_time* tm, const char* tz_abbr) + TIMELIB_TIME_FREE(tm->tz_abbr); + tm->tz_abbr = timelib_strdup(tz_abbr); + for (i = 0; i < tz_abbr_len; i++) { +- tm->tz_abbr[i] = toupper(tz_abbr[i]); ++ tm->tz_abbr[i] = toupper((unsigned char)tz_abbr[i]); + } + } + +diff --git a/ext/filter/logical_filters.c b/ext/filter/logical_filters.c +index 3db0ef40905..472e2768651 100644 +--- a/ext/filter/logical_filters.c ++++ b/ext/filter/logical_filters.c +@@ -528,21 +528,21 @@ static int _php_filter_validate_domain(char * domain, size_t len, zend_long flag + } + + /* First char must be alphanumeric */ +- if(*s == '.' || (hostname && !isalnum((int)*(unsigned char *)s))) { ++ if(*s == '.' || (hostname && !isalnum((unsigned char)*s))) { + return 0; + } + + while (s < e) { + if (*s == '.') { + /* The first and the last character of a label must be alphanumeric */ +- if (*(s + 1) == '.' || (hostname && (!isalnum((int)*(unsigned char *)(s - 1)) || !isalnum((int)*(unsigned char *)(s + 1))))) { ++ if (*(s + 1) == '.' || (hostname && (!isalnum((unsigned char)s[-1]) || !isalnum((unsigned char)s[1])))) { + return 0; + } + + /* Reset label length counter */ + i = 1; + } else { +- if (i > 63 || (hostname && *s != '-' && !isalnum((int)*(unsigned char *)s))) { ++ if (i > 63 || (hostname && *s != '-' && !isalnum((unsigned char)*s))) { + return 0; + } + +@@ -569,9 +569,9 @@ static int is_userinfo_valid(zend_string *str) + const char *valid = "-._~!$&'()*+,;=:"; + const char *p = ZSTR_VAL(str); + while (p - ZSTR_VAL(str) < ZSTR_LEN(str)) { +- if (isalpha(*p) || isdigit(*p) || strchr(valid, *p)) { ++ if (isalpha((unsigned char)*p) || isdigit((unsigned char)*p) || strchr(valid, *p)) { + p++; +- } else if (*p == '%' && p - ZSTR_VAL(str) <= ZSTR_LEN(str) - 3 && isdigit(*(p+1)) && isxdigit(*(p+2))) { ++ } else if (*p == '%' && p - ZSTR_VAL(str) <= ZSTR_LEN(str) - 3 && isdigit((unsigned char)p[1]) && isxdigit((unsigned char)p[2])) { + p += 3; + } else { + return 0; +diff --git a/ext/ftp/ftp.c b/ext/ftp/ftp.c +index 9253edc5589..9da59eabfb2 100644 +--- a/ext/ftp/ftp.c ++++ b/ext/ftp/ftp.c +@@ -499,7 +499,7 @@ ftp_raw(ftpbuf_t *ftp, const char *cmd, const size_t cmd_len, zval *return_value + array_init(return_value); + while (ftp_readline(ftp)) { + add_next_index_string(return_value, ftp->inbuf); +- if (isdigit(ftp->inbuf[0]) && isdigit(ftp->inbuf[1]) && isdigit(ftp->inbuf[2]) && ftp->inbuf[3] == ' ') { ++ if (isdigit((unsigned char)ftp->inbuf[0]) && isdigit((unsigned char)ftp->inbuf[1]) && isdigit((unsigned char)ftp->inbuf[2]) && ftp->inbuf[3] == ' ') { + return; + } + } +@@ -841,7 +841,7 @@ ftp_pasv(ftpbuf_t *ftp, int pasv) + return 0; + } + /* parse out the IP and port */ +- for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++); ++ for (ptr = ftp->inbuf; *ptr && !isdigit((unsigned char)*ptr); ptr++); + n = sscanf(ptr, "%lu,%lu,%lu,%lu,%lu,%lu", &b[0], &b[1], &b[2], &b[3], &b[4], &b[5]); + if (n != 6) { + return 0; +@@ -1144,7 +1144,7 @@ ftp_mdtm(ftpbuf_t *ftp, const char *path, const size_t path_len) + return -1; + } + /* parse out the timestamp */ +- for (ptr = ftp->inbuf; *ptr && !isdigit(*ptr); ptr++); ++ for (ptr = ftp->inbuf; *ptr && !isdigit((unsigned char)*ptr); ptr++); + n = sscanf(ptr, "%4u%2u%2u%2u%2u%2u", &tm.tm_year, &tm.tm_mon, &tm.tm_mday, &tm.tm_hour, &tm.tm_min, &tm.tm_sec); + if (n != 6) { + return -1; +@@ -1342,13 +1342,13 @@ ftp_getresp(ftpbuf_t *ftp) + } + + /* Break out when the end-tag is found */ +- if (isdigit(ftp->inbuf[0]) && isdigit(ftp->inbuf[1]) && isdigit(ftp->inbuf[2]) && ftp->inbuf[3] == ' ') { ++ if (isdigit((unsigned char)ftp->inbuf[0]) && isdigit((unsigned char)ftp->inbuf[1]) && isdigit((unsigned char)ftp->inbuf[2]) && ftp->inbuf[3] == ' ') { + break; + } + } + + /* translate the tag */ +- if (!isdigit(ftp->inbuf[0]) || !isdigit(ftp->inbuf[1]) || !isdigit(ftp->inbuf[2])) { ++ if (!isdigit((unsigned char)ftp->inbuf[0]) || !isdigit((unsigned char)ftp->inbuf[1]) || !isdigit((unsigned char)ftp->inbuf[2])) { + return 0; + } + +diff --git a/ext/gd/libgd/gd_xbm.c b/ext/gd/libgd/gd_xbm.c +index 3c655a2998c..8efb34fbb0d 100644 +--- a/ext/gd/libgd/gd_xbm.c ++++ b/ext/gd/libgd/gd_xbm.c +@@ -191,7 +191,7 @@ void gdImageXbmCtx(gdImagePtr image, char* file_name, int fg, gdIOCtx * out) + } else { + for (i=0; i<l; i++) { + /* only in C-locale isalnum() would work */ +- if (!isupper(name[i]) && !islower(name[i]) && !isdigit(name[i])) { ++ if (!isupper((unsigned char)name[i]) && !islower((unsigned char)name[i]) && !isdigit((unsigned char)name[i])) { + name[i] = '_'; + } + } +diff --git a/ext/imap/php_imap.c b/ext/imap/php_imap.c +index 5c45e213aa5..74fa59d1c5d 100644 +--- a/ext/imap/php_imap.c ++++ b/ext/imap/php_imap.c +@@ -2316,7 +2316,7 @@ PHP_FUNCTION(imap_utf8) + #define SPECIAL(c) ((c) <= 0x1f || (c) >= 0x7f) + + /* validate a modified-base64 character */ +-#define B64CHAR(c) (isalnum(c) || (c) == '+' || (c) == ',') ++#define B64CHAR(c) (isalnum((unsigned char)(c)) || (c) == '+' || (c) == ',') + + /* map the low 64 bits of `n' to the modified-base64 characters */ + #define B64(n) ("ABCDEFGHIJKLMNOPQRSTUVWXYZ" \ +diff --git a/ext/intl/locale/locale_methods.c b/ext/intl/locale/locale_methods.c +index 159b3ea0a19..adca3ed3e32 100644 +--- a/ext/intl/locale/locale_methods.c ++++ b/ext/intl/locale/locale_methods.c +@@ -1135,7 +1135,7 @@ static int strToMatch(const char* str ,char *retstr) + if( *str == '-' ){ + *retstr = '_'; + } else { +- *retstr = tolower(*str); ++ *retstr = tolower((unsigned char)*str); + } + str++; + retstr++; +diff --git a/ext/mbstring/mbstring.c b/ext/mbstring/mbstring.c +index 238d74e4838..265356a21ce 100644 +--- a/ext/mbstring/mbstring.c ++++ b/ext/mbstring/mbstring.c +@@ -626,7 +626,7 @@ static char *php_mb_rfc1867_getword(const zend_encoding *encoding, char **line, + + static char *php_mb_rfc1867_getword_conf(const zend_encoding *encoding, char *str) /* {{{ */ + { +- while (*str && isspace(*(unsigned char *)str)) { ++ while (*str && isspace((unsigned char)*str)) { + ++str; + } + +@@ -642,7 +642,7 @@ static char *php_mb_rfc1867_getword_conf(const zend_encoding *encoding, char *st + } else { + char *strend = str; + +- while (*strend && !isspace(*(unsigned char *)strend)) { ++ while (*strend && !isspace((unsigned char)*strend)) { + ++strend; + } + return php_mb_rfc1867_substring_conf(encoding, str, strend - str, 0); +diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c +index 0734011f9fb..5342de2b4ca 100644 +--- a/ext/mbstring/php_mbregex.c ++++ b/ext/mbstring/php_mbregex.c +@@ -784,7 +784,7 @@ static inline void mb_regex_substitute( + continue; + } + if (name_end[0] == delim) break; +- if (maybe_num && !isdigit(name_end[0])) maybe_num = 0; ++ if (maybe_num && !isdigit((unsigned char)name_end[0])) maybe_num = 0; + name_end++; + } + p = name_end + 1; +diff --git a/ext/pcre/php_pcre.c b/ext/pcre/php_pcre.c +index 6249a807970..65891091256 100644 +--- a/ext/pcre/php_pcre.c ++++ b/ext/pcre/php_pcre.c +@@ -648,7 +648,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in + + /* Parse through the leading whitespace, and display a warning if we + get to the end without encountering a delimiter. */ +- while (isspace((int)*(unsigned char *)p)) p++; ++ while (isspace((unsigned char)*p)) p++; + if (*p == 0) { + if (key != regex) { + zend_string_release_ex(key, 0); +@@ -662,7 +662,7 @@ PHPAPI pcre_cache_entry* pcre_get_compiled_regex_cache_ex(zend_string *regex, in + /* Get the delimiter and display a warning if it is alphanumeric + or a backslash. */ + delimiter = *p++; +- if (isalnum((int)*(unsigned char *)&delimiter) || delimiter == '\\') { ++ if (isalnum((unsigned char)delimiter) || delimiter == '\\') { + if (key != regex) { + zend_string_release_ex(key, 0); + } +diff --git a/ext/pdo/pdo.c b/ext/pdo/pdo.c +index b18efe46284..03925abbc3b 100644 +--- a/ext/pdo/pdo.c ++++ b/ext/pdo/pdo.c +@@ -229,7 +229,7 @@ PDO_API int php_pdo_parse_data_source(const char *data_source, zend_ulong data_s + } + } + +- while (i < data_source_len && isspace(data_source[i])) { ++ while (i < data_source_len && isspace((unsigned char)data_source[i])) { + i++; + } + +diff --git a/ext/pdo/pdo_sql_parser.re b/ext/pdo/pdo_sql_parser.re +index 7f4721d12a6..7d282352396 100644 +--- a/ext/pdo/pdo_sql_parser.re ++++ b/ext/pdo/pdo_sql_parser.re +@@ -105,7 +105,7 @@ PDO_API int pdo_parse_params(pdo_stmt_t *stmt, zend_string *inquery, zend_string + + if (t == PDO_PARSER_BIND) { + ptrdiff_t len = s.cur - s.tok; +- if ((ZSTR_VAL(inquery) < (s.cur - len)) && isalnum(*(s.cur - len - 1))) { ++ if ((ZSTR_VAL(inquery) < (s.cur - len)) && isalnum((unsigned char)s.cur[-len - 1])) { + continue; + } + query_type |= PDO_PLACEHOLDER_NAMED; +diff --git a/ext/pdo/pdo_stmt.c b/ext/pdo/pdo_stmt.c +index c3c466fbdd2..ea2046a134b 100644 +--- a/ext/pdo/pdo_stmt.c ++++ b/ext/pdo/pdo_stmt.c +@@ -148,7 +148,7 @@ bool pdo_stmt_describe_columns(pdo_stmt_t *stmt) /* {{{ */ + stmt->columns[col].name = zend_string_separate(orig_name, 0); + char *s = ZSTR_VAL(stmt->columns[col].name); + while (*s != '\0') { +- *s = toupper(*s); ++ *s = toupper((unsigned char)*s); + s++; + } + break; +diff --git a/ext/standard/dl.c b/ext/standard/dl.c +index 0df3848852f..babab64864c 100644 +--- a/ext/standard/dl.c ++++ b/ext/standard/dl.c +@@ -93,7 +93,7 @@ PHPAPI void *php_load_shlib(const char *path, char **errp) + size_t i = strlen(err); + (*errp)=estrdup(err); + php_win32_error_msg_free(err); +- while (i > 0 && isspace((*errp)[i-1])) { (*errp)[i-1] = '\0'; i--; } ++ while (i > 0 && isspace((unsigned char)(*errp)[i-1])) { (*errp)[i-1] = '\0'; i--; } + } else { + (*errp) = estrdup("<No message>"); + } +diff --git a/ext/standard/exec.c b/ext/standard/exec.c +index 1831b8eaa54..156eaa2cd3d 100644 +--- a/ext/standard/exec.c ++++ b/ext/standard/exec.c +@@ -83,7 +83,7 @@ PHP_MINIT_FUNCTION(exec) + + static size_t strip_trailing_whitespace(char *buf, size_t bufl) { + size_t l = bufl; +- while (l-- > 0 && isspace(((unsigned char *)buf)[l])); ++ while (l-- > 0 && isspace((unsigned char)buf[l])); + if (l != (bufl - 1)) { + bufl = l + 1; + buf[bufl] = '\0'; +diff --git a/ext/standard/file.c b/ext/standard/file.c +index 8bab36096b1..bf20702e976 100644 +--- a/ext/standard/file.c ++++ b/ext/standard/file.c +@@ -2086,7 +2086,7 @@ PHPAPI void php_fgetcsv(php_stream *stream, char delimiter, char enclosure, int + inc_len = (bptr < limit ? (*bptr == '\0' ? 1 : php_mblen(bptr, limit - bptr)): 0); + if (inc_len == 1) { + char *tmp = bptr; +- while ((*tmp != delimiter) && isspace((int)*(unsigned char *)tmp)) { ++ while ((*tmp != delimiter) && isspace((unsigned char)*tmp)) { + tmp++; + } + if (*tmp == enclosure && tmp < limit) { +diff --git a/ext/standard/filters.c b/ext/standard/filters.c +index 9b54b3deab1..08678f8d5d8 100644 +--- a/ext/standard/filters.c ++++ b/ext/standard/filters.c +@@ -958,7 +958,7 @@ static php_conv_err_t php_conv_qprint_decode_convert(php_conv_qprint_decode *ins + goto out; + } + +- if (!isxdigit((int) *ps)) { ++ if (!isxdigit(*ps)) { + err = PHP_CONV_ERR_INVALID_SEQ; + goto out; + } +diff --git a/ext/standard/formatted_print.c b/ext/standard/formatted_print.c +index b988422df21..a1927b5fe88 100644 +--- a/ext/standard/formatted_print.c ++++ b/ext/standard/formatted_print.c +@@ -378,7 +378,7 @@ php_sprintf_getnumber(char **buffer, size_t *len) + + int php_sprintf_get_argnum(char **format, size_t *format_len) { + char *temppos = *format; +- while (isdigit((int) *temppos)) temppos++; ++ while (isdigit((unsigned char)*temppos)) temppos++; + if (*temppos != '$') { + return ARG_NUM_NEXT; + } +@@ -466,7 +466,7 @@ php_formatted_print(char *format, size_t format_len, zval *args, int argc, int n + + PRINTF_DEBUG(("sprintf: first looking at '%c', inpos=%d\n", + *format, format - Z_STRVAL_P(z_format))); +- if (isalpha((int)*format)) { ++ if (isalpha((unsigned char)*format)) { + width = precision = 0; + argnum = ARG_NUM_NEXT; + } else { +@@ -535,7 +535,7 @@ php_formatted_print(char *format, size_t format_len, zval *args, int argc, int n + } + width = Z_LVAL_P(tmp); + adjusting |= ADJ_WIDTH; +- } else if (isdigit((int)*format)) { ++ } else if (isdigit((unsigned char)*format)) { + PRINTF_DEBUG(("sprintf: getting width\n")); + if ((width = php_sprintf_getnumber(&format, &format_len)) < 0) { + zend_value_error("Width must be greater than zero and less than %d", INT_MAX); +@@ -580,7 +580,7 @@ php_formatted_print(char *format, size_t format_len, zval *args, int argc, int n + precision = Z_LVAL_P(tmp); + adjusting |= ADJ_PRECISION; + expprec = 1; +- } else if (isdigit((int)*format)) { ++ } else if (isdigit((unsigned char)*format)) { + if ((precision = php_sprintf_getnumber(&format, &format_len)) < 0) { + zend_value_error("Precision must be greater than zero and less than %d", INT_MAX); + goto fail; +diff --git a/ext/standard/ftp_fopen_wrapper.c b/ext/standard/ftp_fopen_wrapper.c +index d19113f7c77..c7491179fa9 100644 +--- a/ext/standard/ftp_fopen_wrapper.c ++++ b/ext/standard/ftp_fopen_wrapper.c +@@ -78,8 +78,8 @@ static inline int get_ftp_result(php_stream *stream, char *buffer, size_t buffer + { + buffer[0] = '\0'; /* in case read fails to read anything */ + while (php_stream_gets(stream, buffer, buffer_size-1) && +- !(isdigit((int) buffer[0]) && isdigit((int) buffer[1]) && +- isdigit((int) buffer[2]) && buffer[3] == ' ')); ++ !(isdigit((unsigned char)buffer[0]) && isdigit((unsigned char)buffer[1]) && ++ isdigit((unsigned char)buffer[2]) && buffer[3] == ' ')); + return strtol(buffer, NULL, 10); + } + /* }}} */ +@@ -228,7 +228,7 @@ static php_stream *php_ftp_fopen_connect(php_stream_wrapper *wrapper, const char + #define PHP_FTP_CNTRL_CHK(val, val_len, err_msg) { \ + unsigned char *s = (unsigned char *) val, *e = (unsigned char *) s + val_len; \ + while (s < e) { \ +- if (iscntrl(*s)) { \ ++ if (iscntrl((unsigned char)*s)) { \ + php_stream_wrapper_log_error(wrapper, options, err_msg, val); \ + goto connect_errexit; \ + } \ +@@ -339,14 +339,14 @@ static unsigned short php_fopen_do_pasv(php_stream *stream, char *ip, size_t ip_ + /* parse pasv command (129, 80, 95, 25, 13, 221) */ + tpath = tmp_line; + /* skip over the "227 Some message " part */ +- for (tpath += 4; *tpath && !isdigit((int) *tpath); tpath++); ++ for (tpath += 4; *tpath && !isdigit((unsigned char)*tpath); tpath++); + if (!*tpath) { + return 0; + } + /* skip over the host ip, to get the port */ + hoststart = tpath; + for (i = 0; i < 4; i++) { +- for (; isdigit((int) *tpath); tpath++); ++ for (; isdigit((unsigned char)*tpath); tpath++); + if (*tpath != ',') { + return 0; + } +@@ -826,7 +826,7 @@ static int php_stream_ftp_url_stat(php_stream_wrapper *wrapper, const char *url, + struct tm tm, tmbuf, *gmt; + time_t stamp; + +- while ((size_t)(p - tmp_line) < sizeof(tmp_line) && !isdigit(*p)) { ++ while ((size_t)(p - tmp_line) < sizeof(tmp_line) && !isdigit((unsigned char)*p)) { + p++; + } + +diff --git a/ext/standard/html.c b/ext/standard/html.c +index 14ccd71a236..8d39490b888 100644 +--- a/ext/standard/html.c ++++ b/ext/standard/html.c +@@ -682,8 +682,8 @@ static inline int process_numeric_entity(const char **buf, unsigned *code_point) + + /* strtol allows whitespace and other stuff in the beginning + * we're not interested */ +- if ((hexadecimal && !isxdigit(**buf)) || +- (!hexadecimal && !isdigit(**buf))) { ++ if ((hexadecimal && !isxdigit((unsigned char)**buf)) || ++ (!hexadecimal && !isdigit((unsigned char)**buf))) { + return FAILURE; + } + +diff --git a/ext/standard/math.c b/ext/standard/math.c +index 8643676b03e..af5869c88bc 100644 +--- a/ext/standard/math.c ++++ b/ext/standard/math.c +@@ -727,9 +727,9 @@ PHPAPI void _php_math_basetozval(zend_string *str, int base, zval *ret) + e = s + ZSTR_LEN(str); + + /* Skip leading whitespace */ +- while (s < e && isspace(*s)) s++; ++ while (s < e && isspace((unsigned char)*s)) s++; + /* Skip trailing whitespace */ +- while (s < e && isspace(*(e-1))) e--; ++ while (s < e && isspace((unsigned char)e[-1])) e--; + + if (e - s >= 2) { + if (base == 16 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) s += 2; +@@ -1031,7 +1031,7 @@ PHPAPI zend_string *_php_math_number_format_ex(double d, int dec, const char *de + tmpbuf = strpprintf(0, "%.*F", dec, d); + if (tmpbuf == NULL) { + return NULL; +- } else if (!isdigit((int)ZSTR_VAL(tmpbuf)[0])) { ++ } else if (!isdigit((unsigned char)ZSTR_VAL(tmpbuf)[0])) { + return tmpbuf; + } + +diff --git a/ext/standard/metaphone.c b/ext/standard/metaphone.c +index 7affde44de1..01ae1f965c1 100644 +--- a/ext/standard/metaphone.c ++++ b/ext/standard/metaphone.c +@@ -78,7 +78,7 @@ static const char _codes[26] = + }; + + +-#define ENCODE(c) (isalpha(c) ? _codes[((toupper(c)) - 'A')] : 0) ++#define ENCODE(c) (isalpha((unsigned char)(c)) ? _codes[((toupper((unsigned char)(c))) - 'A')] : 0) + + #define isvowel(c) (ENCODE(c) & 1) /* AEIOU */ + +@@ -102,17 +102,17 @@ static const char _codes[26] = + * accesssing the array directly... */ + + /* Look at the next letter in the word */ +-#define Next_Letter (toupper(word[w_idx+1])) ++#define Next_Letter (toupper((unsigned char)word[w_idx+1])) + /* Look at the current letter in the word */ +-#define Curr_Letter (toupper(word[w_idx])) ++#define Curr_Letter (toupper((unsigned char)word[w_idx])) + /* Go N letters back. */ +-#define Look_Back_Letter(n) (w_idx >= n ? toupper(word[w_idx-n]) : '\0') ++#define Look_Back_Letter(n) (w_idx >= n ? toupper((unsigned char)word[w_idx-n]) : '\0') + /* Previous letter. I dunno, should this return null on failure? */ + #define Prev_Letter (Look_Back_Letter(1)) + /* Look two letters down. It makes sure you don't walk off the string. */ +-#define After_Next_Letter (Next_Letter != '\0' ? toupper(word[w_idx+2]) \ ++#define After_Next_Letter (Next_Letter != '\0' ? toupper((unsigned char)word[w_idx+2]) \ + : '\0') +-#define Look_Ahead_Letter(n) (toupper(Lookahead((char *) word+w_idx, n))) ++#define Look_Ahead_Letter(n) (toupper((unsigned char)Lookahead((char *) word+w_idx, n))) + + + /* Allows us to safely look ahead an arbitrary # of letters */ +@@ -156,7 +156,7 @@ static char Lookahead(char *word, size_t how_far) + #define Phone_Len (p_idx) + + /* Note is a letter is a 'break' in the word */ +-#define Isbreak(c) (!isalpha(c)) ++#define Isbreak(c) (!isalpha((unsigned char)(c))) + + /* {{{ metaphone */ + static void metaphone(unsigned char *word, size_t word_len, zend_long max_phonemes, zend_string **phoned_word, int traditional) +@@ -179,7 +179,7 @@ static void metaphone(unsigned char *word, size_t word_len, zend_long max_phonem + + /*-- The first phoneme has to be processed specially. --*/ + /* Find our first letter */ +- for (; !isalpha(Curr_Letter); w_idx++) { ++ for (; !isalpha((unsigned char)Curr_Letter); w_idx++) { + /* On the off chance we were given nothing but crap... */ + if (Curr_Letter == '\0') { + End_Phoned_Word(); +@@ -263,7 +263,7 @@ static void metaphone(unsigned char *word, size_t word_len, zend_long max_phonem + */ + + /* Ignore non-alphas */ +- if (!isalpha(Curr_Letter)) ++ if (!isalpha((unsigned char)Curr_Letter)) + continue; + + /* Drop duplicates, except CC */ +diff --git a/ext/standard/quot_print.c b/ext/standard/quot_print.c +index e6aa2e43f4c..fba61f9f484 100644 +--- a/ext/standard/quot_print.c ++++ b/ext/standard/quot_print.c +@@ -216,11 +216,11 @@ PHP_FUNCTION(quoted_printable_decode) + switch (str_in[i]) { + case '=': + if (str_in[i + 1] && str_in[i + 2] && +- isxdigit((int) str_in[i + 1]) && +- isxdigit((int) str_in[i + 2])) ++ isxdigit((unsigned char)str_in[i + 1]) && ++ isxdigit((unsigned char)str_in[i + 2])) + { +- ZSTR_VAL(str_out)[j++] = (php_hex2int((int) str_in[i + 1]) << 4) +- + php_hex2int((int) str_in[i + 2]); ++ ZSTR_VAL(str_out)[j++] = (php_hex2int((unsigned char)str_in[i + 1]) << 4) ++ + php_hex2int((unsigned char)str_in[i + 2]); + i += 3; + } else /* check for soft line break according to RFC 2045*/ { + k = 1; +diff --git a/ext/standard/scanf.c b/ext/standard/scanf.c +index 78ecc1642cf..61154eca3a3 100644 +--- a/ext/standard/scanf.c ++++ b/ext/standard/scanf.c +@@ -345,7 +345,7 @@ PHPAPI int ValidateFormat(char *format, int numVars, int *totalSubs) + goto xpgCheckDone; + } + +- if ( isdigit( (int)*ch ) ) { ++ if ( isdigit( (unsigned char)*ch ) ) { + /* + * Check for an XPG3-style %n$ specification. Note: there + * must not be a mixture of XPG3 specs and non-XPG3 specs +@@ -656,9 +656,9 @@ PHPAPI int php_sscanf_internal( char *string, char *format, + /* + * If we see whitespace in the format, skip whitespace in the string. + */ +- if ( isspace( (int)*ch ) ) { ++ if ( isspace( (unsigned char)*ch ) ) { + sch = *string; +- while ( isspace( (int)sch ) ) { ++ while ( isspace( (unsigned char)sch ) ) { + if (*string == '\0') { + goto done; + } +@@ -809,7 +809,7 @@ literal: + if (!(flags & SCAN_NOSKIP)) { + while (*string != '\0') { + sch = *string; +- if (! isspace((int)sch) ) { ++ if (! isspace((unsigned char)sch) ) { + break; + } + string++; +@@ -835,7 +835,7 @@ literal: + end = string; + while (*end != '\0') { + sch = *end; +- if ( isspace( (int)sch ) ) { ++ if ( isspace( (unsigned char)sch ) ) { + break; + } + end++; +diff --git a/ext/standard/soundex.c b/ext/standard/soundex.c +index 7d50be97e75..4dded617a65 100644 +--- a/ext/standard/soundex.c ++++ b/ext/standard/soundex.c +@@ -67,7 +67,7 @@ PHP_FUNCTION(soundex) + /* BUG: should also map here accented letters used in non */ + /* English words or names (also found in English text!): */ + /* esstsett, thorn, n-tilde, c-cedilla, s-caron, ... */ +- code = toupper((int)(unsigned char)str[i]); ++ code = toupper((unsigned char)str[i]); + if (code >= 'A' && code <= 'Z') { + if (_small == 0) { + /* remember first valid char */ +diff --git a/ext/standard/string.c b/ext/standard/string.c +index da1a97f49da..8ca36ed7186 100644 +--- a/ext/standard/string.c ++++ b/ext/standard/string.c +@@ -3534,9 +3534,9 @@ PHPAPI void php_stripcslashes(zend_string *str) + case 'f': *target++='\f'; nlen--; break; + case '\\': *target++='\\'; nlen--; break; + case 'x': +- if (source+1 < end && isxdigit((int)(*(source+1)))) { ++ if (source+1 < end && isxdigit((unsigned char)source[1])) { + numtmp[0] = *++source; +- if (source+1 < end && isxdigit((int)(*(source+1)))) { ++ if (source+1 < end && isxdigit((unsigned char)source[1])) { + numtmp[1] = *++source; + numtmp[2] = '\0'; + nlen-=3; +@@ -4386,7 +4386,7 @@ PHP_FUNCTION(hebrev) + + do { + if (block_type == _HEB_BLOCK_TYPE_HEB) { +- while ((isheb((int)*(tmp+1)) || _isblank((int)*(tmp+1)) || ispunct((int)*(tmp+1)) || (int)*(tmp+1)=='\n' ) && block_end<str_len-1) { ++ while ((isheb((int)*(tmp+1)) || _isblank((int)*(tmp+1)) || ispunct((unsigned char)tmp[1]) || (int)*(tmp+1)=='\n' ) && block_end<str_len-1) { + tmp++; + block_end++; + block_length++; +@@ -4436,7 +4436,7 @@ PHP_FUNCTION(hebrev) + block_end++; + block_length++; + } +- while ((_isblank((int)*tmp) || ispunct((int)*tmp)) && *tmp!='/' && *tmp!='-' && block_end > block_start) { ++ while ((_isblank((int)*tmp) || ispunct((unsigned char)*tmp)) && *tmp!='/' && *tmp!='-' && block_end > block_start) { + tmp--; + block_end--; + } +@@ -4818,7 +4818,7 @@ int php_tag_find(char *tag, size_t len, const char *set) { + done =1; + break; + default: +- if (!isspace((int)c)) { ++ if (!isspace((unsigned char)c)) { + if (state == 0) { + state=1; + } +@@ -4908,7 +4908,7 @@ state_0: + if (in_q) { + break; + } +- if (isspace(*(p + 1)) && !allow_tag_spaces) { ++ if (isspace((unsigned char)p[1]) && !allow_tag_spaces) { + *(rp++) = c; + break; + } +@@ -4955,7 +4955,7 @@ state_1: + if (in_q) { + break; + } +- if (isspace(*(p + 1)) && !allow_tag_spaces) { ++ if (isspace((unsigned char)p[1]) && !allow_tag_spaces) { + goto reg_char_1; + } + depth++; +diff --git a/ext/standard/strnatcmp.c b/ext/standard/strnatcmp.c +index 8cbc0db1c3f..6d45785bcdd 100644 +--- a/ext/standard/strnatcmp.c ++++ b/ext/standard/strnatcmp.c +@@ -40,12 +40,12 @@ compare_right(char const **a, char const *aend, char const **b, char const *bend + both numbers to know that they have the same magnitude, so we + remember it in BIAS. */ + for(;; (*a)++, (*b)++) { +- if ((*a == aend || !isdigit((int)(unsigned char)**a)) && +- (*b == bend || !isdigit((int)(unsigned char)**b))) ++ if ((*a == aend || !isdigit((unsigned char)**a)) && ++ (*b == bend || !isdigit((unsigned char)**b))) + return bias; +- else if (*a == aend || !isdigit((int)(unsigned char)**a)) ++ else if (*a == aend || !isdigit((unsigned char)**a)) + return -1; +- else if (*b == bend || !isdigit((int)(unsigned char)**b)) ++ else if (*b == bend || !isdigit((unsigned char)**b)) + return +1; + else if (**a < **b) { + if (!bias) +@@ -67,12 +67,12 @@ compare_left(char const **a, char const *aend, char const **b, char const *bend) + /* Compare two left-aligned numbers: the first to have a + different value wins. */ + for(;; (*a)++, (*b)++) { +- if ((*a == aend || !isdigit((int)(unsigned char)**a)) && +- (*b == bend || !isdigit((int)(unsigned char)**b))) ++ if ((*a == aend || !isdigit((unsigned char)**a)) && ++ (*b == bend || !isdigit((unsigned char)**b))) + return 0; +- else if (*a == aend || !isdigit((int)(unsigned char)**a)) ++ else if (*a == aend || !isdigit((unsigned char)**a)) + return -1; +- else if (*b == bend || !isdigit((int)(unsigned char)**b)) ++ else if (*b == bend || !isdigit((unsigned char)**b)) + return +1; + else if (**a < **b) + return -1; +@@ -103,27 +103,27 @@ PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len + ca = *ap; cb = *bp; + + /* skip over leading zeros */ +- while (ca == '0' && (ap+1 < aend) && isdigit((int)(unsigned char)*(ap+1))) { ++ while (ca == '0' && (ap+1 < aend) && isdigit((unsigned char)ap[1])) { + ca = *++ap; + } + +- while (cb == '0' && (bp+1 < bend) && isdigit((int)(unsigned char)*(bp+1))) { ++ while (cb == '0' && (bp+1 < bend) && isdigit((unsigned char)bp[1])) { + cb = *++bp; + } + + while (1) { + + /* Skip consecutive whitespace */ +- while (isspace((int)(unsigned char)ca)) { ++ while (isspace(ca)) { + ca = *++ap; + } + +- while (isspace((int)(unsigned char)cb)) { ++ while (isspace(cb)) { + cb = *++bp; + } + + /* process run of digits */ +- if (isdigit((int)(unsigned char)ca) && isdigit((int)(unsigned char)cb)) { ++ if (isdigit(ca) && isdigit(cb)) { + fractional = (ca == '0' || cb == '0'); + + if (fractional) +@@ -147,8 +147,8 @@ PHPAPI int strnatcmp_ex(char const *a, size_t a_len, char const *b, size_t b_len + } + + if (fold_case) { +- ca = toupper((int)(unsigned char)ca); +- cb = toupper((int)(unsigned char)cb); ++ ca = toupper(ca); ++ cb = toupper(cb); + } + + if (ca < cb) +diff --git a/ext/standard/type.c b/ext/standard/type.c +index 93df434fe31..bf56c70d73d 100644 +--- a/ext/standard/type.c ++++ b/ext/standard/type.c +@@ -161,7 +161,7 @@ PHP_FUNCTION(intval) + char *strval = Z_STRVAL_P(num); + size_t strlen = Z_STRLEN_P(num); + +- while (isspace(*strval) && strlen) { ++ while (isspace((unsigned char)*strval) && strlen) { + strval++; + strlen--; + } +diff --git a/ext/standard/url.c b/ext/standard/url.c +index e3d95768fb0..def29df906a 100644 +--- a/ext/standard/url.c ++++ b/ext/standard/url.c +@@ -117,7 +117,7 @@ PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port + p = s; + while (p < e) { + /* scheme = 1*[ lowalpha | digit | "+" | "-" | "." ] */ +- if (!isalpha(*p) && !isdigit(*p) && *p != '+' && *p != '.' && *p != '-') { ++ if (!isalpha((unsigned char)*p) && !isdigit((unsigned char)*p) && *p != '+' && *p != '.' && *p != '-') { + if (e + 1 < ue && e < binary_strcspn(s, ue, "?#")) { + goto parse_port; + } else if (s + 1 < ue && *s == '/' && *(s + 1) == '/') { /* relative-scheme URL */ +@@ -146,7 +146,7 @@ PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port + * correctly parse things like a.com:80 + */ + p = e + 1; +- while (p < ue && isdigit(*p)) { ++ while (p < ue && isdigit((unsigned char)*p)) { + p++; + } + +@@ -186,7 +186,7 @@ PHPAPI php_url *php_url_parse_ex2(char const *str, size_t length, bool *has_port + p = e + 1; + pp = p; + +- while (pp < ue && pp - p < 6 && isdigit(*pp)) { ++ while (pp < ue && pp - p < 6 && isdigit((unsigned char)*pp)) { + pp++; + } + +@@ -429,12 +429,12 @@ static int php_htoi(char *s) + int value; + int c; + +- c = ((unsigned char *)s)[0]; ++ c = (unsigned char)s[0]; + if (isupper(c)) + c = tolower(c); + value = (c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10) * 16; + +- c = ((unsigned char *)s)[1]; ++ c = (unsigned char)s[1]; + if (isupper(c)) + c = tolower(c); + value += c >= '0' && c <= '9' ? c - '0' : c - 'a' + 10; +@@ -601,8 +601,8 @@ PHPAPI size_t php_url_decode(char *str, size_t len) + if (*data == '+') { + *dest = ' '; + } +- else if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) +- && isxdigit((int) *(data + 2))) { ++ else if (*data == '%' && len >= 2 && isxdigit((unsigned char)data[1]) ++ && isxdigit((unsigned char)data[2])) { + *dest = (char) php_htoi(data + 1); + data += 2; + len -= 2; +@@ -660,8 +660,8 @@ PHPAPI size_t php_raw_url_decode(char *str, size_t len) + char *data = str; + + while (len--) { +- if (*data == '%' && len >= 2 && isxdigit((int) *(data + 1)) +- && isxdigit((int) *(data + 2))) { ++ if (*data == '%' && len >= 2 && isxdigit((unsigned char)data[1]) ++ && isxdigit((unsigned char)data[2])) { + *dest = (char) php_htoi(data + 1); + data += 2; + len -= 2; +@@ -722,7 +722,7 @@ no_name_header: + c = *p; + *p = '\0'; + s = p + 1; +- while (isspace((int)*(unsigned char *)s)) { ++ while (isspace((unsigned char)*s)) { + s++; + } + +diff --git a/ext/standard/url_scanner_ex.re b/ext/standard/url_scanner_ex.re +index bac49206e63..30b395b3957 100644 +--- a/ext/standard/url_scanner_ex.re ++++ b/ext/standard/url_scanner_ex.re +@@ -85,7 +85,7 @@ static int php_ini_on_update_tags(zend_ini_entry *entry, zend_string *new_value, + + *val++ = '\0'; + for (q = key; *q; q++) { +- *q = tolower(*q); ++ *q = tolower((unsigned char)*q); + } + keylen = q - key; + str = zend_string_init(key, keylen, 1); +@@ -134,7 +134,7 @@ static int php_ini_on_update_hosts(zend_ini_entry *entry, zend_string *new_value + char *q; + + for (q = key; *q; q++) { +- *q = tolower(*q); ++ *q = tolower((unsigned char)*q); + } + keylen = q - key; + if (keylen > 0) { +@@ -454,7 +454,7 @@ static inline void handle_tag(STD_PARA) + } + smart_str_appendl(&ctx->tag, start, YYCURSOR - start); + for (i = 0; i < ZSTR_LEN(ctx->tag.s); i++) +- ZSTR_VAL(ctx->tag.s)[i] = tolower((int)(unsigned char)ZSTR_VAL(ctx->tag.s)[i]); ++ ZSTR_VAL(ctx->tag.s)[i] = tolower((unsigned char)ZSTR_VAL(ctx->tag.s)[i]); + /* intentionally using str_find here, in case the hash value is set, but the string val is changed later */ + if ((ctx->lookup_data = zend_hash_str_find_ptr(ctx->tags, ZSTR_VAL(ctx->tag.s), ZSTR_LEN(ctx->tag.s))) != NULL) { + ok = 1; +diff --git a/ext/standard/versioning.c b/ext/standard/versioning.c +index aa60d974672..178539709c7 100644 +--- a/ext/standard/versioning.c ++++ b/ext/standard/versioning.c +@@ -45,8 +45,8 @@ php_canonicalize_version(const char *version) + * s/([^\d\.])([^\D\.])/$1.$2/g; + * s/([^\D\.])([^\d\.])/$1.$2/g; + */ +-#define isdig(x) (isdigit(x)&&(x)!='.') +-#define isndig(x) (!isdigit(x)&&(x)!='.') ++#define isdig(x) (isdigit((unsigned char)(x))&&(x)!='.') ++#define isndig(x) (!isdigit((unsigned char)(x))&&(x)!='.') + #define isspecialver(x) ((x)=='-'||(x)=='_'||(x)=='+') + + lq = *(q - 1); +@@ -59,7 +59,7 @@ php_canonicalize_version(const char *version) + *q++ = '.'; + } + *q++ = *p; +- } else if (!isalnum(*p)) { ++ } else if (!isalnum((unsigned char)*p)) { + if (lq != '.') { + *q++ = '.'; + } +@@ -152,17 +152,17 @@ php_version_compare(const char *orig_ver1, const char *orig_ver2) + if ((n2 = strchr(p2, '.')) != NULL) { + *n2 = '\0'; + } +- if (isdigit(*p1) && isdigit(*p2)) { ++ if (isdigit((unsigned char)*p1) && isdigit((unsigned char)*p2)) { + /* compare element numerically */ + l1 = strtol(p1, NULL, 10); + l2 = strtol(p2, NULL, 10); + compare = ZEND_NORMALIZE_BOOL(l1 - l2); +- } else if (!isdigit(*p1) && !isdigit(*p2)) { ++ } else if (!isdigit((unsigned char)*p1) && !isdigit((unsigned char)*p2)) { + /* compare element names */ + compare = compare_special_version_forms(p1, p2); + } else { + /* mix of names and numbers */ +- if (isdigit(*p1)) { ++ if (isdigit((unsigned char)*p1)) { + compare = compare_special_version_forms("#N#", p2); + } else { + compare = compare_special_version_forms(p1, "#N#"); +@@ -180,13 +180,13 @@ php_version_compare(const char *orig_ver1, const char *orig_ver2) + } + if (compare == 0) { + if (n1 != NULL) { +- if (isdigit(*p1)) { ++ if (isdigit((unsigned char)*p1)) { + compare = 1; + } else { + compare = php_version_compare(p1, "#N#"); + } + } else if (n2 != NULL) { +- if (isdigit(*p2)) { ++ if (isdigit((unsigned char)*p2)) { + compare = -1; + } else { + compare = php_version_compare("#N#", p2); +diff --git a/main/SAPI.c b/main/SAPI.c +index 561cf6d598c..8b47a6c828c 100644 +--- a/main/SAPI.c ++++ b/main/SAPI.c +@@ -193,7 +193,7 @@ static void sapi_read_post_data(void) + *p = 0; + break; + default: +- *p = tolower(*p); ++ *p = tolower((unsigned char)*p); + break; + } + } +@@ -710,10 +710,10 @@ SAPI_API int sapi_header_op(sapi_header_op_enum op, void *arg) + } + + /* cut off trailing spaces, linefeeds and carriage-returns */ +- if (header_line_len && isspace(header_line[header_line_len-1])) { ++ if (header_line_len && isspace((unsigned char)header_line[header_line_len - 1])) { + do { + header_line_len--; +- } while(header_line_len && isspace(header_line[header_line_len-1])); ++ } while(header_line_len && isspace((unsigned char)header_line[header_line_len - 1])); + header_line[header_line_len]='\0'; + } + +diff --git a/main/fopen_wrappers.c b/main/fopen_wrappers.c +index efb110171b1..2ba2615ee6f 100644 +--- a/main/fopen_wrappers.c ++++ b/main/fopen_wrappers.c +@@ -487,7 +487,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt + } + + /* Don't resolve paths which contain protocol (except of file://) */ +- for (p = filename; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); ++ for (p = filename; isalnum((unsigned char)*p) || *p == '+' || *p == '-' || *p == '.'; p++); + if ((*p == ':') && (p - filename > 1) && (p[1] == '/') && (p[2] == '/')) { + wrapper = php_stream_locate_url_wrapper(filename, &actual_path, STREAM_OPEN_FOR_INCLUDE); + if (wrapper == &php_plain_files_wrapper) { +@@ -519,7 +519,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt + /* Check for stream wrapper */ + int is_stream_wrapper = 0; + +- for (p = ptr; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); ++ for (p = ptr; isalnum((unsigned char)*p) || *p == '+' || *p == '-' || *p == '.'; p++); + if ((*p == ':') && (p - ptr > 1) && (p[1] == '/') && (p[2] == '/')) { + /* .:// or ..:// is not a stream wrapper */ + if (p[-1] != '.' || p[-2] != '.' || p - 2 != ptr) { +@@ -588,7 +588,7 @@ PHPAPI zend_string *php_resolve_path(const char *filename, size_t filename_lengt + actual_path = trypath; + + /* Check for stream wrapper */ +- for (p = trypath; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++); ++ for (p = trypath; isalnum((unsigned char)*p) || *p == '+' || *p == '-' || *p == '.'; p++); + if ((*p == ':') && (p - trypath > 1) && (p[1] == '/') && (p[2] == '/')) { + wrapper = php_stream_locate_url_wrapper(trypath, &actual_path, STREAM_OPEN_FOR_INCLUDE); + if (!wrapper) { +diff --git a/main/php_ini.c b/main/php_ini.c +index 136942896da..f28c7db7de5 100644 +--- a/main/php_ini.c ++++ b/main/php_ini.c +@@ -40,7 +40,7 @@ + char *tmp = path; \ + while (*tmp) { \ + if (*tmp == '\\') *tmp = '/'; \ +- else *tmp = tolower(*tmp); \ ++ else *tmp = tolower((unsigned char)*tmp); \ + tmp++; \ + } \ + } +diff --git a/main/php_variables.c b/main/php_variables.c +index da7266416a5..a851c347601 100644 +--- a/main/php_variables.c ++++ b/main/php_variables.c +@@ -185,7 +185,7 @@ PHPAPI void php_register_variable_ex(const char *var_name, zval *val, zval *trac + + ip++; + index_s = ip; +- if (isspace(*ip)) { ++ if (isspace((unsigned char)*ip)) { + ip++; + } + if (*ip==']') { +@@ -508,7 +508,7 @@ SAPI_API SAPI_TREAT_DATA_FUNC(php_default_treat_data) + + if (arg == PARSE_COOKIE) { + /* Remove leading spaces from cookie names, needed for multi-cookie header where ; can be followed by a space */ +- while (isspace(*var)) { ++ while (isspace((unsigned char)*var)) { + var++; + } + if (var == val || *var == '\0') { +diff --git a/main/rfc1867.c b/main/rfc1867.c +index 83d141d38b1..c57e26b11b9 100644 +--- a/main/rfc1867.c ++++ b/main/rfc1867.c +@@ -413,7 +413,7 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header) + } + + /* space in the beginning means same header */ +- if (!isspace(line[0])) { ++ if (!isspace((unsigned char)line[0])) { + value = strchr(line, ':'); + } + +@@ -429,7 +429,7 @@ static int multipart_buffer_headers(multipart_buffer *self, zend_llist *header) + } + + *value = '\0'; +- do { value++; } while (isspace(*value)); ++ do { value++; } while (isspace((unsigned char)*value)); + + key = estrdup(line); + smart_string_appends(&buf_value, value); +@@ -526,7 +526,7 @@ static char *substring_conf(char *start, int len, char quote) + + static char *php_ap_getword_conf(const zend_encoding *encoding, char *str) + { +- while (*str && isspace(*str)) { ++ while (*str && isspace((unsigned char)*str)) { + ++str; + } + +@@ -542,7 +542,7 @@ static char *php_ap_getword_conf(const zend_encoding *encoding, char *str) + } else { + char *strend = str; + +- while (*strend && !isspace(*strend)) { ++ while (*strend && !isspace((unsigned char)*strend)) { + ++strend; + } + return substring_conf(str, strend - str, 0); +@@ -809,7 +809,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + goto fileupload_done; + } + +- while (isspace(*cd)) { ++ while (isspace((unsigned char)*cd)) { + ++cd; + } + +@@ -817,7 +817,7 @@ SAPI_API SAPI_POST_HANDLER_FUNC(rfc1867_post_handler) /* {{{ */ + { + char *key = NULL, *word = pair; + +- while (isspace(*cd)) { ++ while (isspace((unsigned char)*cd)) { + ++cd; + } + +diff --git a/main/snprintf.c b/main/snprintf.c +index f082115c676..b591169012b 100644 +--- a/main/snprintf.c ++++ b/main/snprintf.c +@@ -286,7 +286,7 @@ PHPAPI char * php_conv_fp(char format, double num, + /* + * Check for Infinity and NaN + */ +- if (isalpha((int)*p)) { ++ if (isalpha((unsigned char)*p)) { + *len = strlen(p); + memcpy(buf, p, *len + 1); + *is_negative = false; +@@ -433,11 +433,11 @@ typedef struct buf_area buffy; + #define NUM( c ) ( c - '0' ) + + #define STR_TO_DEC( str, num ) \ +- num = NUM( *str++ ) ; \ +- while ( isdigit((int)*str ) ) \ ++ num = NUM( *(str)++ ) ; \ ++ while ( isdigit((unsigned char)*(str) ) ) \ + { \ + num *= 10 ; \ +- num += NUM( *str++ ) ; \ ++ num += NUM( *(str)++ ) ; \ + } + + /* +@@ -531,7 +531,7 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{ + /* + * Try to avoid checking for flags, width or precision + */ +- if (isascii((int)*fmt) && !islower((int)*fmt)) { ++ if (isascii((unsigned char)*fmt) && !islower((unsigned char)*fmt)) { + /* + * Recognize flags: -, #, BLANK, + + */ +@@ -553,7 +553,7 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{ + /* + * Check if a width was specified + */ +- if (isdigit((int)*fmt)) { ++ if (isdigit((unsigned char)*fmt)) { + STR_TO_DEC(fmt, min_width); + adjust_width = true; + } else if (*fmt == '*') { +@@ -573,7 +573,7 @@ static size_t format_converter(buffy * odp, const char *fmt, va_list ap) /* {{{ + if (*fmt == '.') { + adjust_precision = true; + fmt++; +- if (isdigit((int)*fmt)) { ++ if (isdigit((unsigned char)*fmt)) { + STR_TO_DEC(fmt, precision); + } else if (*fmt == '*') { + precision = va_arg(ap, int); +diff --git a/main/spprintf.c b/main/spprintf.c +index 4c01347fcf4..2a31e3ae38b 100644 +--- a/main/spprintf.c ++++ b/main/spprintf.c +@@ -146,12 +146,12 @@ + #define NUM(c) (c - '0') + + #define STR_TO_DEC(str, num) do { \ +- num = NUM(*str++); \ +- while (isdigit((int)*str)) { \ ++ num = NUM(*(str)++); \ ++ while (isdigit((unsigned char)*(str))) {\ + num *= 10; \ +- num += NUM(*str++); \ ++ num += NUM(*(str)++); \ + if (num >= INT_MAX / 10) { \ +- while (isdigit((int)*str++)); \ ++ while (isdigit((unsigned char)*(str)++)); \ + break; \ + } \ + } \ +@@ -238,7 +238,7 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_ + /* + * Try to avoid checking for flags, width or precision + */ +- if (isascii((int)*fmt) && !islower((int)*fmt)) { ++ if (isascii((unsigned char)*fmt) && !islower((unsigned char)*fmt)) { + /* + * Recognize flags: -, #, BLANK, + + */ +@@ -260,7 +260,7 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_ + /* + * Check if a width was specified + */ +- if (isdigit((int)*fmt)) { ++ if (isdigit((unsigned char)*fmt)) { + STR_TO_DEC(fmt, min_width); + adjust_width = true; + } else if (*fmt == '*') { +@@ -280,7 +280,7 @@ static void xbuf_format_converter(void *xbuf, bool is_char, const char *fmt, va_ + if (*fmt == '.') { + adjust_precision = true; + fmt++; +- if (isdigit((int)*fmt)) { ++ if (isdigit((unsigned char)*fmt)) { + STR_TO_DEC(fmt, precision); + } else if (*fmt == '*') { + precision = va_arg(ap, int); +diff --git a/main/streams/streams.c b/main/streams/streams.c +index 634c0d58348..030c2453e50 100644 +--- a/main/streams/streams.c ++++ b/main/streams/streams.c +@@ -1739,7 +1739,7 @@ static inline int php_stream_wrapper_scheme_validate(const char *protocol, unsig + unsigned int i; + + for(i = 0; i < protocol_len; i++) { +- if (!isalnum((int)protocol[i]) && ++ if (!isalnum((unsigned char)protocol[i]) && + protocol[i] != '+' && + protocol[i] != '-' && + protocol[i] != '.') { +@@ -1819,7 +1819,7 @@ PHPAPI php_stream_wrapper *php_stream_locate_url_wrapper(const char *path, const + return (php_stream_wrapper*)((options & STREAM_LOCATE_WRAPPERS_ONLY) ? NULL : &php_plain_files_wrapper); + } + +- for (p = path; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { ++ for (p = path; isalnum((unsigned char)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { + n++; + } + +diff --git a/main/streams/transports.c b/main/streams/transports.c +index 35ac4ae27ad..306f7ff5e4b 100644 +--- a/main/streams/transports.c ++++ b/main/streams/transports.c +@@ -94,7 +94,7 @@ PHPAPI php_stream *_php_stream_xport_create(const char *name, size_t namelen, in + } + } + +- for (p = name; isalnum((int)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { ++ for (p = name; isalnum((unsigned char)*p) || *p == '+' || *p == '-' || *p == '.'; p++) { + n++; + } + +diff --git a/sapi/cli/php_cli_server.c b/sapi/cli/php_cli_server.c +index 82cf5c10d15..ab0ad1d6e5c 100644 +--- a/sapi/cli/php_cli_server.c ++++ b/sapi/cli/php_cli_server.c +@@ -633,7 +633,7 @@ static int sapi_cli_server_register_entry_cb(char **entry, int num_args, va_list + if (key[i] == '-') { + key[i] = '_'; + } else { +- key[i] = toupper(key[i]); ++ key[i] = toupper((unsigned char)key[i]); + } + } + spprintf(&real_key, 0, "%s_%s", "HTTP", key); +diff --git a/sapi/fpm/fpm/fpm_conf.c b/sapi/fpm/fpm/fpm_conf.c +index cc7102eabbc..01c4ee2d573 100644 +--- a/sapi/fpm/fpm/fpm_conf.c ++++ b/sapi/fpm/fpm/fpm_conf.c +@@ -932,7 +932,7 @@ static int fpm_conf_process_all_pools(void) + } + + for (i = 0; i < strlen(status); i++) { +- if (!isalnum(status[i]) && status[i] != '/' && status[i] != '-' && status[i] != '_' && status[i] != '.' && status[i] != '~') { ++ if (!isalnum((unsigned char)status[i]) && status[i] != '/' && status[i] != '-' && status[i] != '_' && status[i] != '.' && status[i] != '~') { + zlog(ZLOG_ERROR, "[pool %s] the status path '%s' must contain only the following characters '[alphanum]/_-.~'", wp->config->name, status); + return -1; + } +@@ -955,7 +955,7 @@ static int fpm_conf_process_all_pools(void) + } + + for (i = 0; i < strlen(ping); i++) { +- if (!isalnum(ping[i]) && ping[i] != '/' && ping[i] != '-' && ping[i] != '_' && ping[i] != '.' && ping[i] != '~') { ++ if (!isalnum((unsigned char)ping[i]) && ping[i] != '/' && ping[i] != '-' && ping[i] != '_' && ping[i] != '.' && ping[i] != '~') { + zlog(ZLOG_ERROR, "[pool %s] the ping path '%s' must contain only the following characters '[alphanum]/_-.~'", wp->config->name, ping); + return -1; + } +diff --git a/sapi/litespeed/lsapi_main.c b/sapi/litespeed/lsapi_main.c +index 2b3d83ad4be..3c0c3cafe02 100644 +--- a/sapi/litespeed/lsapi_main.c ++++ b/sapi/litespeed/lsapi_main.c +@@ -1707,12 +1707,12 @@ PHP_FUNCTION(litespeed_response_headers) + len = p - h->header; + if (p && len > 0 && len < LSAPI_RESP_HTTP_HEADER_MAX) { + memmove( headerBuf, h->header, len ); +- while( len > 0 && (isspace( headerBuf[len-1])) ) { ++ while( len > 0 && (isspace((unsigned char)headerBuf[len - 1])) ) { + --len; + } + headerBuf[len] = 0; + if ( len ) { +- while( isspace(*++p)); ++ while(isspace((unsigned char)*++p)); + add_assoc_string_ex(return_value, headerBuf, len, p); + } + } +diff --git a/sapi/litespeed/lsapilib.c b/sapi/litespeed/lsapilib.c +index 09cd2e6bf9a..038e43137f2 100644 +--- a/sapi/litespeed/lsapilib.c ++++ b/sapi/litespeed/lsapilib.c +@@ -2242,7 +2242,7 @@ static char * GetHeaderVar( LSAPI_Request * pReq, const char * name ) + + while(( pKey < pKeyEnd )&&( *p )) + { +- char ch = toupper( *pKey ); ++ char ch = toupper( (unsigned char)*pKey ); + if ((ch != *p )||(( *p == '_' )&&( ch != '-'))) + break; + ++p; ++pKey; +@@ -2426,7 +2426,7 @@ int LSAPI_ForeachHeader_r( LSAPI_Request * pReq, + if ( ch == '-' ) + *p++ = '_'; + else +- *p++ = toupper( ch ); ++ *p++ = toupper( (unsigned char)ch ); + } + *p = 0; + keyLen += 5; +@@ -2671,7 +2671,7 @@ int LSAPI_ParseSockAddr( const char * pBind, struct sockaddr * pAddr ) + if ( !pBind ) + return -1; + +- while( isspace( *pBind ) ) ++ while(isspace( (unsigned char)*pBind ) ) + ++pBind; + + strncpy(achAddr, pBind, 255); +diff --git a/sapi/phpdbg/phpdbg_cmd.c b/sapi/phpdbg/phpdbg_cmd.c +index 7e6a87fcc89..2b18949e8fd 100644 +--- a/sapi/phpdbg/phpdbg_cmd.c ++++ b/sapi/phpdbg/phpdbg_cmd.c +@@ -766,9 +766,9 @@ PHPDBG_API char *phpdbg_read_input(const char *buffered) /* {{{ */ + } + } + +- if (buffer && isspace(*buffer)) { ++ if (buffer && isspace((unsigned char)*buffer)) { + char *trimmed = buffer; +- while (isspace(*trimmed)) ++ while (isspace((unsigned char)*trimmed)) + trimmed++; + + trimmed = estrdup(trimmed); +diff --git a/sapi/phpdbg/phpdbg_prompt.c b/sapi/phpdbg/phpdbg_prompt.c +index 8ca6d83c78c..ebf36eae781 100644 +--- a/sapi/phpdbg/phpdbg_prompt.c ++++ b/sapi/phpdbg/phpdbg_prompt.c +@@ -213,7 +213,7 @@ static void phpdbg_line_init(char *cmd, struct phpdbg_init_state *state) { + + state->line++; + +- while (cmd_len > 0L && isspace(cmd[cmd_len-1])) { ++ while (cmd_len > 0L && isspace((unsigned char)cmd[cmd_len-1])) { + cmd_len--; + } + +diff --git a/sapi/phpdbg/phpdbg_utils.c b/sapi/phpdbg/phpdbg_utils.c +index f638d608905..04bc117ffb3 100644 +--- a/sapi/phpdbg/phpdbg_utils.c ++++ b/sapi/phpdbg/phpdbg_utils.c +@@ -82,10 +82,10 @@ PHPDBG_API int phpdbg_is_numeric(const char *str) /* {{{ */ + return 0; + + for (; *str; str++) { +- if (isspace(*str) || *str == '-') { ++ if (isspace((unsigned char)*str) || *str == '-') { + continue; + } +- return isdigit(*str); ++ return isdigit((unsigned char)*str); + } + return 0; + } /* }}} */ +@@ -96,7 +96,7 @@ PHPDBG_API int phpdbg_is_empty(const char *str) /* {{{ */ + return 1; + + for (; *str; str++) { +- if (isspace(*str)) { ++ if (isspace((unsigned char)*str)) { + continue; + } + return 0; +@@ -199,12 +199,12 @@ PHPDBG_API char *phpdbg_trim(const char *str, size_t len, size_t *new_len) /* {{ + const char *p = str; + char *new = NULL; + +- while (p && isspace(*p)) { ++ while (p && isspace((unsigned char)*p)) { + ++p; + --len; + } + +- while (*p && isspace(*(p + len -1))) { ++ while (*p && isspace((unsigned char)p[len - 1])) { + --len; + } + +diff --git a/win32/sendmail.c b/win32/sendmail.c +index d4de4645d67..e08424bf058 100644 +--- a/win32/sendmail.c ++++ b/win32/sendmail.c +@@ -57,7 +57,7 @@ + efree(response); \ + } \ + } +-#define SMTP_SKIP_SPACE(str) { while (isspace(*str)) { str++; } } ++#define SMTP_SKIP_SPACE(str) { while (isspace((unsigned char)*(str))) { (str)++; } } + + + char seps[] = " ,\t\n"; +@@ -725,7 +725,7 @@ static int PostHeader(char *RPath, const char *Subject, const char *mailTo, char + headers_lc_len = strlen(headers_lc); + + for (i = 0; i < headers_lc_len; i++) { +- headers_lc[i] = tolower(headers_lc[i]); ++ headers_lc[i] = tolower((unsigned char)headers_lc[i]); + } + } + +@@ -853,7 +853,7 @@ return 0; + + /* Resolve the servers IP */ + /* +- if (!isdigit(PW32G(mail_host)[0])||!gethostbyname(PW32G(mail_host))) ++ if (!isdigit((unsigned char)PW32G(mail_host)[0])||!gethostbyname(PW32G(mail_host))) + { + return (FAILED_TO_RESOLVE_HOST); + } +-- +2.54.0 + +From 7dff10e9a31d469fcd436e10b06f8b2bf2758a68 Mon Sep 17 00:00:00 2001 +From: Remi Collet <remi@remirepo.net> +Date: Thu, 7 May 2026 09:01:35 +0200 +Subject: [PATCH 10/10] NEWS from 8.2.31 + +--- + NEWS | 30 ++++++++++++++++++++++++++++++ + 1 file changed, 30 insertions(+) + +diff --git a/NEWS b/NEWS +index 9d420d24da6..c245d3e757e 100644 +--- a/NEWS ++++ b/NEWS +@@ -1,5 +1,35 @@ + PHP NEWS + ||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||| ++ ++Backported from 8.2.31 ++ ++- FPM: ++ . Fixed GHSA-7qg2-v9fj-4mwv (XSS within status endpoint). (CVE-2026-6735) ++ (Jakub Zelenka) ++ ++- MBString: ++ . Fixed GHSA-wm6j-2649-pv75 (Null pointer dereference in ++ php_mb_check_encoding() via mb_ereg_search_init()). (CVE-2026-7259) ++ (vi3tL0u1s) ++ ++- PDO_Firebird: ++ . Fixed GHSA-w476-322c-wpvm (SQL injection via NUL bytes in quoted strings). ++ (CVE-2025-14179) (SakiTakamachi) ++ ++- SOAP: ++ . Fixed GHSA-85c2-q967-79q5 (Stale SOAP_GLOBAL(ref_map) pointer with Apache ++ Map). (CVE-2026-6722) (ilutov) ++ . Fixed GHSA-m33r-qmcv-p97q (Use-after-free after header parsing failure with ++ SOAP_PERSISTENCE_SESSION). (CVE-2026-7261) (ilutov) ++ . Fixed GHSA-hmxp-6pc4-f3vv (Broken Apache map value NULL check). ++ (CVE-2026-7262) (ilutov) ++ ++- Standard: ++ . Fixed GHSA-96wq-48vp-hh57 (Signed integer overflow of char array offset). ++ (CVE-2026-7568) (TimWolla) ++ . Fixed GHSA-m8rr-4c36-8gq4 (Consistently pass unsigned char to ctype.h ++ functions). (CVE-2026-7258) (ilutov) ++ + 18 Dec 2025, PHP 8.1.34 + + - Curl: +-- +2.54.0 + diff --git a/php-cve-2026-7259.patch b/php-cve-2026-7259.patch new file mode 100644 index 0000000..13393af --- /dev/null +++ b/php-cve-2026-7259.patch @@ -0,0 +1,66 @@ +From 785bcb5dd5980a4f3173ab0b80c70a5602bc9339 Mon Sep 17 00:00:00 2001 +From: vi3tL0u1s <luuviethoang.attt@gmail.com> +Date: Sun, 3 May 2026 20:02:21 +0200 +Subject: [PATCH 05/10] GHSA-wm6j-2649-pv75: [mbstring] Fix null pointer + dereference in php_mb_check_encoding() via mb_ereg_search_init() + +Fixes GHSA-wm6j-2649-pv75 +Fixes CVE-2026-7259 + +(cherry picked from commit 79a054eae016c56409432e69aebc8ca908a88838) +--- + Zend/tests/GHSA-wm6j-2649-pv75.phpt | 22 ++++++++++++++++++++++ + ext/mbstring/php_mbregex.c | 7 ++++++- + 2 files changed, 28 insertions(+), 1 deletion(-) + create mode 100644 Zend/tests/GHSA-wm6j-2649-pv75.phpt + +diff --git a/Zend/tests/GHSA-wm6j-2649-pv75.phpt b/Zend/tests/GHSA-wm6j-2649-pv75.phpt +new file mode 100644 +index 00000000000..7257af27cb8 +--- /dev/null ++++ b/Zend/tests/GHSA-wm6j-2649-pv75.phpt +@@ -0,0 +1,22 @@ ++--TEST-- ++GHSA-wm6j-2649-pv75: Null pointer dereference in php_mb_check_encoding() via mb_ereg_search_init() ++--CREDITS-- ++vi3tL0u1s ++--EXTENSIONS-- ++mbstring ++--SKIPIF-- ++<?php ++if (!function_exists('mb_regex_encoding')) die('skip No mbregex support'); ++?> ++--FILE-- ++<?php ++// iso-8859-11 is supported by Oniguruma but not by mbfl ++mb_regex_encoding('iso-8859-11'); ++mb_ereg_search_init('x'); ++?> ++--EXPECTF-- ++Fatal error: Uncaught ValueError: mb_regex_encoding(): Argument #1 ($encoding) must be a valid encoding, "iso-8859-11" given in %s:%d ++Stack trace: ++#0 %s(%d): mb_regex_encoding('iso-8859-11') ++#1 {main} ++ thrown in %s on line %d +diff --git a/ext/mbstring/php_mbregex.c b/ext/mbstring/php_mbregex.c +index 06f65f5c567..0734011f9fb 100644 +--- a/ext/mbstring/php_mbregex.c ++++ b/ext/mbstring/php_mbregex.c +@@ -409,8 +409,13 @@ int php_mb_regex_set_mbctype(const char *encname) + if (mbctype == ONIG_ENCODING_UNDEF) { + return FAILURE; + } ++ const mbfl_encoding *mbfl_enc = mbfl_name2encoding(encname); ++ if (mbfl_enc == NULL) { ++ /* Encoding supported by Oniguruma but not by mbfl */ ++ return FAILURE; ++ } + MBREX(current_mbctype) = mbctype; +- MBREX(current_mbctype_mbfl_encoding) = mbfl_name2encoding(encname); ++ MBREX(current_mbctype_mbfl_encoding) = mbfl_enc; + return SUCCESS; + } + /* }}} */ +-- +2.54.0 + diff --git a/php-cve-2026-7261.patch b/php-cve-2026-7261.patch new file mode 100644 index 0000000..aa5c835 --- /dev/null +++ b/php-cve-2026-7261.patch @@ -0,0 +1,111 @@ +From 5dd8dd8493d49bb6fcd810a6e9d2ffb6fdc15714 Mon Sep 17 00:00:00 2001 +From: Ilija Tovilo <ilija.tovilo@me.com> +Date: Sun, 3 May 2026 19:57:16 +0200 +Subject: [PATCH 02/10] 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 + +(cherry picked from commit db2a7f9348fd5dda5fd162061786a664c417bf5b) +--- + 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 3bc713ca76b..bb8b664af58 100644 +--- a/ext/soap/soap.c ++++ b/ext/soap/soap.c +@@ -1477,13 +1477,21 @@ PHP_METHOD(SoapServer, handle) + php_output_discard(); + soap_server_fault_ex(function, &h->retval, h); + zend_string_release(fn_name); +- 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); + zend_string_release(fn_name); +- 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 00000000000..bcf441ccd18 +--- /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-- ++<?php ++ ++class Handler { ++ public function return() { ++ return new SoapFault('Server', 'denied'); ++ } ++ public function throw() { ++ throw new SoapFault('Server', 'denied'); ++ } ++ public function hello() { ++ return 'ok'; ++ } ++} ++ ++session_start(); ++ ++$srv = new SoapServer(null, ['uri' => 'urn:a']); ++$srv->setClass(Handler::class); ++$srv->setPersistence(SOAP_PERSISTENCE_SESSION); ++ ++$srv->handle(<<<XML ++<?xml version="1.0" encoding="UTF-8"?> ++<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="urn:a"> ++ <soap:Header> ++ <a:return/> ++ </soap:Header> ++ <soap:Body> ++ <a:hello/> ++ </soap:Body> ++</soap:Envelope> ++XML); ++ ++$srv->handle(<<<XML ++<?xml version="1.0" encoding="UTF-8"?> ++<soap:Envelope xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" xmlns:a="urn:a"> ++ <soap:Header> ++ <a:throw/> ++ </soap:Header> ++ <soap:Body> ++ <a:hello/> ++ </soap:Body> ++</soap:Envelope> ++XML); ++ ++?> ++--EXPECT-- ++<?xml version="1.0" encoding="UTF-8"?> ++<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>denied</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope> ++<?xml version="1.0" encoding="UTF-8"?> ++<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>denied</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope> +-- +2.54.0 + diff --git a/php-cve-2026-7262.patch b/php-cve-2026-7262.patch new file mode 100644 index 0000000..84623f2 --- /dev/null +++ b/php-cve-2026-7262.patch @@ -0,0 +1,77 @@ +From aed3e63e282235b32a07ca28cc20728eedfcfec3 Mon Sep 17 00:00:00 2001 +From: Ilija Tovilo <ilija.tovilo@me.com> +Date: Sat, 25 Apr 2026 00:44:37 +0200 +Subject: [PATCH 03/10] GHSA-hmxp-6pc4-f3vv: [soap] Fix broken Apache map value + NULL check + +Fixes GHSA-hmxp-6pc4-f3vv +Fixes CVE-2026-7262 + +(cherry picked from commit 79551ab8b1a97760c739e372f9bc359619f3554d) +--- + 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 bf394f7ea92..9bd6f50834e 100644 +--- a/ext/soap/php_encoding.c ++++ b/ext/soap/php_encoding.c +@@ -2711,7 +2711,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 00000000000..e46ab2e4607 +--- /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-- ++<?php ++ ++$request = <<<XML ++<?xml version="1.0" encoding="UTF-8"?> ++<soap:Envelope ++ xmlns:soap="http://schemas.xmlsoap.org/soap/envelope/" ++ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" ++ xmlns:xsd="http://www.w3.org/2001/XMLSchema" ++ xmlns:apache="http://xml.apache.org/xml-soap"> ++ ++ <soap:Body> ++ <test> ++ <map xsi:type="apache:Map"> ++ <item><key>hello</key></item> ++ </map> ++ </test> ++ </soap:Body> ++</soap:Envelope> ++XML; ++ ++$server = new SoapServer(null, [ ++ 'uri' => 'urn:test', ++ 'typemap' => [['type_name' => 'anything']], ++]); ++$server->addFunction('test'); ++function test($m) { return null; } ++$server->handle($request); ++ ++?> ++--EXPECT-- ++<?xml version="1.0" encoding="UTF-8"?> ++<SOAP-ENV:Envelope xmlns:SOAP-ENV="http://schemas.xmlsoap.org/soap/envelope/"><SOAP-ENV:Body><SOAP-ENV:Fault><faultcode>SOAP-ENV:Server</faultcode><faultstring>SOAP-ERROR: Encoding: Can't decode apache map, missing value</faultstring></SOAP-ENV:Fault></SOAP-ENV:Body></SOAP-ENV:Envelope> +-- +2.54.0 + diff --git a/php-cve-2026-7568.patch b/php-cve-2026-7568.patch new file mode 100644 index 0000000..68c1de6 --- /dev/null +++ b/php-cve-2026-7568.patch @@ -0,0 +1,101 @@ +From e4fc187a011d91f26178f6dfbccdb07041b99153 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= <tim@tideways-gmbh.com> +Date: Sun, 3 May 2026 20:02:57 +0200 +Subject: [PATCH 06/10] GHSA-96wq-48vp-hh57: [metaphone] Fix signed integer + overflow of char array offset + +Fixes GHSA-96wq-48vp-hh57 +Fixes CVE-2026-7568 + +(cherry picked from commit 47def8ce1db1fdbffcfc1f5bb11877a0e22d4b32) +--- + ext/standard/metaphone.c | 6 +++--- + ext/standard/tests/GHSA-96wq-48vp-hh57.phpt | 22 +++++++++++++++++++++ + 2 files changed, 25 insertions(+), 3 deletions(-) + create mode 100644 ext/standard/tests/GHSA-96wq-48vp-hh57.phpt + +diff --git a/ext/standard/metaphone.c b/ext/standard/metaphone.c +index 2ba7a839c88..7affde44de1 100644 +--- a/ext/standard/metaphone.c ++++ b/ext/standard/metaphone.c +@@ -117,10 +117,10 @@ static const char _codes[26] = + + /* Allows us to safely look ahead an arbitrary # of letters */ + /* I probably could have just used strlen... */ +-static char Lookahead(char *word, int how_far) ++static char Lookahead(char *word, size_t how_far) + { + char letter_ahead = '\0'; /* null by default */ +- int idx; ++ size_t idx; + for (idx = 0; word[idx] != '\0' && idx < how_far; idx++); + /* Edge forward in the string... */ + +@@ -161,7 +161,7 @@ static char Lookahead(char *word, int how_far) + /* {{{ metaphone */ + static void metaphone(unsigned char *word, size_t word_len, zend_long max_phonemes, zend_string **phoned_word, int traditional) + { +- int w_idx = 0; /* point in the phonization we're at. */ ++ size_t w_idx = 0; /* point in the phonization we're at. */ + size_t p_idx = 0; /* end of the phoned phrase */ + size_t max_buffer_len = 0; /* maximum length of the destination buffer */ + ZEND_ASSERT(word != NULL); +diff --git a/ext/standard/tests/GHSA-96wq-48vp-hh57.phpt b/ext/standard/tests/GHSA-96wq-48vp-hh57.phpt +new file mode 100644 +index 00000000000..79c6b656733 +--- /dev/null ++++ b/ext/standard/tests/GHSA-96wq-48vp-hh57.phpt +@@ -0,0 +1,22 @@ ++--TEST-- ++GHSA-96wq-48vp-hh57: signed integer overflow of char array offset ++--CREDITS-- ++012git012 ++--INI-- ++memory_limit=3G ++--SKIPIF-- ++<?php ++if (!getenv('RUN_RESOURCE_HEAVY_TESTS')) die('skip resource-heavy test'); ++if (getenv('SKIP_SLOW_TESTS')) die('skip slow test'); ++if (PHP_INT_SIZE != 8) echo 'skip 64-bit only'; ++?> ++--FILE-- ++<?php ++ ++$str = str_repeat('0', 2 * (1024 ** 3) - 2) . 'AE'; ++metaphone($str, 1); ++ ++?> ++===DONE=== ++--EXPECT-- ++===DONE=== +-- +2.54.0 + +From 101e93900888ef43d42ec0e33866bca3824f51a8 Mon Sep 17 00:00:00 2001 +From: Ilija Tovilo <ilija.tovilo@me.com> +Date: Wed, 6 May 2026 16:33:44 +0200 +Subject: [PATCH 09/10] [skip ci] Adjust credits for GHSA-96wq-48vp-hh57.phpt + +As requested by the reporter. + +(cherry picked from commit fee84dd8c7699e4e7f9b2e864a393ee5a372f974) +--- + ext/standard/tests/GHSA-96wq-48vp-hh57.phpt | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +diff --git a/ext/standard/tests/GHSA-96wq-48vp-hh57.phpt b/ext/standard/tests/GHSA-96wq-48vp-hh57.phpt +index 79c6b656733..cf9a40062f8 100644 +--- a/ext/standard/tests/GHSA-96wq-48vp-hh57.phpt ++++ b/ext/standard/tests/GHSA-96wq-48vp-hh57.phpt +@@ -1,7 +1,7 @@ + --TEST-- + GHSA-96wq-48vp-hh57: signed integer overflow of char array offset + --CREDITS-- +-012git012 ++Aleksey Solovev (Positive Technologies) + --INI-- + memory_limit=3G + --SKIPIF-- +-- +2.54.0 + @@ -24,7 +24,7 @@ %global mysql_sock %(mysql_config --socket 2>/dev/null || echo /var/lib/mysql/mysql.sock) -%global oraclever 23.9 +%global oraclever 23.26.1 %global oraclemax 24 %global oraclelib 23.1 %global oracledir 23 @@ -124,7 +124,7 @@ Summary: PHP scripting language for creating dynamic web sites Name: php Version: %{upver}%{?rcver:~%{rcver}} -Release: 1%{?dist} +Release: 2%{?dist} # All files licensed under PHP version 3.01, except # Zend is licensed under Zend # TSRM is licensed under BSD @@ -187,6 +187,14 @@ Patch91: php-7.2.0-oci8conf.patch # Upstream fixes (100+) # Security fixes (200+) +Patch200: php-cve-2026-14179.patch +Patch201: php-cve-2026-6722.patch +Patch202: php-cve-2026-7261.patch +Patch203: php-cve-2026-7262.patch +Patch204: php-cve-2026-6735.patch +Patch205: php-cve-2026-7259.patch +Patch206: php-cve-2026-7568.patch +Patch207: php-cve-2026-7258.patch # Fixes for tests (300+) # Factory is droped from system tzdata @@ -1205,6 +1213,14 @@ in pure PHP. # upstream patches # security patches +%patch -P200 -p1 -b .cve14179 +%patch -P201 -p1 -b .cve6722 +%patch -P202 -p1 -b .cve7261 +%patch -P203 -p1 -b .cve7262 +%patch -P204 -p1 -b .cve6735 +%patch -P205 -p1 -b .cve7259 +%patch -P206 -p1 -b .cve7268 +%patch -P207 -p1 -b .cve7258 # Fixes for tests related to tzdata %if %{with tzdata} @@ -2037,6 +2053,19 @@ fi %endif +%posttrans common +cat << EOF +===================================================================== + + WARNING : PHP 8.1 have reached its "End of Life" in + December 2025. Even, if this package includes some of + the important security fixes, backported from 8.2, the + UPGRADE to a maintained version is very strongly RECOMMENDED. + +===================================================================== +EOF + + %{!?_licensedir:%global license %%doc} %files @@ -2201,6 +2230,24 @@ fi %changelog +* Thu May 7 2026 Remi Collet <remi@remirepo.net> - 8.1.34-2 +- Fix XSS within status endpoint + CVE-2026-6735 +- Fix Null pointer dereference in php_mb_check_encoding() via mb_ereg_search_init() + CVE-2026-7259 +- Fix SQL injection via NUL bytes in quoted strings + CVE-2025-14179 +- Fix Stale SOAP_GLOBAL(ref_map) pointer with Apache Map + CVE-2026-6722 +- Fix Use-after-free after header parsing failure with SOAP_PERSISTENCE_SESSION + CVE-2026-7261 +- Fix Broken Apache map value NULL check + CVE-2026-7262 +- Fix Signed integer overflow of char array offset + CVE-2026-7568 +- Fix Consistently pass unsigned char to ctype.h functions + CVE-2026-7258 + * Wed Dec 17 2025 Remi Collet <remi@remirepo.net> - 8.1.34-1 - Update to 8.1.34 - http://www.php.net/releases/8_1_34.php |
