URL: https://github.com/freeipa/freeipa/pull/5709
Author: tiran
 Title: #5709: Add max/min safe integer
Action: opened

PR body:
"""
JSON cannot safely handle integers outside range ``-(2**53) - 1`` to
``(2**53) - 1``. Add constants for safe integers and limit the Int
parameter to safe JSON values.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER

See: https://pagure.io/freeipa/issue/8802
See: https://pagure.io/freeipa/issue/8361
Signed-off-by: Christian Heimes <chei...@redhat.com>
"""

To pull the PR as Git branch:
git remote add ghfreeipa https://github.com/freeipa/freeipa
git fetch ghfreeipa pull/5709/head:pr5709
git checkout pr5709
From 6227a3addc046f6baf948f6f3ad7eae5f1cb99b3 Mon Sep 17 00:00:00 2001
From: Christian Heimes <chei...@redhat.com>
Date: Tue, 13 Apr 2021 10:23:46 +0200
Subject: [PATCH] Add max/min safe integer

JSON cannot safely handle integers outside range ``-(2**53) - 1`` to
``(2**53) - 1``. Add constants for safe integers and limit the Int
parameter to safe JSON values.

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/MAX_SAFE_INTEGER

See: https://pagure.io/freeipa/issue/8802
See: https://pagure.io/freeipa/issue/8361
Signed-off-by: Christian Heimes <chei...@redhat.com>
---
 ipalib/parameters.py                    | 23 +++++++++++++++++++++++
 ipatests/test_ipalib/test_parameters.py | 17 +++++++++++++++++
 2 files changed, 40 insertions(+)

diff --git a/ipalib/parameters.py b/ipalib/parameters.py
index 22c82f6b6d8..dfdf10516a2 100644
--- a/ipalib/parameters.py
+++ b/ipalib/parameters.py
@@ -130,6 +130,13 @@
 from ipapython.dnsutil import DNSName
 
 
+MAX_UINT32 = (1 << 32) - 1
+# JavaScript Number.MAX_SAFE_INTEGER / Number.MIN_SAFE_INTEGER
+# JSON cannot safely encode values outside this range as regular number
+MAX_SAFE_INTEGER = (2**53) - 1
+MIN_SAFE_INTEGER = -MAX_SAFE_INTEGER
+
+
 def _is_null(value):
     if value:
         return False
@@ -1093,6 +1100,12 @@ class Int(Number):
     allowed_types = (int,)
     type_error = _('must be an integer')
 
+    MININT = MININT
+    MAXINT = MAXINT
+    MAX_UINT32 = MAX_UINT32
+    MAX_SAFE_INTEGER = MAX_SAFE_INTEGER
+    MIN_SAFE_INTEGER = MIN_SAFE_INTEGER
+
     kwargs = Param.kwargs + (
         ('minvalue', int, int(MININT)),
         ('maxvalue', int, int(MAXINT)),
@@ -1124,6 +1137,16 @@ def __init__(self, name, *rules, **kw):
                 '%s: minvalue > maxvalue (minvalue=%r, maxvalue=%r)' % (
                     self.nice, self.minvalue, self.maxvalue)
             )
+        if self.minvalue < self.MIN_SAFE_INTEGER:
+            raise ValueError(
+                f"minvalue {self.minvalue} outside range of safe JSON "
+                f"integer limit {self.MIN_SAFE_INTEGER}"
+            )
+        if self.maxvalue > self.MAX_SAFE_INTEGER:
+            raise ValueError(
+                f"maxvalue {self.maxvalue} outside range of safe JSON "
+                f"integer limit {self.MAX_SAFE_INTEGER}"
+            )
 
     def _convert_scalar(self, value, index=None):
         """
diff --git a/ipatests/test_ipalib/test_parameters.py b/ipatests/test_ipalib/test_parameters.py
index d71faf4f770..ea92d683f8e 100644
--- a/ipatests/test_ipalib/test_parameters.py
+++ b/ipatests/test_ipalib/test_parameters.py
@@ -1318,6 +1318,23 @@ def test_convert_scalar(self):
         param = self.cls('my_number')
         check_int_scalar_conversions(param)
 
+    def test_safe_json(self):
+        param = self.cls(
+            "large",
+            minvalue=self.cls.MIN_SAFE_INTEGER,
+            maxvalue=self.cls.MAX_SAFE_INTEGER
+        )
+        for value in (-((2**53)-1), 0, (2**53)-1):
+            param.validate(value)
+        for value in (-2**53, 2**53):
+            with pytest.raises(errors.ValidationError):
+                param.validate(value)
+
+        with pytest.raises(ValueError):
+            self.cls("toolarge", maxvalue=2**53)
+        with pytest.raises(ValueError):
+            self.cls("toosmall", minvalue=-2**53)
+
 
 class test_Decimal(ClassChecker):
     """
_______________________________________________
FreeIPA-devel mailing list -- freeipa-devel@lists.fedorahosted.org
To unsubscribe send an email to freeipa-devel-le...@lists.fedorahosted.org
Fedora Code of Conduct: 
https://docs.fedoraproject.org/en-US/project/code-of-conduct/
List Guidelines: https://fedoraproject.org/wiki/Mailing_list_guidelines
List Archives: 
https://lists.fedorahosted.org/archives/list/freeipa-devel@lists.fedorahosted.org
Do not reply to spam on the list, report it: 
https://pagure.io/fedora-infrastructure

Reply via email to