Skip to content

Remove unsafe string mutation code from repo #31821

Closed
@GrabYourPitchforks

Description

@GrabYourPitchforks

Strings in .NET are immutable, and we want to experiment with runtime features (deduplication, codegen optimizations, etc.) which rely on this fact. To accomplish this we'll need to start moving away from existing code which mutates string instances in-place. Here's a first-pass at all the places in this repo which mutate strings and recommended workarounds for them.

public static unsafe string GetLatin1StringNonNullCharacters(this ReadOnlySpan<byte> span)
{
if (span.IsEmpty)
{
return string.Empty;
}
var resultString = new string('\0', span.Length);
fixed (char* output = resultString)
fixed (byte* buffer = span)
{
// This returns false if there are any null (0 byte) characters in the string.
if (!TryGetLatin1String(buffer, output, span.Length))
{
// null characters are considered invalid
throw new InvalidOperationException();
}
}
return resultString;
}

(Similar code here and here.)

Suggested workaround (pseudocode):

fixed (byte* pBytes = bytes)
{
    return string.Create(bytes.Length, (IntPtr)pBytes, (span, ptr) =>
    {
        fixed (char* pChars = span)
        {
            WidenAndCopy((byte*)ptr, pChars, span.Length);
        }
    });
}

// Allocate a string object and write directly into it (CLR team approves of this mechanism).
string retVal = new String((char)0, checked((int)numCharsWithoutNull));
uint numBytesCopied;
fixed (char* pRetVal = retVal)
{
numBytesCopied = GetProperty(Constants.BCRYPT_ALGORITHM_NAME, pRetVal, byteLengthOfNameWithTerminatingNull);
}

Suggested workaround: Write to a stackalloced buffer, or rent a char array and write to that, then turn it into a string. Or use string.Create and avoid the intermediate rentals.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions