[gjs: 1/2] arg: Fix MIN/MAX safe big integer limits




commit 4746f8ba0d37b7d59a0de9da50c57782dfa8c348
Author: Marco Trevisan (TreviƱo) <mail 3v1n0 net>
Date:   Mon Sep 7 14:22:51 2020 +0200

    arg: Fix MIN/MAX safe big integer limits
    
    Current JS Number's MAX_SAFE_INTEGER value is set to 9007199254740991,
    however we set this value to 9007199254740992.
    
    Fix the number computation and add an unit test to ensure that the value
    we use is always matching JS definition (so that we are protected in the
    unlikely case that anything would change).

 gi/arg-inl.h       |  4 ++--
 test/gjs-tests.cpp | 32 ++++++++++++++++++++++++++++++++
 2 files changed, 34 insertions(+), 2 deletions(-)
---
diff --git a/gi/arg-inl.h b/gi/arg-inl.h
index 063308841..d1a36c805 100644
--- a/gi/arg-inl.h
+++ b/gi/arg-inl.h
@@ -167,13 +167,13 @@ inline void gjs_arg_unset(GIArgument* arg) {
 
 template <typename BigT>
 [[nodiscard]] inline constexpr BigT max_safe_big_number() {
-    return BigT(1) << std::numeric_limits<double>::digits;
+    return (BigT(1) << std::numeric_limits<double>::digits) - 1;
 }
 
 template <typename BigT>
 [[nodiscard]] inline constexpr BigT min_safe_big_number() {
     if constexpr (std::is_signed_v<BigT>)
-        return -(max_safe_big_number<BigT>()) + 1;
+        return -(max_safe_big_number<BigT>());
 
     return std::numeric_limits<BigT>::lowest();
 }
diff --git a/test/gjs-tests.cpp b/test/gjs-tests.cpp
index 60f1b493f..2e4b10e96 100644
--- a/test/gjs-tests.cpp
+++ b/test/gjs-tests.cpp
@@ -23,6 +23,7 @@
 
 #include <config.h>
 
+#include <stdint.h>
 #include <string.h>  // for size_t, strlen
 
 #include <string>  // for u16string, u32string
@@ -39,7 +40,9 @@
 #include <js/Value.h>
 #include <js/ValueArray.h>
 #include <jsapi.h>
+#include <jspubtd.h>  // for JSProto_Number
 
+#include "gi/arg-inl.h"
 #include "gjs/context.h"
 #include "gjs/error-types.h"
 #include "gjs/jsapi-util.h"
@@ -398,6 +401,30 @@ gjstest_test_profiler_start_stop(void)
         g_message("Temp profiler file not deleted");
 }
 
+static void gjstest_test_safe_integer_max(GjsUnitTestFixture* fx, const void*) {
+    JS::RootedObject number_class_object(fx->cx);
+    JS::RootedValue safe_value(fx->cx);
+
+    g_assert_true(
+        JS_GetClassObject(fx->cx, JSProto_Number, &number_class_object));
+    g_assert_true(JS_GetProperty(fx->cx, number_class_object,
+                                 "MAX_SAFE_INTEGER", &safe_value));
+
+    g_assert_cmpint(safe_value.toNumber(), ==, max_safe_big_number<int64_t>());
+}
+
+static void gjstest_test_safe_integer_min(GjsUnitTestFixture* fx, const void*) {
+    JS::RootedObject number_class_object(fx->cx);
+    JS::RootedValue safe_value(fx->cx);
+
+    g_assert_true(
+        JS_GetClassObject(fx->cx, JSProto_Number, &number_class_object));
+    g_assert_true(JS_GetProperty(fx->cx, number_class_object,
+                                 "MIN_SAFE_INTEGER", &safe_value));
+
+    g_assert_cmpint(safe_value.toNumber(), ==, min_safe_big_number<int64_t>());
+}
+
 int
 main(int    argc,
      char **argv)
@@ -444,6 +471,11 @@ main(int    argc,
     ADD_JSAPI_UTIL_TEST("debug_string/object-with-complicated-to-string",
                         test_jsapi_util_debug_string_object_with_complicated_to_string);
 
+    ADD_JSAPI_UTIL_TEST("gi/args/safe-integer/max",
+                        gjstest_test_safe_integer_max);
+    ADD_JSAPI_UTIL_TEST("gi/args/safe-integer/min",
+                        gjstest_test_safe_integer_min);
+
 #undef ADD_JSAPI_UTIL_TEST
 
     gjs_test_add_tests_for_coverage ();


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]