Skip to content

Fix a native integer decoding bug#43885

Merged
4 commits merged intodotnet:masterfrom
333fred:nint-decode-bug
May 6, 2020
Merged

Fix a native integer decoding bug#43885
4 commits merged intodotnet:masterfrom
333fred:nint-decode-bug

Conversation

@333fred
Copy link
Member

@333fred 333fred commented May 1, 2020

We weren't consuming an index when decoding type parameters or dynamic types, meaning that we could get into a scenario where the remaining flags are applying to the wrong types. I also tightened our assertions around ignored indexes.

@cston for review.

We weren't consuming an index when decoding type parameters or dynamic types, meaning that we could get into a scenario where the remaining flags are applying to the wrong types.
@333fred 333fred requested review from a team and cston May 1, 2020 21:26
return TransformPointerType((PointerTypeSymbol)type);
case TypeKind.TypeParameter:
case TypeKind.Dynamic:
IgnoreIndex();
Copy link
Member Author

Choose a reason for hiding this comment

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

This part is the bug fix.

private void IgnoreIndex()
{
var index = Increment();
Debug.Assert(!_transformFlags[index]);
Copy link
Contributor

@cston cston May 1, 2020

Choose a reason for hiding this comment

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

Debug.Assert(!_transformFlags[index]) [](start = 12, length = 37)

This may fail for handwritten attribute data.

Please add a test.

class C<T, U, V>
{{
public {sourceType} F;
}}
Copy link
Contributor

@cston cston May 1, 2020

Choose a reason for hiding this comment

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

Please consider writing out all the cases inline as separate fields in a single test, for readability and to match other tests.

}}
", options: TestOptions.ReleaseDll, parseOptions: TestOptions.RegularPreview, symbolValidator: symbolValidator);

void symbolValidator(ModuleSymbol module)
Copy link
Contributor

Choose a reason for hiding this comment

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

void [](start = 12, length = 4)

Consider making static or inline in CompileAndVerify to match the other tests.

@@ -125,6 +128,12 @@ private int Increment()
throw new ArgumentException();
Copy link
Member

@gafter gafter May 1, 2020

Choose a reason for hiding this comment

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

throw new ArgumentException [](start = 12, length = 27)

If we're worried about handwritten attribute data, this could crash the compiler as well. Please add a test. #Resolved

Copy link
Member Author

@333fred 333fred May 1, 2020

Choose a reason for hiding this comment

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

It can't crash the compiler, it's caught above. I already tried to crash it with this :). #Resolved

Copy link
Contributor

Choose a reason for hiding this comment

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

There should be existing tests for this case.


In reply to: 418757779 [](ancestors = 418757779)

gafter
gafter previously approved these changes May 1, 2020
Copy link
Member

@gafter gafter left a comment

Choose a reason for hiding this comment

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

:shipit:

default:
Debug.Assert(type.TypeKind == TypeKind.Error);
_decodeStatus = DecodeStatus.FailedToErrorType;
throw new ArgumentException();
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider extracting a helper method with DecodeStatus argument.

{
NotFailed,
FailedToErrorType,
FailedToBadMetadata,
Copy link
Contributor

Choose a reason for hiding this comment

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

Consider renaming fields, perhaps:

enum DecodeStatus
{
    Succeeded,
    ErrorType,
    BadMetadata,
}


private readonly ImmutableArray<bool> _transformFlags;
private int _index;
private DecodeStatus _decodeStatus;
Copy link
Contributor

Choose a reason for hiding this comment

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

DecodeStatus _decodeStatus [](start = 16, length = 26)

Is this field needed?

Rather than using a field, could we just throw ArgumentException for cases that have error types (where we catch the exception locally and return the original type), and throw UnsupportMetadataTypeSymbol for case where we fail completely?

if (_transformFlags[index])
{
_decodeStatus = DecodeStatus.FailedToBadMetadata;
throw new ArgumentException();
Copy link
Contributor

Choose a reason for hiding this comment

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

throw new ArgumentException(); [](start = 16, length = 30)

Are we testing this case?

Copy link
Contributor

@cston cston left a comment

Choose a reason for hiding this comment

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

LGTM. Thanks for fixing this.

@333fred 333fred requested a review from gafter May 2, 2020 07:36
@333fred
Copy link
Member Author

333fred commented May 2, 2020

@gafter there have been more changes since your review, probably needs another look.

Copy link
Contributor

@AlekseyTs AlekseyTs left a comment

Choose a reason for hiding this comment

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

We should either produce successfully decoded type, or ignore the malformed attribute and return original type. This is how I believe we always handle attributes like that.

@AlekseyTs AlekseyTs dismissed their stale review May 2, 2020 14:52

Obsolete

@AlekseyTs
Copy link
Contributor

AlekseyTs commented May 2, 2020

We should either produce successfully decoded type, or ignore the malformed attribute and return original type. This is how I believe we always handle attributes like that.

Actually, it looks like only nullable decoder ignores malformed attribute, which probably makes sense because annotations can cause only warnings. #Closed

@333fred
Copy link
Member Author

333fred commented May 2, 2020

Actually, it looks like only nullable decoder ignores malformed attribute, which probably makes sense because annotations can cause only warnings.

Yeah. My concern with bad nint data is that it will affect codegen.

@gafter gafter dismissed their stale review May 5, 2020 23:25

revoking review

{
return new UnsupportedMetadataTypeSymbol();
}
catch (ArgumentException)
Copy link
Member

@gafter gafter May 5, 2020

Choose a reason for hiding this comment

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

ArgumentException [](start = 19, length = 17)

Using ArgumentException to manage these failure modes (line 88) seems a bit dangerous, as you can't have complete confidence that it was one thrown as part of decoding in this class. It might be better to make a custom exception (private?) for this purpose/

Copy link
Member

@gafter gafter left a comment

Choose a reason for hiding this comment

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

I suggest you stop using ArgumentException in the decoder, because when you catch it you cannot be sure it was thrown in your code on line 88. Instead perhaps use a new private exception for that purpose.

Otherwise looks good.

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

Auto-approval

@ghost ghost merged commit cb1f6ee into dotnet:master May 6, 2020
@333fred 333fred deleted the nint-decode-bug branch May 6, 2020 19:48
This pull request was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants