php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #71334 Cannot access array keys while uksort()
Submitted: 2016-01-11 11:03 UTC Modified: 2016-02-22 12:55 UTC
Votes:2
Avg. Score:4.0 ± 1.0
Reproduced:2 of 2 (100.0%)
Same Version:2 (100.0%)
Same OS:0 (0.0%)
From: alex dot schneider at sevenval dot com Assigned: laruence
Status: Closed Package: Arrays related
PHP Version: 7.0.2 OS: Linux Mint 17.3
Private report: No CVE-ID:
 [2016-01-11 11:03 UTC] alex dot schneider at sevenval dot com
Description:
------------
Cannot access array keys while uksort().

Sorry for my English...

Test script:
---------------
<?php

class myClass
{
	private $a = [
		'foo-test' => [1],
		'-' => [2],
		'bar-test' => [3]
	];

	private function _mySort($x, $y)
	{
		if (!isset($this->a[$x])) {
			throw new Exception('Missing X: "' . $x . '"');
		}

		if (!isset($this->a[$y])) {
			throw new Exception('Missing Y: "' . $y . '"');
		}

		return $x < $y;
	}

	public function __construct()
	{
		uksort($this->a, [$this, '_mySort']);
	}
}

new myClass();

Expected result:
----------------
No Exceptions

Actual result:
--------------
Exception:

PHP Fatal error:  Uncaught Exception: Missing Y: "bar-test" in ...

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2016-01-12 15:37 UTC] nikic@php.net
-Assigned To: +Assigned To: laruence
 [2016-01-12 15:37 UTC] nikic@php.net
The problem is that we're doing the sort in-place, so any access to the array during the sort will see it in an inconsistent state. I don't see any way to solve this problem without requiring the array to always be duplicated before sorts with user-defined callbacks.

Here's a patch to implement this: https://github.com/nikic/php-src/commit/703fed650319f9e2d78e2dc2cafb422e558c5841 It also removes the array modification check, as it's no longer relevant after this change.

@laruence: You worked on the sorting functionality, do you see a way to fix this in any other way?
 [2016-01-12 16:36 UTC] nikic@php.net
It looks like ArrayObject relies on sorting functions not to duplicate the array for the rc=1 case, so this will need some more work :(
 [2016-01-13 06:36 UTC] laruence@php.net
hmm, we could also adjust arHash after swap, but it must not be a simple patch..

thanks
 [2016-01-13 16:15 UTC] jsgoupil at gmail dot com
I have the same problem, I am able to access the values, but the sorting is not correct.

<?php
function cmp($a, $b)
{
    $x = $GLOBALS['x'];
    
    $v1 = $x[$a];
    $v2 = $x[$b];
    if ($v1 < $v2) {
        return -1;
    } elseif ($v1 > $v2) {
        return 1;
    } else {
        // Would then sort by key, irrelevant here.
    }
}

$x = array(1 => 1, 2 => 3, 3 => 2);
uksort($x, 'cmp');
var_dump($x);

// PHP5
array(3) { [1]=> int(1) [3]=> int(2) [2]=> int(3) }

// PHP7
array(3) { [3]=> int(2) [2]=> int(3) [1]=> int(1) }


Let me know if you want me to open another bug instead.
 [2016-02-22 12:55 UTC] nikic@php.net
New patch that resolves the ArrayObject issue: https://github.com/nikic/php-src/commit/73e6c257abc9ad5a5aef6b91a2238e941b2045d5
 [2016-03-30 20:50 UTC] nikic@php.net
Automatic comment on behalf of nikic
Revision: http://git.php.net/?p=php-src.git;a=commit;h=b1e854f7762b2e0648ddc240835cb446ee4d20a7
Log: Fix bug #71334
 [2016-03-30 20:50 UTC] nikic@php.net
-Status: Assigned +Status: Closed
 [2016-07-20 11:32 UTC] davey@php.net
Automatic comment on behalf of nikic
Revision: http://git.php.net/?p=php-src.git;a=commit;h=b1e854f7762b2e0648ddc240835cb446ee4d20a7
Log: Fix bug #71334
 
PHP Copyright © 2001-2017 The PHP Group
All rights reserved.
Last updated: Wed Feb 22 15:01:37 2017 UTC