diff options
author | cinap_lenrek <cinap_lenrek@localhost> | 2011-05-03 11:25:13 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@localhost> | 2011-05-03 11:25:13 +0000 |
commit | 458120dd40db6b4df55a4e96b650e16798ef06a0 (patch) | |
tree | 8f82685be24fef97e715c6f5ca4c68d34d5074ee /sys/lib/python/test/crashers | |
parent | 3a742c699f6806c1145aea5149bf15de15a0afd7 (diff) |
add hg and python
Diffstat (limited to 'sys/lib/python/test/crashers')
-rw-r--r-- | sys/lib/python/test/crashers/README | 20 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/bogus_code_obj.py | 19 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/borrowed_ref_1.py | 29 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/borrowed_ref_2.py | 38 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/dangerous_subclassing.py | 12 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/gc_inspection.py | 32 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/infinite_rec_1.py | 11 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/infinite_rec_2.py | 10 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/infinite_rec_4.py | 7 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/infinite_rec_5.py | 10 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/loosing_dict_ref.py | 21 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/modify_dict_attr.py | 19 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/nasty_eq_vs_dict.py | 47 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/recursion_limit_too_high.py | 16 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/recursive_call.py | 15 | ||||
-rw-r--r-- | sys/lib/python/test/crashers/weakref_in_del.py | 17 |
16 files changed, 323 insertions, 0 deletions
diff --git a/sys/lib/python/test/crashers/README b/sys/lib/python/test/crashers/README new file mode 100644 index 000000000..070c3f122 --- /dev/null +++ b/sys/lib/python/test/crashers/README @@ -0,0 +1,20 @@ +This directory only contains tests for outstanding bugs that cause +the interpreter to segfault. Ideally this directory should always +be empty. Sometimes it may not be easy to fix the underlying cause. + +Each test should fail when run from the command line: + + ./python Lib/test/crashers/weakref_in_del.py + +Each test should have a link to the bug report: + + # http://python.org/sf/BUG# + +Put as much info into a docstring or comments to help determine +the cause of the failure. Particularly note if the cause is +system or environment dependent and what the variables are. + +Once the crash is fixed, the test case should be moved into an appropriate +test (even if it was originally from the test suite). This ensures the +regression doesn't happen again. And if it does, it should be easier +to track down. diff --git a/sys/lib/python/test/crashers/bogus_code_obj.py b/sys/lib/python/test/crashers/bogus_code_obj.py new file mode 100644 index 000000000..613ae518d --- /dev/null +++ b/sys/lib/python/test/crashers/bogus_code_obj.py @@ -0,0 +1,19 @@ +""" +Broken bytecode objects can easily crash the interpreter. + +This is not going to be fixed. It is generally agreed that there is no +point in writing a bytecode verifier and putting it in CPython just for +this. Moreover, a verifier is bound to accept only a subset of all safe +bytecodes, so it could lead to unnecessary breakage. + +For security purposes, "restricted" interpreters are not going to let +the user build or load random bytecodes anyway. Otherwise, this is a +"won't fix" case. + +""" + +import types + +co = types.CodeType(0, 0, 0, 0, '\x04\x71\x00\x00', (), + (), (), '', '', 1, '') +exec co diff --git a/sys/lib/python/test/crashers/borrowed_ref_1.py b/sys/lib/python/test/crashers/borrowed_ref_1.py new file mode 100644 index 000000000..d16ede2e4 --- /dev/null +++ b/sys/lib/python/test/crashers/borrowed_ref_1.py @@ -0,0 +1,29 @@ +""" +_PyType_Lookup() returns a borrowed reference. +This attacks the call in dictobject.c. +""" + +class A(object): + pass + +class B(object): + def __del__(self): + print 'hi' + del D.__missing__ + +class D(dict): + class __missing__: + def __init__(self, *args): + pass + + +d = D() +a = A() +a.cycle = a +a.other = B() +del a + +prev = None +while 1: + d[5] + prev = (prev,) diff --git a/sys/lib/python/test/crashers/borrowed_ref_2.py b/sys/lib/python/test/crashers/borrowed_ref_2.py new file mode 100644 index 000000000..1a7b3ff75 --- /dev/null +++ b/sys/lib/python/test/crashers/borrowed_ref_2.py @@ -0,0 +1,38 @@ +""" +_PyType_Lookup() returns a borrowed reference. +This attacks PyObject_GenericSetAttr(). + +NB. on my machine this crashes in 2.5 debug but not release. +""" + +class A(object): + pass + +class B(object): + def __del__(self): + print "hi" + del C.d + +class D(object): + def __set__(self, obj, value): + self.hello = 42 + +class C(object): + d = D() + + def g(): + pass + + +c = C() +a = A() +a.cycle = a +a.other = B() + +lst = [None] * 1000000 +i = 0 +del a +while 1: + c.d = 42 # segfaults in PyMethod_New(im_func=D.__set__, im_self=d) + lst[i] = c.g # consume the free list of instancemethod objects + i += 1 diff --git a/sys/lib/python/test/crashers/dangerous_subclassing.py b/sys/lib/python/test/crashers/dangerous_subclassing.py new file mode 100644 index 000000000..0479952b2 --- /dev/null +++ b/sys/lib/python/test/crashers/dangerous_subclassing.py @@ -0,0 +1,12 @@ + +# http://python.org/sf/1174712 + +import types + +class X(types.ModuleType, str): + """Such a subclassing is incorrectly allowed -- + see the SF bug report for explanations""" + +if __name__ == '__main__': + X('name') # segfault: ModuleType.__init__() reads + # the dict at the wrong offset diff --git a/sys/lib/python/test/crashers/gc_inspection.py b/sys/lib/python/test/crashers/gc_inspection.py new file mode 100644 index 000000000..10caa7978 --- /dev/null +++ b/sys/lib/python/test/crashers/gc_inspection.py @@ -0,0 +1,32 @@ +""" +gc.get_referrers() can be used to see objects before they are fully built. + +Note that this is only an example. There are many ways to crash Python +by using gc.get_referrers(), as well as many extension modules (even +when they are using perfectly documented patterns to build objects). + +Identifying and removing all places that expose to the GC a +partially-built object is a long-term project. A patch was proposed on +SF specifically for this example but I consider fixing just this single +example a bit pointless (#1517042). + +A fix would include a whole-scale code review, possibly with an API +change to decouple object creation and GC registration, and according +fixes to the documentation for extension module writers. It's unlikely +to happen, though. So this is currently classified as +"gc.get_referrers() is dangerous, use only for debugging". +""" + +import gc + + +def g(): + marker = object() + yield marker + # now the marker is in the tuple being constructed + [tup] = [x for x in gc.get_referrers(marker) if type(x) is tuple] + print tup + print tup[1] + + +tuple(g()) diff --git a/sys/lib/python/test/crashers/infinite_rec_1.py b/sys/lib/python/test/crashers/infinite_rec_1.py new file mode 100644 index 000000000..573a509b5 --- /dev/null +++ b/sys/lib/python/test/crashers/infinite_rec_1.py @@ -0,0 +1,11 @@ + +# http://python.org/sf/1202533 + +import new, operator + +class A: + pass +A.__mul__ = new.instancemethod(operator.mul, None, A) + +if __name__ == '__main__': + A()*2 # segfault: infinite recursion in C diff --git a/sys/lib/python/test/crashers/infinite_rec_2.py b/sys/lib/python/test/crashers/infinite_rec_2.py new file mode 100644 index 000000000..5a14b33ea --- /dev/null +++ b/sys/lib/python/test/crashers/infinite_rec_2.py @@ -0,0 +1,10 @@ + +# http://python.org/sf/1202533 + +class A(str): + __get__ = getattr + +if __name__ == '__main__': + a = A('a') + A.a = a + a.a # segfault: infinite recursion in C diff --git a/sys/lib/python/test/crashers/infinite_rec_4.py b/sys/lib/python/test/crashers/infinite_rec_4.py new file mode 100644 index 000000000..14f15208e --- /dev/null +++ b/sys/lib/python/test/crashers/infinite_rec_4.py @@ -0,0 +1,7 @@ + +# http://python.org/sf/1202533 + +if __name__ == '__main__': + lst = [apply] + lst.append(lst) + apply(*lst) # segfault: infinite recursion in C diff --git a/sys/lib/python/test/crashers/infinite_rec_5.py b/sys/lib/python/test/crashers/infinite_rec_5.py new file mode 100644 index 000000000..18d296323 --- /dev/null +++ b/sys/lib/python/test/crashers/infinite_rec_5.py @@ -0,0 +1,10 @@ + +# http://python.org/sf/1267884 + +import types + +class C: + __str__ = types.InstanceType.__str__ + +if __name__ == '__main__': + str(C()) # segfault: infinite recursion in C diff --git a/sys/lib/python/test/crashers/loosing_dict_ref.py b/sys/lib/python/test/crashers/loosing_dict_ref.py new file mode 100644 index 000000000..f44370b9a --- /dev/null +++ b/sys/lib/python/test/crashers/loosing_dict_ref.py @@ -0,0 +1,21 @@ + +# http://python.org/sf/1303614 + +class Strange(object): + def __hash__(self): + return hash('hello') + + def __eq__(self, other): + x.__dict__ = {} # the old x.__dict__ is deallocated + return False + + +class X(object): + pass + +if __name__ == '__main__': + v = 123 + x = X() + x.__dict__ = {Strange(): 42, + 'hello': v+456} + x.hello # segfault: the above dict is accessed after it's deallocated diff --git a/sys/lib/python/test/crashers/modify_dict_attr.py b/sys/lib/python/test/crashers/modify_dict_attr.py new file mode 100644 index 000000000..dfce467c8 --- /dev/null +++ b/sys/lib/python/test/crashers/modify_dict_attr.py @@ -0,0 +1,19 @@ + +# http://python.org/sf/1303614 + +class Y(object): + pass + +class type_with_modifiable_dict(Y, type): + pass + +class MyClass(object): + """This class has its __dict__ attribute completely exposed: + user code can read, reassign and even delete it. + """ + __metaclass__ = type_with_modifiable_dict + + +if __name__ == '__main__': + del MyClass.__dict__ # if we set tp_dict to NULL, + print MyClass # doing anything with MyClass segfaults diff --git a/sys/lib/python/test/crashers/nasty_eq_vs_dict.py b/sys/lib/python/test/crashers/nasty_eq_vs_dict.py new file mode 100644 index 000000000..3f3083da8 --- /dev/null +++ b/sys/lib/python/test/crashers/nasty_eq_vs_dict.py @@ -0,0 +1,47 @@ +# from http://mail.python.org/pipermail/python-dev/2001-June/015239.html + +# if you keep changing a dictionary while looking up a key, you can +# provoke an infinite recursion in C + +# At the time neither Tim nor Michael could be bothered to think of a +# way to fix it. + +class Yuck: + def __init__(self): + self.i = 0 + + def make_dangerous(self): + self.i = 1 + + def __hash__(self): + # direct to slot 4 in table of size 8; slot 12 when size 16 + return 4 + 8 + + def __eq__(self, other): + if self.i == 0: + # leave dict alone + pass + elif self.i == 1: + # fiddle to 16 slots + self.__fill_dict(6) + self.i = 2 + else: + # fiddle to 8 slots + self.__fill_dict(4) + self.i = 1 + + return 1 + + def __fill_dict(self, n): + self.i = 0 + dict.clear() + for i in range(n): + dict[i] = i + dict[self] = "OK!" + +y = Yuck() +dict = {y: "OK!"} + +z = Yuck() +y.make_dangerous() +print dict[z] diff --git a/sys/lib/python/test/crashers/recursion_limit_too_high.py b/sys/lib/python/test/crashers/recursion_limit_too_high.py new file mode 100644 index 000000000..1fa4d3254 --- /dev/null +++ b/sys/lib/python/test/crashers/recursion_limit_too_high.py @@ -0,0 +1,16 @@ +# The following example may crash or not depending on the platform. +# E.g. on 32-bit Intel Linux in a "standard" configuration it seems to +# crash on Python 2.5 (but not 2.4 nor 2.3). On Windows the import +# eventually fails to find the module, possibly because we run out of +# file handles. + +# The point of this example is to show that sys.setrecursionlimit() is a +# hack, and not a robust solution. This example simply exercices a path +# where it takes many C-level recursions, consuming a lot of stack +# space, for each Python-level recursion. So 1000 times this amount of +# stack space may be too much for standard platforms already. + +import sys +if 'recursion_limit_too_high' in sys.modules: + del sys.modules['recursion_limit_too_high'] +import recursion_limit_too_high diff --git a/sys/lib/python/test/crashers/recursive_call.py b/sys/lib/python/test/crashers/recursive_call.py new file mode 100644 index 000000000..31c896330 --- /dev/null +++ b/sys/lib/python/test/crashers/recursive_call.py @@ -0,0 +1,15 @@ +#!/usr/bin/env python + +# No bug report AFAIK, mail on python-dev on 2006-01-10 + +# This is a "won't fix" case. It is known that setting a high enough +# recursion limit crashes by overflowing the stack. Unless this is +# redesigned somehow, it won't go away. + +import sys + +sys.setrecursionlimit(1 << 30) +f = lambda f:f(f) + +if __name__ == '__main__': + f(f) diff --git a/sys/lib/python/test/crashers/weakref_in_del.py b/sys/lib/python/test/crashers/weakref_in_del.py new file mode 100644 index 000000000..2e9b18683 --- /dev/null +++ b/sys/lib/python/test/crashers/weakref_in_del.py @@ -0,0 +1,17 @@ +import weakref + +# http://python.org/sf/1377858 +# Fixed for new-style classes in 2.5c1. + +ref = None + +def test_weakref_in_del(): + class Target(): + def __del__(self): + global ref + ref = weakref.ref(self) + + w = Target() + +if __name__ == '__main__': + test_weakref_in_del() |