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

TypeNameParser produces wrong IsValueType on value types not in current module #598

Open
puff opened this issue Nov 24, 2024 · 0 comments
Open
Labels

Comments

@puff
Copy link

puff commented Nov 24, 2024

AsmResolver Version

6.0.0-beta.1

.NET Version

.NET 6.0

Operating System

Windows

Describe the Bug

TypeNameParser.Parse will always create a TypeDefOrRefSignature with IsValueType set as false for types not defined in the module passed to it.

The underlying TypeDefOrRef will have the correct value if the type is able to be resolved.

This happens because TypeDefOrRefSignature takes in IsValueType as an argument in its constructor, and TypeNameParser does not properly resolve this before it creates the signature.

TypeNameParser creates the signature before resolving the scope:

// Parse type signature.
_lexer.HasConsumedTypeName = false;
var typeSpec = ParseSimpleTypeSpec();
_lexer.HasConsumedTypeName = true;

In parsing the signature, it eventually creates a TypeReference and calls ToTypeSignature:

This creates a new TypeDefOrRefSignature with the wrong IsValueType, as the TypeReference does not have the correct scope to resolve it.

Only after the signature was created, the scope is parsed and set:

// See if the type full name contains an assembly ref.
var scope = TryExpect(TypeNameTerminal.Comma).HasValue
? (IResolutionScope) ParseAssemblyNameSpec()
: null;
_lexer.HasConsumedTypeName = lastHasConsumedTypeName;
if (typeSpec.GetUnderlyingTypeDefOrRef() is TypeReference reference)
SetScope(reference, scope);

This results in the TypeDefOrRefSignature having the wrong IsValueType, while the underlying Type has the correct IsValueType as it is now able to be resolved.

This also causes an issue in SignatureComparer when comparing GenericInstanceTypeSignatures created from parsed types as IsValueType isn't correct.

How To Reproduce

const string typeName = "System.Nullable`1, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
var module = ModuleDefinition.FromModule(typeof(Program).Module);
var type = TypeNameParser.Parse(module, typeName) as TypeDefOrRefSignature;
Console.WriteLine(type.IsValueType);
Console.WriteLine(type.Type.IsValueType);

Expected Behavior

True
True

Actual Behavior

False
True

Additional Context

Only ways I see to fix it are to either parse the type name backwards starting with the scope, or to use Type.IsValueType in TypeDefOrRefSignature instead of passing it in as an argument during creation.

EDIT: As discussed in Discord, another way of fixing it could be to delay creating the signature until after parsing the scope by storing the TypeReference and modifiers (byref, pointer, etc) to apply afterwards.

@puff puff added the bug label Nov 24, 2024
@puff puff changed the title TypeNameParser produces wrong signature on value types not in current module TypeNameParser produces wrong IsValueType on value types not in current module Nov 24, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant