Skip to content

ext/bcmath - Fixed GH-17049: Correctly compare 0 and -0 #17051

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 4 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion NEWS
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand All @@ -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:
Expand Down
12 changes: 12 additions & 0 deletions ext/bcmath/libbcmath/src/compare.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
9 changes: 9 additions & 0 deletions ext/bcmath/libbcmath/src/str2num.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions ext/bcmath/tests/bccomp_variation002.phpt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -22,3 +23,4 @@ echo bccomp("-2.29", "0", "1") . "\n";
1
1
-1
0
71 changes: 71 additions & 0 deletions ext/bcmath/tests/number/methods/compare_near_zero.phpt
Original file line number Diff line number Diff line change
@@ -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
Loading