Skip to content

Commit

Permalink
Fix phpGH-9296: ksort behaves incorrectly on arrays with string and…
Browse files Browse the repository at this point in the history
… numeric keys

The comparator function used at ksort in SORT_REGULAR mode
need to be consistent with basic comparison rules. These rules
were changed in PHP-8.0 for numeric strings, but comparator
used at ksort kept the old behaviour. It leads to inconsistent
situations, when after ksort the first key is GREATER than some
of the next ones by according to the basic comparison operators.
  • Loading branch information
DrDet committed Aug 11, 2022
1 parent 8aeae63 commit 10c2160
Showing 1 changed file with 14 additions and 34 deletions.
48 changes: 14 additions & 34 deletions ext/standard/array.c
Original file line number Diff line number Diff line change
Expand Up @@ -166,40 +166,20 @@ static zend_never_inline ZEND_COLD int stable_sort_fallback(Bucket *a, Bucket *b

static zend_always_inline int php_array_key_compare_unstable_i(Bucket *f, Bucket *s) /* {{{ */
{
zend_uchar t;
zend_long l1, l2;
double d;

if (f->key == NULL) {
if (s->key == NULL) {
return (zend_long)f->h > (zend_long)s->h ? 1 : -1;
} else {
l1 = (zend_long)f->h;
t = is_numeric_string(s->key->val, s->key->len, &l2, &d, 1);
if (t == IS_LONG) {
/* pass */
} else if (t == IS_DOUBLE) {
return ZEND_NORMALIZE_BOOL((double)l1 - d);
} else {
l2 = 0;
}
}
} else {
if (s->key) {
return zendi_smart_strcmp(f->key, s->key);
} else {
l2 = (zend_long)s->h;
t = is_numeric_string(f->key->val, f->key->len, &l1, &d, 1);
if (t == IS_LONG) {
/* pass */
} else if (t == IS_DOUBLE) {
return ZEND_NORMALIZE_BOOL(d - (double)l2);
} else {
l1 = 0;
}
}
}
return ZEND_NORMALIZE_BOOL(l1 - l2);
zval first;
zval second;

if (f->key) {
ZVAL_STR(&first, f->key);
} else {
ZVAL_LONG(&first, f->h);
}
if (s->key) {
ZVAL_STR(&second, s->key);
} else {
ZVAL_LONG(&second, s->h);
}
return zend_compare(&first, &second);
}
/* }}} */

Expand Down

0 comments on commit 10c2160

Please sign in to comment.