diff --git a/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs b/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs index f1835b1fa5ecc9..8ec3790784b621 100644 --- a/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs +++ b/src/tasks/MonoTargetsTasks/ILStrip/AssemblyStripper/AssemblyStripper.cs @@ -12,6 +12,16 @@ namespace AssemblyStripper { + class CustomAttrRowComparer : IComparer + { + public int Compare(object left, object right) + { + CustomAttributeRow row_left = (CustomAttributeRow)left; + CustomAttributeRow row_right = (CustomAttributeRow)right; + return row_left.Parent.RID.CompareTo(row_right.Parent.RID); + } + } + public class AssemblyStripper { AssemblyDefinition assembly; @@ -40,6 +50,7 @@ void Strip() PatchMethods(); PatchFields(); PatchResources(); + SortCustomAttributes(); Write(); } @@ -192,6 +203,20 @@ void PatchResources() } } + // Types that are trimmed away also have their respective rows removed from the + // custom attribute table. This introduces holes in their places, causing the table + // to no longer be sorted by Parent, corrupting the assembly. Runtimes assume ordering + // and may fail to locate the attributes set for a particular type. This step sorts + // the custom attribute table again. + void SortCustomAttributes() + { + CustomAttributeTable table = (CustomAttributeTable)stripped_tables[CustomAttributeTable.RId]; + if (table == null) + return; + + table.Rows.Sort(new CustomAttrRowComparer()); + } + void Write() { stripped.MetadataRoot.Accept(metadata_writer); @@ -209,7 +234,6 @@ public static void StripAssembly(string assemblyFile, string outputPath) { AssemblyDefinition assembly = AssemblyFactory.GetAssembly(assemblyFile); AssemblyStripper.StripAssembly(assembly, outputPath); - } } }