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
Under ReadyToRun on WebAssembly (Release / shipping config), System.Buffers.Text.Base64Url.DecodeFromUtf8 throws a spurious NullReferenceException for inputs large enough to take the Vector128 (SIMD) decode path. The same call is correct under the interpreter (DOTNET_ReadyToRun=0). Reproduces on both browser and wasi with Release crossgen2 + Release corerun, so it is an OS-neutral R2R codegen bug.
This is distinct from #131298 (that one is Debug/checked-only). This one reproduces in the Release/shipping configuration.
R2R off (interp):status=DestinationTooSmall c=... w=... (correct)
R2R on:
Unhandled exception. System.NullReferenceException
at System.Buffers.Text.Base64Helper.DecodeFrom[TBase64Decoder,T](TBase64Decoder decoder, ReadOnlySpan`1 source, Span`1 bytes, Int32& bytesConsumed, Int32& bytesWritten, Boolean isFinalBlock, Boolean ignoreWhiteSpace)
at System.Buffers.Text.Base64Url.DecodeFromUtf8(...)
Trigger threshold
source length
path
R2R result
≤ 32 bytes
scalar
correct (DestinationTooSmall)
≥ 64 bytes
Vector128Decode
NullReferenceException
Independent of isFinalBlock (both true/false fail at ≥64). Reproduces with both--codegenopt:JitWasmSimdNyiToR2RUnsupported=0 and =1, so it is not simply "SIMD allowed in R2R".
Localization
Faulting method: Base64Helper.DecodeFrom<TBase64Decoder,T> → the wasm vectorized branch Vector128Decode<TBase64Decoder,T> (guarded by PackedSimd.IsSupported, src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64DecoderHelper.cs).
The scalar path uses decoder.DecodingMap (a ReadOnlySpan<sbyte> → RVA data blob) and works. The vectorized path additionally loads decoder.Vector128LutHigh/Low/Shift (ReadOnlySpan<int>/<uint> LUTs) and calls generic struct-interface methods decoder.TryLoadVector128 / decoder.TryDecode128Core.
Isolated micro-repros that do not reproduce (so the bug is more specific than any of these alone): a plain ReadOnlySpan<int> collection-expression + Vector128.Create; and a generic struct span-property dispatch + Vector128.Create. The NRE only appears in the full Vector128Decode context, pointing at the R2R codegen of that specialized generic method (Vector128Decode<TBase64Decoder,T>) rather than any single lowered construct.
Impact
Affects shipping (Release) R2R-on-wasm: any Base64Url (and likely Base64) decode ≥ ~64 bytes throws. Surfaced by Microsoft.Bcl.Memory.Tests (Base64UrlDecoderUnitTests.*) — 12 tests fail with this NRE under R2R, all pass under interp.
Summary
Under ReadyToRun on WebAssembly (Release / shipping config),
System.Buffers.Text.Base64Url.DecodeFromUtf8throws a spuriousNullReferenceExceptionfor inputs large enough to take the Vector128 (SIMD) decode path. The same call is correct under the interpreter (DOTNET_ReadyToRun=0). Reproduces on bothbrowserandwasiwith Release crossgen2 + Release corerun, so it is an OS-neutral R2R codegen bug.This is distinct from #131298 (that one is Debug/checked-only). This one reproduces in the Release/shipping configuration.
Minimal repro
status=DestinationTooSmall c=... w=...(correct)Trigger threshold
DestinationTooSmall)Vector128DecodeIndependent of
isFinalBlock(bothtrue/falsefail at ≥64). Reproduces with both--codegenopt:JitWasmSimdNyiToR2RUnsupported=0and=1, so it is not simply "SIMD allowed in R2R".Localization
Base64Helper.DecodeFrom<TBase64Decoder,T>→ the wasm vectorized branchVector128Decode<TBase64Decoder,T>(guarded byPackedSimd.IsSupported,src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Helper/Base64DecoderHelper.cs).decoder.DecodingMap(aReadOnlySpan<sbyte>→ RVA data blob) and works. The vectorized path additionally loadsdecoder.Vector128LutHigh/Low/Shift(ReadOnlySpan<int>/<uint>LUTs) and calls generic struct-interface methodsdecoder.TryLoadVector128/decoder.TryDecode128Core.ReadOnlySpan<int>collection-expression +Vector128.Create; and a generic struct span-property dispatch +Vector128.Create. The NRE only appears in the fullVector128Decodecontext, pointing at the R2R codegen of that specialized generic method (Vector128Decode<TBase64Decoder,T>) rather than any single lowered construct.Impact
Microsoft.Bcl.Memory.Tests(Base64UrlDecoderUnitTests.*) — 12 tests fail with this NRE under R2R, all pass under interp.Environment
browserandwasi, wasm32.Note
This issue was authored with the assistance of GitHub Copilot.