From 2d3d8b03c82f7e9971c2690ba4d446f835996039 Mon Sep 17 00:00:00 2001 From: =?utf8?q?Tom=C3=A1=C5=A1=20Rylek?= Date: Tue, 14 May 2019 09:40:46 -0700 Subject: [PATCH] Further improvements for R2RDump robustness in the presence of bugs (dotnet/coreclr#24429) Based on JanV's suggestion I have added checks for token ranges to MetadataNameFormatter to make it resilient towards invalid tokens. Thanks Tomas Commit migrated from https://github.com/dotnet/coreclr/commit/e3227026f99b149f6f02afef5896306b7cd38270 --- .../src/tools/r2rdump/DisassemblingTypeProvider.cs | 4 ++-- src/coreclr/src/tools/r2rdump/R2RSignature.cs | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/src/coreclr/src/tools/r2rdump/DisassemblingTypeProvider.cs b/src/coreclr/src/tools/r2rdump/DisassemblingTypeProvider.cs index 19621f1..c8008fc 100644 --- a/src/coreclr/src/tools/r2rdump/DisassemblingTypeProvider.cs +++ b/src/coreclr/src/tools/r2rdump/DisassemblingTypeProvider.cs @@ -64,7 +64,7 @@ namespace R2RDump public virtual string GetGenericMethodParameter(DisassemblingGenericContext genericContext, int index) { - if (index >= genericContext.MethodParameters.Length) + if (genericContext.MethodParameters == null || index >= genericContext.MethodParameters.Length) { return "!!" + index.ToString(); } @@ -73,7 +73,7 @@ namespace R2RDump public virtual string GetGenericTypeParameter(DisassemblingGenericContext genericContext, int index) { - if (index >= genericContext.TypeParameters.Length) + if (genericContext.TypeParameters == null || index >= genericContext.TypeParameters.Length) { return "!" + index.ToString(); } diff --git a/src/coreclr/src/tools/r2rdump/R2RSignature.cs b/src/coreclr/src/tools/r2rdump/R2RSignature.cs index 15773f0..63d6ddf 100644 --- a/src/coreclr/src/tools/r2rdump/R2RSignature.cs +++ b/src/coreclr/src/tools/r2rdump/R2RSignature.cs @@ -90,11 +90,26 @@ namespace R2RDump } /// + /// Check that the metadata handle has valid range in the appropriate table context. + /// + /// Metadata handle to validate + private void ValidateHandle(EntityHandle handle, TableIndex tableIndex) + { + int rowid = MetadataTokens.GetRowNumber(handle); + int tableRowCount = _metadataReader.GetTableRowCount(tableIndex); + if (rowid <= 0 || rowid > tableRowCount) + { + throw new NotImplementedException($"Invalid handle {MetadataTokens.GetToken(handle):X8} in table {tableIndex.ToString()} ({tableRowCount} rows)"); + } + } + + /// /// Emit a method specification. /// /// Method specification handle private string EmitMethodSpecificationName(MethodSpecificationHandle methodSpecHandle, string owningTypeOverride, string signaturePrefix) { + ValidateHandle(methodSpecHandle, TableIndex.MethodSpec); MethodSpecification methodSpec = _metadataReader.GetMethodSpecification(methodSpecHandle); DisassemblingGenericContext genericContext = new DisassemblingGenericContext(Array.Empty(), Array.Empty()); return EmitHandleName(methodSpec.Method, namespaceQualified: true, owningTypeOverride: owningTypeOverride, signaturePrefix: signaturePrefix) @@ -107,6 +122,7 @@ namespace R2RDump /// Member reference handle private string EmitMemberReferenceName(MemberReferenceHandle memberRefHandle, string owningTypeOverride, string signaturePrefix) { + ValidateHandle(memberRefHandle, TableIndex.MemberRef); MemberReference memberRef = _metadataReader.GetMemberReference(memberRefHandle); StringBuilder builder = new StringBuilder(); DisassemblingGenericContext genericContext = new DisassemblingGenericContext(Array.Empty(), Array.Empty()); @@ -144,6 +160,7 @@ namespace R2RDump /// Method definition handle private string EmitMethodDefinitionName(MethodDefinitionHandle methodDefinitionHandle, string owningTypeOverride, string signaturePrefix) { + ValidateHandle(methodDefinitionHandle, TableIndex.MethodDef); MethodDefinition methodDef = _metadataReader.GetMethodDefinition(methodDefinitionHandle); DisassemblingGenericContext genericContext = new DisassemblingGenericContext(Array.Empty(), Array.Empty()); MethodSignature methodSig = methodDef.DecodeSignature(this, genericContext); @@ -229,6 +246,7 @@ namespace R2RDump /// Optional type name signature prefix private string EmitTypeReferenceName(TypeReferenceHandle typeRefHandle, bool namespaceQualified, string signaturePrefix) { + ValidateHandle(typeRefHandle, TableIndex.TypeRef); TypeReference typeRef = _metadataReader.GetTypeReference(typeRefHandle); string typeName = EmitString(typeRef.Name); string output = ""; @@ -257,6 +275,7 @@ namespace R2RDump /// private string EmitTypeDefinitionName(TypeDefinitionHandle typeDefHandle, bool namespaceQualified, string signaturePrefix) { + ValidateHandle(typeDefHandle, TableIndex.TypeDef); TypeDefinition typeDef = _metadataReader.GetTypeDefinition(typeDefHandle); string typeName = signaturePrefix + EmitString(typeDef.Name); if (typeDef.IsNested) @@ -288,6 +307,7 @@ namespace R2RDump /// When set to true, include namespace information private string EmitTypeSpecificationName(TypeSpecificationHandle typeSpecHandle, bool namespaceQualified, string signaturePrefix) { + ValidateHandle(typeSpecHandle, TableIndex.TypeSpec); TypeSpecification typeSpec = _metadataReader.GetTypeSpecification(typeSpecHandle); DisassemblingGenericContext genericContext = new DisassemblingGenericContext(Array.Empty(), Array.Empty()); return typeSpec.DecodeSignature(this, genericContext); @@ -303,6 +323,7 @@ namespace R2RDump /// Textual representation of the field declaration private string EmitFieldDefinitionName(FieldDefinitionHandle fieldDefHandle, bool namespaceQualified, string owningTypeOverride, string signaturePrefix) { + ValidateHandle(fieldDefHandle, TableIndex.Field); FieldDefinition fieldDef = _metadataReader.GetFieldDefinition(fieldDefHandle); DisassemblingGenericContext genericContext = new DisassemblingGenericContext(Array.Empty(), Array.Empty()); StringBuilder output = new StringBuilder(); -- 2.7.4