Repository navigation
Conversation
The copy-assignment of a smart virtual_ptr from a smart pointer dereferenced the source unconditionally, where the constructor from the same argument and the move-assignment both check for an empty pointer and store a null v-table pointer instead. Assigning an empty std::shared_ptr lvalue therefore read the dynamic type of a null object. Align the overload with its siblings, and cover the lvalue path in the value-semantics test, which exercised only the rvalue one. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016fFU6fW4SeTaPcAAEt41xu
Say what runtime_checks is the only guard against: without it, a call on an unregistered class reads a v-table slot that initialize never filled, and calls what it finds there. Say that the library does not synchronize initialize, finalize or the loading of a library with dispatch in other threads; that a library's overriders become stale function pointers in the tables between its unload and the next initialize; that the tables live in writable memory, unlike the compiler's v-tables; that the pointer constructor and assignment of virtual_ptr do not accept null; and that trace::from_env hands the decision to print addresses to the environment. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016fFU6fW4SeTaPcAAEt41xu
|
An automated preview of the documentation is available at https://143.openmethod.prtest3.cppalliance.org/libs/openmethod/doc/html/index.html If more commits are pushed to the pull request, the docs will rebuild at the same URL. 2026-11-07 01:57:02 UTC |
This branch has not been deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
(Written by Claude Code, on behalf of @jll63.)
Found while auditing the library for memory-safety defects. Two commits: a fix, and the documentation the audit suggested.
Fix
The copy-assignment of a smart
virtual_ptrfrom a smart pointer,virtual_ptr<SmartPtr>::operator=(const Other&), dereferenced the source unconditionally:The constructor from the same argument and the move-assignment both guard with
other ? acquire_vptr(*other) : null_vptr; this overload was the one exception. Assigning an emptystd::shared_ptrlvalue therefore read the dynamic type of a null object (UBSan: "reference binding to null pointer", then a SEGV instd_rtti::dynamic_type). The rvalue path,p = dog_ptr(), was fine and was the only one the tests covered.This aligns the overload with its siblings, and adds the lvalue case to
test_smart_virtual_ptr_value_semantics.cpp, where it runs for bothstd::shared_ptrandboost::intrusive_ptr.Verified with
-fsanitize=address,undefinedand runtime checks on: the new test fails on the unfixed header and passes with the fix; the full suite of 79 tests and 33 examples is clean under the same flags.Documentation
Nothing else in the audit was a bug; these are the properties a security-minded user has to know and the pages did not say:
error_handling.adoc, new Runtime Checks section: without the policy, a call on an unregistered class reads a v-table slot thatinitializenever filled and calls the word it finds there; what the policy costs; when to keep it in release builds.shared_libraries.adoc: between a library's unload and the nextinitialize, its overriders are stale function pointers in the tables, andruntime_checksdoes not notice by itself (finalizefirst makes it refuse). The library performs no synchronization:initialize,finalizeand loading or unloading must not overlap with dispatch in other threads, and concurrent loads race on the registration lists.registries_and_policies.adoc: the dispatch tables and static v-table pointers live in writable memory, unlike the compiler's v-tables, and may be made read-only afterinitializereturns.initializegains a Thread safety paragraph; thevirtual_ptrpointer constructor and assignment state that the pointer must not be null (the smart-pointer overloads accept an empty pointer, this one reads the object);trace::from_envnotes that the trace prints addresses, so a privileged program should not let the environment enable it.🤖 Generated with Claude Code
https://claude.ai/code/session_016fFU6fW4SeTaPcAAEt41xu