You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
Inside task { }, sprintf "%A %s" tuple x returns a closure typed as string (type-unsafe IL; .Length reads garbage) #20675
task, tuple first, 2 args -> Program+formatted@10
task, formatted.Length -> 1614856976 (a different garbage value on every build)
sync, tuple first, 2 args -> System.String
Expected:System.String and formatted.Length = 9 (("a", "b") c).
What we observed:
The value bound to formatted : string is a printf continuation closure, not a string. .Length does not throw. It reads arbitrary memory: the emitted IL passes an object where string is declared.
Triggers:sprintf or failwithf, with %A or %O, two or more arguments, and a reference tuple as the first argument, inside task { } or backgroundTask { }.
Does not trigger:
the tuple in a later position, or a single argument;
an enum, a union with fields, a record, an option, DateOnly or a struct tuple;
async { }, or the same code outside a computation expression;
interpolation ($"%A{pair} %s{other}").
Impact we hit: a failing Assert.True(false, sprintf "... %A ..." tuple ...) inside a task test made xUnit 2.6.2 crash its test host with ArrayTypeMismatchException, and dotnet test reported a partial run as successful. xUnit 2.9.3 counts the failure but loses the message.
Repro (.NET SDK 10.0.112 / F# 10,
net10.0console, Debug and Release):Actual output:
Expected:
System.Stringandformatted.Length = 9(("a", "b") c).What we observed:
formatted : stringis a printf continuation closure, not a string..Lengthdoes not throw. It reads arbitrary memory: the emitted IL passes an object wherestringis declared.sprintforfailwithf, with%Aor%O, two or more arguments, and a reference tuple as the first argument, insidetask { }orbackgroundTask { }.DateOnlyor a struct tuple;async { }, or the same code outside a computation expression;$"%A{pair} %s{other}").Assert.True(false, sprintf "... %A ..." tuple ...)inside atasktest made xUnit 2.6.2 crash its test host withArrayTypeMismatchException, anddotnet testreported a partial run as successful. xUnit 2.9.3 counts the failure but loses the message.