php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #66544 uasort works incorrent in some cases
Submitted: 2014-01-22 14:11 UTC Modified: 2014-01-22 18:46 UTC
From: korovkin dot kirill at gmail dot com Assigned:
Status: Not a bug Package: *General Issues
PHP Version: 5.4.24 OS: Linux 2.6.32-042stab07
Private report: No CVE-ID: None
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: korovkin dot kirill at gmail dot com
New email:
PHP Version: OS:

 

 [2014-01-22 14:11 UTC] korovkin dot kirill at gmail dot com
Description:
------------
You can see all information in the test script.

Test script:
---------------
$inputArray = array(
	'shipping' => array(
		'after' => array(),
		'before' => array(),
		'_code' => 'shipping'
	),
	'freeshipping' => array(
		'after' => array(),
		'before' => array(),
		'_code' => 'freeshipping'
	),
	'discount' => array(
		'after' => array('shipping', 'tax_shipping'),
		'before' => array(),
		'_code' => 'discount'
	),
	'tax_shipping' => array(
		'after' => array('shipping'),
		'before' => array('discount'),
		'_code' => 'tax_shipping'
	)
);

function compare ($a, $b) {
	$aCode = $a['_code'];
	$bCode = $b['_code'];
	if (in_array($aCode, $b['after']) || in_array($bCode, $a['before'])) {
		$res = -1;
	} elseif (in_array($bCode, $a['after']) || in_array($aCode, $b['before'])) {
		$res = 1;
	} else {
		$res = 0;
	}
	return $res;
}

uasort($inputArray, 'compare');
var_dump(array_keys($inputArray));

Expected result:
----------------
array (size=4)
  0 => string 'shipping' (length=8)
  1 => string 'tax_shipping' (length=12)
  2 => string 'discount' (length=8)
  3 => string 'freeshipping' (length=12)

Or another position for 'freeshipping'. But 'shipping' must be before 'tax_shipping' and 'discount' must be after 'tax_shipping'.

Actual result:
--------------
array (size=4)
  0 => string 'tax_shipping' (length=12)
  1 => string 'discount' (length=8)
  2 => string 'freeshipping' (length=12)
  3 => string 'shipping' (length=8)

Patches

Pull Requests

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2014-01-22 18:38 UTC] mail at requinix dot net
Looks like undefined behavior to me: your comparison function claims that discount == freeshipping and tax_shipping == freeshipping, yet tax_shipping < discount.
Pick an unambiguous place for freeshipping to go, update the arrays so that your function can definitively state the sort order for every pairing, and it will sort correctly. Besides, allowing freeshipping to land wherever the sort happens to place it doesn't sound like a good idea.
 [2014-01-22 18:46 UTC] rasmus@php.net
-Status: Open +Status: Not a bug
 [2014-01-22 18:46 UTC] rasmus@php.net
Yup, the logic is wrong here. The sort function will compare them in this order:

a = freeshipping, b = shipping
a = tax_shipping, b = freeshipping
a = discount, b = freeshipping
a = tax_shipping, b = discount

If you go through it one by one you will see that the first 3 checks all return 0, only the tax_shipping vs. discount is going to return -1 so those two elements are the only two affected.
 
PHP Copyright © 2001-2026 The PHP Group
All rights reserved.
Last updated: Wed Oct 07 12:00:02 2026 UTC