Oh!  I did miss your patch, sorry.  Thanks!

It looks to me like your patch calls PyTuple_GET_ITEM() with None as the python object (when kv is None). The python docs for PyTuple_GET_ITEM say, "Like PyTuple_GetItem(), but does no checking of its arguments." To me that means that the object you pass really needs to be a tuple.

Here's the patch I'm using -- it simply checks to see if kv is None, which is true if the overload doesn't accept a keyword arg in that position, and if so it simply rejects the overload. This is working for me in the example and across our codebase and testsuite.

I will file a bug as you suggest, and thanks again.

Alex

--- ./boost_1_53_0/libs/python/src/object/function.cpp.orig 2013-07-22 17:38:54.000000000 -0700 +++ ./boost_1_53_0/libs/python/src/object/function.cpp 2013-08-07 10:25:26.963988000 -0700
@@ -182,6 +182,16 @@
                             // Get the keyword[, value pair] corresponding
PyObject* kv = PyTuple_GET_ITEM(f->m_arg_names.ptr(), arg_pos);

+ // If kv is None, this overload does not accept a + // keyword argument in this position, meaning that
+                            // the caller did not supply enough positional
+                            // arguments.  Reject the overload.
+                            if (kv == Py_None) {
+                                PyErr_Clear();
+                                inner_args = handle<>();
+                                break;
+                            }
+
                             // If there were any keyword arguments,
                             // look up the one we need for this
                             // argument position


On 8/8/2013 2:28 AM, Alex Leach wrote:
Hi Alex,

On Wed, 07 Aug 2013 18:06:24 +0100, Alex Mohr <am...@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)

_______________________________________________
Cplusplus-sig mailing list
Cplusplus-sig@python.org
http://mail.python.org/mailman/listinfo/cplusplus-sig

Reply via email to