-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Fix crash inside OverlayImpl
loops over ids_
#5071
Fix crash inside OverlayImpl
loops over ids_
#5071
Conversation
ids_
OverlayImpl
loops over ids_
f273f4d
to
89fd018
Compare
Codecov ReportAll modified and coverable lines are covered by tests ✅
Additional details and impacted files@@ Coverage Diff @@
## develop #5071 +/- ##
=========================================
- Coverage 71.4% 71.3% -0.0%
=========================================
Files 796 796
Lines 67073 67075 +2
Branches 10866 10881 +15
=========================================
- Hits 47881 47854 -27
- Misses 19192 19221 +29
|
Here's a smaller reproduction of the bug https://godbolt.org/z/9rGsx9eEP and of the proposed fix https://godbolt.org/z/qPbc9oYM9 |
b7500df
to
fa59802
Compare
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 looks good.
I did a little bit of a search, and came across a few more places that at a glance could have a non-zero chance of having the same problem, and could probably be quickly and easily fixed with this same pattern. Would they be worth changing in the PR, or another one?
- https://github.com/ximinez/rippled/blob/1e3ab9f76615cf9bb74b7bfeb6d2bd1cd257fe33/include/xrpl/server/detail/io_list.h#L246
- https://github.com/ximinez/rippled/blob/1e3ab9f76615cf9bb74b7bfeb6d2bd1cd257fe33/src/xrpld/app/ledger/detail/InboundLedger.cpp#L1311
- https://github.com/ximinez/rippled/blob/1e3ab9f76615cf9bb74b7bfeb6d2bd1cd257fe33/src/xrpld/app/ledger/detail/LedgerReplayer.cpp#L274 (because the lambda is used in a call to
std::for_each
)
@ximinez those first two are fine because the collection being iterated is held in a local variable, and the destructor of the objects in the collection cannot remove that object from the collection. I don't think the third is in danger, either, but I haven't looked very deeply. |
Yes, the first two operate on a stack-based collection within the scope of the function, so these are not a problem. The last one is not a problem either, because both collections Their base class https://github.com/ximinez/rippled/blob/1e3ab9f76615cf9bb74b7bfeb6d2bd1cd257fe33/src/xrpld/app/ledger/detail/TimeoutCounter.cpp#L118 |
I am thinking a little bit about future-proofing. This seems like a good pattern to use in general just in case the behavior of these objects changes in the future. However, that is definitely beyond the scope of this PR. |
High Level Overview of Change
Functions
OverlayImpl::getActivePeers
andOverlayImpl::findPeerByPublicKey
may cause a crash when iterating overids_
Context of Change
Functions
OverlayImpl::getActivePeers
andOverlayImpl::findPeerByPublicKey
use the following buggy pattern to iterate overids_
:The problem is that, given specific thread scheduling, when
p
is destroyed at a marked location, it might also cause the destruction of thePeerImp
that it owned since the start ofif (auto p = w.lock())
block. This destruction in turn will callOverlayImpl::onPeerDeactivate
which will remove the current element fromids_
collection, hence invalidating the iterator to the removed element. This is all happening whilep
is being destroyed, that is before thefor
at the start of the loop tries to increment the iterator (that just got invalidated) to reach to the next element. Incrementing the invalidated operator is an invalid operation, in practice it will yield bad data, causing a crash.Type of Change
.gitignore
, formatting, dropping support for older tooling)