Skip to content

Commit b074090

Browse files
committed
Reject bases>36 for compatibility with int
1 parent 6182d10 commit b074090

File tree

2 files changed

+10
-69
lines changed

2 files changed

+10
-69
lines changed

main.c

Lines changed: 6 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -150,11 +150,8 @@ MPZ_abs(MPZ_Object *u)
150150
return res;
151151
}
152152

153-
/* Maps 1-byte integer to digit character for bases up to 36 and
154-
from 37 up to 62, respectively. */
155-
static const char *num_to_text36 = "0123456789abcdefghijklmnopqrstuvwxyz";
156-
static const char *num_to_text62 = ("0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"
157-
"abcdefghijklmnopqrstuvwxyz");
153+
/* Maps 1-byte integer to digit character for bases up to 36. */
154+
static const char *num_to_text = "0123456789abcdefghijklmnopqrstuvwxyz";
158155

159156
static const char *mpz_tag = "mpz(";
160157
static int OPT_TAG = 0x1;
@@ -163,9 +160,9 @@ static int OPT_PREFIX = 0x2;
163160
static PyObject *
164161
MPZ_to_str(MPZ_Object *u, int base, int options)
165162
{
166-
if (base < 2 || base > 62) {
163+
if (base < 2 || base > 36) {
167164
PyErr_SetString(PyExc_ValueError,
168-
"base must be in the interval [2, 62]");
165+
"mpz base must be >= 2 and <= 36");
169166
return NULL;
170167
}
171168

@@ -209,9 +206,6 @@ MPZ_to_str(MPZ_Object *u, int base, int options)
209206
return PyErr_NoMemory();
210207
/* LCOV_EXCL_STOP */
211208
}
212-
213-
const char *num_to_text = base > 36 ? num_to_text62 : num_to_text36;
214-
215209
for (size_t i = 0; i < len; i++) {
216210
*p = num_to_text[*p];
217211
p++;
@@ -266,9 +260,9 @@ const unsigned char gmp_digit_value_tab[] =
266260
static MPZ_Object *
267261
MPZ_from_str(PyObject *obj, int base)
268262
{
269-
if (base != 0 && (base < 2 || base > 62)) {
263+
if (base != 0 && (base < 2 || base > 36)) {
270264
PyErr_SetString(PyExc_ValueError,
271-
"base must be 0 or in the interval [2, 62]");
265+
"mpz base must be >= 2 and <= 36, or 0");
272266
return NULL;
273267
}
274268

@@ -339,11 +333,6 @@ MPZ_from_str(PyObject *obj, int base)
339333
}
340334

341335
const unsigned char *digit_value = gmp_digit_value_tab;
342-
343-
if (base > 36) {
344-
digit_value += 208;
345-
}
346-
347336
Py_ssize_t new_len = len;
348337

349338
for (Py_ssize_t i = 0; i < len; i++) {

tests/test_mpz.py

Lines changed: 4 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -685,11 +685,9 @@ def test___sizeof__():
685685
def to_digits(n, base):
686686
if n == 0:
687687
return "0"
688-
if base < 2 or base > 62:
689-
raise ValueError("base must be in the interval [2, 62]")
688+
if base < 2 or base > 36:
689+
raise ValueError("mpz base must be >= 2 and <= 36")
690690
num_to_text = string.digits + string.ascii_lowercase
691-
if base > 36:
692-
num_to_text = num_to_text.upper() + string.ascii_lowercase
693691
digits = []
694692
if n < 0:
695693
sign = "-"
@@ -704,37 +702,7 @@ def to_digits(n, base):
704702
return sign + "".join(digits[::-1])
705703

706704

707-
def from_digits(s, base):
708-
if s == "0":
709-
return 0
710-
if base < 2 or base > 62:
711-
raise ValueError("base must be in the interval [2, 62]")
712-
if base <= 36:
713-
return int(s, base)
714-
if s[0] == "-":
715-
negative = True
716-
s = s[1:]
717-
else:
718-
negative = False
719-
n = 0
720-
b = 1
721-
for c in reversed(s):
722-
v = ord(c)
723-
if ord("0") <= v <= ord("9"):
724-
v -= ord("0")
725-
elif ord("A") <= v <= ord("Z"):
726-
v -= ord("A") - 10
727-
else:
728-
if base <= 36:
729-
v -= ord("a") - 10
730-
else:
731-
v -= ord("a") - 36
732-
n += v*b
733-
b *= base
734-
return -n if negative else n
735-
736-
737-
@given(integers(), integers(min_value=2, max_value=62))
705+
@given(integers(), integers(min_value=2, max_value=36))
738706
def test_digits(x, base):
739707
mx = mpz(x)
740708
res = to_digits(x, base)
@@ -761,7 +729,7 @@ def test_digits_interface():
761729

762730

763731
@given(integers(), integers(min_value=2, max_value=36))
764-
def test_digits_frombase_low(x, base):
732+
def test_digits_frombase(x, base):
765733
mx = mpz(x)
766734
smx = mx.digits(base)
767735
assert mpz(smx, base) == mx
@@ -777,22 +745,6 @@ def test_digits_frombase_low(x, base):
777745
assert mpz(smx, smaller_base) == i
778746

779747

780-
@given(integers(), integers(min_value=37, max_value=62))
781-
def test_digits_frombase_high(x, base):
782-
mx = mpz(x)
783-
smx = mx.digits(base)
784-
assert mpz(smx, base) == mx
785-
assert from_digits(smx, base) == mx
786-
smaller_base = (base + 2)//2 + 1
787-
try:
788-
g = from_digits(smx, smaller_base)
789-
except ValueError:
790-
with pytest.raises(ValueError):
791-
mpz(smx, smaller_base)
792-
else:
793-
assert mpz(smx, smaller_base) == g
794-
795-
796748
@given(integers())
797749
def test_frombase_auto(x):
798750
mx = mpz(x)

0 commit comments

Comments
 (0)