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

ResolveAssemblyReference throws InvalidOperationException on invalid PE files #6200

Closed
FiniteReality opened this issue Feb 26, 2021 · 2 comments · Fixed by #6270
Closed

ResolveAssemblyReference throws InvalidOperationException on invalid PE files #6200

FiniteReality opened this issue Feb 26, 2021 · 2 comments · Fixed by #6270
Labels
bug needs-triage Have yet to determine what bucket this goes in.

Comments

@FiniteReality
Copy link
Contributor

Issue Description

I have a project which produces native binaries (on linux, so ELF format) and when I use ProjectReference to indicate project dependencies, ResolveAssemblyReference tries to read the metadata of these files and throws InvalidOperationException because the dependencies don't use the PE format, or have metadata.

Steps to Reproduce

Reproducing this is pretty hard in my experience, since most ELF files make the PEReader throw a BadImageFormatException. I've opened a related issue in the .NET runtime because of this: dotnet/runtime#48419

The summary is, though:

  1. Create a MSBuild project which produces a non-PE format file (e.g. by writing a large text file to $(IntermediateOutputPath)$(TargetName)$(TargetExt))
  2. Try to reference that project from another using ProjectReference
  3. Build the project in step 2

Expected Behavior

ResolveAssemblyReference skips the project because it doesn't have any metadata

Actual Behavior

ResolveAssemblyReference throws an InvalidOperationException from PEReader.GetMetadataBlock()

Analysis

Doing some digging, this appears to be caused by AssemblyInformation.CorePopulateMetadata not checking whether the created PEReader has any metadata. This appears to be checked everywhere else a PEReader is used:

Versions & Configurations

$ dotnet --info
.NET SDK (reflecting any global.json):
 Version:   5.0.103
 Commit:    9effbc8ad5

Runtime Environment:
 OS Name:     debian
 OS Version:  
 OS Platform: Linux
 RID:         debian-x64
 Base Path:   /usr/share/dotnet/sdk/5.0.103/

Host (useful for support):
  Version: 5.0.3
  Commit:  eae88cc11b

.NET SDKs installed:
  3.1.406 [/usr/share/dotnet/sdk]
  5.0.103 [/usr/share/dotnet/sdk]

.NET runtimes installed:
  Microsoft.AspNetCore.App 3.1.12 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.AspNetCore.App 5.0.3 [/usr/share/dotnet/shared/Microsoft.AspNetCore.App]
  Microsoft.NETCore.App 3.1.12 [/usr/share/dotnet/shared/Microsoft.NETCore.App]
  Microsoft.NETCore.App 5.0.3 [/usr/share/dotnet/shared/Microsoft.NETCore.App]

To install additional .NET runtimes or SDKs:
  https://aka.ms/dotnet-download
$ dotnet msbuild -version
Microsoft (R) Build Engine version 16.8.3+39993bd9d for .NET
Copyright (C) Microsoft Corporation. All rights reserved.

16.8.3.61104

Attach a binlog

This binlog reproduces the issue, and I've been unable to reproduce it using smaller projects. I think this may be because smaller projects produce smaller binaries, which PEReader ends up rejecting. The source for the ClangLink and ClangCompile tasks can be found here.

@FiniteReality FiniteReality added bug needs-triage Have yet to determine what bucket this goes in. labels Feb 26, 2021
@cdmihai
Copy link
Contributor

cdmihai commented Mar 19, 2021

I think the story with non-managed assemblies is that you have to add the ReferenceOutputAssembly="False" OutputItemType="Content" metadata to your ProjectReference item (docs). Can you please check whether this works for you?

@FiniteReality
Copy link
Contributor Author

FiniteReality commented Mar 20, 2021

I think the story with non-managed assemblies is that you have to add the ReferenceOutputAssembly="False" OutputItemType="Content" metadata to your ProjectReference item (docs). Can you please check whether this works for you?

I'm currently building an MSBuild SDK to allow building of native projects (which is probably outside of the supported use case, which I'm fine with), so I'd rather not have to do that in each project - if there's an alternative place I can specify this (like GetTargetPath) then I might be able to build my own infrastructure for this. However, as it stands currently, I'm stuck relying on ResolveAssemblyReference working correctly, since it's an incredibly complex task which does a lot of things.

EDIT: For what it's worth, somehow the Visual C++ toolchain manages to let you use <ProjectReference Include="path/to/project.vcxproj"/> without ReferenceOutputAssembly and OutputItemType - I'm interested in replicating that behaviour for consumption. However, for legal reasons I obviously can't just look at how the Visual C++ toolchain manages it 😛

Forgind pushed a commit that referenced this issue Mar 31, 2021
Fixes #6200

Context
InvalidOperationException was being thrown by AssemblyInformation.CorePopulateMetadata, causing the ResolveAssemblyReference task to fail rather than disregarding the file.

Changes Made
I copied the code from AssemblyNameExtension to ensure there is metadata present before getting a metadata reader
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug needs-triage Have yet to determine what bucket this goes in.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants