[njs] Fixed ToInt32() with values >= 2**(53+30).
Dmitry Volyntsev
xeioex at nginx.com
Mon May 24 14:18:49 UTC 2021
details: https://hg.nginx.org/njs/rev/801e2dbc79c9
branches:
changeset: 1643:801e2dbc79c9
user: Dmitry Volyntsev <xeioex at nginx.com>
date: Mon May 24 14:18:15 2021 +0000
description:
Fixed ToInt32() with values >= 2**(53+30).
diffstat:
src/njs_number.h | 6 ++--
src/test/njs_unit_test.c | 65 ++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 68 insertions(+), 3 deletions(-)
diffs (109 lines):
diff -r a33a16ec5aa0 -r 801e2dbc79c9 src/njs_number.h
--- a/src/njs_number.h Mon May 24 14:17:59 2021 +0000
+++ b/src/njs_number.h Mon May 24 14:18:15 2021 +0000
@@ -85,12 +85,12 @@ njs_number_to_int32(double num)
exp = (conv.u64 & NJS_DBL_EXPONENT_MASK) >> NJS_DBL_SIGNIFICAND_SIZE;
- if (njs_fast_path(exp < (NJS_DBL_EXPONENT_OFFSET + 30))) {
+ if (njs_fast_path(exp < (NJS_DBL_EXPONENT_OFFSET + 31))) {
/* |num| < 2**31. */
return num;
}
- if (exp < (NJS_DBL_EXPONENT_OFFSET + 30 + 53)) {
+ if (exp < (NJS_DBL_EXPONENT_OFFSET + 31 + 53)) {
v = (conv.u64 & NJS_DBL_SIGNIFICAND_MASK) | NJS_DBL_HIDDEN_BIT;
v <<= (exp - NJS_DBL_EXPONENT_BIAS + 32);
r = v >> 32;
@@ -105,7 +105,7 @@ njs_number_to_int32(double num)
/*
* ES5.1: integer must be modulo 2^32.
* The distance between larger doubles
- * (exp >= NJS_DBL_EXPONENT_OFFSET + 30 + 53) is a multiple of 2**32 => 0.
+ * (exp >= NJS_DBL_EXPONENT_OFFSET + 31 + 53) is a multiple of 2**32 => 0.
* This also handles NaN and Inf.
*/
diff -r a33a16ec5aa0 -r 801e2dbc79c9 src/test/njs_unit_test.c
--- a/src/test/njs_unit_test.c Mon May 24 14:17:59 2021 +0000
+++ b/src/test/njs_unit_test.c Mon May 24 14:18:15 2021 +0000
@@ -22304,6 +22304,69 @@ njs_string_to_index_test(njs_vm_t *vm, n
static njs_int_t
+njs_to_int32_test(njs_vm_t *vm, njs_opts_t *opts, njs_stat_t *stat)
+{
+ int32_t i32, second;
+ njs_uint_t i;
+
+ static const struct {
+ double value;
+ int32_t expected;
+ } tests[] = {
+ { -1.0, -1 },
+ { 0.0, 0 },
+ { 0.001, 0 },
+ { 1.0, 1 },
+ { 2147483647.0, 2147483647 },
+ { 2147483648.0, -2147483648 },
+ { 2147483649.0, -2147483647 },
+ { -1844674406941458432.0, -2147483648 },
+ { 4.835703278458518e+24 /* 2**(53+29) + 2**30 */, 1073741824 },
+ { 9.671406556917036e+24 /* 2**(53+30) + 2**31 */, -2147483648 },
+ };
+
+ for (i = 0; i < njs_nitems(tests); i++) {
+ i32 = njs_number_to_int32(tests[i].value);
+
+ if (i32 != tests[i].expected) {
+ njs_printf("njs_to_int32_test(%f):\n"
+ "expected: %D\n got: %D\n",
+ tests[i].value, tests[i].expected, i32);
+
+ stat->failed++;
+ continue;
+ }
+
+ second = njs_number_to_int32(i32);
+
+ if (i32 != second) {
+ njs_printf("njs_to_int32_test(%f): not idempodent\n"
+ "expected: %D\n got: %D\n",
+ tests[i].value, i32, second);
+
+ stat->failed++;
+ continue;
+ }
+
+ second = njs_number_to_int32(njs_number_to_uint32(tests[i].value));
+
+ if (i32 != second) {
+ njs_printf("ToInt32(%f) != ToInt32(ToUint32(%f))\n"
+ "left: %D\n right: %D\n",
+ tests[i].value, tests[i].value, i32, second);
+
+ stat->failed++;
+ continue;
+ }
+
+ stat->passed++;
+ }
+
+ return NJS_OK;
+}
+
+
+static njs_int_t
njs_vm_internal_api_test(njs_unit_test_t unused[], size_t num, njs_str_t *name,
njs_opts_t *opts, njs_stat_t *stat)
{
@@ -22329,6 +22392,8 @@ njs_vm_internal_api_test(njs_unit_test_t
njs_str("njs_sort_test") },
{ njs_string_to_index_test,
njs_str("njs_string_to_index_test") },
+ { njs_to_int32_test,
+ njs_str("njs_to_int32_test") },
};
vm = NULL;
More information about the nginx-devel
mailing list