Skip to content

StringBuilder.Append(char, int) can still fail mid-way #11375

@GSPP

Description

@GSPP

In https://github.com/dotnet/coreclr/issues/4514 I had reported that StringBuilder.Append(char, int) can fail mid-way causing a partial update to be made. The team decided to fix this but today I discovered that the fix does not quite work.

In particular the capacity check succeeds but the allocation of a new block fails. .NET char arrays are limited to 0x7FEFFFFF elements. That way an allocation of a block can fail even though the argument validation succeeded.

            var sb = new StringBuilder();

            sb.Append('x', 2);
            sb.Length--;

            Console.WriteLine($"Length: {sb.Length}, Capacity: {sb.Capacity}, MaxCapacity: {sb.MaxCapacity}");

            try
            {
                sb.Append('x', Int32.MaxValue - 1);
                Console.WriteLine($"Length: {sb.Length}, Capacity: {sb.Capacity}, MaxCapacity: {sb.MaxCapacity}");
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex); //Expected.
            }

            Console.WriteLine($"Length: {sb.Length}, Capacity: {sb.Capacity}, MaxCapacity: {sb.MaxCapacity}");
            Console.WriteLine(sb.ToString()); //Prints "xxxxxxxxxxxxxxxx", should print "x".

Int32.MaxValue is correctly caught by validation but Int32.MaxValue - 1 is not.

I don't quite know what the right fix is. ExpandByABlock should never be called with a min block size that is greater than the max supported array size.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions