|  | 
| 1 | 1 | // Licensed to the .NET Foundation under one or more agreements. | 
| 2 | 2 | // The .NET Foundation licenses this file to you under the MIT license. | 
| 3 | 3 | 
 | 
|  | 4 | +using System.Diagnostics; | 
| 4 | 5 | using System.Runtime.CompilerServices; | 
| 5 |  | -using static System.Buffers.Text.Base64Helper; | 
| 6 | 6 | 
 | 
| 7 | 7 | namespace System.Buffers.Text | 
| 8 | 8 | { | 
| @@ -94,33 +94,33 @@ public bool ValidateAndDecodeLength(char lastChar, int length, int paddingCount, | 
| 94 | 94 |             [MethodImpl(MethodImplOptions.AggressiveInlining)] | 
| 95 | 95 |             public bool ValidateAndDecodeLength(byte lastChar, int length, int paddingCount, out int decodedLength) | 
| 96 | 96 |             { | 
| 97 |  | -                // Padding is optional for Base64Url, so need to account remainder. If remainder is 1, then it's invalid. | 
| 98 |  | -#if NET | 
| 99 |  | -                (uint whole, uint remainder) = uint.DivRem((uint)(length), 4); | 
| 100 |  | -                if (remainder == 1 || (remainder > 1 && (remainder - paddingCount == 1 || paddingCount == remainder))) | 
| 101 |  | -                { | 
| 102 |  | -                    decodedLength = 0; | 
| 103 |  | -                    return false; | 
| 104 |  | -                } | 
| 105 |  | - | 
| 106 |  | -                decodedLength = (int)((whole * 3) + (remainder > 0 ? remainder - 1 : 0) - paddingCount); | 
| 107 |  | -#else | 
|  | 97 | +                // Padding is optional for Base64Url, so need to account remainder. | 
| 108 | 98 |                 int remainder = (int)((uint)length % 4); | 
| 109 |  | -                if (remainder == 1 || (remainder > 1 && (remainder - paddingCount == 1 || paddingCount == remainder))) | 
|  | 99 | + | 
|  | 100 | +                if (paddingCount != 0) | 
| 110 | 101 |                 { | 
| 111 |  | -                    decodedLength = 0; | 
| 112 |  | -                    return false; | 
|  | 102 | +                    length -= paddingCount; | 
|  | 103 | +                    remainder = (int)((uint)length % 4); | 
|  | 104 | + | 
|  | 105 | +                    // if there is a padding, there should be remainder and the sum of remainder and padding should not exceed 4 | 
|  | 106 | +                    if (remainder == 0 || remainder + paddingCount > 4) | 
|  | 107 | +                    { | 
|  | 108 | +                        decodedLength = 0; | 
|  | 109 | +                        return false; | 
|  | 110 | +                    } | 
| 113 | 111 |                 } | 
| 114 | 112 | 
 | 
| 115 |  | -                decodedLength = (length >> 2) * 3 + (remainder > 0 ? remainder - 1 : 0) - paddingCount; | 
| 116 |  | -#endif | 
| 117 |  | -                int decoded = default(Base64DecoderByte).DecodingMap[lastChar]; | 
| 118 |  | -                if (((remainder == 3 || paddingCount == 1) && (decoded & 0x03) != 0) || | 
| 119 |  | -                    ((remainder == 2 || paddingCount == 2) && (decoded & 0x0F) != 0)) | 
|  | 113 | +                decodedLength = (length >> 2) * 3 + (remainder > 0 ? remainder - 1 : 0); | 
|  | 114 | + | 
|  | 115 | +                if (remainder > 0) | 
| 120 | 116 |                 { | 
| 121 |  | -                    // unused lower bits are not 0, reject input | 
| 122 |  | -                    decodedLength = 0; | 
| 123 |  | -                    return false; | 
|  | 117 | +                    int decoded = default(Base64UrlDecoderByte).DecodingMap[lastChar]; | 
|  | 118 | +                    switch (remainder) | 
|  | 119 | +                    { | 
|  | 120 | +                        case 1: return false; // 1 byte is not decodable => invalid. | 
|  | 121 | +                        case 2: return ((decoded & 0x0F) == 0); // if unused lower 4 bits are set to 0 | 
|  | 122 | +                        case 3: return ((decoded & 0x03) == 0); // if unused lower 2 bits are set to 0 | 
|  | 123 | +                    } | 
| 124 | 124 |                 } | 
| 125 | 125 | 
 | 
| 126 | 126 |                 return true; | 
|  | 
0 commit comments