Skip to content

Commit 063c3c8

Browse files
committed
Correctly compare 0 and -0 (#17051)
Fixes #17049 Closes #17051
1 parent c192a34 commit 063c3c8

File tree

5 files changed

+98
-1
lines changed

5 files changed

+98
-1
lines changed

NEWS

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ PHP NEWS
22
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
33
?? ??? ????, PHP 8.4.3
44

5+
- BcMath:
6+
. Fixed bug GH-17049 (Correctly compare 0 and -0). (Saki Takamachi)
7+
58
- Iconv:
69
. Fixed bug GH-17047 (UAF on iconv filter failure). (nielsdos)
710

@@ -12,7 +15,7 @@ PHP NEWS
1215
05 Dec 2024, PHP 8.4.2
1316

1417
- BcMath:
15-
. Fixed bug GH-16978 (Avoid unnecessary padding with leading zeros)
18+
. Fixed bug GH-16978 (Avoid unnecessary padding with leading zeros).
1619
(Saki Takamachi)
1720

1821
- COM:

ext/bcmath/libbcmath/src/compare.c

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,18 @@ bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, size_t scale, bool us
4545

4646
/* First, compare signs. */
4747
if (use_sign && n1->n_sign != n2->n_sign) {
48+
/*
49+
* scale and n->n_scale differ only in Number objects.
50+
* This happens when explicitly specify the scale in a Number method.
51+
*/
52+
if ((n1->n_scale > scale || n2->n_scale > scale) &&
53+
n1->n_len == 1 && n2->n_len == 1 &&
54+
n1->n_value[0] == 0 && n2->n_value[0] == 0 &&
55+
bc_is_zero_for_scale(n1, scale) && bc_is_zero_for_scale(n2, scale)
56+
) {
57+
/* e.g. 0.00 <=> -0.00 */
58+
return BCMATH_EQUAL;
59+
}
4860
if (n1->n_sign == PLUS) {
4961
/* Positive N1 > Negative N2 */
5062
return BCMATH_LEFT_GREATER;

ext/bcmath/libbcmath/src/str2num.c

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -173,6 +173,15 @@ bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, siz
173173
if (str_scale > scale && !auto_scale) {
174174
fractional_end -= str_scale - scale;
175175
str_scale = scale;
176+
177+
/*
178+
* e.g. 123.0001 with scale 2 -> 123.00
179+
* So, remove the trailing 0 again.
180+
*/
181+
if (str_scale > 0) {
182+
const char *fractional_new_end = bc_skip_zero_reverse(fractional_end, fractional_ptr);
183+
str_scale -= fractional_new_end - fractional_end;
184+
}
176185
}
177186
} else {
178187
if (full_scale) {

ext/bcmath/tests/bccomp_variation002.phpt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ echo bccomp("-2.29", "2.3", "2") . "\n";
1313
echo bccomp("2.29", "-2.3", "2") . "\n";
1414
echo bccomp("-2.29", "-2.3", "1") . "\n";
1515
echo bccomp("-2.29", "0", "1") . "\n";
16+
echo bccomp("0.001", "-0.001", "1") . "\n";
1617
?>
1718
--EXPECT--
1819
0
@@ -22,3 +23,4 @@ echo bccomp("-2.29", "0", "1") . "\n";
2223
1
2324
1
2425
-1
26+
0
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
--TEST--
2+
BcMath\Number compare() with scale
3+
--EXTENSIONS--
4+
bcmath
5+
--FILE--
6+
<?php
7+
8+
$values1 = [
9+
new BcMath\Number('0.001'),
10+
new BcMath\Number('-0.001'),
11+
];
12+
13+
$values2 = [
14+
0,
15+
-0,
16+
'0.0011',
17+
'-0.0011',
18+
];
19+
20+
$value1 = new BcMath\Number('0.001');
21+
22+
$scales = [0, 2, 3, 4];
23+
24+
foreach ($scales as $scale) {
25+
echo "========== scale is {$scale} ==========\n";
26+
foreach ($values1 as $value1) {
27+
foreach ($values2 as $value2) {
28+
$output = str_pad("{$value1} <=> {$value2}: ", 20, ' ', STR_PAD_LEFT);
29+
$output .= str_pad((string) $value1->compare($value2, $scale), 2, ' ', STR_PAD_LEFT);
30+
echo "{$output}\n";
31+
}
32+
}
33+
}
34+
?>
35+
--EXPECT--
36+
========== scale is 0 ==========
37+
0.001 <=> 0: 0
38+
0.001 <=> 0: 0
39+
0.001 <=> 0.0011: 0
40+
0.001 <=> -0.0011: 0
41+
-0.001 <=> 0: 0
42+
-0.001 <=> 0: 0
43+
-0.001 <=> 0.0011: 0
44+
-0.001 <=> -0.0011: 0
45+
========== scale is 2 ==========
46+
0.001 <=> 0: 0
47+
0.001 <=> 0: 0
48+
0.001 <=> 0.0011: 0
49+
0.001 <=> -0.0011: 0
50+
-0.001 <=> 0: 0
51+
-0.001 <=> 0: 0
52+
-0.001 <=> 0.0011: 0
53+
-0.001 <=> -0.0011: 0
54+
========== scale is 3 ==========
55+
0.001 <=> 0: 1
56+
0.001 <=> 0: 1
57+
0.001 <=> 0.0011: 0
58+
0.001 <=> -0.0011: 1
59+
-0.001 <=> 0: -1
60+
-0.001 <=> 0: -1
61+
-0.001 <=> 0.0011: -1
62+
-0.001 <=> -0.0011: 0
63+
========== scale is 4 ==========
64+
0.001 <=> 0: 1
65+
0.001 <=> 0: 1
66+
0.001 <=> 0.0011: -1
67+
0.001 <=> -0.0011: 1
68+
-0.001 <=> 0: -1
69+
-0.001 <=> 0: -1
70+
-0.001 <=> 0.0011: -1
71+
-0.001 <=> -0.0011: 1

0 commit comments

Comments
 (0)