Repository: dotnet/runtime
File: src/coreclr/vm/jitinterface.cpp (C++)

Code before:
    IfFailThrow(p.GetData(&dwExpectedSize));

    if (!(dwFlags & READYTORUN_LAYOUT_GCLayout))
    {
        return nullptr;
    }

    // Use the global loader allocator (System module's allocator) for R2R fixups
    LoaderAllocator* allocator = SystemDomain::GetGlobalLoaderAllocator();
    AsyncContinuationsManager* asyncConts = allocator->GetAsyncContinuationsManager();

    if (!(dwFlags & READYTORUN_LAYOUT_GCLayout_Empty))
    {
        uint8_t* pGCRefMapBlob = (uint8_t*)p.GetPtr();
        size_t objRefsSize = (dwExpectedSize / TARGET_POINTER_SIZE);
        bool* objRefs = (bool*)_alloca(objRefsSize * sizeof(bool));
        size_t bytesInBlob = (objRefsSize + 7) / 8;
        // Read bitmap from blob
        for(size_t byteIndex = 0; byteIndex < bytesInBlob; byteIndex++)
        {
            uint8_t b = pGCRefMapBlob[byteIndex];
            for (int bit = 0; bit < 8 && byteIndex * 8 + bit < objRefsSize; bit++)
            {
                objRefs[byteIndex * 8 + bit] = (b & (1 << bit)) != 0;
            }
        }
        return asyncConts->LookupOrCreateContinuationMethodTableFromLayout(
            (unsigned)dwExpectedSize,
            objRefs
        );
    }
    else
    {
        return asyncConts->LookupOrCreateContinuationMethodTableFromLayout(
            (unsigned)dwExpectedSize,
            nullptr
        );
    }
}


//
// Type layout check verifies that there was no incompatible change in the value type layout.
// If there was one, we will fall back to JIT instead of using the pre-generated code from the ready to run image.
// This should be rare situation. Changes in value type layout not common.
//
// The following properties of the value type layout are checked:
// - Size
// - HFA-ness (on platform that support HFAs)
// - Alignment
// - Position of GC references

Review comment (bug):
The division of dwExpectedSize by TARGET_POINTER_SIZE should be validated to ensure dwExpectedSize is a multiple of TARGET_POINTER_SIZE. If it's not aligned to pointer size, this could lead to incorrect objRefsSize calculation and potential buffer issues when reading the bitmap.
```suggestion
    {
        if ((dwExpectedSize % TARGET_POINTER_SIZE) != 0)
        {
            COMPlusThrowHR(COR_E_BADIMAGEFORMAT);
        }
```

Code after:
    STANDARD_VM_CONTRACT;

    SigPointer p(pBlob);
    // Skip Continuation type signature
    IfFailThrow(p.SkipExactlyOne());

    uint32_t dwFlags;
    IfFailThrow(p.GetData(&dwFlags));

    uint32_t dwExpectedSize;
    IfFailThrow(p.GetData(&dwExpectedSize));

    if (((dwFlags & READYTORUN_LAYOUT_GCLayout) == 0)
        || ((dwFlags & READYTORUN_LAYOUT_Alignment_Native) == 0)
        || ((dwExpectedSize % TARGET_POINTER_SIZE) != 0))
    {
        return nullptr;
    }

    if (dwFlags & READYTORUN_LAYOUT_GCLayout_Empty)
    {
        // No GC references, don't read a bitmap
        return ::getContinuationType(dwExpectedSize, nullptr, 0, currentModule);
    }
    else
    {
        uint8_t* pGCRefMapBlob = (uint8_t*)p.GetPtr();
        size_t objRefsSize = (dwExpectedSize / TARGET_POINTER_SIZE);
        bool* objRefs = (bool*)_alloca(objRefsSize * sizeof(bool));
        size_t bytesInBlob = (objRefsSize + 7) / 8;
        // Expand bitmap to bool array for use with getContinuationType
        for (size_t byteIndex = 0; byteIndex < bytesInBlob; byteIndex++)
        {
            uint8_t b = pGCRefMapBlob[byteIndex];
            for (int bit = 0; bit < 8 && byteIndex * 8 + bit < objRefsSize; bit++)
            {
                objRefs[byteIndex * 8 + bit] = (b & (1 << bit)) != 0;
            }
        }
        return ::getContinuationType(dwExpectedSize, objRefs, objRefsSize, currentModule);
    }
}


//
// Type layout check verifies that there was no incompatible change in the value type layout.
// If there was one, we will fall back to JIT instead of using the pre-generated code from the ready to run image.
// This should be rare situation. Changes in value type layout not common.
//
// The following properties of the value type layout are checked:
// - Size