Repository: dotnet/runtime
File: src/coreclr/interpreter/compiler.cpp (C++)

Code before:
    }

    if ((m_compHnd->getClassAttribs(peepInfo.newObjResolvedToken.hClass) & CORINFO_FLG_DELEGATE) == 0)
    {
        return false;
    }

    // The jit is expected to call the getNewHelper api to trigger a set of validations
    bool hasSideEffects = false;
    m_compHnd->getNewHelper(peepInfo.newObjResolvedToken.hClass, &hasSideEffects);

    CORINFO_METHOD_HANDLE alternateCtor = nullptr;
    DelegateCtorArgs      ctorData;
    ctorData.pMethod = m_methodInfo->ftn;
    ctorData.pArg3   = nullptr;
    ctorData.pArg4   = nullptr;
    ctorData.pArg5   = nullptr;

    alternateCtor = m_compHnd->GetDelegateCtor(peepInfo.newObjResolvedToken.hMethod, peepInfo.newObjResolvedToken.hClass, peepInfo.ldftnResolvedToken.hMethod, &ctorData);
    if (alternateCtor == peepInfo.newObjResolvedToken.hMethod)
    {
        return false;
    }

    LdftnDelegateCtorPeepInfo *pPeepInfo = (LdftnDelegateCtorPeepInfo*)AllocMemPool(sizeof(LdftnDelegateCtorPeepInfo));
    *pPeepInfo = peepInfo;
    *ppComputedInfo = pPeepInfo;
    return true;
}

int InterpCompiler::ApplyLdftnDelegateCtorPeep(const uint8_t* ip, OpcodePeepElement* pattern, void* pComputedInfo)
{
    LdftnDelegateCtorPeepInfo *peepInfo = (LdftnDelegateCtorPeepInfo*)pComputedInfo;
    // If there is a virtual load scenario, implement the dup
    if (pattern[0].opcode == CEE_DUP)
    {
        EmitDup();
    }

    // Do the function pointer load
    EmitLdftn(&peepInfo->ldftnResolvedToken, peepInfo->isLdVirtFtn);

    // Load any extra args needed for the alternate delegate constructor
    int extraArgCount = 0;
    if (peepInfo->ctorData.pArg3 != NULL)
    {
        EmitLoadPointer((intptr_t)peepInfo->ctorData.pArg3);
        extraArgCount++;
        if (peepInfo->ctorData.pArg4 != NULL)
        {
            EmitLoadPointer((intptr_t)peepInfo->ctorData.pArg4);

Review comment (suggestion):
The local variable `ctorData` is populated by the `GetDelegateCtor` call on line 6442, but it is never assigned to `peepInfo.ctorData`. This means when `peepInfo` is copied to `pPeepInfo` on line 6449, the `ctorData` field will contain uninitialized or default values rather than the data returned from `GetDelegateCtor`. This will cause the `ApplyLdftnDelegateCtorPeep` function to miss the extra arguments (pArg3, pArg4, pArg5) that should be loaded for the alternate delegate constructor. Add `peepInfo.ctorData = ctorData;` after line 6442.

Code after:
        return false;
    }

    if ((m_compHnd->getClassAttribs(peepInfo.newObjResolvedToken.hClass) & CORINFO_FLG_DELEGATE) == 0)
    {
        return false;
    }

    // The jit is expected to call the getNewHelper api to trigger a set of validations
    bool hasSideEffects = false;
    m_compHnd->getNewHelper(peepInfo.newObjResolvedToken.hClass, &hasSideEffects);

    peepInfo.ctorData.pMethod = m_methodInfo->ftn;
    peepInfo.ctorData.pArg3   = nullptr;
    peepInfo.ctorData.pArg4   = nullptr;
    peepInfo.ctorData.pArg5   = nullptr;

    peepInfo.alternateCtor = m_compHnd->GetDelegateCtor(peepInfo.newObjResolvedToken.hMethod, peepInfo.newObjResolvedToken.hClass, peepInfo.ldftnResolvedToken.hMethod, &peepInfo.ctorData);
    if (peepInfo.alternateCtor == peepInfo.newObjResolvedToken.hMethod)
    {
        return false;
    }

    LdftnDelegateCtorPeepInfo *pPeepInfo = (LdftnDelegateCtorPeepInfo*)AllocMemPool(sizeof(LdftnDelegateCtorPeepInfo));
    *pPeepInfo = peepInfo;
    *ppComputedInfo = pPeepInfo;
    return true;
}

int InterpCompiler::ApplyLdftnDelegateCtorPeep(const uint8_t* ip, OpcodePeepElement* pattern, void* pComputedInfo)
{
    LdftnDelegateCtorPeepInfo *peepInfo = (LdftnDelegateCtorPeepInfo*)pComputedInfo;
    // If there is a virtual load scenario, implement the dup
    if (pattern[0].opcode == CEE_DUP)
    {
        EmitDup();
    }

    // Do the function pointer load
    EmitLdftn(&peepInfo->ldftnResolvedToken, peepInfo->isLdVirtFtn);

    // Load any extra args needed for the alternate delegate constructor
    int extraArgCount = 0;
    if (peepInfo->ctorData.pArg3 != NULL)
    {
        EmitLoadPointer((intptr_t)peepInfo->ctorData.pArg3);
        extraArgCount++;
        if (peepInfo->ctorData.pArg4 != NULL)
        {
            EmitLoadPointer((intptr_t)peepInfo->ctorData.pArg4);
            extraArgCount++;