Fix null pointer dereferences after dynamic_cast (rewritten)#2020
Fix null pointer dereferences after dynamic_cast (rewritten)#2020jminor wants to merge 6 commits intoAcademySoftwareFoundation:mainfrom
Conversation
Signed-off-by: Joshua Minor <jminor@users.noreply.github.com>
Signed-off-by: Joshua Minor <jminor@users.noreply.github.com>
Signed-off-by: Joshua Minor <jminor@users.noreply.github.com>
Signed-off-by: Joshua Minor <jminor@users.noreply.github.com>
Signed-off-by: Joshua Minor <jminor@users.noreply.github.com>
Signed-off-by: Joshua Minor <jminor@users.noreply.github.com>
Codecov Report❌ Patch coverage is
Additional details and impacted files@@ Coverage Diff @@
## main #2020 +/- ##
==========================================
- Coverage 84.50% 84.26% -0.25%
==========================================
Files 181 181
Lines 13223 13261 +38
Branches 1202 1218 +16
==========================================
Hits 11174 11174
- Misses 1866 1904 +38
Partials 183 183
Flags with carried forward coverage won't be shown. Click here to find out more.
Continue to review full report in Codecov by Sentry.
🚀 New features to boost your workflow:
|
meshula
left a comment
There was a problem hiding this comment.
This looks more rigorous than the initial fix.
darbyjohnston
left a comment
There was a problem hiding this comment.
Thanks, I think this is clearer about what is being tested than the previous PR. When we are happy with this one, try asking Claude to compare the two and see what it thinks about the changes.
| if (!cloned_item) | ||
| { | ||
| if (error_status) | ||
| *error_status = ErrorStatus::CANNOT_CLONE_ITEM; |
There was a problem hiding this comment.
I think this error status should be set in clone(), so it is set only once and not at each call site. Something like:
auto cloned_item = items.front()->clone(error_status);
if (!cloned_item || (error_status && is_error(error_status))
return;
SerializableObject*
SerializableObject::clone(ErrorStatus* error_status) const
{
...
SerializableObject*r = e._root.type() == typeid(SerializableObject::Retainer<>)
? std::any_cast<SerializableObject::Retainer<>&>(e._root)
.take_value()
: nullptr;
if (!r && error_status)
*error_status = ErrorStatus::CANNOT_CLONE_ITEM;
return r;
}
Certain invalid OTIO object graphs may cause crashes due to code that assumes a dynamic_cast always returns a valid object. This PR introduces tests which demonstrate the issue and a fix to prevent the crash in those cases.
I made sure to write the tests first, ensure that they caused the crash (SEGFAULT) and then made the fix to each of the affected functions. I introduced a new ErrorStatus::CANNOT_CLONE_ITEM for this specific case. The code may also return ErrorStatus::TYPE_MISMATCH in a related edge case, but I was not able to create a scenario which triggers that case.
Note that the discovery of this issue was assisted by Claude Code Opus 4.6 and Opus 4.7, but all of the code in this PR was written by a human (me). This PR replaces #2017 which had LLM-generated code in it.