Ensure MetadataEnumResult is sufficiently updated by MetaDataImport::Enum (#56756)
authorAndy Ayers <andya@microsoft.com>
Tue, 3 Aug 2021 16:06:47 +0000 (09:06 -0700)
committerGitHub <noreply@github.com>
Tue, 3 Aug 2021 16:06:47 +0000 (09:06 -0700)
`MetadataEnumResult` has a fixed inline buffer for returning small results
and a pointer to allow it to return larger ones. The indexer for this
checks the pointer and if non-null assumes that's the current set of
values.

But if a `MetadataEnumResult` is re-used within a loop, values written to it
by `MetaDataImport::Enum` may bleed from one loop iteration to the next
if the iterations first get a large result and then a small one.

One case where this could happen was in libraries PGO tests, where PGO data
encouraged the jit to inline `MemberInfoCache<T>.PopulateProperties(Filter,...)`
into `MemberInfoCache<T>.PopulateProperties(Filter)`.

Note this also is a conseqeunce of skipping zero init locals; without that
the struct would have been zeroed each loop iteration.

Fixes #56655.

src/coreclr/vm/managedmdimport.cpp

index 6bea537..ec2aef0 100644 (file)
@@ -163,6 +163,7 @@ static int * EnsureResultSize(MetadataEnumResult * pResult, ULONG length)
     else
     {
         ZeroMemory(pResult->smallResult, sizeof(pResult->smallResult));
+        pResult->largeResult = NULL;
         p = pResult->smallResult;
     }