-
Notifications
You must be signed in to change notification settings - Fork 53
Add test for external_pointer attribute preservation and fix move assignment operator #486
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
Conversation
…ssue #308) Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
Co-authored-by: krlmlr <1741643+krlmlr@users.noreply.github.com>
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.
Pull request overview
This PR fixes a critical bug in the external_pointer move assignment operator and adds comprehensive test coverage for attribute preservation during move operations, addressing issue #308.
Changes:
- Added missing return statement in
external_pointer::operator=(external_pointer&&)to fix undefined behavior - Added test case verifying attributes are preserved during both move construction and move assignment
- Added CodeQL configuration file
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
| inst/include/cpp11/external_pointer.hpp | Fixed move assignment operator by adding missing return statement |
| cpp11test/src/test-external_pointer.cpp | Added comprehensive test for attribute preservation in move operations |
| _codeql_detected_source_root | Added CodeQL source root configuration |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| expect_true(strcmp(CHAR(STRING_ELT(class_attr_after, 0)), "test_class") == 0); | ||
|
|
||
| // Clean up | ||
| delete p_moved.release(); |
Copilot
AI
Jan 22, 2026
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.
Calling delete on the result of release() will attempt to delete the memory that was already wrapped by the external pointer, but the external pointer's finalizer has already been set up to delete this memory when the R object is garbage collected. This creates a double-free scenario. Since the external pointer owns the memory, simply allowing p_moved to go out of scope is sufficient - the finalizer will handle cleanup.
| expect_true(strcmp(CHAR(STRING_ELT(class_attr_after, 0)), "test_class") == 0); | ||
|
|
||
| // Clean up | ||
| delete p2.release(); |
Copilot
AI
Jan 22, 2026
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.
Same double-free issue as above. The external pointer's finalizer will delete the memory when the R object is garbage collected. Calling delete on release() creates a double-free scenario. Remove this manual deletion and let the external pointer's destructor handle cleanup.
Issue #308 reported that moving an
external_pointerclears its attributes. The fix was already applied (changing move operations to transferdata_directly instead of callingreset(rhs.release())), but lacked test coverage and had a critical bug.Changes
external_pointer::operator=(external_pointer&&)- the operator was declared to returnexternal_pointer&but had no return, causing undefined behaviorTest Example
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.