Re: Segfault in name mapper
"R. Tyler Croy" <[email protected]> Wed, 15 Sep 2010 10:54:18 -0700
| Newsgroups | gmane.comp.python.cheetah |
|---|---|
| Message-ID | <[email protected]> |
On Wed, 15 Sep 2010, Jon Siddle wrote:
> On 15/09/10 04:32, R. Tyler Croy wrote:
> >On Mon, 13 Sep 2010, Jon Siddle wrote:
> >
> >> It is possible to trivially cause the name mapper to segfault if
> >>getattr throws an exception:
> >
> >I just sat down to try to apply this patch and I realized it looks like you
> >passed along the output from git-diff(1). Would you mind using
> >git-format-patch(1) to generate a commit patch? This will allow your commit
> >message and attribution to be properly carried along.
>
> Oops. I'm fairly new to git I'm afraid. See attached.
Mahhhrrvelous. I've applied your commit and pushed it up to GitHub:
http://github.com/rtyler/cheetah/commit/0287a0833cc30e0e469f6a774770002128a0281f
I'll do some more rigorous testing and cut a new release this evening when I
get back from $DAYJOB.
Once again, great catch and thanks for the patch.
> >
> >>$a.b.c
> >>
> >>If a.__getattr__('b') throws an exception, the name mapper will
> >>segfault. This is caused by the
> >>following code in PyNamemapper_valueForName():
> >>
> >>nextVal = PyObject_GetAttrString(currentVal, currentKey);
> >>if (exc != NULL) {
> >> // if exception == AttributeError
> >> if (PyErr_ExceptionMatches(PyExc_AttributeError)) {
> >> setNotFoundException(currentKey, currentVal);
> >> if (i> 0) {
> >> Py_DECREF(currentVal);
> >> }
> >> return NULL;
> >> }
> >>}
> >>
> >>As you can see, only AttributeError is handled. Any other exception
> >>will cause currentVal to be NULL
> >>the next time round the loop and the call to
> >>PyObject_GetAttrString(currentVal, currentKey) will segfault.
> >>
> >>The solution is simply to move the decref-return code outside the
> >>check for AttributeError so that it happens
> >>for all exceptions.
> >>
> >>The attached patch fixes the bug, and adds a test for it. I've added
> >>a return code check to the buildandrun
> >>script so the segfault doesn't go unnoticed when the test fails.
> >>
> >>FYI We encountered this when using the sqlalchemy ORM, which can
> >>throw exceptions from __getattr__ on
> >>objects in the session, so it's quite likely that others will
> >>encounter this.
> >>
> >>Thanks
> >>
> >>Jon
> >>
> >>--
> >>Jon Siddle, CoreFiling Limited
> >>Software Tools Developer
> >>http://www.corefiling.com
> >>Phone: +44-1865-203192
> >>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 @@ class DummyClass(object):
> >> except:
> >> raise
> >>
> >>+class DummyClassGetAttrRaises(object):
> >>+ def __getattr__(self, name):
> >>+ raise ValueError
> >>+
> >>
> >> def dummyFunc(arg="Scooby"):
> >> return arg
> >>@@ -67,6 +71,7 @@ testNamespace = {
> >> 'aClass': DummyClass,
> >> 'aFunc': dummyFunc,
> >> 'anObj': DummyClass(),
> >>+ 'anObjThatRaises': DummyClassGetAttrRaises(),
> >> 'aMeth': DummyClass().meth1,
> >> 'none': None,
> >> 'emptyString': '',
> >>@@ -419,6 +424,14 @@ class VFN(NameMapperTest):
> >> 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) {
> >>
> >>------------------------------------------------------------------------------
> >>Start uncovering the many advantages of virtual appliances
> >>and start using them to simplify application deployment and
> >>accelerate your shift to cloud computing
> >>http://p.sf.net/sfu/novell-sfdev2dev
> >>_______________________________________________
> >>Cheetahtemplate-discuss mailing list
> >>[email protected]
> >>https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
> >- R. Tyler Croy
> >--------------------------------------
> > GitHub: http://github.com/rtyler
> > Twitter: http://twitter.com/agentdero
> >
>
>
> --
> Jon Siddle, CoreFiling Limited
> Software Tools Developer
> http://www.corefiling.com
> Phone: +44-1865-203192
>
> From 19da0cb29f143a1559a1776dab7f6a01aef863ab Mon Sep 17 00:00:00 2001
> From: Jon Siddle <[email protected]>
> Date: Tue, 14 Sep 2010 15:08:26 +0100
> Subject: [PATCH] Added test and fix for segfault in namemapper where exception is thrown
> by __getattr__.
>
> ---
> buildandrun | 3 ++-
> cheetah/Tests/NameMapper.py | 13 +++++++++++++
> cheetah/c/_namemapper.c | 11 ++++++-----
> 3 files changed, 21 insertions(+), 6 deletions(-)
>
> 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 @@ class DummyClass(object):
> except:
> raise
>
> +class DummyClassGetAttrRaises(object):
> + def __getattr__(self, name):
> + raise ValueError
> +
>
> def dummyFunc(arg="Scooby"):
> return arg
> @@ -67,6 +71,7 @@ testNamespace = {
> 'aClass': DummyClass,
> 'aFunc': dummyFunc,
> 'anObj': DummyClass(),
> + 'anObjThatRaises': DummyClassGetAttrRaises(),
> 'aMeth': DummyClass().meth1,
> 'none': None,
> 'emptyString': '',
> @@ -419,6 +424,14 @@ class VFN(NameMapperTest):
> 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) {
> --
> 1.6.6.1
>
- R. Tyler Croy
--------------------------------------
GitHub: http://github.com/rtyler
Twitter: http://twitter.com/agentdero
------------------------------------------------------------------------------
Start uncovering the many advantages of virtual appliances
and start using them to simplify application deployment and
accelerate your shift to cloud computing.
http://p.sf.net/sfu/novell-sfdev2dev
_______________________________________________
Cheetahtemplate-discuss mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/cheetahtemplate-discuss
signature.asc
(application/pgp-signature, 198 B)
-----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.16 (GNU/Linux) iEYEARECAAYFAkyRCEoACgkQFCbH3D9R4W8r8gCePYwFsgdeGMDXaTeo6wPn12DO nHgAn0GwIeXsX4cbxA3HzYt8EAfp+e7h =8xxw -----END PGP SIGNATURE-----