From ff9d834088f1ad43827054d1e685b72ac9b03dea Mon Sep 17 00:00:00 2001 From: user202729 <25191436+user202729@users.noreply.github.com> Date: Tue, 19 Nov 2024 08:27:10 +0700 Subject: [PATCH] Fix crash when specify invalid base for RR and RIF construction --- src/sage/rings/convert/mpfi.pyx | 29 +++++++++++++++++++++++++++++ src/sage/rings/real_mpfr.pyx | 29 +++++++++++++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/sage/rings/convert/mpfi.pyx b/src/sage/rings/convert/mpfi.pyx index 803eed59146..106a94c5aca 100644 --- a/src/sage/rings/convert/mpfi.pyx +++ b/src/sage/rings/convert/mpfi.pyx @@ -72,6 +72,33 @@ cdef int mpfi_set_sage(mpfi_ptr re, mpfi_ptr im, x, field, int base) except -1: imaginary component is 0. - in all other cases: raise an exception. + + TESTS:: + + sage: RIF('0xabc') + Traceback (most recent call last): + ... + TypeError: unable to convert '0xabc' to real interval + sage: RIF("0x123.e1", base=0) # rel tol 1e-12 + 291.87890625000000? + sage: RIF("0x123.@1", base=0) # rel tol 1e-12 + 4656 + sage: RIF("1Xx", base=36) # rel tol 1e-12 + 2517 + sage: RIF("-1Xx@-10", base=62) # rel tol 1e-12 + -7.088054920481391?e-15 + sage: RIF("1", base=1) + Traceback (most recent call last): + ... + ValueError: base (=1) must be 0 or between 2 and 62 + sage: RIF("1", base=-1) + Traceback (most recent call last): + ... + ValueError: base (=-1) must be 0 or between 2 and 62 + sage: RIF("1", base=63) + Traceback (most recent call last): + ... + ValueError: base (=63) must be 0 or between 2 and 62 """ cdef RealIntervalFieldElement ri cdef ComplexIntervalFieldElement zi @@ -79,6 +106,8 @@ cdef int mpfi_set_sage(mpfi_ptr re, mpfi_ptr im, x, field, int base) except -1: cdef ComplexDoubleElement zd cdef bytes s + if base != 0 and (base < 2 or base > 62): + raise ValueError(f"base (={base}) must be 0 or between 2 and 62") if im is not NULL and isinstance(x, tuple): # For complex numbers, interpret tuples as real/imag parts if len(x) != 2: diff --git a/src/sage/rings/real_mpfr.pyx b/src/sage/rings/real_mpfr.pyx index 7e1ab748b55..a870c6bf0c7 100644 --- a/src/sage/rings/real_mpfr.pyx +++ b/src/sage/rings/real_mpfr.pyx @@ -1437,6 +1437,33 @@ cdef class RealNumber(sage.structure.element.RingElement): sage: RealNumber('1_3.1e-32_45') 1.31000000000000e-3244 + + Test conversion from base different from `10`:: + + sage: RR('0xabc') + Traceback (most recent call last): + ... + TypeError: unable to convert '0xabc' to a real number + sage: RR("0x123.e1", base=0) # rel tol 1e-12 + 291.878906250000 + sage: RR("0x123.@1", base=0) # rel tol 1e-12 + 4656.00000000000 + sage: RR("1Xx", base=36) # rel tol 1e-12 + 2517.00000000000 + sage: RR("-1Xx@-10", base=62) # rel tol 1e-12 + -7.08805492048139e-15 + sage: RR("1", base=1) + Traceback (most recent call last): + ... + ValueError: base (=1) must be 0 or between 2 and 62 + sage: RR("1", base=-1) + Traceback (most recent call last): + ... + ValueError: base (=-1) must be 0 or between 2 and 62 + sage: RR("1", base=63) + Traceback (most recent call last): + ... + ValueError: base (=63) must be 0 or between 2 and 62 """ if x is not None: self._set(x, base) @@ -1485,6 +1512,8 @@ cdef class RealNumber(sage.structure.element.RingElement): # Real Numbers are supposed to be immutable. cdef RealField_class parent parent = self._parent + if base != 0 and (base < 2 or base > 62): + raise ValueError(f"base (={base}) must be 0 or between 2 and 62") if isinstance(x, RealNumber): if isinstance(x, RealLiteral): s = (x).literal