Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
4409c6cf
Commit
4409c6cf
authored
Nov 23, 2015
by
Serhiy Storchaka
Browse files
Options
Browse Files
Download
Plain Diff
Issue #23914: Fixed SystemError raised by unpickler on broken pickle data.
parents
3715cab3
e9b3074c
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
105 additions
and
4 deletions
+105
-4
Lib/test/pickletester.py
Lib/test/pickletester.py
+84
-1
Lib/test/test_pickle.py
Lib/test/test_pickle.py
+3
-0
Misc/NEWS
Misc/NEWS
+2
-0
Modules/_pickle.c
Modules/_pickle.c
+16
-3
No files found.
Lib/test/pickletester.py
View file @
4409c6cf
...
...
@@ -12,7 +12,7 @@ import weakref
from
http.cookies
import
SimpleCookie
from
test.support
import
(
TestFailed
,
TESTFN
,
run_with_locale
,
no_tracing
,
TestFailed
,
TESTFN
,
run_with_locale
,
no_tracing
,
captured_stdout
,
_2G
,
_4G
,
bigmemtest
,
)
...
...
@@ -987,6 +987,89 @@ class AbstractUnpickleTests(unittest.TestCase):
self
.
assertIs
(
type
(
unpickled
),
collections
.
UserDict
)
self
.
assertEqual
(
unpickled
,
collections
.
UserDict
({
1
:
2
}))
def
test_bad_stack
(
self
):
badpickles
=
[
b'0.'
,
# POP
b'1.'
,
# POP_MARK
b'2.'
,
# DUP
# b'(2.', # PyUnpickler doesn't raise
b'R.'
,
# REDUCE
b')R.'
,
b'a.'
,
# APPEND
b'Na.'
,
b'b.'
,
# BUILD
b'Nb.'
,
b'd.'
,
# DICT
b'e.'
,
# APPENDS
# b'(e.', # PyUnpickler raises AttributeError
b'ibuiltins
\
n
list
\
n
.'
,
# INST
b'l.'
,
# LIST
b'o.'
,
# OBJ
b'(o.'
,
b'p1
\
n
.'
,
# PUT
b'q
\
x00
.'
,
# BINPUT
b'r
\
x00
\
x00
\
x00
\
x00
.'
,
# LONG_BINPUT
b's.'
,
# SETITEM
b'Ns.'
,
b'NNs.'
,
b't.'
,
# TUPLE
b'u.'
,
# SETITEMS
b'(u.'
,
b'}(Nu.'
,
b'
\
x81
.'
,
# NEWOBJ
b')
\
x81
.'
,
b'
\
x85
.'
,
# TUPLE1
b'
\
x86
.'
,
# TUPLE2
b'N
\
x86
.'
,
b'
\
x87
.'
,
# TUPLE3
b'N
\
x87
.'
,
b'NN
\
x87
.'
,
b'
\
x90
.'
,
# ADDITEMS
# b'(\x90.', # PyUnpickler raises AttributeError
b'
\
x91
.'
,
# FROZENSET
b'
\
x92
.'
,
# NEWOBJ_EX
b')}
\
x92
.'
,
b'
\
x93
.'
,
# STACK_GLOBAL
b'Vlist
\
n
\
x93
.'
,
b'
\
x94
.'
,
# MEMOIZE
]
for
p
in
badpickles
:
with
self
.
subTest
(
p
):
self
.
assertRaises
(
self
.
bad_stack_errors
,
self
.
loads
,
p
)
def
test_bad_mark
(
self
):
badpickles
=
[
b'cbuiltins
\
n
list
\
n
)(R.'
,
# REDUCE
b'cbuiltins
\
n
list
\
n
()R.'
,
b']N(a.'
,
# APPEND
b'cbuiltins
\
n
ValueError
\
n
)R}(b.'
,
# BUILD
b'cbuiltins
\
n
ValueError
\
n
)R(}b.'
,
b'(Nd.'
,
# DICT
b'}NN(s.'
,
# SETITEM
b'}N(Ns.'
,
b'cbuiltins
\
n
list
\
n
)(
\
x81
.'
,
# NEWOBJ
b'cbuiltins
\
n
list
\
n
()
\
x81
.'
,
b'N(
\
x85
.'
,
# TUPLE1
b'NN(
\
x86
.'
,
# TUPLE2
b'N(N
\
x86
.'
,
b'NNN(
\
x87
.'
,
# TUPLE3
b'NN(N
\
x87
.'
,
b'N(NN
\
x87
.'
,
b'cbuiltins
\
n
list
\
n
)}(
\
x92
.'
,
# NEWOBJ_EX
b'cbuiltins
\
n
list
\
n
)(}
\
x92
.'
,
b'cbuiltins
\
n
list
\
n
()}
\
x92
.'
,
b'Vbuiltins
\
n
(Vlist
\
n
\
x93
.'
,
# STACK_GLOBAL
b'Vbuiltins
\
n
Vlist
\
n
(
\
x93
.'
,
]
for
p
in
badpickles
:
# PyUnpickler prints reduce errors to stdout
with
self
.
subTest
(
p
),
captured_stdout
():
try
:
self
.
loads
(
p
)
except
(
IndexError
,
AttributeError
,
TypeError
,
pickle
.
UnpicklingError
):
pass
class
AbstractPickleTests
(
unittest
.
TestCase
):
# Subclass must define self.dumps, self.loads.
...
...
Lib/test/test_pickle.py
View file @
4409c6cf
...
...
@@ -32,6 +32,7 @@ class PickleTests(AbstractPickleModuleTests):
class
PyUnpicklerTests
(
AbstractUnpickleTests
):
unpickler
=
pickle
.
_Unpickler
bad_stack_errors
=
(
IndexError
,)
def
loads
(
self
,
buf
,
**
kwds
):
f
=
io
.
BytesIO
(
buf
)
...
...
@@ -62,6 +63,7 @@ class InMemoryPickleTests(AbstractPickleTests, AbstractUnpickleTests,
pickler
=
pickle
.
_Pickler
unpickler
=
pickle
.
_Unpickler
bad_stack_errors
=
(
pickle
.
UnpicklingError
,
IndexError
)
def
dumps
(
self
,
arg
,
protocol
=
None
):
return
pickle
.
dumps
(
arg
,
protocol
)
...
...
@@ -119,6 +121,7 @@ class PyChainDispatchTableTests(AbstractDispatchTableTests):
if
has_c_implementation
:
class
CUnpicklerTests
(
PyUnpicklerTests
):
unpickler
=
_pickle
.
Unpickler
bad_stack_errors
=
(
pickle
.
UnpicklingError
,)
class
CPicklerTests
(
PyPicklerTests
):
pickler
=
_pickle
.
Pickler
...
...
Misc/NEWS
View file @
4409c6cf
...
...
@@ -13,6 +13,8 @@ Core and Builtins
Library
-------
- Issue #23914: Fixed SystemError raised by unpickler on broken pickle data.
- Issue #25691: Fixed crash on deleting ElementTree.Element attributes.
- Issue #25624: ZipFile now always writes a ZIP_STORED header for directory
...
...
Modules/_pickle.c
View file @
4409c6cf
...
...
@@ -459,8 +459,8 @@ Pdata_grow(Pdata *self)
static
PyObject
*
Pdata_pop
(
Pdata
*
self
)
{
PickleState
*
st
=
_Pickle_GetGlobalState
();
if
(
Py_SIZE
(
self
)
==
0
)
{
PickleState
*
st
=
_Pickle_GetGlobalState
();
PyErr_SetString
(
st
->
UnpicklingError
,
"bad pickle data"
);
return
NULL
;
}
...
...
@@ -5148,6 +5148,9 @@ load_obj(UnpicklerObject *self)
if
((
i
=
marker
(
self
))
<
0
)
return
-
1
;
if
(
Py_SIZE
(
self
->
stack
)
-
i
<
1
)
return
stack_underflow
();
args
=
Pdata_poptuple
(
self
->
stack
,
i
+
1
);
if
(
args
==
NULL
)
return
-
1
;
...
...
@@ -5806,13 +5809,18 @@ do_append(UnpicklerObject *self, Py_ssize_t x)
static
int
load_append
(
UnpicklerObject
*
self
)
{
if
(
Py_SIZE
(
self
->
stack
)
-
1
<=
0
)
return
stack_underflow
();
return
do_append
(
self
,
Py_SIZE
(
self
->
stack
)
-
1
);
}
static
int
load_appends
(
UnpicklerObject
*
self
)
{
return
do_append
(
self
,
marker
(
self
));
Py_ssize_t
i
=
marker
(
self
);
if
(
i
<
0
)
return
-
1
;
return
do_append
(
self
,
i
);
}
static
int
...
...
@@ -5862,7 +5870,10 @@ load_setitem(UnpicklerObject *self)
static
int
load_setitems
(
UnpicklerObject
*
self
)
{
return
do_setitems
(
self
,
marker
(
self
));
Py_ssize_t
i
=
marker
(
self
);
if
(
i
<
0
)
return
-
1
;
return
do_setitems
(
self
,
i
);
}
static
int
...
...
@@ -5872,6 +5883,8 @@ load_additems(UnpicklerObject *self)
Py_ssize_t
mark
,
len
,
i
;
mark
=
marker
(
self
);
if
(
mark
<
0
)
return
-
1
;
len
=
Py_SIZE
(
self
->
stack
);
if
(
mark
>
len
||
mark
<=
0
)
return
stack_underflow
();
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment