php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #81556 ksort generate different results with the same keys in two arrays
Submitted: 2021-10-26 15:38 UTC Modified: 2021-11-04 17:30 UTC
From: friedrich dot lucas at os-cillation dot de Assigned:
Status: Not a bug Package: Arrays related
PHP Version: 8.0.12 OS: Ubuntu 18.04.6 LTS
Private report: No CVE-ID: None
View Add Comment Developer Edit
Anyone can comment on a bug. Have a simpler test case? Does it work for you on a different platform? Let us know!
Just going to say 'Me too!'? Don't clutter the database with that please !
Your email address:
MUST BE VALID
Solve the problem:
40 - 32 = ?
Subscribe to this entry?

 
 [2021-10-26 15:38 UTC] friedrich dot lucas at os-cillation dot de
Description:
------------
ksort generate different results with the same keys in two arrays under php with the version 8 or higher.

This case do only occurs in special conditions: array element count, '0' for array key must exists.

-----
No specific php setup.

Test script:
---------------
// define arrays with the same keys - different key order ('4' and '@' are swapped)
$array_at = [
    '_' => '', 'Y' => '', '0' => '', '+' => '', 'X' => '', 'W' => '', '1' => '', '3' => '', '@' => '', '4' => '', '5' => '', 'P' => '', 'O' => '', 'N' => '', 'M' => '', 'L' => '', 'K' => '',
];
$array_fr = [
     '_' => '', 'Y' => '', '0' => '', '+' => '', 'X' => '', 'W' => '', '1' => '', '3' => '', '4' => '', '@' => '', '5' => '', 'P' => '', 'O' => '', 'N' => '', 'M' => '', 'L' => '', 'K' => '',
];

ksort($array_at);     // sort by key
ksort($array_fr);     // sort by key

// expects the same key at the sorted array first position
var_dump(array_slice($array_at, 0, 1));  // result: [0 => '''], but only '0' is defined as a key
var_dump(array_slice($array_fr, 0, 1));  // result: ['+' => '' ]

Expected result:
----------------
The same keysort output from array_at and array_fr.

(correct output with php7.x)
array(1) {
  ["+"]=>
  string(0) ""
}
array(1) {
  ["+"]=>
  string(0) ""
}


Actual result:
--------------
(wrong output with php8.x)
array(1) {
  ["+"]=>
  string(0) ""
}
array(1) {
  [0]=>
  string(0) ""
}


Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2021-10-26 17:20 UTC] requinix@php.net
-Status: Open +Status: Not a bug -Package: Unknown/Other Function +Package: Arrays related
 [2021-10-26 17:20 UTC] requinix@php.net
Thank you for taking the time to write to us, but this is not
a bug. Please double-check the documentation available at
http://www.php.net/manual/ and the instructions on how to report
a bug at http://bugs.php.net/how-to-report.php

1. As with the other sorting functions, ksort will sort according to how PHP's standard comparison operations work. Mixing numeric values like "0" or "4" with non-numeric values like "+" or "@" can give unexpected results.
2. Before PHP 8, the order of elements when they compare equal was undefined.

Use the SORT_STRING flag.
https://www.php.net/manual/en/function.ksort.php
https://3v4l.org/D84lS
 [2021-11-04 14:06 UTC] friedrich dot lucas at os-cillation dot de
1. As with the other sorting functions, ksort will sort according to how PHP's standard comparison operations work. Mixing numeric values like "0" or "4" with non-numeric values like "+" or "@" can give unexpected results.

Please double check the bug report. There are no mixed values. All keys was set as strings.

With more or lesser keys the code working. Also with mixed data as string key. Only in this combination will produce this result.
 [2021-11-04 17:30 UTC] requinix@php.net
> There are no mixed values. All keys was set as strings.
I was talking about mixing numeric strings with non-numeric strings. So yes, there are mixed values because one of them is "0".

But even if you say "0" is a string, PHP will translate it to an integer.
https://www.php.net/manual/en/language.types.array.php
https://3v4l.org/dvYgP

But even if PHP did not translate to an integer, ksort() defaults to SORT_REGULAR and that uses PHP's loose comparison rules, and they differentiate between numeric and non-numeric strings.
https://www.php.net/manual/en/language.operators.comparison.php

If you expect ksort() to compare everything as strings then you need to know that (a) it will not do that by default but (b) you can make it do that with the SORT_STRING flag.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 23:01:27 2024 UTC