-
Notifications
You must be signed in to change notification settings - Fork 408
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prevent segfault in PyKDL when asking for nonexisting segment of chain #228
base: master
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM, thanks for your contribution!
python_orocos_kdl/PyKDL/kinfam.sip
Outdated
PyErr_SetString(PyExc_IndexError, "Chain index out of range"); | ||
return 0; | ||
} | ||
sipRes = &(sipCpp->getSegment(a0)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually I am not sure if this is valid in SIP. The /Factory/
annotation indicates that the returned pointer is owned by Python, but actually the returned pointer must not be deleted independently. I wonder whether that annotation was actually correct even for the original version of the method.
Why did you change the return type from const Segment&
to const Segment*
?
Could anybody who is more proficient with SIP could jump in (@smits)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I did not mean to change the return type, that must have slipped in while I was testing, good catch.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should also be implemented in pybind version
@@ -175,8 +175,12 @@ void init_kinfam(pybind11::module &m) | |||
chain.def("addChain", &Chain::addChain); | |||
chain.def("getNrOfJoints", &Chain::getNrOfJoints); | |||
chain.def("getNrOfSegments", &Chain::getNrOfSegments); | |||
chain.def("getSegment", (Segment& (Chain::*)(unsigned int)) &Chain::getSegment); | |||
chain.def("getSegment", (const Segment& (Chain::*)(unsigned int) const) &Chain::getSegment); | |||
chain.def("getSegment", [](const Chain &c, unsigned int nr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am not so familiar with PyBind11, but this lambda function returns a const Segment &
unconditionally, because the input is a const Chain &
. Does it make a difference? Is the returned Segment
supposed to have reference semantics or does const-correctness matter at all for the Python bindings?
The previous version had a const and a non-const overload, and the SIP version below only has a non-const implementation of getSegment(nr)
and the const declaration has been removed.
From this document in the pybind11
repo I understand that the const-ness of returned values is even cast away by pybind11
, and that the returned Segment
instance is still mutable in Python, with reference semantics? In that case, would
chain.def("getSegment", [](const Chain &c, unsigned int nr) | |
chain.def("getSegment", [](Chain &c, unsigned int nr) |
have worked here, too, to emphasize that the returned Segment
is mutable and the Chain
instance can be modified through this method?
It should be noted that this change is not consistent with the C++ version of orocos_kinematics_dynamics/orocos_kdl/src/chain.hpp Lines 78 to 96 in a2a2dff
|
@meyerj Do you think we should implement such checks for all index functions in PyKDL? I will work on a new PR as this one is outdated. |
Added methodcode to the Chain class to throw an IndexError when trying to retrieve a segment that doesn't exist.