From 9ad8aa762d7fb3e7eca2ce1c7e23d53b932da963 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim=20D=C3=BCsterhus?= Date: Sat, 23 Sep 2023 16:23:08 +0200 Subject: [PATCH] round: Bypass the precision logic when rounding to 0 places Since GH-12220 the implementation of `php_round_helper()`, which performs rounding to an integral value, is easy to verify for correctness up to the floating point precision. If rounding to 0 places is desired, i.e. the userland `round()` function is called with `$precision = 0`, we bypass all logic for the decimal point adjustment and instead directly call `php_round_helper()`. This change fixes the remaining two cases of GH-12143 and likely guarantees correct rounding for all possible inputs and `$precision = 0`. --- ext/standard/math.c | 4 +++ ext/standard/tests/math/round_gh12143_5.phpt | 27 ++++++++++++++++++++ ext/standard/tests/math/round_gh12143_6.phpt | 27 ++++++++++++++++++++ 3 files changed, 58 insertions(+) create mode 100644 ext/standard/tests/math/round_gh12143_5.phpt create mode 100644 ext/standard/tests/math/round_gh12143_6.phpt diff --git a/ext/standard/math.c b/ext/standard/math.c index 6b16b0755f69b..2f6743865b464 100644 --- a/ext/standard/math.c +++ b/ext/standard/math.c @@ -177,6 +177,10 @@ PHPAPI double _php_math_round(double value, int places, int mode) { return value; } + if (places == 0) { + return php_round_helper(value, mode); + } + places = places < INT_MIN+1 ? INT_MIN+1 : places; precision_places = 14 - php_intlog10abs(value); diff --git a/ext/standard/tests/math/round_gh12143_5.phpt b/ext/standard/tests/math/round_gh12143_5.phpt new file mode 100644 index 0000000000000..9f05628e5de84 --- /dev/null +++ b/ext/standard/tests/math/round_gh12143_5.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-12143: Test rounding of 1.4999999999999998. +--FILE-- + %+.17g\n", $mode, $number, round($number, 0, constant($mode))); + } +} +?> +--EXPECT-- +PHP_ROUND_HALF_UP : +1.4999999999999998 -> +1 +PHP_ROUND_HALF_DOWN : +1.4999999999999998 -> +1 +PHP_ROUND_HALF_EVEN : +1.4999999999999998 -> +1 +PHP_ROUND_HALF_ODD : +1.4999999999999998 -> +1 +PHP_ROUND_HALF_UP : -1.4999999999999998 -> -1 +PHP_ROUND_HALF_DOWN : -1.4999999999999998 -> -1 +PHP_ROUND_HALF_EVEN : -1.4999999999999998 -> -1 +PHP_ROUND_HALF_ODD : -1.4999999999999998 -> -1 diff --git a/ext/standard/tests/math/round_gh12143_6.phpt b/ext/standard/tests/math/round_gh12143_6.phpt new file mode 100644 index 0000000000000..07b1cc73ce615 --- /dev/null +++ b/ext/standard/tests/math/round_gh12143_6.phpt @@ -0,0 +1,27 @@ +--TEST-- +GH-12143: Test rounding of 4503599627370495.5. +--FILE-- + %+.17g\n", $mode, $number, round($number, 0, constant($mode))); + } +} +?> +--EXPECT-- +PHP_ROUND_HALF_UP : +4503599627370495.5 -> +4503599627370496 +PHP_ROUND_HALF_DOWN : +4503599627370495.5 -> +4503599627370495 +PHP_ROUND_HALF_EVEN : +4503599627370495.5 -> +4503599627370496 +PHP_ROUND_HALF_ODD : +4503599627370495.5 -> +4503599627370495 +PHP_ROUND_HALF_UP : -4503599627370495.5 -> -4503599627370496 +PHP_ROUND_HALF_DOWN : -4503599627370495.5 -> -4503599627370495 +PHP_ROUND_HALF_EVEN : -4503599627370495.5 -> -4503599627370496 +PHP_ROUND_HALF_ODD : -4503599627370495.5 -> -4503599627370495