Skip to content

Parsing format string precision intends to validate for overflow but the check does not work #67891

@GSPP

Description

@GSPP

In #47353 the way format strings are validated was changed. This resulted in this code:

// 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.

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions