Case-insensitive substr_compare, ksort, krsort are still locale-dependent
維護者通常 1 天內回覆
評估
研究方向
從 php-src 中 substr_compare() 對 zend_binary_strncasecmp_l() 的呼叫,以及不區分大小寫的陣列鍵比較器 php_array_key_compare_string_case_unstable_i() 開始;issue 指出了這兩個進入點和替代比較函式。檢查 substr_compare()、ksort() 和 krsort() 搭配 SORT_STRING | SORT_FLAG_CASE 的現有測試,接著為土耳其語地區設定新增迴歸測試。完成條件是這些案例符合所述的 ASCII 不區分大小寫行為,且現有測試通過。
由索引模型根據 Issue 內容生成。
描述
Description
The following code:
<?php
foreach (['C', 'tr_TR.UTF-8'] as $locale) {
if (setlocale(LC_CTYPE, $locale) === false) {
throw new RuntimeException("Locale unavailable: $locale");
}
$values = ['I', 'h'];
sort($values, SORT_STRING | SORT_FLAG_CASE);
$keys = ['I' => 0, 'h' => 0];
ksort($keys, SORT_STRING | SORT_FLAG_CASE);
echo $locale, "\n";
echo ' stripos: ', var_export(stripos('I', 'i'), true), "\n";
echo ' strncasecmp: ', strncasecmp('I', 'i', 1), "\n";
echo ' substr_compare: ', substr_compare('I', 'i', 0, 1, true), "\n";
echo ' sort: ', implode(',', $values), "\n";
echo ' ksort: ', implode(',', array_keys($keys)), "\n";
}
Resulted in this output:
C
stripos: 0
strncasecmp: 0
substr_compare: 0
sort: h,I
ksort: h,I
tr_TR.UTF-8
stripos: 0
strncasecmp: 0
substr_compare: -32
sort: h,I
ksort: I,h
But I expected this output instead:
C
stripos: 0
strncasecmp: 0
substr_compare: 0
sort: h,I
ksort: h,I
tr_TR.UTF-8
stripos: 0
strncasecmp: 0
substr_compare: 0
sort: h,I
ksort: h,I
PHP 8.2 switched strtolower(), stripos(), sort() with SORT_STRING | SORT_FLAG_CASE # and related functions to ASCII case conversion, but substr_compare() with $case_insensitive = true and ksort()/krsort() with SORT_STRING | SORT_FLAG_CASE still follow LC_CTYPE.
The output above is from PHP 8.2.35, 8.3.36, 8.4.27 and 8.5.12. PHP 8.1.34 prints the same, except that stripos() and sort() also follow the locale (false and I,h). 8.2 changed those two but not substr_compare() or ksort().
Reproducing on PHP 8.1 to 8.5 with Docker
The official php:*-cli images have no tr_TR.UTF-8 locale, so each run generates it first. With the snippet above saved as repro.php:
for v in 8.1 8.2 8.3 8.4 8.5; do
docker run --rm -i "php:$v-cli" sh -c '
apt-get update -qq >/dev/null &&
apt-get install -y -qq locales >/dev/null 2>&1 &&
localedef -i tr_TR -f UTF-8 tr_TR.UTF-8 &&
php -v | head -n 1 &&
php' < repro.php
done
The 8.2 UPGRADING notes say sorting with SORT_FLAG_CASE uses ASCII case conversion, and the strtolower-ascii RFC says case-insensitive substr_compare() already did.
On master, substr_compare() calls zend_binary_strncasecmp_l(), and php_array_key_compare_string_case_unstable_i(), which ksort() and krsort() use, calls zend_binary_strcasecmp_l().
Switching these two call sites to zend_binary_strncasecmp() and zend_binary_strcasecmp() would give the documented behavior.
See https://github.com/php/php-src/pull/7506.
PHP Version
PHP 8.5.12 (cli) (built: Oct 21 2026 15:53:40) (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), glibc 2.41 (php:8.5-cli Docker image)
- 主要語言
- C
- 星號
- 40.7k
- 分支
- 8.3k
- 平均合併
- 2 天 15 小時
- 30 天內合併 PR
- 155
環境準備
- 沒有 Dockerfile 或 Docker Compose 檔案
- 沒有 Pull Request 範本
- 閱讀貢獻指南
從這裡開始
- 先讀完整個 Issue,再讀專案的貢獻指南。
- 在 Issue 下留言說明你要接手 —— 這能避免兩個人做同樣的事。
- Fork 儲存庫,在一個分支上完成修改。
- 送出 Pull Request,並在描述裡引用這個 Issue 編號。
php/php-src 的其他 Issue
-
難度 2/5 1-3 小時 新手友好度 72/100
維護者通常 1 天內回覆
-
HTTP wrapper leaks Location buffer when an empty Location header is followed by another Location header可能已有人在做 @bercedev 於 2 天前認領。 未關閉Bug Category: Streams Status: Verified
難度 2/5 1-3 小時 新手友好度 78/100
維護者通常 1 天內回覆
-
`Time\Duration::__unserialize()` accepts a "negative zero" payload.可能已有人在做 @TimWolla 今天認領。 未關閉Bug Status: Needs Triage
難度 2/5 1-3 小時 新手友好度 71/100
php/php-src#24505 · 2 則留言 · 已指派 1 人 ·
維護者通常 1 天內回覆
-
master: part of the mbstring bailout fix got lost in a merge可能已有人在做 @lazerg 於 2 天前認領。 未關閉
難度 2/5 1-3 小時 新手友好度 78/100
維護者通常 1 天內回覆
-
Bug Status: Needs Triage
難度 2/5 1-3 小時 新手友好度 64/100
維護者通常 1 天內回覆
相似的 Issue
-
category:port-update
難度 2/5 1-3 小時 新手友好度 66/100
維護者通常 2 天內回覆
-
emerge failure MARK mark-unstable media-kit
難度 2/5 1-3 小時 新手友好度 82/100
macaroni-os/mark-issues#834 ·
-
難度 2/5 1-3 小時 新手友好度 76/100
NVIDIA/open-gpu-kernel-modules#1479 · 2 則留言 ·
維護者通常 1 天內回覆
-
難度 2/5 1-3 小時 新手友好度 76/100
-
難度 1/5 1 小時以內 新手友好度 93/100
webarkit/WebARKitLib#107 ·
維護者通常 1 天內回覆