Browse Source

Fix #1206: Could not decode attribute arguments. There was a bug in the calculation of public key tokens of assembly definitions.

pull/1213/head
Siegfried Pammer 7 years ago
parent
commit
b82f4dd773
  1. 57
      ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs
  2. 7
      ICSharpCode.Decompiler/Util/CollectionExtensions.cs
  3. 3
      ILSpy/LoadedAssembly.cs

57
ICSharpCode.Decompiler/Metadata/MetadataExtensions.cs

@ -18,6 +18,37 @@ namespace ICSharpCode.Decompiler.Metadata @@ -18,6 +18,37 @@ namespace ICSharpCode.Decompiler.Metadata
{
public static class MetadataExtensions
{
static HashAlgorithm GetHashAlgorithm(this MetadataReader reader)
{
switch (reader.GetAssemblyDefinition().HashAlgorithm) {
case AssemblyHashAlgorithm.None:
// only for multi-module assemblies?
return SHA1.Create();
case AssemblyHashAlgorithm.MD5:
return MD5.Create();
case AssemblyHashAlgorithm.Sha1:
return SHA1.Create();
case AssemblyHashAlgorithm.Sha256:
return SHA256.Create();
case AssemblyHashAlgorithm.Sha384:
return SHA384.Create();
case AssemblyHashAlgorithm.Sha512:
return SHA512.Create();
default:
return SHA1.Create(); // default?
}
}
static string CalculatePublicKeyToken(BlobHandle blob, MetadataReader reader)
{
// Calculate public key token:
// 1. hash the public key using the appropriate algorithm.
byte[] publicKeyTokenBytes = reader.GetHashAlgorithm().ComputeHash(reader.GetBlobBytes(blob));
// 2. take the last 8 bytes
// 3. according to Cecil we need to reverse them, other sources did not mention this.
return publicKeyTokenBytes.TakeLast(8).Reverse().ToHexString(8);
}
public static string GetFullAssemblyName(this MetadataReader reader)
{
if (!reader.IsAssembly)
@ -25,33 +56,37 @@ namespace ICSharpCode.Decompiler.Metadata @@ -25,33 +56,37 @@ namespace ICSharpCode.Decompiler.Metadata
var asm = reader.GetAssemblyDefinition();
string publicKey = "null";
if (!asm.PublicKey.IsNil) {
SHA1 sha1 = SHA1.Create();
var publicKeyTokenBytes = sha1.ComputeHash(reader.GetBlobBytes(asm.PublicKey)).Skip(12).ToArray();
publicKey = publicKeyTokenBytes.ToHexString();
// AssemblyFlags.PublicKey does not apply to assembly definitions
publicKey = CalculatePublicKeyToken(asm.PublicKey, reader);
}
return $"{reader.GetString(asm.Name)}, Version={asm.Version}, Culture={(asm.Culture.IsNil ? "neutral" : reader.GetString(asm.Culture))}, PublicKeyToken={publicKey}";
return $"{reader.GetString(asm.Name)}, " +
$"Version={asm.Version}, " +
$"Culture={(asm.Culture.IsNil ? "neutral" : reader.GetString(asm.Culture))}, " +
$"PublicKeyToken={publicKey}";
}
public static string GetFullAssemblyName(this SRM.AssemblyReference reference, MetadataReader reader)
{
string publicKey = "null";
if (!reference.PublicKeyOrToken.IsNil) {
byte[] publicKeyTokenBytes = reader.GetBlobBytes(reference.PublicKeyOrToken);
if ((reference.Flags & AssemblyFlags.PublicKey) != 0) {
SHA1 sha1 = SHA1.Create();
publicKeyTokenBytes = sha1.ComputeHash(publicKeyTokenBytes).Skip(12).ToArray();
publicKey = CalculatePublicKeyToken(reference.PublicKeyOrToken, reader);
} else {
publicKey = reader.GetBlobBytes(reference.PublicKeyOrToken).ToHexString(8);
}
publicKey = publicKeyTokenBytes.ToHexString();
}
string properties = "";
if ((reference.Flags & AssemblyFlags.Retargetable) != 0)
properties = ", Retargetable=true";
return $"{reader.GetString(reference.Name)}, Version={reference.Version}, Culture={(reference.Culture.IsNil ? "neutral" : reader.GetString(reference.Culture))}, PublicKeyToken={publicKey}{properties}";
return $"{reader.GetString(reference.Name)}, " +
$"Version={reference.Version}, " +
$"Culture={(reference.Culture.IsNil ? "neutral" : reader.GetString(reference.Culture))}, " +
$"PublicKeyToken={publicKey}{properties}";
}
static string ToHexString(this byte[] bytes)
static string ToHexString(this IEnumerable<byte> bytes, int estimatedLength)
{
StringBuilder sb = new StringBuilder(bytes.Length * 2);
StringBuilder sb = new StringBuilder(estimatedLength * 2);
foreach (var b in bytes)
sb.AppendFormat("{0:x2}", b);
return sb.ToString();

7
ICSharpCode.Decompiler/Util/CollectionExtensions.cs

@ -60,7 +60,12 @@ namespace ICSharpCode.Decompiler.Util @@ -60,7 +60,12 @@ namespace ICSharpCode.Decompiler.Util
{
return input.Take(input.Count - count);
}
public static IEnumerable<T> TakeLast<T>(this IReadOnlyCollection<T> input, int count)
{
return input.Skip(input.Count - count);
}
public static T PopOrDefault<T>(this Stack<T> stack)
{
if (stack.Count == 0)

3
ILSpy/LoadedAssembly.cs

@ -308,7 +308,8 @@ namespace ICSharpCode.ILSpy @@ -308,7 +308,8 @@ namespace ICSharpCode.ILSpy
var reader = loaded.GetPEFileOrNull()?.Metadata;
if (reader == null || !reader.IsAssembly) continue;
var asmDef = reader.GetAssemblyDefinition();
if (GetName(fullName).Equals(isWinRT ? reader.GetString(asmDef.Name) : reader.GetFullAssemblyName(), StringComparison.OrdinalIgnoreCase)) {
var asmDefName = isWinRT ? reader.GetString(asmDef.Name) : reader.GetFullAssemblyName();
if (GetName(fullName).Equals(asmDefName, StringComparison.OrdinalIgnoreCase)) {
LoadedAssemblyReferencesInfo.AddMessageOnce(fullName.FullName, MessageKind.Info, "Success - Found in Assembly List");
return loaded;
}

Loading…
Cancel
Save