1
0
mirror of https://github.com/php/php-src.git synced 2026-03-24 00:02:20 +01:00

Correctly compare 0 and -0 (#17051)

Fixes #17049
Closes #17051
This commit is contained in:
Saki Takamachi
2024-12-07 01:52:30 +09:00
parent c192a341ec
commit 063c3c8522
5 changed files with 98 additions and 1 deletions

5
NEWS
View File

@@ -2,6 +2,9 @@ PHP NEWS
|||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||||
?? ??? ????, PHP 8.4.3
- BcMath:
. Fixed bug GH-17049 (Correctly compare 0 and -0). (Saki Takamachi)
- Iconv:
. Fixed bug GH-17047 (UAF on iconv filter failure). (nielsdos)
@@ -12,7 +15,7 @@ PHP NEWS
05 Dec 2024, PHP 8.4.2
- BcMath:
. Fixed bug GH-16978 (Avoid unnecessary padding with leading zeros)
. Fixed bug GH-16978 (Avoid unnecessary padding with leading zeros).
(Saki Takamachi)
- COM:

View File

@@ -45,6 +45,18 @@ bcmath_compare_result _bc_do_compare(bc_num n1, bc_num n2, size_t scale, bool us
/* First, compare signs. */
if (use_sign && n1->n_sign != n2->n_sign) {
/*
* scale and n->n_scale differ only in Number objects.
* This happens when explicitly specify the scale in a Number method.
*/
if ((n1->n_scale > scale || n2->n_scale > scale) &&
n1->n_len == 1 && n2->n_len == 1 &&
n1->n_value[0] == 0 && n2->n_value[0] == 0 &&
bc_is_zero_for_scale(n1, scale) && bc_is_zero_for_scale(n2, scale)
) {
/* e.g. 0.00 <=> -0.00 */
return BCMATH_EQUAL;
}
if (n1->n_sign == PLUS) {
/* Positive N1 > Negative N2 */
return BCMATH_LEFT_GREATER;

View File

@@ -173,6 +173,15 @@ bool bc_str2num(bc_num *num, const char *str, const char *end, size_t scale, siz
if (str_scale > scale && !auto_scale) {
fractional_end -= str_scale - scale;
str_scale = scale;
/*
* e.g. 123.0001 with scale 2 -> 123.00
* So, remove the trailing 0 again.
*/
if (str_scale > 0) {
const char *fractional_new_end = bc_skip_zero_reverse(fractional_end, fractional_ptr);
str_scale -= fractional_new_end - fractional_end;
}
}
} else {
if (full_scale) {

View File

@@ -13,6 +13,7 @@ echo bccomp("-2.29", "2.3", "2") . "\n";
echo bccomp("2.29", "-2.3", "2") . "\n";
echo bccomp("-2.29", "-2.3", "1") . "\n";
echo bccomp("-2.29", "0", "1") . "\n";
echo bccomp("0.001", "-0.001", "1") . "\n";
?>
--EXPECT--
0
@@ -22,3 +23,4 @@ echo bccomp("-2.29", "0", "1") . "\n";
1
1
-1
0

View File

@@ -0,0 +1,71 @@
--TEST--
BcMath\Number compare() with scale
--EXTENSIONS--
bcmath
--FILE--
<?php
$values1 = [
new BcMath\Number('0.001'),
new BcMath\Number('-0.001'),
];
$values2 = [
0,
-0,
'0.0011',
'-0.0011',
];
$value1 = new BcMath\Number('0.001');
$scales = [0, 2, 3, 4];
foreach ($scales as $scale) {
echo "========== scale is {$scale} ==========\n";
foreach ($values1 as $value1) {
foreach ($values2 as $value2) {
$output = str_pad("{$value1} <=> {$value2}: ", 20, ' ', STR_PAD_LEFT);
$output .= str_pad((string) $value1->compare($value2, $scale), 2, ' ', STR_PAD_LEFT);
echo "{$output}\n";
}
}
}
?>
--EXPECT--
========== scale is 0 ==========
0.001 <=> 0: 0
0.001 <=> 0: 0
0.001 <=> 0.0011: 0
0.001 <=> -0.0011: 0
-0.001 <=> 0: 0
-0.001 <=> 0: 0
-0.001 <=> 0.0011: 0
-0.001 <=> -0.0011: 0
========== scale is 2 ==========
0.001 <=> 0: 0
0.001 <=> 0: 0
0.001 <=> 0.0011: 0
0.001 <=> -0.0011: 0
-0.001 <=> 0: 0
-0.001 <=> 0: 0
-0.001 <=> 0.0011: 0
-0.001 <=> -0.0011: 0
========== scale is 3 ==========
0.001 <=> 0: 1
0.001 <=> 0: 1
0.001 <=> 0.0011: 0
0.001 <=> -0.0011: 1
-0.001 <=> 0: -1
-0.001 <=> 0: -1
-0.001 <=> 0.0011: -1
-0.001 <=> -0.0011: 0
========== scale is 4 ==========
0.001 <=> 0: 1
0.001 <=> 0: 1
0.001 <=> 0.0011: -1
0.001 <=> -0.0011: 1
-0.001 <=> 0: -1
-0.001 <=> 0: -1
-0.001 <=> 0.0011: -1
-0.001 <=> -0.0011: 1