# HG changeset patch # User Paul Boddie # Date 1243036006 -7200 # Node ID 2fb8b284aba302f570328c8bf1195f5e17db49cd # Parent b58aae0af656187bf2c220b683e466577ea26382 Added callable context vs. self argument validation in CheckFrame, plus a test which detects an attempt to fake the self argument with an incompatible instance. diff -r b58aae0af656 -r 2fb8b284aba3 rsvp.py --- a/rsvp.py Fri May 22 00:17:35 2009 +0200 +++ b/rsvp.py Sat May 23 01:46:46 2009 +0200 @@ -508,17 +508,40 @@ nlocals -= 1 else: context_data = self.load(context_ref) + + # Classes are not themselves usable as the self argument. + # NOTE: This may change at some point. + # However, where classes appear as the context, instance + # compatibility is required in the first argument. + if context_data.attrcode is None: # absent attrcode == class + + # Slide the frame to exclude the context. + self.local_sp_stack[-1] += 1 nlocals -= 1 - # NOTE: Should check the context here. + # Check the context against the first argument. + # NOTE: Raise a proper exception here. + + if nlocals > 0: + self_context, self_ref = self.frame_stack[frame + 1] + if not self._CheckInstance(self_ref, context_context): + raise Exception, "CheckFrame %r (%r vs. %r)" % (self.operand, self.load(self_ref), self.load(context_context)) + #self.exception = self.type_error + #return self.RaiseException() + else: + raise Exception, "CheckFrame %r (no self argument)" % self.operand + #self.exception = self.type_error + #return self.RaiseException() # Test the frame size. # NOTE: Raise a proper exception here. if not ((nargs - ndefaults) <= nlocals and (nlocals <= nargs or has_star)): raise Exception, "CheckFrame %r (%r <= %r <= %r)" % (self.operand, nargs - ndefaults, nlocals, nargs) + #self.exception = self.type_error + #return self.RaiseException() def FillDefaults(self): # NOTE: Make the get_operand method of the instruction provide the @@ -637,8 +660,11 @@ # Find the table entry for the descendant. element = self.objlist[target_data.classcode + data.attrcode] - attr_index, class_attr, offset = element - return attr_index == data.attrcode + if element is not None: + attr_index, class_attr, offset = element + return attr_index == data.attrcode + else: + return 0 def _MakeObject(self, size, ref): # Load the template. diff -r b58aae0af656 -r 2fb8b284aba3 tests/attributes_class_bind_function_unbound_fake_self.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/tests/attributes_class_bind_function_unbound_fake_self.py Sat May 23 01:46:46 2009 +0200 @@ -0,0 +1,16 @@ +#!/usr/bin/env python + +def e(self, x): + return x + +class C: + e = e + +class D: + e = C.e + +d = D() +q = d.e # unbound C.e +result = q(123, 321) + +# vim: tabstop=4 expandtab shiftwidth=4