From 2d3806cc89d24166e03d80635f5c4d805a544f31 Mon Sep 17 00:00:00 2001 From: Pavel Koneski Date: Wed, 28 Oct 2026 14:54:34 -0700 Subject: [PATCH] Do not throw when detecting bug Corefx29898 --- src/core/IronPython/Runtime/PythonEncoding.cs | 37 +++++++++++++++---- 1 file changed, 30 insertions(+), 7 deletions(-) diff --git a/src/core/IronPython/Runtime/PythonEncoding.cs b/src/core/IronPython/Runtime/PythonEncoding.cs index 042349f3b..4deae6d92 100644 --- a/src/core/IronPython/Runtime/PythonEncoding.cs +++ b/src/core/IronPython/Runtime/PythonEncoding.cs @@ -201,22 +201,45 @@ public override Decoder GetDecoder() public override byte[] GetPreamble() => Pass1Encoding.GetPreamble(); public override bool IsAlwaysNormalized(NormalizationForm form) => false; + #region BugCorefx29898 + public static bool HasBugCorefx29898 { get { if (_hasBugCorefx29898 == null) { - try { - var codec = (Encoding)new UTF8Encoding(false, throwOnInvalidBytes: true); - codec.GetCharCount(new byte[] { 255 }); - _hasBugCorefx29898 = false; - } catch (DecoderFallbackException ex) { - _hasBugCorefx29898 = (ex.Index < 0); - } + var codec = (Encoding)UTF8.Clone(); + codec.DecoderFallback = new TestUtf8DecoderFallback(); + var decoder = codec.GetDecoder(); + decoder.GetCharCount([255], 0, 1); + _hasBugCorefx29898 = ((TestUtf8DecoderFallbackBuffer)decoder.FallbackBuffer).BugDetected; } return (bool)_hasBugCorefx29898; } } private static bool? _hasBugCorefx29898; + private class TestUtf8DecoderFallback : DecoderFallback { + public override int MaxCharCount => 0; + + public override DecoderFallbackBuffer CreateFallbackBuffer() => new TestUtf8DecoderFallbackBuffer(); + } + + private class TestUtf8DecoderFallbackBuffer : DecoderFallbackBuffer { + public bool BugDetected { get; private set; } + + public override int Remaining => 0; + + public override bool Fallback(byte[] bytesUnknown, int index) { + BugDetected |= (index < 0); + return false; + } + + public override char GetNextChar() => '\0'; + + public override bool MovePrevious() => false; + } + + #endregion + internal static int GetUtf16SequenceLength(int rune) => rune > char.MaxValue ? 2 : 1; private readonly struct MemInt {