Handle renamed compressed .mibc files gracefully in crossgen2/dotnet-pgo (#81955)
authorJakob Botsch Nielsen <Jakob.botsch.nielsen@gmail.com>
Sat, 11 Feb 2023 12:14:55 +0000 (13:14 +0100)
committerGitHub <noreply@github.com>
Sat, 11 Feb 2023 12:14:55 +0000 (13:14 +0100)
The existing logic would throw a NullReferenceException if you renamed a
compressed .mibc file and then tried to pass it to dotnet-pgo or
crossgen2. This PR adds a fallback case to look for a single .dll file
inside the archive when an entry with the expected name is not present.

In addition throw an exception with a better error message when the
lookup fails.

src/coreclr/tools/aot/ILCompiler.ReadyToRun/IBC/MIbcProfileParser.cs

index b82f6f9..28b327a 100644 (file)
@@ -102,7 +102,19 @@ namespace ILCompiler.IBC
                         using (var zipFile = new ZipArchive(fsMibcFile, ZipArchiveMode.Read, leaveOpen: false, entryNameEncoding: null))
                         {
                             disposeOnException = false;
-                            var mibcDataEntry = zipFile.GetEntry(Path.GetFileName(filename) + ".dll");
+                            ZipArchiveEntry mibcDataEntry = zipFile.GetEntry(Path.GetFileName(filename) + ".dll");
+
+                            if (mibcDataEntry == null)
+                            {
+                                // Input may have been renamed at some point; look for a single .dll inside the ZIP.
+                                mibcDataEntry = zipFile.Entries.Count == 1 ? zipFile.Entries[0] : null;
+
+                                if (mibcDataEntry == null || !mibcDataEntry.Name.EndsWith(".dll"))
+                                {
+                                    throw new InvalidDataException("Could not find input assembly in compressed MIBC file (expected archive to contain a single .dll file)");
+                                }
+                            }
+
                             using (var mibcDataStream = mibcDataEntry.Open())
                             {
                                 peData = new byte[mibcDataEntry.Length];