Fix MA0113 NullReferenceException and named-argument false negatives - #1382
Merged
Merged
Conversation
`new DateTime(1970, 1, 1, 0, 0, 0, null)` binds to the `DateTime(int, int, int, int, int, int, Calendar)` overload. The 7-argument branch passed that `null` `Calendar` argument to `IsDateTimeKindUtc`, which unboxed the constant with `(DateTimeKind)value!`. A `null` literal has a constant value, so the unboxing threw a `NullReferenceException`, surfacing as `AD0001` and disabling the rule for the rest of the compilation. `IsDateTimeKindUtc` now checks that the parameter type is `System.DateTimeKind` and pattern-matches the constant instead of unboxing it. The rule also assumed `IObjectCreationOperation.Arguments` is in parameter order, while it is in source order, so any named-argument reordering such as `new DateTime(day: 1, month: 1, year: 1970)` silently defeated the rule. `ArgumentsEquals` now indexes the expected values by `IParameterSymbol.Ordinal` and requires every leading parameter to be matched, and the arguments the rule inspects on their own (`DateTimeKind`, the `TimeSpan` offset and `DateTime.UnixEpoch`) are looked up by ordinal. Trailing parameters that the rule does not model, such as the `Calendar` of `DateTimeOffset(..., Calendar, TimeSpan)`, are skipped instead of being compared to an `int`.
This was referenced Sep 6, 2026
Closed
This was referenced Sep 17, 2026
Open
Open
Open
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.
The crash
binds to
DateTime(int, int, int, int, int, int, Calendar). The 7-argument branch ofUseDateTimeUnixEpochAnalyzerpassed thatnullCalendarargument toIsDateTimeKindUtc, which did:A
nullliteral hasConstantValue.HasValue == truewith anullvalue, so unboxing it to theDateTimeKindstruct threw aNullReferenceException. The!suppressed the only compile-time signal thatvaluewas nullable.An unhandled analyzer exception surfaces as
AD0001and disables MA0113 for the rest of the compilation; in the IDE it recurs while the user types. The trigger is ordinary, compiling C#.IsDateTimeKindUtcnow verifies the argument's parameter type isSystem.DateTimeKindbefore looking at the constant, and pattern-matches it (value is int intValue) instead of unboxing. Either check alone stops the crash; both are cheap.The positional-argument assumption
The rule also indexed
IObjectCreationOperation.Argumentspositionally, assuming parameter order.Argumentsis in source order, so this was a real false-negative source rather than a theoretical one — any named-argument reordering silently defeated the rule:ArgumentsEqualsnow indexes the expected values byIParameterSymbol.Ordinaland requires every leading parameter to have been matched. The arguments the rule inspects on their own — theDateTimeKind, theTimeSpanoffset, and theDateTime.UnixEpochreference — are looked up by ordinal through a newGetArgumenthelper instead ofArguments[n].As a side effect, trailing parameters the rule does not model (the
CalendarofDateTimeOffset(..., Calendar, TimeSpan)) are now skipped by ordinal rather than compared against anint, so they can neither crash nor accidentally match.Tests
8 cases added to
UseDateTimeUnixEpochAnalyzerTests: thenulland non-nullCalendaroverloads for bothDateTimeandDateTimeOffset, and named/reordered arguments in both the match and the non-match direction.I ran the new tests against the unfixed analyzer first to confirm they are meaningful — 4 failed, including the
AD0001/NullReferenceExceptiononnew DateTime(1970, 1, 1, 0, 0, 0, null)and three missed diagnostics on reordered named arguments.With the fix, all 32 tests in the class pass on Roslyn 4.8, 4.14, 5.0, 5.6 and 5.9, and the full 3884-test default-version suite passes.
dotnet run --project src/DocumentationGeneratorproduced no markdown changes, as expected for a behavior-only fix.