Skip to content

Commit 1094a85

Browse files
committed
Merge branch 'PHP-8.1'
* PHP-8.1: Fix GH-9296: `ksort` behaves incorrectly on arrays with mixed keys
2 parents 0028c24 + 7908aae commit 1094a85

File tree

7 files changed

+86
-84
lines changed

7 files changed

+86
-84
lines changed

ext/standard/array.c

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -166,40 +166,25 @@ static zend_never_inline ZEND_COLD int stable_sort_fallback(Bucket *a, Bucket *b
166166

167167
static zend_always_inline int php_array_key_compare_unstable_i(Bucket *f, Bucket *s) /* {{{ */
168168
{
169-
zend_uchar t;
170-
zend_long l1, l2;
171-
double d;
172-
173-
if (f->key == NULL) {
174-
if (s->key == NULL) {
175-
return (zend_long)f->h > (zend_long)s->h ? 1 : -1;
176-
} else {
177-
l1 = (zend_long)f->h;
178-
t = is_numeric_string(s->key->val, s->key->len, &l2, &d, 1);
179-
if (t == IS_LONG) {
180-
/* pass */
181-
} else if (t == IS_DOUBLE) {
182-
return ZEND_NORMALIZE_BOOL((double)l1 - d);
183-
} else {
184-
l2 = 0;
185-
}
186-
}
187-
} else {
188-
if (s->key) {
189-
return zendi_smart_strcmp(f->key, s->key);
190-
} else {
191-
l2 = (zend_long)s->h;
192-
t = is_numeric_string(f->key->val, f->key->len, &l1, &d, 1);
193-
if (t == IS_LONG) {
194-
/* pass */
195-
} else if (t == IS_DOUBLE) {
196-
return ZEND_NORMALIZE_BOOL(d - (double)l2);
197-
} else {
198-
l1 = 0;
199-
}
200-
}
201-
}
202-
return ZEND_NORMALIZE_BOOL(l1 - l2);
169+
zval first;
170+
zval second;
171+
172+
if (f->key == NULL && s->key == NULL) {
173+
return (zend_long)f->h > (zend_long)s->h ? 1 : -1;
174+
} else if (f->key && s->key) {
175+
return zendi_smart_strcmp(f->key, s->key);
176+
}
177+
if (f->key) {
178+
ZVAL_STR(&first, f->key);
179+
} else {
180+
ZVAL_LONG(&first, f->h);
181+
}
182+
if (s->key) {
183+
ZVAL_STR(&second, s->key);
184+
} else {
185+
ZVAL_LONG(&second, s->h);
186+
}
187+
return zend_compare(&first, &second);
203188
}
204189
/* }}} */
205190

ext/standard/tests/array/002.phpt

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -276,6 +276,8 @@ array(8) {
276276
-- Testing krsort() --
277277
No second argument:
278278
array(8) {
279+
["test"]=>
280+
int(27)
279281
[16777216]=>
280282
float(-0.3333333333333333)
281283
[1001]=>
@@ -288,8 +290,6 @@ array(8) {
288290
string(4) "Test"
289291
[0]=>
290292
string(3) "PHP"
291-
["test"]=>
292-
int(27)
293293
[-1000]=>
294294
array(2) {
295295
[0]=>
@@ -300,6 +300,8 @@ array(8) {
300300
}
301301
Using SORT_REGULAR:
302302
array(8) {
303+
["test"]=>
304+
int(27)
303305
[16777216]=>
304306
float(-0.3333333333333333)
305307
[1001]=>
@@ -312,8 +314,6 @@ array(8) {
312314
string(4) "Test"
313315
[0]=>
314316
string(3) "PHP"
315-
["test"]=>
316-
int(27)
317317
[-1000]=>
318318
array(2) {
319319
[0]=>
@@ -334,10 +334,10 @@ array(8) {
334334
string(27) "PHP: Hypertext Preprocessor"
335335
[5]=>
336336
string(4) "Test"
337-
[0]=>
338-
string(3) "PHP"
339337
["test"]=>
340338
int(27)
339+
[0]=>
340+
string(3) "PHP"
341341
[-1000]=>
342342
array(2) {
343343
[0]=>
@@ -383,8 +383,6 @@ array(8) {
383383
}
384384
[0]=>
385385
string(3) "PHP"
386-
["test"]=>
387-
int(27)
388386
[5]=>
389387
string(4) "Test"
390388
[17]=>
@@ -395,6 +393,8 @@ array(8) {
395393
string(6) "monkey"
396394
[16777216]=>
397395
float(-0.3333333333333333)
396+
["test"]=>
397+
int(27)
398398
}
399399
Using SORT_REGULAR:
400400
array(8) {
@@ -407,8 +407,6 @@ array(8) {
407407
}
408408
[0]=>
409409
string(3) "PHP"
410-
["test"]=>
411-
int(27)
412410
[5]=>
413411
string(4) "Test"
414412
[17]=>
@@ -419,6 +417,8 @@ array(8) {
419417
string(6) "monkey"
420418
[16777216]=>
421419
float(-0.3333333333333333)
420+
["test"]=>
421+
int(27)
422422
}
423423
Using SORT_NUMERIC:
424424
array(8) {

ext/standard/tests/array/gh9296.phpt

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
--TEST--
2+
GH-9296: incorrect ksort(..., SORT_REGULAR) behaviour on arrays with numeric and string keys
3+
--FILE--
4+
<?php
5+
$array = ["aaa" => 0, 600 => 1];
6+
ksort($array, SORT_REGULAR);
7+
var_dump($array);
8+
var_dump(array_key_first($array) <=> array_key_last($array));
9+
?>
10+
--EXPECT--
11+
array(2) {
12+
[600]=>
13+
int(1)
14+
["aaa"]=>
15+
int(0)
16+
}
17+
int(-1)

ext/standard/tests/array/krsort_variation8.phpt

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,6 @@ echo "Done\n";
4141
-- Testing krsort() by supplying mixed value array, 'flag' value is default --
4242
bool(true)
4343
array(13) {
44-
[5]=>
45-
string(1) "5"
46-
[4]=>
47-
float(4.01)
4844
["b"]=>
4945
string(1) "b"
5046
["array2"]=>
@@ -85,23 +81,23 @@ array(13) {
8581
string(2) "ab"
8682
["True"]=>
8783
string(4) "True"
84+
[5]=>
85+
string(1) "5"
86+
[4]=>
87+
float(4.01)
8888
[0]=>
8989
float(0.001)
9090
["-.9"]=>
9191
string(3) "-.9"
92-
[""]=>
93-
string(0) ""
9492
[-2]=>
9593
float(-2.98989)
94+
[""]=>
95+
string(0) ""
9696
}
9797

9898
-- Testing krsort() by supplying mixed value array, 'flag' value is SORT_REGULAR --
9999
bool(true)
100100
array(13) {
101-
[5]=>
102-
string(1) "5"
103-
[4]=>
104-
float(4.01)
105101
["b"]=>
106102
string(1) "b"
107103
["array2"]=>
@@ -142,13 +138,17 @@ array(13) {
142138
string(2) "ab"
143139
["True"]=>
144140
string(4) "True"
141+
[5]=>
142+
string(1) "5"
143+
[4]=>
144+
float(4.01)
145145
[0]=>
146146
float(0.001)
147147
["-.9"]=>
148148
string(3) "-.9"
149-
[""]=>
150-
string(0) ""
151149
[-2]=>
152150
float(-2.98989)
151+
[""]=>
152+
string(0) ""
153153
}
154154
Done

ext/standard/tests/array/krsort_variation9.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -82,22 +82,22 @@ array(5) {
8282
- With default sort flag -
8383
bool(true)
8484
array(3) {
85+
["c"]=>
86+
string(5) "apple"
8587
["a"]=>
8688
string(6) "orange"
8789
[0]=>
8890
string(6) "banana"
89-
["c"]=>
90-
string(5) "apple"
9191
}
9292
- Sort flag = SORT_REGULAR -
9393
bool(true)
9494
array(3) {
95+
["c"]=>
96+
string(5) "apple"
9597
["a"]=>
9698
string(6) "orange"
9799
[0]=>
98100
string(6) "banana"
99-
["c"]=>
100-
string(5) "apple"
101101
}
102102

103103
-- Iteration 3 --

ext/standard/tests/array/ksort_variation8.phpt

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -40,18 +40,26 @@ echo "Done\n";
4040
-- Testing ksort() by supplying mixed value array, 'flag' value is default --
4141
bool(true)
4242
array(13) {
43-
[-2]=>
44-
float(-2.98989)
4543
[""]=>
4644
string(0) ""
45+
[-2]=>
46+
float(-2.98989)
4747
["-.9"]=>
4848
string(3) "-.9"
49+
[0]=>
50+
float(0.001)
51+
[4]=>
52+
float(4.01)
53+
[5]=>
54+
string(1) "5"
4955
["True"]=>
5056
string(4) "True"
5157
["ab"]=>
5258
string(2) "ab"
5359
["abcd"]=>
5460
string(4) "abcd"
61+
["abcd%0abcd%0abcd"]=>
62+
string(14) "abcd%0abcd%0abcd"
5563
["array1"]=>
5664
array(0) {
5765
}
@@ -84,31 +92,31 @@ array(13) {
8492
}
8593
["b"]=>
8694
string(1) "b"
87-
[0]=>
88-
float(0.001)
89-
["abcd%0abcd%0abcd"]=>
90-
string(14) "abcd%0abcd%0abcd"
91-
[4]=>
92-
float(4.01)
93-
[5]=>
94-
string(1) "5"
9595
}
9696

9797
-- Testing ksort() by supplying mixed value array, 'flag' value is SORT_REGULAR --
9898
bool(true)
9999
array(13) {
100-
[-2]=>
101-
float(-2.98989)
102100
[""]=>
103101
string(0) ""
102+
[-2]=>
103+
float(-2.98989)
104104
["-.9"]=>
105105
string(3) "-.9"
106+
[0]=>
107+
float(0.001)
108+
[4]=>
109+
float(4.01)
110+
[5]=>
111+
string(1) "5"
106112
["True"]=>
107113
string(4) "True"
108114
["ab"]=>
109115
string(2) "ab"
110116
["abcd"]=>
111117
string(4) "abcd"
118+
["abcd%0abcd%0abcd"]=>
119+
string(14) "abcd%0abcd%0abcd"
112120
["array1"]=>
113121
array(0) {
114122
}
@@ -141,13 +149,5 @@ array(13) {
141149
}
142150
["b"]=>
143151
string(1) "b"
144-
[0]=>
145-
float(0.001)
146-
["abcd%0abcd%0abcd"]=>
147-
string(14) "abcd%0abcd%0abcd"
148-
[4]=>
149-
float(4.01)
150-
[5]=>
151-
string(1) "5"
152152
}
153153
Done

ext/standard/tests/array/ksort_variation9.phpt

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,20 +81,20 @@ array(5) {
8181
- With default sort flag -
8282
bool(true)
8383
array(3) {
84-
["a"]=>
85-
string(6) "orange"
8684
[0]=>
8785
string(6) "banana"
86+
["a"]=>
87+
string(6) "orange"
8888
["c"]=>
8989
string(5) "apple"
9090
}
9191
- Sort flag = SORT_REGULAR -
9292
bool(true)
9393
array(3) {
94-
["a"]=>
95-
string(6) "orange"
9694
[0]=>
9795
string(6) "banana"
96+
["a"]=>
97+
string(6) "orange"
9898
["c"]=>
9999
string(5) "apple"
100100
}

0 commit comments

Comments
 (0)