Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Correct redaction of Array.Empty<char>() and new char[0] #4309

Merged
merged 1 commit into from
Aug 28, 2023

Conversation

RussKie
Copy link
Member

@RussKie RussKie commented Aug 18, 2023

Fixes #4308

Microsoft Reviewers: Open in CodeFlow

@RussKie RussKie requested a review from geeknoid August 18, 2023 01:20
@ghost ghost assigned RussKie Aug 18, 2023
@@ -181,6 +186,11 @@ public int Redact<T>(T value, Span<char> destination, string? format = null, IFo
return Redact(((IFormattable)value).ToString(format, provider), destination);
}

if (value is char[] arrayOfChar)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not sure whether this is semantically correct behavior. Why should a char array have special treatment over any other kind of array?

I think the test passing an empty array of char may need to be fixed instead.

Copy link
Member Author

@RussKie RussKie Aug 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Because the redactor works with sequence of chars or strings represented as ReadOnlySpan<char>:

Converting an array of char to a string is a wasteful allocation because at the next steps the new string is converted back to a span.

public virtual string Redact(string? source) => Redact(source.AsSpan());

Besides, when a user passes Array.Empty<char> or new char[0], the user expects the work to be performed on essentially the empty sequence, and not on the string System.Char[].

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The real issue is the overload resolution. The test is passing a char[] and that's binding to the generic version of the call instead of binding to the overload that takes a ReadOnlySpan. We didn't use to have a generic version of the call, so the test would bind to the ReadOnlySpan overload and things worked.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably this usage is niche, I am not sure if we need this optimization. I don't think it is wrong though, we already have typechecks for iformattable, and it looks the same IMO.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

OK, then let's keep it.

@RussKie, please update the code to not use pattern matching and use the same pattern as the if checks for IFormattable and ISpanFormattable above. This pattern is recognized by the JIT and since this is a generic type, the JIT ends up generating code without any of those conditional statements being present. But this only happens when not using pattern matching.

Also, the same change needs to be applied to TryRedact.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can't directly cast, and have to do it via an object cast
image
image

Copy link
Member

@geeknoid geeknoid left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We may want to rename Redact<T> to RedactObject<T> to avoid the overload resolution problem.

Looking at this code, I'm also wondering why we don't have other TryRedact overloads to mirror the Redact overloads. Seems like an oversight...

@rafal-mz thought?

@@ -31,38 +31,38 @@ public static void Redaction_Extensions_Return_Zero_On_Null_Input_Value()
[InlineData(10000)]
public static void User_Can_Get_String_From_IRedactor_Using_Extension_Method_With_Different_Input_Length(int length)
{
var data = new string('*', length);
string data = new string('*', length);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why this change?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In many .NET repos we don't use var for integral types and when the type isn't obvious, see https://github.com/dotnet/runtime/blob/main/docs/coding-guidelines/coding-style.md points 10 and 11.
I rolled back this specific one.

@@ -181,6 +186,11 @@ public int Redact<T>(T value, Span<char> destination, string? format = null, IFo
return Redact(((IFormattable)value).ToString(format, provider), destination);
}

if (value is char[] arrayOfChar)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probably this usage is niche, I am not sure if we need this optimization. I don't think it is wrong though, we already have typechecks for iformattable, and it looks the same IMO.

@geeknoid
Copy link
Member

@rafal-mz What about adding more TryRedact overloads to cover the full set? Do you think that would make sense?

@RussKie RussKie changed the base branch from main to release/8.0 August 28, 2023 03:29
@RussKie
Copy link
Member Author

RussKie commented Aug 28, 2023

Ready for another round of review.

@RussKie RussKie merged commit c7f3469 into dotnet:release/8.0 Aug 28, 2023
6 checks passed
@RussKie
Copy link
Member Author

RussKie commented Aug 28, 2023

Thank you

@RussKie RussKie added this to the 8.0 RC2 milestone Aug 28, 2023
@RussKie RussKie deleted the fix_4308_redaction branch August 28, 2023 22:30
@ghost ghost locked as resolved and limited conversation to collaborators Sep 28, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Breaking change in Redactor implementation
3 participants