diff options
author | Michal Strehovský <MichalStrehovsky@users.noreply.github.com> | 2019-06-18 09:07:15 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2019-06-18 09:07:15 +0200 |
commit | 84dc3732c6fd0f4739214eb83ffd643a33a5da17 (patch) | |
tree | 5170ba2ac10b890ca5f2a43f595eb6a6cb0487ea /src/vm/methodtablebuilder.cpp | |
parent | 2b85852af5e4e46973af07ce36c4d2f2a0e30616 (diff) | |
download | coreclr-84dc3732c6fd0f4739214eb83ffd643a33a5da17.tar.gz coreclr-84dc3732c6fd0f4739214eb83ffd643a33a5da17.tar.bz2 coreclr-84dc3732c6fd0f4739214eb83ffd643a33a5da17.zip |
Prevent loading byref-like types with invalid layout (#25200)
First approximation of a fix for #25057.
This has two problems:
* We're checking for any byref-like typed fields. Types that don't actually contain interior pointers but were marked as `ref struct` will fail to load when not aligned properly.
* We're not doing the deep validation that we do for reference types to make sure the `ByReference<T>` field doesn't overlap with another non-byreference field.
Question is whether we're okay with those limitations, or whether we need a better fix. Better fix would likely entail inefficiently walking over the fields à la `FindByRefPointerOffsetsInByRefLikeObject` (doing the more efficient thing that we do for object references below would require a GCDesc representation of byrefness).
Contributes to #25057.
Diffstat (limited to 'src/vm/methodtablebuilder.cpp')
-rw-r--r-- | src/vm/methodtablebuilder.cpp | 10 |
1 files changed, 10 insertions, 0 deletions
diff --git a/src/vm/methodtablebuilder.cpp b/src/vm/methodtablebuilder.cpp index bec874ef45..f5038138f1 100644 --- a/src/vm/methodtablebuilder.cpp +++ b/src/vm/methodtablebuilder.cpp @@ -8397,6 +8397,16 @@ MethodTableBuilder::HandleExplicitLayout( if (pFD->IsByValue()) { MethodTable *pByValueMT = pByValueClassCache[valueClassCacheIndex]; + if (pByValueMT->IsByRefLike()) + { + if ((pFD->GetOffset_NoLogging() & ((ULONG)TARGET_POINTER_SIZE - 1)) != 0) + { + // If we got here, then a byref-like valuetype was misaligned. + badOffset = pFD->GetOffset_NoLogging(); + fieldTrust.SetTrust(ExplicitFieldTrust::kNone); + break; + } + } if (pByValueMT->ContainsPointers()) { if ((pFD->GetOffset_NoLogging() & ((ULONG)TARGET_POINTER_SIZE - 1)) == 0) |