Handle empty string parameter value in MetadataLoadContext (#61457)
authorPetr Onderka <gsvick@gmail.com>
Wed, 24 Nov 2021 21:10:50 +0000 (22:10 +0100)
committerGitHub <noreply@github.com>
Wed, 24 Nov 2021 21:10:50 +0000 (13:10 -0800)
src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Ecma/EcmaDefaultValueProcessing.cs
src/libraries/System.Reflection.MetadataLoadContext/tests/src/SampleMetadata/SampleMetadata.cs
src/libraries/System.Reflection.MetadataLoadContext/tests/src/Tests/Parameter/ParameterTests.cs

index 75e0e0e..eb0afc9 100644 (file)
@@ -15,7 +15,11 @@ namespace System.Reflection.TypeLoading.Ecma
                 throw new BadImageFormatException();
 
             Constant constantValue = metadataReader.GetConstant(constantHandle);
-            if (constantValue.Value.IsNil)
+            // Partition II section 24.2.4:
+            // The first entry in both these heaps is the empty 'blob' that consists of the single byte 0x00.
+            //
+            // This means zero value is valid for string and is used to represent the empty string.
+            if (constantValue.Value.IsNil && constantValue.TypeCode != ConstantTypeCode.String)
                 throw new BadImageFormatException();
 
             BlobReader reader = metadataReader.GetBlobReader(constantValue.Value);
index 9835e14..15d4673 100644 (file)
@@ -198,6 +198,8 @@ namespace SampleMetadata
         public void Foo4(short s = -34) { }
         public void Foo5(decimal d = 1234m) { }
         public void Foo6([DateTimeConstant(ticks: 8736726782)] DateTime dt) { }
+        public void Foo7(string s1 = "foo", string s2 = "", string s3 = null) { }
+        public void Foo8(Action a = null) { }
     }
 
     public class ParametersWithPseudoCustomtAttributes
index 52fda61..df4f18f 100644 (file)
@@ -67,6 +67,32 @@ namespace System.Reflection.Tests
         }
 
         [Fact]
+        public static void TestRawDefaultValue7()
+        {
+            var parameters = typeof(ParametersWithDefaultValues).Project().GetTypeInfo().GetDeclaredMethod("Foo7").GetParameters();
+            ParameterInfo p1 = parameters[0];
+            Assert.True(p1.HasDefaultValue);
+            object dv1 = p1.RawDefaultValue;
+            Assert.Equal("foo", dv1);
+            ParameterInfo p2 = parameters[1];
+            Assert.True(p2.HasDefaultValue);
+            object dv2 = p2.RawDefaultValue;
+            Assert.Equal("", dv2);
+            ParameterInfo p3 = parameters[2];
+            Assert.True(p3.HasDefaultValue);
+            Assert.Null(p3.RawDefaultValue);
+        }
+
+        [Fact]
+        public static void TestRawDefaultValue8()
+        {
+            ParameterInfo p = typeof(ParametersWithDefaultValues).Project().GetTypeInfo().GetDeclaredMethod("Foo8").GetParameters()[0];
+            Assert.True(p.HasDefaultValue);
+            object dv = p.RawDefaultValue;
+            Assert.Null(dv);
+        }
+
+        [Fact]
         [ActiveIssue("https://github.com/mono/mono/issues/15340", TestRuntimes.Mono)]
         public static void TestPseudoCustomAttributes()
         {