A detailed analysis of _zope_interface_coptimizations.c was published at
https://gist.github.com/devdanzin/5afbad864934b165a2cc080f110aa720 by @devdanzin.
We reviewed the report with agent support and verified the findings against the
current source (zope.interface 8.2). This issue is one of several extracted from
that review.
Problem
When _implied or _cls fields are NULL (possible because they use
T_OBJECT_EX which allows deletion), three functions return NULL without setting
a Python exception, causing SystemError:
SB_extends line 331: if (implied == NULL) return NULL;
IB__adapt__ line 789: same pattern for _implied
CPB_descr_get line 618: if (self->_cls == NULL) return NULL;
Reproducer
from zope.interface._zope_interface_coptimizations import SpecificationBase
from zope.interface import Interface
sb = SpecificationBase()
sb.isOrExtends(Interface)
# SystemError: <method 'isOrExtends' of 'SpecificationBase' objects>
# returned NULL without setting an exception
from zope.interface._zope_interface_coptimizations import ClassProvidesBase
cpb = ClassProvidesBase.__new__(ClassProvidesBase)
cpb.__get__(object(), type)
# SystemError: <slot wrapper '__get__' of 'ClassProvidesBase' objects>
# returned NULL without setting an exception
Fix
Set an exception before returning NULL:
if (implied == NULL) {
PyErr_SetString(PyExc_AttributeError, "_implied");
return NULL;
}
Same for _cls in CPB_descr_get.
Scope
3 sites. No behavioral change for properly initialized objects.
Tests
Directly testable. The reproducers from the report work as-is as test cases:
def test_isOrExtends_raises_AttributeError_when_implied_is_None(self):
from zope.interface.interface import SpecificationBase
sb = SpecificationBase()
# _implied is not set (NULL in C)
with self.assertRaises(AttributeError):
sb.isOrExtends(object())
def test_CPB_descr_get_raises_AttributeError_when_cls_is_None(self):
from zope.interface._zope_interface_coptimizations import ClassProvidesBase
cpb = ClassProvidesBase.__new__(ClassProvidesBase)
with self.assertRaises(AttributeError):
cpb.__get__(object(), type)
These currently raise SystemError (the bug). After the fix they raise
AttributeError. The tests verify the fix works.
Note: these test the C implementation specifically. The Python fallback may
behave differently (regular AttributeError from Python attribute access). Both
paths should be tested via the existing Fallback/Optimized test class pattern.
Performance impact
Zero. The NULL check already exists in the current code. The fix only adds a
PyErr_SetString call inside the existing never-taken branch. No new branches,
no new instructions on the happy path.
A detailed analysis of
_zope_interface_coptimizations.cwas published athttps://gist.github.com/devdanzin/5afbad864934b165a2cc080f110aa720 by @devdanzin.
We reviewed the report with agent support and verified the findings against the
current source (zope.interface 8.2). This issue is one of several extracted from
that review.
Problem
When
_impliedor_clsfields are NULL (possible because they useT_OBJECT_EXwhich allows deletion), three functions return NULL without settinga Python exception, causing
SystemError:SB_extendsline 331:if (implied == NULL) return NULL;IB__adapt__line 789: same pattern for_impliedCPB_descr_getline 618:if (self->_cls == NULL) return NULL;Reproducer
Fix
Set an exception before returning NULL:
Same for
_clsinCPB_descr_get.Scope
3 sites. No behavioral change for properly initialized objects.
Tests
Directly testable. The reproducers from the report work as-is as test cases:
These currently raise
SystemError(the bug). After the fix they raiseAttributeError. The tests verify the fix works.Note: these test the C implementation specifically. The Python fallback may
behave differently (regular
AttributeErrorfrom Python attribute access). Bothpaths should be tested via the existing Fallback/Optimized test class pattern.
Performance impact
Zero. The NULL check already exists in the current code. The fix only adds a
PyErr_SetStringcall inside the existing never-taken branch. No new branches,no new instructions on the happy path.