Skip to content

Commit 73acb51

Browse files
committed
Fix bug in char overload and other small updates
1 parent c1c586b commit 73acb51

File tree

4 files changed

+66
-18
lines changed

4 files changed

+66
-18
lines changed

src/libraries/Microsoft.Bcl.Memory/src/System/Buffers/Text/Base64UrlDecoder.cs

+12-16
Original file line numberDiff line numberDiff line change
@@ -443,7 +443,6 @@ private static OperationStatus DecodeWithWhiteSpaceBlockwise(ReadOnlySpan<byte>
443443
}
444444

445445
bool hasAnotherBlock = source.Length > 1;
446-
447446
bool localIsFinalBlock = !hasAnotherBlock;
448447

449448
// If this block contains padding and there's another block, then only whitespace may follow for being valid.
@@ -559,7 +558,7 @@ internal static unsafe OperationStatus DecodeFromUtf8InPlace(Span<byte> buffer,
559558
uint sourceIndex = 0;
560559
uint destIndex = 0;
561560

562-
if ((bufferLength & 3) == 1) // One byte cannot be decoded completely)
561+
if ((bufferLength & 3) == 1) // One byte cannot be decoded completely
563562
{
564563
goto InvalidExit;
565564
}
@@ -703,21 +702,18 @@ private static OperationStatus DecodeWithWhiteSpaceFromUtf8InPlace(Span<byte> so
703702
continue;
704703
}
705704

706-
if (bufferIdx != 4)
705+
// For Base64Url 1 byte is not decodeable.
706+
if (bufferIdx == 1)
707707
{
708-
// For Base64Url 1 byte is not decodeable.
709-
if (bufferIdx == 1)
710-
{
711-
status = OperationStatus.InvalidData;
712-
break;
713-
}
714-
else // Fill empty slots in last block with padding
708+
status = OperationStatus.InvalidData;
709+
break;
710+
}
711+
else // Fill empty slots in last block with padding
712+
{
713+
while (bufferIdx < BlockSize) // Can happen only for last block
715714
{
716-
while (bufferIdx < BlockSize) // Can happen only for last block
717-
{
718-
Debug.Assert(source.Length == sourceIndex);
719-
buffer[bufferIdx++] = (byte)EncodingPadEqual;
720-
}
715+
Debug.Assert(source.Length == sourceIndex);
716+
buffer[bufferIdx++] = (byte)EncodingPadEqual;
721717
}
722718
}
723719

@@ -1197,7 +1193,7 @@ private static OperationStatus DecodeWithWhiteSpaceBlockwise(ReadOnlySpan<char>
11971193
continue;
11981194
}
11991195

1200-
bool hasAnotherBlock = source.Length >= BlockSize && bufferIdx == BlockSize;
1196+
bool hasAnotherBlock = source.Length > 1;
12011197
bool localIsFinalBlock = !hasAnotherBlock;
12021198

12031199
// If this block contains padding and there's another block, then only whitespace may follow for being valid.

src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@
1313
<Link>System\Memory\Base64\Base64TestBase.cs</Link>
1414
</Compile>
1515
<Compile Include="..\..\System.Memory\tests\Base64\Base64TestHelper.cs">
16-
<Link>System\Memory\Base64Url\Base64TestHelper.cs</Link>
16+
<Link>System\Memory\Base64\Base64TestHelper.cs</Link>
1717
</Compile>
1818
<Compile Include="..\..\System.Memory\tests\Base64Url\Base64UrlDecoderUnitTests.cs">
1919
<Link>System\Memory\Base64Url\Base64UrlDecoderUnitTests.cs</Link>

src/libraries/System.Memory/tests/Base64Url/Base64UrlDecoderUnitTests.cs

+42
Original file line numberDiff line numberDiff line change
@@ -801,6 +801,29 @@ public void DecodingLessThan4BytesWithWhiteSpaces(byte[] utf8Bytes, byte decoded
801801
Assert.Equal(decoded, utf8Bytes[0]);
802802
}
803803

804+
[Theory]
805+
[InlineData(new char[] { '\r', '\r', '-', '-' }, 251)]
806+
[InlineData(new char[] { '\r', '_', '\r', '-' }, 255)]
807+
[InlineData(new char[] { '_', '_', '\r', '\r' }, 255)]
808+
[InlineData(new char[] { 'p', '\r', 'a', '\r' }, 165)]
809+
[InlineData(new char[] { '\r', 'p', '\r', 'a', '\r' }, 165)]
810+
[InlineData(new char[] { 'p', '\r', 'a', '\r', '=', '=' }, 165)]
811+
public void DecodingLessThan4CharsWithWhiteSpaces(char[] utf8Bytes, byte decoded)
812+
{
813+
Assert.True(Base64Url.IsValid(utf8Bytes, out int decodedLength));
814+
Assert.Equal(1, decodedLength);
815+
Span<byte> decodedSpan = new byte[decodedLength];
816+
OperationStatus status = Base64Url.DecodeFromChars(utf8Bytes, decodedSpan, out int bytesRead, out int bytesDecoded);
817+
Assert.Equal(OperationStatus.Done, status);
818+
Assert.Equal(utf8Bytes.Length, bytesRead);
819+
Assert.Equal(decodedLength, bytesDecoded);
820+
Assert.Equal(decoded, decodedSpan[0]);
821+
decodedSpan.Clear();
822+
Assert.True(Base64Url.TryDecodeFromChars(utf8Bytes, decodedSpan, out bytesDecoded));
823+
Assert.Equal(decodedLength, bytesDecoded);
824+
Assert.Equal(decoded, decodedSpan[0]);
825+
}
826+
804827
[Theory]
805828
[InlineData(new byte[] { 0x4a, 0x74, 0xa, 0x4a, 0x4a, 0x74, 0xa, 0x4a }, new byte[] { 38, 210, 73, 180 })]
806829
[InlineData(new byte[] { 0xa, 0x2d, 0x56, 0xa, 0xa, 0xa, 0x2d, 0x4a, 0x4a, 0x4a, }, new byte[] { 249, 95, 137, 36 })]
@@ -823,6 +846,25 @@ public void DecodingNotMultipleOf4WithWhiteSpace(byte[] utf8Bytes, byte[] decode
823846
Assert.True(utf8Bytes.AsSpan().Slice(0, bytesDecoded).SequenceEqual(decoded));
824847
}
825848

849+
[Theory]
850+
[InlineData(new char[] { 'J', 't', '\r', 'J', 'J', 't', '\r', 'J' }, new byte[] { 38, 210, 73, 180 })]
851+
[InlineData(new char[] { '\r', '-', 'V', '\r', '\r', '\r', '-', 'J', 'J', 'J', }, new byte[] { 249, 95, 137, 36 })]
852+
public void DecodingNotMultipleOf4CharsWithWhiteSpace(char[] utf8Bytes, byte[] decoded)
853+
{
854+
Assert.True(Base64Url.IsValid(utf8Bytes, out int decodedLength));
855+
Assert.Equal(4, decodedLength);
856+
Span<byte> decodedSpan = new byte[decodedLength];
857+
OperationStatus status = Base64Url.DecodeFromChars(utf8Bytes, decodedSpan, out int bytesRead, out int bytesDecoded);
858+
Assert.Equal(OperationStatus.Done, status);
859+
Assert.Equal(utf8Bytes.Length, bytesRead);
860+
Assert.Equal(decodedLength, bytesDecoded);
861+
Assert.True(decodedSpan.SequenceEqual(decoded));
862+
decodedSpan.Clear();
863+
Assert.True(Base64Url.TryDecodeFromChars(utf8Bytes, decodedSpan, out bytesDecoded));
864+
Assert.Equal(decodedLength, bytesDecoded);
865+
Assert.True(decodedSpan.SequenceEqual(decoded));
866+
}
867+
826868
[Theory]
827869
[MemberData(nameof(BasicDecodingWithExtraWhitespaceShouldBeCountedInConsumedBytes_MemberData))]
828870
public void BasicDecodingWithExtraWhitespaceShouldBeCountedInConsumedBytes(string inputString, int expectedConsumed, int expectedWritten)

src/libraries/System.Private.CoreLib/src/System/Buffers/Text/Base64Url/Base64UrlDecoder.cs

+11-1
Original file line numberDiff line numberDiff line change
@@ -221,7 +221,17 @@ private static OperationStatus DecodeWithWhiteSpaceBlockwise<TBase64Decoder>(Rea
221221
continue;
222222
}
223223

224-
bool hasAnotherBlock = source.Length >= BlockSize && bufferIdx == BlockSize;
224+
bool hasAnotherBlock;
225+
226+
if (typeof(TBase64Decoder) == typeof(Base64DecoderByte))
227+
{
228+
hasAnotherBlock = source.Length >= BlockSize;
229+
}
230+
else
231+
{
232+
hasAnotherBlock = source.Length > 1;
233+
}
234+
225235
bool localIsFinalBlock = !hasAnotherBlock;
226236

227237
// If this block contains padding and there's another block, then only whitespace may follow for being valid.

0 commit comments

Comments
 (0)