diff --git a/buildandrun b/buildandrun index d3b4e42..41a636a 100755 --- a/buildandrun +++ b/buildandrun @@ -58,7 +58,8 @@ def main(): os.putenv('PYTHONPATH', libdir) rc = subprocess.call( ['python',] + args ) - + if rc == -11: + logging.error('Segmentation fault in test process. Test failed.') if __name__ == '__main__': diff --git a/cheetah/Tests/NameMapper.py b/cheetah/Tests/NameMapper.py index ac42244..c44fb4c 100644 --- a/cheetah/Tests/NameMapper.py +++ b/cheetah/Tests/NameMapper.py @@ -43,6 +43,10 @@ def meth3(self): except: raise +class DummyClassGetAttrRaises(object): + def __getattr__(self, name): + raise ValueError + def dummyFunc(arg="Scooby"): return arg @@ -67,6 +71,7 @@ def funcThatRaises(): 'aClass': DummyClass, 'aFunc': dummyFunc, 'anObj': DummyClass(), + 'anObjThatRaises': DummyClassGetAttrRaises(), 'aMeth': DummyClass().meth1, 'none': None, 'emptyString': '', @@ -419,6 +424,14 @@ def test60(self): for i in range(10): self.get('aDict.nestedDict.funcThatRaises', False) + def test61(self): + """Accessing attribute where __getattr__ raises shouldn't segfault if something follows it""" + + def test(self=self): + self.get('anObjThatRaises.willraise.anything') + self.assertRaises(ValueError, test) + + class VFS(VFN): _searchListLength = 1 diff --git a/cheetah/c/_namemapper.c b/cheetah/c/_namemapper.c index a41571b..a114658 100644 --- a/cheetah/c/_namemapper.c +++ b/cheetah/c/_namemapper.c @@ -188,14 +188,15 @@ static PyObject *PyNamemapper_valueForName(PyObject *obj, char *nameChunks[], in nextVal = PyObject_GetAttrString(currentVal, currentKey); exc = PyErr_Occurred(); if (exc != NULL) { - // if exception == AttributeError + // if exception == AttributeError, report our own exception if (PyErr_ExceptionMatches(PyExc_AttributeError)) { setNotFoundException(currentKey, currentVal); - if (i > 0) { - Py_DECREF(currentVal); - } - return NULL; } + // any exceptions results in failure + if (i > 0) { + Py_DECREF(currentVal); + } + return NULL; } } if (i > 0) {