[C++-sig] Segfault with keyword arguments and overloads.

Alex Leach beamesleach at gmail.com
Thu Aug 8 11:28:24 CEST 2013


Hi Alex,

On Wed, 07 Aug 2013 18:06:24 +0100, Alex Mohr <amohr at pixar.com> wrote:

> Thanks for your response.  I've responded to your comments in-line below.
>
> After further investigation, I believe this can be fixed by simply  
> checking for None when we get 'kv' from f->m_arg_names while resolving  
> keywords.  If we encounter None, that means the overload doesn't accept  
> a keyword argument in that position (so not enough positional args were  
> passed), and we can reject the overload.
>
> If it works, I think that's a simple, targeted fix that isn't  
> particularly risky.  I'll try to work up a patch.
>


Sounds like you missed it, but I did add a fairly simple patch to my  
previous email. I used your code as a test case and it worked fine; no seg  
faults. I've copied it again below...

I don't have commit privileges to Boost Python, but I think from your  
explanations, that this is a valid bug in BP. So it would probably be  
worthwhile filing a bug report, at  
http://www.boost.org/development/bugs.html

Unless someone with commit privileges wants to consider merging it? My  
only thought on the patch regards return value optimisation. Would moving  
the `PyObject *` declarations out of the loop impair the compiler's  
ability to perform RVO?


Hope that helps anyway.

Kind regards,
Alex


--- ./boost_1_53_0/libs/python/src/object/function.cpp.orig     2013-08-07  
11:02:28.569236835 +0100
+++ ./boost_1_53_0/libs/python/src/object/function.cpp  2013-08-07  
11:56:10.926045853 +0100
@@ -177,16 +177,18 @@
                          // Grab remaining arguments by name from the  
keyword dictionary
                          std::size_t n_actual_processed = n_unnamed_actual;

+                        PyObject *kv, *k, *value;
                          for (std::size_t arg_pos = n_unnamed_actual;  
arg_pos < max_arity ; ++arg_pos)
                          {
                              // Get the keyword[, value pair] corresponding
-                            PyObject* kv =  
PyTuple_GET_ITEM(f->m_arg_names.ptr(), arg_pos);
+                            kv = PyTuple_GET_ITEM(f->m_arg_names.ptr(),  
arg_pos);

                              // If there were any keyword arguments,
                              // look up the one we need for this
                              // argument position
-                            PyObject* value = n_keyword_actual
-                                ? PyDict_GetItem(keywords,  
PyTuple_GET_ITEM(kv, 0))
+                            k = PyTuple_GET_ITEM(kv, 0);
+                            value = (k != NULL && n_keyword_actual)
+                                ? PyDict_GetItem(keywords, k)
                                  : 0;

                              if (!value)


More information about the Cplusplus-sig mailing list