[php-src] Issue #24606: mbstring.http_input is ignored in subsequent requests after changing default_charset
| From: | OddOnes | Date: | Fri, 23 Oct 2026 15:25:49 +0000 |
| Subject: | [php-src] Issue #24606: mbstring.http_input is ignored in subsequent requests after changing default_charset | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-253132@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/24606
Author: OddOnes
### Description
With
mbstring.http_input=auto explicitly configured, calling
ini_set('default_charset', 'UTF-8') in one request causes the
effective HTTP input encoding candidates to change for subsequent requests handled by the same
process.
The INI value remains auto, but mb_http_input('I') returns only
EUC-JP, and UTF-8 POST data is corrupted.
### Reproduction
PHP must have mbstring enabled.
Save the following configuration as php.ini:
```ini
default_charset = EUC-JP
input_encoding = ""
mbstring.language = Japanese
mbstring.encoding_translation = On
mbstring.http_input = auto
mbstring.internal_encoding = EUC-JP
display_errors = stderr
error_reporting = E_ALL & ~E_DEPRECATED
```
Save the following code as index.php:
```php
<?php
header('Content-Type: application/json; charset=UTF-8');
echo json_encode([
'pid' => getmypid(),
'default_charset' => ini_get('default_charset'),
'http_input_ini' => ini_get('mbstring.http_input'),
'candidates' => mb_http_input('I'),
'detected_post' => mb_http_input('P'),
'post_hex' => bin2hex($_POST['text'] ?? ''),
], JSON_UNESCAPED_SLASHES), "\n";
if (isset($_GET['change'])) {
ini_set('default_charset', 'UTF-8');
}
```
Start a fresh built-in server from the directory containing these files:
```sh
unset PHP_CLI_SERVER_WORKERS
php -c ./php.ini -S 127.0.0.1:18983 -t .
```
In another terminal, send the following two requests in order. Both send the same UTF-8 string,
日本語テスト. The first request changes default_charset after
printing the initial state.
```sh
body='text=%E6%97%A5%E6%9C%AC%E8%AA%9E%E3%83%86%E3%82%B9%E3%83%88'
curl --data "$body" 'http://127.0.0.1:18983/index.php?change=1'
curl --data "$body" 'http://127.0.0.1:18983/index.php'
```
### Actual output
```text
{"pid":7,"default_charset":"EUC-JP","http_input_ini":"auto","candidates":["ASCII","JIS","UTF-8","EUC-JP","SJIS"],"detected_post":"UTF-8","post_hex":"c6fccbdcb8eca5c6a5b9a5c8"}
{"pid":7,"default_charset":"EUC-JP","http_input_ini":"auto","candidates":["EUC-JP"],"detected_post":"EUC-JP","post_hex":"3fa5e63f3f3f3f3f3fb9e33f3f"}
```
PID values may differ, but both requests must be handled by the same PID.
The second request has the original default_charset and still reports
mbstring.http_input=auto. However, its effective candidate list contains only
EUC-JP. The converted POST value contains replacement characters (3f, or
?).
### Expected output
The second request should retain the explicitly configured input candidates and convert the POST
value correctly, just as the first request does:
```text
{"pid":7,"default_charset":"EUC-JP","http_input_ini":"auto","candidates":["ASCII","JIS","UTF-8","EUC-JP","SJIS"],"detected_post":"UTF-8","post_hex":"c6fccbdcb8eca5c6a5b9a5c8"}
```
### Additional verification
The same behavior was reproduced in Docker with:
- PHP 8.2.35, 8.3.36, 8.4.27, and 8.5.12, using both the built-in server and FPM with a single
worker.
- PHP 7.4.0, using the built-in server.
It was not reproduced with PHP 7.3.33 using the built-in server.
Adding input_encoding=auto to php.ini prevents the corruption in these
tests. Explicitly listing the five encodings in mbstring.http_input does not prevent
it.
### Suspected cause
The relevant hook and flags were introduced in commit:
https://github.com/php/php-src/commit/f73f190c3f97479f735b97c22a8e4885344edca1
PHP_RSHUTDOWN_FUNCTION(mbstring) clears http_input_set before modified INI
settings are restored. Restoring default_charset then invokes
mbstring_internal_encoding_changed_hook(), which rebuilds the persistent HTTP input
list from php_get_input_encoding().
With an empty input_encoding, this returns EUC-JP.
The next request does not restore the explicitly configured mbstring.http_input
candidate list.
This reproducer requires sequential HTTP requests handled by the same process, rather than a single
CLI execution.
### PHP Version
```plain
PHP Version
PHP 8.5.12 (cli) (built: Oct 21 2026 15:48:53) (NTS)
Copyright (c) The PHP Group
Built by https://github.com/docker-library/php
Zend Engine v4.5.12, Copyright (c) Zend Technologies
with Zend OPcache v8.5.12, Copyright (c), by Zend Technologies
```
### Operating System
Debian GNU/Linux 13 (trixie), Docker image php:8.5.12-cli, x86_64d