Fix FindPublicMethodBySignature matching static methods for instance calls#14191
Fix FindPublicMethodBySignature matching static methods for instance calls#14191lewing wants to merge 2 commits into
Conversation
…calls FindPublicMethodBySignature uses GetMethods() without binding flags, which returns all public methods including static ones. When resolving an instance call like String.Equals with types [string, string], it incorrectly matches the static String.Equals(String, String) instead of falling through to CoerceArguments which would parse the enum string argument correctly. The old Type.GetMethod(name, bindingFlags, null, types, null) respected BindingFlags.Instance and excluded static methods. Pass _bindingFlags to GetMethods() so it filters by instance/static correctly, matching the behavior of the replaced code. Fixes dotnet#14190 Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
There was a problem hiding this comment.
Pull request overview
Fixes a regression in property-function late-bound method resolution where instance calls could incorrectly match static overloads due to unfiltered reflection enumeration.
Changes:
- Update
FindPublicMethodBySignatureto enumerate methods via_receiverType.GetMethods(_bindingFlags)so instance/static filtering matches the originalGetMethod(..., bindingFlags, ...)behavior.
- Update XML doc comment for FindPublicMethodBySignature - Fix second GetMethods() in LateBindExecute fallback (line 1247) - Fix GetMethods() in out-parameter branch (line 515) - Add StringEqualsWithStringComparisonTests covering the regression Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
|
[MODERATE] Correctness — related The // line 1247 — unchanged in this PR
members = _receiverType.GetMethods().Where(m => string.Equals(m.Name, _methodMethodName, StringComparison.OrdinalIgnoreCase));
Note that the Recommendation: Replace
|
Follow-up issues from PR #14079 not addressed in this fixThree sibling concerns, all tracing back to the same PR #14079 that introduced the regression, are still present after this fix. 1. Stale
|
There was a problem hiding this comment.
Code Review — PR #14191
The fix is correct: _bindingFlags always has either BindingFlags.Static or BindingFlags.Instance set (and BindingFlags.Public, never BindingFlags.NonPublic) by the time LateBindExecute calls FindPublicMethodBySignature, so GetMethods(_bindingFlags) correctly filters to instance-only or static-only methods and exactly matches the behavior of the original GetMethod(..., bindingFlags, ...) call that was replaced in #14079.
| # | Dimension | Verdict |
|---|---|---|
| 4 | Test Coverage | 🟠 1 MAJOR |
| 18 | Documentation Accuracy | 🟡 1 NIT |
| 22 | Correctness (related GetMethods() at line 1247) |
🟡 1 MODERATE |
✅ 21/24 dimensions clean.
- Test Coverage — no regression test for this bug fix
- Correctness —
LateBindExecuteline 1247 has the same unguardedGetMethods()from #14079; should usebindingFlagsparameter (see inline comment on PR) - Docs — XML doc for
FindPublicMethodBySignaturestill references the parameterless overload
Generated by Expert Code Review (on open) for issue #14191 · 2.1K AIC · ⊞ 29.9K
| if (args.Any(a => "out _".Equals(a))) | ||
| { | ||
| IEnumerable<MethodInfo> methods = _receiverType.GetMethods().Where(m => m.Name.Equals(_methodMethodName) && m.GetParameters().Length == args.Length); | ||
| IEnumerable<MethodInfo> methods = _receiverType.GetMethods(_bindingFlags).Where(m => m.Name.Equals(_methodMethodName) && m.GetParameters().Length == args.Length); |
There was a problem hiding this comment.
@Forgind it looks like this compare has been case sensitive since it was introduced, is this worth addressing here or in a follow up?
Summary
FindPublicMethodBySignature(introduced in #14079) uses_receiverType.GetMethods()without binding flags, which returns all public methods including static ones. When resolving an instance call likeString.Equalswith types[string, string], it incorrectly matches the staticString.Equals(String, String)overload instead of falling through toCoerceArgumentswhich would parse the enum string argument ("StringComparison.InvariantCulture") correctly.The old
Type.GetMethod(name, bindingFlags, null, types, null)respectedBindingFlags.Instanceand excluded static methods, so it returned null and correctly fell through to enum coercion.Fix
Pass
_bindingFlagstoGetMethods()so it filters by instance/static correctly, matching the behavior of the replaced code.Reproduction
The bug breaks any MSBuild condition using instance methods with enum parameters passed as strings. For example, runtime's
Directory.Build.targets:This fires an error claiming
TargetOS='linux'is not lowercase, becauseString.Equals("linux", "StringComparison.InvariantCulture")(static, ordinal comparison) returnsfalse.Reproduced locally by building MSBuild from commit 161f9ea and running against a minimal test project. Fix verified.
Impact
This regression blocks the msbuild flow PR to the VMR (dotnet/dotnet#7406) — the
SB_CentOSStream10_Offlineleg fails because it's the first consumer of the newly-built MSBuild.Fixes #14190