Case-insensitive substr_compare, ksort, krsort are still locale-dependent
I maintainer di solito rispondono entro 1 giorno
@lazerg ci sta già lavorando.
Dal 22/10/2026.
Valutazione
- Difficoltà
- 2/5
- Tempo stimato
- 1-3 ore
- Idoneità per principianti
- 73/100
Direzione di ricerca
Inizia dalla chiamata di substr_compare() a zend_binary_strncasecmp_l() e dal comparatore di chiavi degli array senza distinzione tra maiuscole e minuscole php_array_key_compare_string_case_unstable_i() in php-src; l’issue identifica entrambi i punti di ingresso e le funzioni di confronto sostitutive. Controlla i test esistenti per substr_compare(), ksort() e krsort() con SORT_STRING | SORT_FLAG_CASE, quindi aggiungi test di regressione per la locale turca. Il lavoro è completato quando questi casi corrispondono al comportamento ASCII descritto, senza distinzione tra maiuscole e minuscole, e i test esistenti passano.
Scritto dal modello di indicizzazione a partire dal testo della issue.
Descrizione
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)
- Lingua principale
- C
- Stelle
- 40.7k
- Fork
- 8.3k
- Merge medio
- 17h 29m
- PR unite (30g)
- 10
Preparare l'ambiente
- Nessun Dockerfile né file Docker Compose
- Nessun modello di pull request
- Leggi la guida per i contributori
Come iniziare
- Leggi tutta la issue e poi la guida ai contributi del progetto.
- Commenta sulla issue per dire che te ne occupi tu — evita che due persone facciano lo stesso lavoro.
- Fai un fork del repository e lavora su un branch.
- Apri una pull request che faccia riferimento al numero della issue.
Altre issue di php/php-src
-
Bug Status: Needs Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Bug Status: Needs Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 71/100
php/php-src#24505 · 2 commenti ·
I maintainer di solito rispondono entro 1 giorno
-
master: part of the mbstring bailout fix got lost in a mergeForse già presa @lazerg l’ha presa 1 giorno fa. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Bug Status: Needs Triage
Difficoltà 2/5 1-3 ore Idoneità per principianti 64/100
I maintainer di solito rispondono entro 1 giorno
-
quoted_printable_encode() produces lines longer than 76 characters for bytes 0xF5 to 0xFFForse già presa Una pull request collegata a questa issue è aperta o già unita. Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 76/100
I maintainer di solito rispondono entro 1 giorno
Issue simili
-
TLS: a stale OpenSSL error makes non-blocking reads fail with "Resource temporarily unavailable"Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
I maintainer di solito rispondono entro 1 giorno
-
Difficoltà 1/5 1-3 ore Idoneità per principianti 82/100
-
Difficoltà 2/5 1-3 ore Idoneità per principianti 84/100
bigtreetech/BIGTREETECH-TouchScreenFirmware#3056 ·
I maintainer di solito rispondono entro 1 giorno
-
Allow pillow 13Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 78/100
-
[pico][astrocade] emu/apply.sh edits src/mame/midway/astrohome.cpp, which current MAME has in bally/Aperta
Difficoltà 2/5 1-3 ore Idoneità per principianti 83/100
FujiNetWIFI/fujinet-firmware#2120 ·
I maintainer di solito rispondono entro 1 giorno