diff --git a/gmp.c b/gmp.c index 65fe44b5..ff5ab5e8 100644 --- a/gmp.c +++ b/gmp.c @@ -135,7 +135,7 @@ MPZ_to_str(MPZ_Object *u, int base, int options) static MPZ_Object * MPZ_from_str(PyObject *obj, int base) { - const char *str = PyUnicode_AsUTF8(obj); + const char *str = PyUnicode_AsUTF8AndSize(obj, NULL); if (!str) { return NULL; /* LCOV_EXCL_LINE */ @@ -157,6 +157,7 @@ MPZ_from_str(PyObject *obj, int base) } else if (ret == ZZ_BUF) { /* LCOV_EXCL_START */ + Py_DECREF(res); PyErr_SetString(PyExc_OverflowError, "too many digits in integer"); return NULL; @@ -438,15 +439,8 @@ new_impl(PyTypeObject *Py_UNUSED(type), PyObject *arg, PyObject *base_arg) } str: if (PyUnicode_Check(arg)) { - PyObject *asciistr = gmp_PyUnicode_TransformDecimalAndSpaceToASCII(arg); - - if (!asciistr) { - return NULL; /* LCOV_EXCL_LINE */ - } - - PyObject *res = (PyObject *)MPZ_from_str(asciistr, base); + PyObject *res = (PyObject *)MPZ_from_str(arg, base); - Py_DECREF(asciistr); return res; } else if (PyByteArray_Check(arg) || PyBytes_Check(arg)) { @@ -1644,7 +1638,7 @@ The signed argument indicates whether two’s complement is used."}, PyDoc_STRVAR(mpz_doc, "mpz(number=0, /)\nmpz(string, /, base=10)\n\n\ -Convert a number or a string to an integer. If numeric argument is not\n\ +Convert a number or an ASCII string to an integer. If numeric argument is not\n\ an int subclass, return mpz(int(number)).\n\n\ If argument is not a number or if base is given, then it must be a string,\n\ bytes, or bytearray instance representing an integer literal in the\n\ diff --git a/tests/test_mpz.py b/tests/test_mpz.py index 146987a6..e0a07744 100644 --- a/tests/test_mpz.py +++ b/tests/test_mpz.py @@ -270,16 +270,13 @@ def test_mpz_interface(): with pytest.raises(ValueError, match="invalid literal"): mpz(" ") with pytest.raises(ValueError, match="invalid literal"): - mpz("ыыы") + mpz("qqq") assert mpz() == mpz(0) == 0 assert mpz(" -123") == -123 assert mpz("123 ") == 123 assert mpz(" -123 ") == -123 assert mpz("+123") == 123 - assert mpz("١٢٣٤") == 1234 # unicode decimal digits - assert mpz("١23") == 123 assert mpz("\t123") == 123 - assert mpz("\xa0123") == 123 assert mpz("-010") == -10 assert mpz("-10") == -10 assert mpz("0b_10", 0) == 2 @@ -950,12 +947,14 @@ def test_from_bytes_interface(): @example(1<<116) @example(646541478744828163276576707651635923929979156076518566789121) @example((0xfffffffffffff8<<(242*4)) + (1<<970)) +@example(0xa<<10000) def test_to_float(x): mx = mpz(x) try: fx = float(x) except OverflowError: - pytest.raises(OverflowError, lambda: float(mx)) + with pytest.raises(OverflowError): + float(mx) else: assert str(float(mx)) == str(fx) diff --git a/utils.c b/utils.c index 7b1bde36..e5cae2ea 100644 --- a/utils.c +++ b/utils.c @@ -61,47 +61,3 @@ gmp_parse_pyargs(const gmp_pyargs *fnargs, Py_ssize_t argidx[], } return 0; } - -/* copied from CPython internals */ -PyObject * -gmp_PyUnicode_TransformDecimalAndSpaceToASCII(PyObject *unicode) -{ - assert(PyUnicode_Check(unicode)); - if (PyUnicode_IS_ASCII(unicode)) { - return Py_NewRef(unicode); - } - - Py_ssize_t len = PyUnicode_GetLength(unicode); - PyObject *result = PyUnicode_New(len, 127); - - if (result == NULL) { - return NULL; /* LCOV_EXCL_LINE */ - } - - Py_UCS1 *out = PyUnicode_1BYTE_DATA(result); - int kind = (int)PyUnicode_KIND(unicode); /* oracle/graalpython#580 */ - const void *data = PyUnicode_DATA(unicode); - - for (Py_ssize_t i = 0; i < len; ++i) { - Py_UCS4 ch = PyUnicode_READ(kind, data, i); - - if (ch < 127) { - out[i] = (Py_UCS1)ch; - } - else if (Py_UNICODE_ISSPACE(ch)) { - out[i] = ' '; - } - else { - int decimal = Py_UNICODE_TODECIMAL(ch); - - if (decimal < 0) { - out[i] = '?'; - out[i + 1] = '\0'; - break; - } - assert(decimal < 127); - out[i] = '0' + (Py_UCS1)decimal; - } - } - return result; -} diff --git a/utils.h b/utils.h index 3233593f..78ee1a1d 100644 --- a/utils.h +++ b/utils.h @@ -34,6 +34,4 @@ int gmp_parse_pyargs(const gmp_pyargs *fnargs, Py_ssize_t argidx[], PyObject *const *args, Py_ssize_t nargs, PyObject *kwnames); -PyObject * gmp_PyUnicode_TransformDecimalAndSpaceToASCII(PyObject *unicode); - #endif /* UTILS_H */