-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
System.Text.Encodings.Web refactoring and code modernization (#49373)
- Unify workhorse implementations across all inbox encoders - Refactor most unsafe code from TextEncoder workhorse routines into standalone helpers - Fix bounds check logic in workhorse routines - SSSE3-optimize central workhorse routine - Remove vestigial code from the library and unit test project - Add significant unit test coverage for the workhorse routines and unsafe helpers - Ref: CVE-2021-26701 (MSRC 62749)
- Loading branch information
1 parent
9f93bcb
commit c569bc1
Showing
62 changed files
with
5,267 additions
and
5,728 deletions.
There are no files selected for viewing
This file contains 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
This file contains 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
This file contains 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
64 changes: 64 additions & 0 deletions
64
...es/System.Text.Encodings.Web/src/Polyfills/System.Numerics.BitOperations.netstandard20.cs
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
// Licensed to the .NET Foundation under one or more agreements. | ||
// The .NET Foundation licenses this file to you under the MIT license. | ||
|
||
using System.Runtime.CompilerServices; | ||
using System.Runtime.InteropServices; | ||
|
||
// Contains a polyfill implementation of System.Numerics.BitOperations that works on netstandard2.0. | ||
// Implementation copied from: | ||
// https://github.com/dotnet/runtime/blob/6072e4d3a7a2a1493f514cdf4be75a3d56580e84/src/libraries/System.Private.CoreLib/src/System/Numerics/BitOperations.cs | ||
// | ||
// Some routines inspired by the Stanford Bit Twiddling Hacks by Sean Eron Anderson: | ||
// http://graphics.stanford.edu/~seander/bithacks.html | ||
|
||
namespace System.Numerics | ||
{ | ||
internal static class BitOperations | ||
{ | ||
private static ReadOnlySpan<byte> Log2DeBruijn => new byte[32] | ||
{ | ||
00, 09, 01, 10, 13, 21, 02, 29, | ||
11, 14, 16, 18, 22, 25, 03, 30, | ||
08, 12, 20, 28, 15, 17, 24, 07, | ||
19, 27, 23, 06, 26, 05, 04, 31 | ||
}; | ||
|
||
/// <summary> | ||
/// Returns the integer (floor) log of the specified value, base 2. | ||
/// Note that by convention, input value 0 returns 0 since log(0) is undefined. | ||
/// </summary> | ||
/// <param name="value">The value.</param> | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
public static int Log2(uint value) | ||
{ | ||
// Fallback contract is 0->0 | ||
return Log2SoftwareFallback(value | 1); | ||
} | ||
|
||
/// <summary> | ||
/// Returns the integer (floor) log of the specified value, base 2. | ||
/// Note that by convention, input value 0 returns 0 since Log(0) is undefined. | ||
/// Does not directly use any hardware intrinsics, nor does it incur branching. | ||
/// </summary> | ||
/// <param name="value">The value.</param> | ||
private static int Log2SoftwareFallback(uint value) | ||
{ | ||
// No AggressiveInlining due to large method size | ||
// Has conventional contract 0->0 (Log(0) is undefined) | ||
|
||
// Fill trailing zeros with ones, eg 00010010 becomes 00011111 | ||
value |= value >> 01; | ||
value |= value >> 02; | ||
value |= value >> 04; | ||
value |= value >> 08; | ||
value |= value >> 16; | ||
|
||
// uint.MaxValue >> 27 is always in range [0 - 31] so we use Unsafe.AddByteOffset to avoid bounds check | ||
return Unsafe.AddByteOffset( | ||
// Using deBruijn sequence, k=2, n=5 (2^5=32) : 0b_0000_0111_1100_0100_1010_1100_1101_1101u | ||
ref MemoryMarshal.GetReference(Log2DeBruijn), | ||
// uint|long -> IntPtr cast on 32-bit platforms does expensive overflow checks not needed here | ||
(nint)((value * 0x07C4ACDDu) >> 27)); | ||
} | ||
} | ||
} |
Oops, something went wrong.