14710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""
24710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmThe gc module can still invoke arbitrary Python code and crash.
34710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmThis is an attack against _PyInstance_Lookup(), which is documented
44710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmas follows:
54710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
64710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    The point of this routine is that it never calls arbitrary Python
74710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    code, so is always "safe":  all it does is dict lookups.
84710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
94710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmBut of course dict lookups can call arbitrary Python code.
104710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmThe following code causes mutation of the object graph during
114710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmthe call to has_finalizer() in gcmodule.c, and that might
124710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmsegfault.
134710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm"""
144710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
154710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmimport gc
164710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
174710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
184710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmclass A:
194710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __hash__(self):
204710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return hash("__del__")
214710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm    def __eq__(self, other):
224710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        del self.other
234710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm        return False
244710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
254710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylma = A()
264710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmb = A()
274710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
284710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylma.__dict__[b] = 'A'
294710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
304710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylma.other = b
314710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmb.other = a
324710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
334710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmgc.collect()
344710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmdel a, b
354710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylm
364710c53dcad1ebf3755f3efb9e80ac24bd72a9b2darylmgc.collect()
37