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

Code before:
{
    size_t *targetSSP = (size_t *)_rdsspq();
    // The SSP we search is pointing to the return address of the frame represented
    // by the passed in IP. So we search for the instruction pointer from
    // the context and return one slot up from there.
    if (targetSSP != NULL)
    {
        while (*targetSSP++ != ip)
        {
        }
    }

    return (size_t)targetSSP;
}

void EECodeManager::UpdateSSP(PREGDISPLAY pRD)
{
    pRD->SSP = GetSSPForFrameOnCurrentStack(pRD->ControlPC);
}
#endif // HOST_AMD64 && HOST_WINDOWS

#ifdef FEATURE_INTERPRETER
DWORD_PTR InterpreterCodeManager::CallFunclet(OBJECTREF throwable, void* pHandler, REGDISPLAY *pRD, ExInfo *pExInfo, bool isFilter)
{
    Thread *pThread = GetThread();
    InterpThreadContext *threadContext = pThread->GetInterpThreadContext();
    if (threadContext == nullptr || threadContext->pStackStart == nullptr)
    {
        COMPlusThrow(kOutOfMemoryException);
    }
    int8_t *sp = threadContext->pStackPointer;

    // This construct ensures that the InterpreterFrame is always stored at a higher address than the
    // InterpMethodContextFrame. This is important for the stack walking code.
    struct Frames
    {
        InterpMethodContextFrame interpMethodContextFrame = {0};
        InterpreterFrame interpreterFrame;

        Frames(TransitionBlock* pTransitionBlock)
        : interpreterFrame(pTransitionBlock, &interpMethodContextFrame)
        {
        }
    }
    frames(NULL);

    // Use the InterpreterFrame address as a representation of the caller SP of the funclet
    // Note: this needs to match what the VirtualUnwindInterpreterCallFrame sets as the SP
    // when it unwinds out of a block of interpreter frames belonging to that InterpreterFrame.
    pExInfo->m_csfEHClause.SP = (TADDR)&frames.interpreterFrame;


Review comment (bug):
After the removal of the null check, this code will now crash with a null pointer dereference if GetInterpThreadContext() returns null. The CallFunclet method is only called when handling exceptions in interpreted code, which means the interpreter must already be active and the context should have been created. However, to be safe and maintain consistency with the refactoring pattern, this should either use GetOrCreateInterpThreadContext() or add back a null check with appropriate error handling.
```suggestion
    InterpThreadContext *threadContext = pThread->GetOrCreateInterpThreadContext();
```

Code after:
{
    size_t *targetSSP = (size_t *)_rdsspq();
    // The SSP we search is pointing to the return address of the frame represented
    // by the passed in IP. So we search for the instruction pointer from
    // the context and return one slot up from there.
    if (targetSSP != NULL)
    {
        while (*targetSSP++ != ip)
        {
        }
    }

    return (size_t)targetSSP;
}

void EECodeManager::UpdateSSP(PREGDISPLAY pRD)
{
    pRD->SSP = GetSSPForFrameOnCurrentStack(pRD->ControlPC);
}
#endif // HOST_AMD64 && HOST_WINDOWS

#ifdef FEATURE_INTERPRETER
DWORD_PTR InterpreterCodeManager::CallFunclet(OBJECTREF throwable, void* pHandler, REGDISPLAY *pRD, ExInfo *pExInfo, bool isFilter)
{
    Thread *pThread = GetThread();
    InterpThreadContext *threadContext = pThread->GetInterpThreadContext();
    int8_t *sp = threadContext->pStackPointer;

    // This construct ensures that the InterpreterFrame is always stored at a higher address than the
    // InterpMethodContextFrame. This is important for the stack walking code.
    struct Frames
    {
        InterpMethodContextFrame interpMethodContextFrame = {0};
        InterpreterFrame interpreterFrame;

        Frames(TransitionBlock* pTransitionBlock)
        : interpreterFrame(pTransitionBlock, &interpMethodContextFrame)
        {
        }
    }
    frames(NULL);

    // Use the InterpreterFrame address as a representation of the caller SP of the funclet
    // Note: this needs to match what the VirtualUnwindInterpreterCallFrame sets as the SP
    // when it unwinds out of a block of interpreter frames belonging to that InterpreterFrame.
    pExInfo->m_csfEHClause.SP = (TADDR)&frames.interpreterFrame;

    InterpMethodContextFrame *pOriginalFrame = (InterpMethodContextFrame*)GetRegdisplaySP(pRD);

    StackVal retVal;