summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSerhiy Storchaka <storchaka@gmail.com>2015-11-29 11:12:40 (GMT)
committerSerhiy Storchaka <storchaka@gmail.com>2015-11-29 11:12:40 (GMT)
commitbf19ce27c44c7bb7ba45cfa18a26132a9e6bf2ca (patch)
treeb167338f9276035212b691ae97df07fd3987544c
parente08496b62ddac29713a9fbc849fde5b9bb4f1121 (diff)
downloadcpython-bf19ce27c44c7bb7ba45cfa18a26132a9e6bf2ca.zip
cpython-bf19ce27c44c7bb7ba45cfa18a26132a9e6bf2ca.tar.gz
cpython-bf19ce27c44c7bb7ba45cfa18a26132a9e6bf2ca.tar.bz2
Issue #25761: Added more test cases for testing unpickling broken data.
Output raised exception at verbose level 2 (-vv).
-rw-r--r--Lib/test/pickletester.py227
-rw-r--r--Lib/test/test_cpickle.py6
-rw-r--r--Lib/test/test_pickle.py13
3 files changed, 170 insertions, 76 deletions
diff --git a/Lib/test/pickletester.py b/Lib/test/pickletester.py
index 827d31b..96df135 100644
--- a/Lib/test/pickletester.py
+++ b/Lib/test/pickletester.py
@@ -6,7 +6,9 @@ import StringIO
import cStringIO
import pickletools
import copy_reg
+import sys
+from test import test_support as support
from test.test_support import TestFailed, verbose, have_unicode, TESTFN
try:
from test.test_support import _2G, _1M, precisionbigmemtest
@@ -473,6 +475,17 @@ class AbstractUnpickleTests(unittest.TestCase):
self.assertEqual(getattr(obj, slot, None),
getattr(objcopy, slot, None), msg=msg)
+ def check_unpickling_error(self, errors, data):
+ with self.assertRaises(errors):
+ try:
+ self.loads(data)
+ except:
+ if support.verbose > 1:
+ exc = sys.exc_info()[1]
+ print('%-32r - %s: %s' %
+ (data, exc.__class__.__name__, exc))
+ raise
+
def test_load_from_canned_string(self):
expected = self._testdata
for canned in DATA0, DATA1, DATA2:
@@ -480,7 +493,7 @@ class AbstractUnpickleTests(unittest.TestCase):
self.assert_is_copy(expected, got)
def test_garyp(self):
- self.assertRaises(self.error, self.loads, 'garyp')
+ self.check_unpickling_error(self.error, 'garyp')
def test_maxint64(self):
maxint64 = (1L << 63) - 1
@@ -490,7 +503,7 @@ class AbstractUnpickleTests(unittest.TestCase):
# Try too with a bogus literal.
data = 'I' + str(maxint64) + 'JUNK\n.'
- self.assertRaises(ValueError, self.loads, data)
+ self.check_unpickling_error(ValueError, data)
def test_insecure_strings(self):
insecure = ["abc", "2 + 2", # not quoted
@@ -511,7 +524,7 @@ class AbstractUnpickleTests(unittest.TestCase):
]
for s in insecure:
buf = "S" + s + "\n."
- self.assertRaises(ValueError, self.loads, buf)
+ self.check_unpickling_error(ValueError, buf)
def test_correctly_quoted_string(self):
goodpickles = [("S''\n.", ''),
@@ -578,11 +591,6 @@ class AbstractUnpickleTests(unittest.TestCase):
'q\x00oq\x01}q\x02b.').replace('X', xname)
self.assert_is_copy(X(*args), self.loads(pickle2))
- def test_pop_empty_stack(self):
- # Test issue7455
- s = '0'
- self.assertRaises((cPickle.UnpicklingError, IndexError), self.loads, s)
-
def test_load_str(self):
# From Python 2: pickle.dumps('a\x00\xa0', protocol=0)
self.assertEqual(self.loads("S'a\\x00\\xa0'\n."), 'a\x00\xa0')
@@ -607,8 +615,8 @@ class AbstractUnpickleTests(unittest.TestCase):
self.assertIs(self.loads('I00\n.'), False)
def test_misc_get(self):
- self.assertRaises(self.error, self.loads, 'g0\np0\n')
- self.assertRaises(self.error, self.loads, 'h\x00q\x00')
+ self.check_unpickling_error(self.error, 'g0\np0\n')
+ self.check_unpickling_error(self.error, 'h\x00q\x00')
def test_get(self):
pickled = '((lp100000\ng100000\nt.'
@@ -636,74 +644,145 @@ class AbstractUnpickleTests(unittest.TestCase):
def test_bad_stack(self):
badpickles = [
- '0.', # POP
- '1.', # POP_MARK
- '2.', # DUP
- # '(2.', # PyUnpickler doesn't raise
- 'R.', # REDUCE
- ')R.',
- 'a.', # APPEND
- 'Na.',
- 'b.', # BUILD
- 'Nb.',
- 'd.', # DICT
- 'e.', # APPENDS
- # '(e.', # PyUnpickler raises AttributeError
- 'i__builtin__\nlist\n.', # INST
- 'l.', # LIST
- 'o.', # OBJ
- '(o.',
- 'p1\n.', # PUT
- 'q\x00.', # BINPUT
- 'r\x00\x00\x00\x00.', # LONG_BINPUT
- 's.', # SETITEM
- 'Ns.',
- 'NNs.',
- 't.', # TUPLE
- 'u.', # SETITEMS
- '(u.',
- '}(Nu.',
- '\x81.', # NEWOBJ
- ')\x81.',
- '\x85.', # TUPLE1
- '\x86.', # TUPLE2
- 'N\x86.',
- '\x87.', # TUPLE3
- 'N\x87.',
- 'NN\x87.',
+ '.', # STOP
+ '0', # POP
+ '1', # POP_MARK
+ '2', # DUP
+ # '(2', # PyUnpickler doesn't raise
+ 'R', # REDUCE
+ ')R',
+ 'a', # APPEND
+ 'Na',
+ 'b', # BUILD
+ 'Nb',
+ 'd', # DICT
+ 'e', # APPENDS
+ # '(e', # PyUnpickler raises AttributeError
+ 'i__builtin__\nlist\n', # INST
+ 'l', # LIST
+ 'o', # OBJ
+ '(o',
+ 'p1\n', # PUT
+ 'q\x00', # BINPUT
+ 'r\x00\x00\x00\x00', # LONG_BINPUT
+ 's', # SETITEM
+ 'Ns',
+ 'NNs',
+ 't', # TUPLE
+ 'u', # SETITEMS
+ # '(u', # PyUnpickler doesn't raise
+ '}(Nu',
+ '\x81', # NEWOBJ
+ ')\x81',
+ '\x85', # TUPLE1
+ '\x86', # TUPLE2
+ 'N\x86',
+ '\x87', # TUPLE3
+ 'N\x87',
+ 'NN\x87',
]
for p in badpickles:
- try:
- self.assertRaises(self.bad_stack_errors, self.loads, p)
- except:
- print '***', repr(p)
- raise
+ self.check_unpickling_error(self.bad_stack_errors, p)
def test_bad_mark(self):
badpickles = [
- 'c__builtin__\nlist\n)(R.', # REDUCE
- 'c__builtin__\nlist\n()R.',
- ']N(a.', # APPEND
- 'cexceptions\nValueError\n)R}(b.', # BUILD
- 'cexceptions\nValueError\n)R(}b.',
- '(Nd.', # DICT
- '}NN(s.', # SETITEM
- '}N(Ns.',
- 'c__builtin__\nlist\n)(\x81.', # NEWOBJ
- 'c__builtin__\nlist\n()\x81.',
- 'N(\x85.', # TUPLE1
- 'NN(\x86.', # TUPLE2
- 'N(N\x86.',
- 'NNN(\x87.', # TUPLE3
- 'NN(N\x87.',
- 'N(NN\x87.',
+ # 'N(.', # STOP
+ 'N(2', # DUP
+ 'c__builtin__\nlist\n)(R', # REDUCE
+ 'c__builtin__\nlist\n()R',
+ ']N(a', # APPEND
+ # BUILD
+ 'c__builtin__\nValueError\n)R}(b',
+ 'c__builtin__\nValueError\n)R(}b',
+ '(Nd', # DICT
+ 'N(p1\n', # PUT
+ 'N(q\x00', # BINPUT
+ 'N(r\x00\x00\x00\x00', # LONG_BINPUT
+ '}NN(s', # SETITEM
+ '}N(Ns',
+ '}(NNs',
+ '}((u', # SETITEMS
+ # NEWOBJ
+ 'c__builtin__\nlist\n)(\x81',
+ 'c__builtin__\nlist\n()\x81',
+ 'N(\x85', # TUPLE1
+ 'NN(\x86', # TUPLE2
+ 'N(N\x86',
+ 'NNN(\x87', # TUPLE3
+ 'NN(N\x87',
+ 'N(NN\x87',
]
for p in badpickles:
- try:
- self.loads(p)
- except (IndexError, AttributeError, TypeError,
- pickle.UnpicklingError):
- pass
+ self.check_unpickling_error(self.bad_mark_errors, p)
+
+ def test_truncated_data(self):
+ self.check_unpickling_error(EOFError, b'')
+ self.check_unpickling_error(EOFError, b'N')
+ badpickles = [
+ 'F', # FLOAT
+ 'F0.0',
+ 'F0.00',
+ 'G', # BINFLOAT
+ 'G\x00\x00\x00\x00\x00\x00\x00',
+ 'I', # INT
+ 'I0',
+ 'J', # BININT
+ 'J\x00\x00\x00',
+ 'K', # BININT1
+ 'L', # LONG
+ 'L0',
+ 'L10',
+ 'L0L',
+ 'L10L',
+ 'M', # BININT2
+ 'M\x00',
+ # 'P', # PERSID
+ # 'Pabc',
+ 'S', # STRING
+ b"S'abc'",
+ 'T', # BINSTRING
+ 'T\x03\x00\x00',
+ 'T\x03\x00\x00\x00',
+ 'T\x03\x00\x00\x00ab',
+ 'U', # SHORT_BINSTRING
+ 'U\x03',
+ 'U\x03ab',
+ 'V', # UNICODE
+ 'Vabc',
+ 'X', # BINUNICODE
+ 'X\x03\x00\x00',
+ 'X\x03\x00\x00\x00',
+ 'X\x03\x00\x00\x00ab',
+ '(c', # GLOBAL
+ '(c__builtin__',
+ '(c__builtin__\n',
+ '(c__builtin__\nlist',
+ 'Ng', # GET
+ 'Ng0',
+ '(i', # INST
+ '(i__builtin__',
+ '(i__builtin__\n',
+ '(i__builtin__\nlist',
+ 'Nh', # BINGET
+ 'Nj', # LONG_BINGET
+ 'Nj\x00\x00\x00',
+ 'Np', # PUT
+ 'Np0',
+ 'Nq', # BINPUT
+ 'Nr', # LONG_BINPUT
+ 'Nr\x00\x00\x00',
+ '\x80', # PROTO
+ '\x82', # EXT1
+ '\x83', # EXT2
+ '\x84\x01',
+ '\x84', # EXT4
+ '\x84\x01\x00\x00',
+ '\x8a', # LONG1
+ '\x8b', # LONG4
+ '\x8b\x00\x00\x00',
+ ]
+ for p in badpickles:
+ self.check_unpickling_error(self.truncated_errors, p)
class AbstractPickleTests(unittest.TestCase):
@@ -1467,11 +1546,7 @@ class AbstractPickleModuleTests(unittest.TestCase):
# Test issue4298
s = '\x58\0\0\0\x54'
self.assertRaises(EOFError, self.module.loads, s)
- # Test issue7455
- s = '0'
- # XXX Why doesn't pickle raise UnpicklingError?
- self.assertRaises((IndexError, cPickle.UnpicklingError),
- self.module.loads, s)
+
class AbstractPersistentPicklerTests(unittest.TestCase):
diff --git a/Lib/test/test_cpickle.py b/Lib/test/test_cpickle.py
index fff2b80..c9ec788 100644
--- a/Lib/test/test_cpickle.py
+++ b/Lib/test/test_cpickle.py
@@ -52,6 +52,9 @@ class cPickleTests(AbstractUnpickleTests, AbstractPickleTests,
error = cPickle.BadPickleGet
module = cPickle
bad_stack_errors = (cPickle.UnpicklingError,)
+ bad_mark_errors = (EOFError,)
+ truncated_errors = (cPickle.UnpicklingError, EOFError,
+ AttributeError, ValueError)
class cPickleUnpicklerTests(AbstractUnpickleTests):
@@ -65,6 +68,9 @@ class cPickleUnpicklerTests(AbstractUnpickleTests):
error = cPickle.BadPickleGet
bad_stack_errors = (cPickle.UnpicklingError,)
+ bad_mark_errors = (EOFError,)
+ truncated_errors = (cPickle.UnpicklingError, EOFError,
+ AttributeError, ValueError)
class cStringIOCUnpicklerTests(cStringIOMixin, cPickleUnpicklerTests):
pass
diff --git a/Lib/test/test_pickle.py b/Lib/test/test_pickle.py
index cbcf491..bb43656 100644
--- a/Lib/test/test_pickle.py
+++ b/Lib/test/test_pickle.py
@@ -1,4 +1,5 @@
import pickle
+import struct
from cStringIO import StringIO
from test import test_support
@@ -24,11 +25,23 @@ class PickleTests(AbstractUnpickleTests, AbstractPickleTests,
module = pickle
error = KeyError
bad_stack_errors = (IndexError,)
+ bad_mark_errors = (IndexError, pickle.UnpicklingError,
+ TypeError, AttributeError, EOFError)
+ truncated_errors = (pickle.UnpicklingError, EOFError,
+ AttributeError, ValueError,
+ struct.error, IndexError, ImportError,
+ TypeError, KeyError)
class UnpicklerTests(AbstractUnpickleTests):
error = KeyError
bad_stack_errors = (IndexError,)
+ bad_mark_errors = (IndexError, pickle.UnpicklingError,
+ TypeError, AttributeError, EOFError)
+ truncated_errors = (pickle.UnpicklingError, EOFError,
+ AttributeError, ValueError,
+ struct.error, IndexError, ImportError,
+ TypeError, KeyError)
def loads(self, buf):
f = StringIO(buf)