diff --git a/src/coreclr/vm/methodtablebuilder.cpp b/src/coreclr/vm/methodtablebuilder.cpp index 154c642cf40d7..b426204e44389 100644 --- a/src/coreclr/vm/methodtablebuilder.cpp +++ b/src/coreclr/vm/methodtablebuilder.cpp @@ -2751,15 +2751,7 @@ MethodTableBuilder::EnumerateClassMethods() BuildMethodTableThrowException(IDS_CLASSLOAD_BADFORMAT); } - // Signature validation - if (!bmtProp->fNoSanityChecks) - { - hr = validateTokenSig(tok,pMemberSignature,cMemberSignature,dwMemberAttrs,pMDInternalImport); - if (FAILED(hr)) - { - BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil); - } - } + bool isVtblGap = false; if (IsMdRTSpecialName(dwMemberAttrs) || IsMdVirtual(dwMemberAttrs) || IsDelegate()) { if (FAILED(pMDInternalImport->GetNameOfMethodDef(tok, (LPCSTR *)&strMethodName))) @@ -2770,12 +2762,24 @@ MethodTableBuilder::EnumerateClassMethods() { BuildMethodTableThrowException(BFA_METHOD_NAME_TOO_LONG); } + + isVtblGap = IsMdRTSpecialName(dwMemberAttrs) && strncmp(strMethodName, "_VtblGap", 8) == 0; } else { strMethodName = NULL; } + // Signature validation + if (!bmtProp->fNoSanityChecks && !isVtblGap) + { + hr = validateTokenSig(tok,pMemberSignature,cMemberSignature,dwMemberAttrs,pMDInternalImport); + if (FAILED(hr)) + { + BuildMethodTableThrowException(hr, BFA_BAD_SIGNATURE, mdMethodDefNil); + } + } + DWORD numGenericMethodArgs = 0; { @@ -2847,85 +2851,78 @@ MethodTableBuilder::EnumerateClassMethods() // single empty slot). // - if (IsMdRTSpecialName(dwMemberAttrs)) + if (isVtblGap) { - PREFIX_ASSUME(strMethodName != NULL); // if we've gotten here we've called GetNameOfMethodDef - - // The slot is special, but it might not be a vtable spacer. To - // determine that we must look at the name. - if (strncmp(strMethodName, "_VtblGap", 8) == 0) - { - // - // This slot doesn't really exist, don't add it to the method - // table. Instead it represents one or more empty slots, encoded - // in the method name. Locate the beginning of the count in the - // name. There are these points to consider: - // There may be no count present at all (in which case the - // count is taken as one). - // There may be an additional count just after Gap but before - // the '_'. We ignore this. - // + // + // This slot doesn't really exist, don't add it to the method + // table. Instead it represents one or more empty slots, encoded + // in the method name. Locate the beginning of the count in the + // name. There are these points to consider: + // There may be no count present at all (in which case the + // count is taken as one). + // There may be an additional count just after Gap but before + // the '_'. We ignore this. + // - LPCSTR pos = strMethodName + 8; + LPCSTR pos = strMethodName + 8; - // Skip optional number. - while (IS_DIGIT(*pos)) - pos++; + // Skip optional number. + while (IS_DIGIT(*pos)) + pos++; - WORD n = 0; + WORD n = 0; - // Check for presence of count. - if (*pos == '\0') - n = 1; - else + // Check for presence of count. + if (*pos == '\0') + { + n = 1; + } + else + { + if (*pos != '_') { - if (*pos != '_') - { - BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, - IDS_CLASSLOAD_BADSPECIALMETHOD, - tok); - } + BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, + IDS_CLASSLOAD_BADSPECIALMETHOD, + tok); + } - // Skip '_'. - pos++; + // Skip '_'. + pos++; - // Read count. - bool fReadAtLeastOneDigit = false; - while (IS_DIGIT(*pos)) - { - _ASSERTE(n < 6552); - n *= 10; - n += DIGIT_TO_INT(*pos); - pos++; - fReadAtLeastOneDigit = true; - } + // Read count. + bool fReadAtLeastOneDigit = false; + while (IS_DIGIT(*pos)) + { + _ASSERTE(n < 6552); + n *= 10; + n += DIGIT_TO_INT(*pos); + pos++; + fReadAtLeastOneDigit = true; + } - // Check for end of name. - if (*pos != '\0' || !fReadAtLeastOneDigit) - { - BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, - IDS_CLASSLOAD_BADSPECIALMETHOD, - tok); - } + // Check for end of name. + if (*pos != '\0' || !fReadAtLeastOneDigit) + { + BuildMethodTableThrowException(COR_E_BADIMAGEFORMAT, + IDS_CLASSLOAD_BADSPECIALMETHOD, + tok); } + } #ifdef FEATURE_COMINTEROP - // Record vtable gap in mapping list. The map is an optional field, so ensure we've allocated - // these fields first. - EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap()); - if (GetHalfBakedClass()->GetSparseCOMInteropVTableMap() == NULL) - GetHalfBakedClass()->SetSparseCOMInteropVTableMap(new SparseVTableMap()); + // Record vtable gap in mapping list. The map is an optional field, so ensure we've allocated + // these fields first. + EnsureOptionalFieldsAreAllocated(GetHalfBakedClass(), m_pAllocMemTracker, GetLoaderAllocator()->GetLowFrequencyHeap()); + if (GetHalfBakedClass()->GetSparseCOMInteropVTableMap() == NULL) + GetHalfBakedClass()->SetSparseCOMInteropVTableMap(new SparseVTableMap()); - GetHalfBakedClass()->GetSparseCOMInteropVTableMap()->RecordGap((WORD)NumDeclaredMethods(), n); + GetHalfBakedClass()->GetSparseCOMInteropVTableMap()->RecordGap((WORD)NumDeclaredMethods(), n); - bmtProp->fSparse = true; + bmtProp->fSparse = true; #endif // FEATURE_COMINTEROP - continue; - } - + continue; } - // // This is a real method so add it to the enumeration of methods. We now need to retrieve // information on the method and store it for later use.