mirror of https://github.com/python/cpython.git
gh-126992: Change pickle code to base 10 for load_long and load_int (GH-127042)
Co-authored-by: Serhiy Storchaka <storchaka@gmail.com>
This commit is contained in:
parent
d5d84c3f13
commit
ce76b547f9
|
@ -1387,7 +1387,7 @@ def load_int(self):
|
|||
elif data == TRUE[1:]:
|
||||
val = True
|
||||
else:
|
||||
val = int(data, 0)
|
||||
val = int(data)
|
||||
self.append(val)
|
||||
dispatch[INT[0]] = load_int
|
||||
|
||||
|
@ -1407,7 +1407,7 @@ def load_long(self):
|
|||
val = self.readline()[:-1]
|
||||
if val and val[-1] == b'L'[0]:
|
||||
val = val[:-1]
|
||||
self.append(int(val, 0))
|
||||
self.append(int(val))
|
||||
dispatch[LONG[0]] = load_long
|
||||
|
||||
def load_long1(self):
|
||||
|
|
|
@ -1012,6 +1012,26 @@ def test_constants(self):
|
|||
self.assertIs(self.loads(b'I01\n.'), True)
|
||||
self.assertIs(self.loads(b'I00\n.'), False)
|
||||
|
||||
def test_zero_padded_integers(self):
|
||||
self.assertEqual(self.loads(b'I010\n.'), 10)
|
||||
self.assertEqual(self.loads(b'I-010\n.'), -10)
|
||||
self.assertEqual(self.loads(b'I0010\n.'), 10)
|
||||
self.assertEqual(self.loads(b'I-0010\n.'), -10)
|
||||
self.assertEqual(self.loads(b'L010\n.'), 10)
|
||||
self.assertEqual(self.loads(b'L-010\n.'), -10)
|
||||
self.assertEqual(self.loads(b'L0010\n.'), 10)
|
||||
self.assertEqual(self.loads(b'L-0010\n.'), -10)
|
||||
self.assertEqual(self.loads(b'L010L\n.'), 10)
|
||||
self.assertEqual(self.loads(b'L-010L\n.'), -10)
|
||||
|
||||
def test_nondecimal_integers(self):
|
||||
self.assertRaises(ValueError, self.loads, b'I0b10\n.')
|
||||
self.assertRaises(ValueError, self.loads, b'I0o10\n.')
|
||||
self.assertRaises(ValueError, self.loads, b'I0x10\n.')
|
||||
self.assertRaises(ValueError, self.loads, b'L0b10L\n.')
|
||||
self.assertRaises(ValueError, self.loads, b'L0o10L\n.')
|
||||
self.assertRaises(ValueError, self.loads, b'L0x10L\n.')
|
||||
|
||||
def test_empty_bytestring(self):
|
||||
# issue 11286
|
||||
empty = self.loads(b'\x80\x03U\x00q\x00.', encoding='koi8-r')
|
||||
|
|
|
@ -443,6 +443,43 @@ def test_persid(self):
|
|||
highest protocol among opcodes = 0
|
||||
''')
|
||||
|
||||
def test_constants(self):
|
||||
self.check_dis(b"(NI00\nI01\n\x89\x88t.", '''\
|
||||
0: ( MARK
|
||||
1: N NONE
|
||||
2: I INT False
|
||||
6: I INT True
|
||||
10: \\x89 NEWFALSE
|
||||
11: \\x88 NEWTRUE
|
||||
12: t TUPLE (MARK at 0)
|
||||
13: . STOP
|
||||
highest protocol among opcodes = 2
|
||||
''')
|
||||
|
||||
def test_integers(self):
|
||||
self.check_dis(b"(I0\nI1\nI10\nI011\nL12\nL13L\nL014\nL015L\nt.", '''\
|
||||
0: ( MARK
|
||||
1: I INT 0
|
||||
4: I INT 1
|
||||
7: I INT 10
|
||||
11: I INT 11
|
||||
16: L LONG 12
|
||||
20: L LONG 13
|
||||
25: L LONG 14
|
||||
30: L LONG 15
|
||||
36: t TUPLE (MARK at 0)
|
||||
37: . STOP
|
||||
highest protocol among opcodes = 0
|
||||
''')
|
||||
|
||||
def test_nondecimal_integers(self):
|
||||
self.check_dis_error(b'I0b10\n.', '', 'invalid literal for int')
|
||||
self.check_dis_error(b'I0o10\n.', '', 'invalid literal for int')
|
||||
self.check_dis_error(b'I0x10\n.', '', 'invalid literal for int')
|
||||
self.check_dis_error(b'L0b10L\n.', '', 'invalid literal for int')
|
||||
self.check_dis_error(b'L0o10L\n.', '', 'invalid literal for int')
|
||||
self.check_dis_error(b'L0x10L\n.', '', 'invalid literal for int')
|
||||
|
||||
|
||||
class MiscTestCase(unittest.TestCase):
|
||||
def test__all__(self):
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Fix LONG and INT opcodes to only use base 10 for string to integer conversion in :mod:`pickle`.
|
|
@ -5211,16 +5211,14 @@ load_int(PickleState *state, UnpicklerObject *self)
|
|||
return bad_readline(state);
|
||||
|
||||
errno = 0;
|
||||
/* XXX: Should the base argument of strtol() be explicitly set to 10?
|
||||
XXX(avassalotti): Should this uses PyOS_strtol()? */
|
||||
x = strtol(s, &endptr, 0);
|
||||
/* XXX(avassalotti): Should this uses PyOS_strtol()? */
|
||||
x = strtol(s, &endptr, 10);
|
||||
|
||||
if (errno || (*endptr != '\n' && *endptr != '\0')) {
|
||||
/* Hm, maybe we've got something long. Let's try reading
|
||||
* it as a Python int object. */
|
||||
errno = 0;
|
||||
/* XXX: Same thing about the base here. */
|
||||
value = PyLong_FromString(s, NULL, 0);
|
||||
value = PyLong_FromString(s, NULL, 10);
|
||||
if (value == NULL) {
|
||||
PyErr_SetString(PyExc_ValueError,
|
||||
"could not convert string to int");
|
||||
|
@ -5370,8 +5368,7 @@ load_long(PickleState *state, UnpicklerObject *self)
|
|||
the 'L' to be present. */
|
||||
if (s[len-2] == 'L')
|
||||
s[len-2] = '\0';
|
||||
/* XXX: Should the base argument explicitly set to 10? */
|
||||
value = PyLong_FromString(s, NULL, 0);
|
||||
value = PyLong_FromString(s, NULL, 10);
|
||||
if (value == NULL)
|
||||
return -1;
|
||||
|
||||
|
|
Loading…
Reference in New Issue