Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 55549ec

Browse files
committed
Issue #12847: Fix a crash with negative PUT and LONG_BINPUT arguments in
the C pickle implementation.
1 parent 82be19f commit 55549ec

4 files changed

Lines changed: 31 additions & 1 deletion

File tree

Lib/pickle.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1156,16 +1156,22 @@ def load_long_binget(self):
11561156

11571157
def load_put(self):
11581158
i = int(self.readline()[:-1])
1159+
if i < 0:
1160+
raise ValueError("negative PUT argument")
11591161
self.memo[i] = self.stack[-1]
11601162
dispatch[PUT[0]] = load_put
11611163

11621164
def load_binput(self):
11631165
i = self.read(1)[0]
1166+
if i < 0:
1167+
raise ValueError("negative BINPUT argument")
11641168
self.memo[i] = self.stack[-1]
11651169
dispatch[BINPUT[0]] = load_binput
11661170

11671171
def load_long_binput(self):
11681172
i = mloads(b'i' + self.read(4))
1173+
if i < 0:
1174+
raise ValueError("negative LONG_BINPUT argument")
11691175
self.memo[i] = self.stack[-1]
11701176
dispatch[LONG_BINPUT[0]] = load_long_binput
11711177

Lib/test/pickletester.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1121,6 +1121,18 @@ def test_negative_32b_binunicode(self):
11211121
# On 32-bit builds, a BINUNICODE of 2**31 or more is refused
11221122
self.check_negative_32b_binXXX(b'\x80\x03X\xff\xff\xff\xffxyzq\x00.')
11231123

1124+
def test_negative_put(self):
1125+
# Issue #12847
1126+
dumped = b'Va\np-1\n.'
1127+
self.assertRaises(ValueError, self.loads, dumped)
1128+
1129+
def test_negative_32b_binput(self):
1130+
# Issue #12847
1131+
if sys.maxsize > 2**32:
1132+
self.skipTest("test is only meaningful on 32-bit builds")
1133+
dumped = b'\x80\x03X\x01\x00\x00\x00ar\xff\xff\xff\xff.'
1134+
self.assertRaises(ValueError, self.loads, dumped)
1135+
11241136

11251137
class BigmemPickleTests(unittest.TestCase):
11261138

Misc/NEWS

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,9 @@ Core and Builtins
2222
Library
2323
-------
2424

25+
- Issue #12847: Fix a crash with negative PUT and LONG_BINPUT arguments in
26+
the C pickle implementation.
27+
2528
- Issue #11564: Avoid crashes when trying to pickle huge objects or containers
2629
(more than 2**31 items). Instead, in most cases, an OverflowError is raised.
2730

Modules/_pickle.c

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4853,8 +4853,12 @@ load_put(UnpicklerObject *self)
48534853
return -1;
48544854
idx = PyLong_AsSsize_t(key);
48554855
Py_DECREF(key);
4856-
if (idx == -1 && PyErr_Occurred())
4856+
if (idx < 0) {
4857+
if (!PyErr_Occurred())
4858+
PyErr_SetString(PyExc_ValueError,
4859+
"negative PUT argument");
48574860
return -1;
4861+
}
48584862

48594863
return _Unpickler_MemoPut(self, idx, value);
48604864
}
@@ -4893,6 +4897,11 @@ load_long_binput(UnpicklerObject *self)
48934897
value = self->stack->data[Py_SIZE(self->stack) - 1];
48944898

48954899
idx = calc_binsize(s, 4);
4900+
if (idx < 0) {
4901+
PyErr_SetString(PyExc_ValueError,
4902+
"negative LONG_BINPUT argument");
4903+
return -1;
4904+
}
48964905

48974906
return _Unpickler_MemoPut(self, idx, value);
48984907
}

0 commit comments

Comments
 (0)