Harden BindingGroup against re-entrant binding-expression changes#11764
Open
wnvko-msft wants to merge 5 commits into
Open
Harden BindingGroup against re-entrant binding-expression changes#11764wnvko-msft wants to merge 5 commits into
wnvko-msft wants to merge 5 commits into
Conversation
Contributor
There was a problem hiding this comment.
Pull request overview
This PR hardens BindingGroup against re-entrant mutation of its internal binding-expression collection during edit/commit/validation flows, preventing ArgumentOutOfRangeException crashes when user code (converters/setters/validation rules) changes group membership mid-iteration.
Changes:
- Replaces index-based downward loops over
_bindingExpressionswith snapshot-based iteration to prevent stale indices under re-entrancy. - Adds
CopyBindingExpressions()helper and uses it inCancelEdit,ObtainConvertedProposedValues,UpdateValues, andCheckValidationRules. - Skips snapshot entries that have since left the group (
bindingExpression.BindingGroup != this) to preserve per-expression semantics for surviving members.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
Member
|
You cannot possibly allocate an array everytime during evaluation. Sure, the re-entrancy case should be handled gracefully, but this only decreases perf for everyone else based on a degenerate edge case. And it still keeps the undefined behaviour of adding new bindings. |
…den-bindinggroup-updatevalues-reentrancy
…ttps://github.com/dotnet/wpf into mvenkov/harden-bindinggroup-updatevalues-reentrancy
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.
Fixes #1690
Description
BindingGroupiterates its internal_bindingExpressionscollection with downward index loops (for (int i = _bindingExpressions.Count - 1; i >= 0; --i)) inObtainConvertedProposedValues,UpdateValues,CheckValidationRules, and theUpdateTargetloop inCancelEdit. During these loops WPF calls out to user code (value converters, property setters, validation rules). If that user code mutates the binding-expression collection - e.g. a binding leaves the group and the collection shrinks - the cached index becomes stale and_bindingExpressions[i]throwsArgumentOutOfRangeException.This change hardens those loops: each now iterates over a snapshot taken before the loop (via a new
CopyBindingExpressionshelper) and skips any expression that has since left the group (bindingExpression.BindingGroup != this). Expressions that join mid-loop always append to the end and were never processed by the original downward loop, so that behavior is unchanged. Side-effecting calls (e.g.UpdateSource) are still invoked for every surviving member, preserving semantics.Customer Impact
Applications using
BindingGroup(commonly viaDataGridrow editing/commit) can crash with an unhandledArgumentOutOfRangeExceptionwhen a commit or validation modifies the set of bindings in the group. Without this fix the crash takes down the app.Regression
No. This is a long-standing latent defect in the iteration pattern, not a regression from a recent release.
Testing
PresentationFrameworkfor x86 and x64 (0 warnings/errors).BindingGroup+ commit repro app on the locally-built runtime, then confirmed the same app no longer throws after overlaying the fixedPresentationFramework.dll.Risk
Low. The change is confined to
BindingGroup.csand only alters how four existing loops enumerate the binding-expression collection (snapshot + membership check) without changing the per-expression work or its ordering. Expressions added mid-loop retain the pre-existing behavior of being deferred to the next pass, and all side-effecting calls continue to run for every surviving member.Microsoft Reviewers: Open in CodeFlow