Hacktoberfest 2026: as issues que os mantenedores marcaram para outubro, abertas e boas para iniciantes. Ver issues do Hacktoberfest

Case-insensitive substr_compare, ksort, krsort are still locale-dependent

Aberta Para iniciantes
#24,552 1 comentário 0 reações 0 responsáveis Ver no GitHub

Mantenedores costumam responder em até 1 dia

@lazerg já está trabalhando nisso.

Desde 22/10/2026.

  • #24558 de @lazerg — aberto
  • #24559 de @sirreal — aberto

Avaliação

Dificuldade
2/5
Tempo estimado
1-3 horas
Facilidade para iniciantes
73/100
Tipo de issue
Bug
Clareza
Claramente especificada
Status de atividade
Ativa
Stack de tecnologia
c, php
Domínio
backend, testing

Direção de pesquisa

Comece pela chamada de substr_compare() a zend_binary_strncasecmp_l() e pelo comparador de chaves de array que não diferencia maiúsculas de minúsculas php_array_key_compare_string_case_unstable_i() no php-src; a issue identifica ambos os pontos de entrada e as funções de comparação substitutas. Confira os testes existentes de substr_compare(), ksort() e krsort() com SORT_STRING | SORT_FLAG_CASE e, em seguida, adicione testes de regressão para a localidade turca. O trabalho estará concluído quando esses casos corresponderem ao comportamento ASCII descrito, que não diferencia maiúsculas de minúsculas, e os testes existentes passarem.

Escrita pelo modelo de indexação a partir do texto da issue.

Descrição

Bug Status: Needs Triage
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

Reproduction link


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)

Linguagem predominante
C
Estrelas
40.7k
Forks
8.3k
Merge médio
2d 15h
PRs com merge (30d)
155

Preparar o ambiente

Primeiros passos

  1. Leia a issue inteira e depois o guia de contribuição do projeto.
  2. Comente na issue dizendo que vai assumir — evita que duas pessoas façam o mesmo trabalho.
  3. Faça um fork do repositório e trabalhe em uma branch.
  4. Abra um pull request que referencie o número da issue.

Mais de php/php-src

Todas as issues de php/php-src

Issues semelhantes

Mais issues de C

Receba novas issues na sua caixa de entrada

Um resumo curto de issues do GitHub para quem está começando.