-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
In #47353 the way format strings are validated was changed. This resulted in this code:
runtime/src/libraries/System.Private.CoreLib/src/System/Number.Formatting.cs
Lines 1705 to 1718 in 5707668
| // Fallback for symbol and any length digits. The digits value must be >= 0 && <= 99, | |
| // but it can begin with any number of 0s, and thus we may need to check more than two | |
| // digits. Further, for compat, we need to stop when we hit a null char. | |
| int n = 0; | |
| int i = 1; | |
| while (i < format.Length && (((uint)format[i] - '0') < 10)) | |
| { | |
| int temp = ((n * 10) + format[i++] - '0'); | |
| if (temp < n) | |
| { | |
| throw new FormatException(SR.Argument_BadFormatSpecifier); | |
| } | |
| n = temp; | |
| } |
The temp < 0 check does not catch all forms of overflow. It is possible to overflow but to create a positive value. Roughly, the argument goes like this: At about n == int.MaxValue / 10 overflow starts to happen and it results in negative results. But then, the remaining value range is stepped through in increments of 10. This quickly leads to crossing into the positive numbers.
An example of this can be found with this code:
public static void StandardFormatStringParsingOverflowRepro()
{
for (int n = 0; n < int.MaxValue; n++)
{
var temp = n * 10;
if (temp < n && temp >= 0)
{
Debugger.Break();
}
}
}The first number is 429496730 (roughly int.MaxValue * 2 / 10) and temp becomes 4. This should work as a repro, although I have not tested it on the live code.
I also wonder how this code guards against characters being other than 0-9. Maybe that is being validated elsewhere.