VYPR
High severityNVD Advisory· Published Nov 14, 2018· Updated Aug 5, 2024

CVE-2018-8541

CVE-2018-8541

Description

Remote code execution in Chakra scripting engine via memory corruption when handling objects in Microsoft Edge and ChakraCore.

AI Insight

LLM-synthesized narrative grounded in this CVE's description and references.

Remote code execution in Chakra scripting engine via memory corruption when handling objects in Microsoft Edge and ChakraCore.

Vulnerability

The Chakra scripting engine in Microsoft Edge and ChakraCore mishandles objects in memory, leading to memory corruption. This affects Microsoft Edge on Windows 10 versions and ChakraCore prior to the November 2018 security update [1][2].

Exploitation

An attacker can host a specially crafted website that triggers the vulnerability when visited using affected Microsoft Edge. No authentication is required; user interaction is needed to visit the malicious page [4].

Impact

Successful exploitation allows remote code execution in the context of the current user, potentially leading to full system compromise [1][2].

Mitigation

Microsoft released a security update in November 2018 as part of the monthly rollup for Windows 10. ChakraCore users should update to the patched version [4]. No workaround is available.

AI Insight generated on May 22, 2026. Synthesized from this CVE's description and the cited reference URLs; citations are validated against the source bundle.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
Microsoft.ChakraCoreNuGet
< 1.11.31.11.3

Affected products

3

Patches

1
3bee8f018e15

CVE-2018-8541

https://github.com/chakra-core/ChakraCoreMeghana GuptaOct 15, 2018via ghsa
2 files changed · +170 138
  • lib/Runtime/Language/InterpreterStackFrame.cpp+4 0 modified
    @@ -6727,6 +6727,10 @@ namespace Js
                 // Finally exited with LeaveNull, We don't throw for early returns
                 if (finallyEndOffset == 0 && exceptionObj)
                 {
    +                if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
    +                {
    +                    JavascriptExceptionOperators::WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
    +                }
                     JavascriptExceptionOperators::DoThrow(const_cast<Js::JavascriptExceptionObject *>(exceptionObj), scriptContext);
                 }
                 if (finallyEndOffset != 0)
    
  • lib/Runtime/Language/JavascriptExceptionOperators.cpp+166 138 modified
    @@ -190,19 +190,23 @@ namespace Js
         {
             void                      *tryContinuation     = nullptr;
             JavascriptExceptionObject *exception           = nullptr;
    +        void                      *tryHandlerAddrOfReturnAddr = nullptr;
     
             Js::JavascriptExceptionOperators::HasBailedOutPtrStack hasBailedOutPtrStack(scriptContext, (bool*)((char*)frame + hasBailedOutOffset));
             PROBE_STACK(scriptContext, Constants::MinStackJitEHBailout + spillSize + argsSize);
    -
    -        try
    -        {
    -            tryContinuation = amd64_CallWithFakeFrame(tryAddr, frame, spillSize, argsSize);
    -        }
    -        catch (const Js::JavascriptException& err)
             {
    -            exception = err.GetAndClear();
    +            void * addrOfReturnAddr = (void*)((char*)frame + sizeof(char*));
    +            Js::JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack tryHandlerAddrOfReturnAddrStack(scriptContext, addrOfReturnAddr);
    +            try
    +            {
    +                tryContinuation = amd64_CallWithFakeFrame(tryAddr, frame, spillSize, argsSize);
    +            }
    +            catch (const Js::JavascriptException& err)
    +            {
    +                exception = err.GetAndClear();
    +                tryHandlerAddrOfReturnAddr = scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr();
    +            }
             }
    -
             if (exception)
             {
                 // Clone static exception object early in case finally block overwrites it
    @@ -212,19 +216,9 @@ namespace Js
             if (exception)
             {
     #if ENABLE_NATIVE_CODEGEN
    -            if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
    -            {
    -                if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
    -                {
    -                    WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
    -                }
    -            }
    -            else
    +            if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
                 {
    -                if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
    -                {
    -                     WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, frame);
    -                }
    +                WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryHandlerAddrOfReturnAddr);
                 }
     #endif
                 bool hasBailedOut = *(bool*)((char*)frame + hasBailedOutOffset); // stack offsets are negative
    @@ -251,21 +245,31 @@ namespace Js
             void                      *tryContinuation = nullptr;
             void                      *finallyContinuation = nullptr;
             JavascriptExceptionObject *exception           = nullptr;
    +        void                      *tryHandlerAddrOfReturnAddr = nullptr;
     
             PROBE_STACK(scriptContext, Constants::MinStackJitEHBailout + spillSize + argsSize);
    -        try
    -        {
    -            tryContinuation = amd64_CallWithFakeFrame(tryAddr, frame, spillSize, argsSize);
    -        }
    -        catch (const Js::JavascriptException& err)
             {
    -            exception = err.GetAndClear();
    +            void * addrOfReturnAddr = (void*)((char*)frame + sizeof(char*));
    +            Js::JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack tryHandlerAddrOfReturnAddrStack(scriptContext, addrOfReturnAddr);
    +            try
    +            {
    +                tryContinuation = amd64_CallWithFakeFrame(tryAddr, frame, spillSize, argsSize);
    +            }
    +            catch (const Js::JavascriptException& err)
    +            {
    +                exception = err.GetAndClear();
    +                tryHandlerAddrOfReturnAddr = scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr();
    +            }
             }
    -
             if (exception)
             {
                 // Clone static exception object early in case finally block overwrites it
                 exception = exception->CloneIfStaticExceptionObject(scriptContext);
    +
    +            if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
    +            {
    +                WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryHandlerAddrOfReturnAddr);
    +            }
             }
     
             finallyContinuation = amd64_CallWithFakeFrame(finallyAddr, frame, spillSize, argsSize);
    @@ -276,6 +280,10 @@ namespace Js
     
             if (exception)
             {
    +            if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
    +            {
    +                WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
    +            }
                 JavascriptExceptionOperators::DoThrow(exception, scriptContext);
             }
     
    @@ -365,44 +373,40 @@ namespace Js
             int hasBailedOutOffset,
             ScriptContext *scriptContext)
         {
    -        void                      *tryContinuation     = nullptr;
    -        JavascriptExceptionObject *exception           = nullptr;
    +        void                      *tryContinuation            = nullptr;
    +        JavascriptExceptionObject *exception                  = nullptr;
    +        void                      *tryHandlerAddrOfReturnAddr = nullptr;
    +
             Js::JavascriptExceptionOperators::HasBailedOutPtrStack hasBailedOutPtrStack(scriptContext, (bool*)((char*)localsPtr + hasBailedOutOffset));
     
             PROBE_STACK(scriptContext, Constants::MinStackJitEHBailout + argsSize);
    -        try
             {
    +            void * addrOfReturnAddr = (void*)((char*)framePtr + sizeof(char*));
    +            Js::JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack tryHandlerAddrOfReturnAddrStack(scriptContext, addrOfReturnAddr);
    +            try
    +            {
     #if defined(_M_ARM)
                 tryContinuation = arm_CallEhFrame(tryAddr, framePtr, localsPtr, argsSize);
     #elif defined(_M_ARM64)
                 tryContinuation = arm64_CallEhFrame(tryAddr, framePtr, localsPtr, argsSize);
     #endif
    -        }
    -        catch (const Js::JavascriptException& err)
    -        {
    -            exception = err.GetAndClear();
    -        }
    -
    -        if (exception)
    -        {
    -#if ENABLE_NATIVE_CODEGEN
    -            if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
    -            {
    -                if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
    -                {
    -                    WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
    -                }
                 }
    -            else
    +            catch (const Js::JavascriptException& err)
                 {
    -                if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
    -                {
    -                    WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, framePtr);
    -                }
    +                exception = err.GetAndClear();
    +                tryHandlerAddrOfReturnAddr = scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr();
                 }
    -#endif
    +        }
    +        if (exception)
    +        {
                 // Clone static exception object early in case finally block overwrites it
                 exception = exception->CloneIfStaticExceptionObject(scriptContext);
    +
    +            if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
    +            {
    +                WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryHandlerAddrOfReturnAddr);
    +            }
    +
                 bool hasBailedOut = *(bool*)((char*)localsPtr + hasBailedOutOffset); // stack offsets are sp relative
                 if (hasBailedOut)
                 {
    @@ -437,26 +441,36 @@ namespace Js
             void                      *tryContinuation = nullptr;
             void                      *finallyContinuation = nullptr;
             JavascriptExceptionObject *exception = nullptr;
    +        void                      *tryHandlerAddrOfReturnAddr = nullptr;
     
             PROBE_STACK(scriptContext, Constants::MinStackJitEHBailout + argsSize);
    -
    -        try
             {
    +            void * addrOfReturnAddr = (void*)((char*)framePtr + sizeof(char*));
    +            Js::JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack tryHandlerAddrOfReturnAddrStack(scriptContext, addrOfReturnAddr);
    +
    +            try
    +            {
     #if defined(_M_ARM)
    -            tryContinuation = arm_CallEhFrame(tryAddr, framePtr, localsPtr, argsSize);
    +                tryContinuation = arm_CallEhFrame(tryAddr, framePtr, localsPtr, argsSize);
     #elif defined(_M_ARM64)
    -            tryContinuation = arm64_CallEhFrame(tryAddr, framePtr, localsPtr, argsSize);
    +                tryContinuation = arm64_CallEhFrame(tryAddr, framePtr, localsPtr, argsSize);
     #endif
    +            }
    +            catch (const Js::JavascriptException& err)
    +            {
    +                exception = err.GetAndClear();
    +                tryHandlerAddrOfReturnAddr = scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr();
    +            }
             }
    -        catch (const Js::JavascriptException& err)
    -        {
    -            exception = err.GetAndClear();
    -        }
    -
             if (exception)
             {
                 // Clone static exception object early in case finally block overwrites it
                 exception = exception->CloneIfStaticExceptionObject(scriptContext);
    +
    +            if (exception->GetExceptionContext() && exception->GetExceptionContext()->ThrowingFunction())
    +            {
    +                WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryHandlerAddrOfReturnAddr);
    +            }
             }
     
     #if defined(_M_ARM)
    @@ -472,6 +486,10 @@ namespace Js
     
             if (exception)
             {
    +            if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
    +            {
    +                WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
    +            }
                 JavascriptExceptionOperators::DoThrow(exception, scriptContext);
             }
     
    @@ -647,21 +665,24 @@ namespace Js
         {
             Js::JavascriptExceptionObject* pExceptionObject = NULL;
             void* continuationAddr = NULL;
    +        void* tryHandlerAddrOfReturnAddr = nullptr;
     
             Js::JavascriptExceptionOperators::HasBailedOutPtrStack hasBailedOutPtrStack(scriptContext, (bool*)((char*)framePtr + hasBailedOutOffset));
             PROBE_STACK(scriptContext, Constants::MinStackJitEHBailout);
    -
    -        try
             {
    -            // Bug in compiler optimizer: try-catch can be optimized away if the try block contains __asm calls into function
    -            // that may throw. The current workaround is to add the following dummy throw to prevent this optimization.
    -            // It seems like compiler got smart and still optimizes if the exception is not JavascriptExceptionObject (see catch handler below).
    -            // In order to circumvent that we are throwing OutOfMemory.
    -            if (!tryAddr)
    +            void * addrOfReturnAddr = (void*)((char*)framePtr + sizeof(char*));
    +            Js::JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack tryHandlerAddrOfReturnAddrStack(scriptContext, addrOfReturnAddr);
    +            try
                 {
    -                Assert(false);
    -                ThrowOutOfMemory(scriptContext);
    -            }
    +                // Bug in compiler optimizer: try-catch can be optimized away if the try block contains __asm calls into function
    +                // that may throw. The current workaround is to add the following dummy throw to prevent this optimization.
    +                // It seems like compiler got smart and still optimizes if the exception is not JavascriptExceptionObject (see catch handler below).
    +                // In order to circumvent that we are throwing OutOfMemory.
    +                if (!tryAddr)
    +                {
    +                    Assert(false);
    +                    ThrowOutOfMemory(scriptContext);
    +                }
     
     #ifdef _M_IX86
                 void *savedEsp;
    @@ -711,28 +732,19 @@ namespace Js
     #else
                 AssertMsg(FALSE, "Unsupported native try-finally handler");
     #endif
    +            }
    +            catch (const Js::JavascriptException& err)
    +            {
    +                pExceptionObject = err.GetAndClear();
    +                tryHandlerAddrOfReturnAddr = scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr();
    +            }
             }
    -        catch(const Js::JavascriptException& err)
    -        {
    -            pExceptionObject = err.GetAndClear();
    -        }
    -
             if (pExceptionObject)
             {
     #if ENABLE_NATIVE_CODEGEN
    -            if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
    -            {
    -                if (pExceptionObject->GetExceptionContext() && pExceptionObject->GetExceptionContext()->ThrowingFunction())
    -                {
    -                    WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
    -                }
    -            }
    -            else
    +            if (pExceptionObject->GetExceptionContext() && pExceptionObject->GetExceptionContext()->ThrowingFunction())
                 {
    -                if (pExceptionObject->GetExceptionContext() && pExceptionObject->GetExceptionContext()->ThrowingFunction())
    -                {
    -                    WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, framePtr);
    -                }
    +                WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryHandlerAddrOfReturnAddr);
                 }
     #endif
                 // Clone static exception object early in case finally block overwrites it
    @@ -817,79 +829,91 @@ namespace Js
         {
             Js::JavascriptExceptionObject* pExceptionObject = NULL;
             void* continuationAddr = NULL;
    +        void * tryHandlerAddrOfReturnAddr = nullptr;
     
             PROBE_STACK(scriptContext, Constants::MinStackJitEHBailout);
    -
    -        try
             {
    -            // Bug in compiler optimizer: try-catch can be optimized away if the try block contains __asm calls into function
    -            // that may throw. The current workaround is to add the following dummy throw to prevent this optimization.
    -            // It seems like compiler got smart and still optimizes if the exception is not JavascriptExceptionObject (see catch handler below).
    -            // In order to circumvent that we are throwing OutOfMemory.
    -            if (!tryAddr)
    +            void * addrOfReturnAddr = (void*)((char*)framePtr + sizeof(char*));
    +            Js::JavascriptExceptionOperators::TryHandlerAddrOfReturnAddrStack tryHandlerAddrOfReturnAddrStack(scriptContext, addrOfReturnAddr);
    +
    +            try
                 {
    -                Assert(false);
    -                ThrowOutOfMemory(scriptContext);
    -            }
    +                // Bug in compiler optimizer: try-catch can be optimized away if the try block contains __asm calls into function
    +                // that may throw. The current workaround is to add the following dummy throw to prevent this optimization.
    +                // It seems like compiler got smart and still optimizes if the exception is not JavascriptExceptionObject (see catch handler below).
    +                // In order to circumvent that we are throwing OutOfMemory.
    +                if (!tryAddr)
    +                {
    +                    Assert(false);
    +                    ThrowOutOfMemory(scriptContext);
    +                }
     
     #ifdef _M_IX86
    -            void *savedEsp;
    -            __asm
    -            {
    -                // Save and restore the callee-saved registers around the call.
    -                // TODO: track register kills by region and generate per-region prologs and epilogs
    -                push esi
    -                push edi
    -                push ebx
    +                void *savedEsp;
    +                __asm
    +                {
    +                    // Save and restore the callee-saved registers around the call.
    +                    // TODO: track register kills by region and generate per-region prologs and epilogs
    +                    push esi
    +                    push edi
    +                    push ebx
     
    -                // 8-byte align frame to improve floating point perf of our JIT'd code.
    -                // Save ESP
    -                mov ecx, esp
    -                mov savedEsp, ecx
    -                and esp, -8
    +                    // 8-byte align frame to improve floating point perf of our JIT'd code.
    +                    // Save ESP
    +                    mov ecx, esp
    +                    mov savedEsp, ecx
    +                    and esp, -8
     
    -                // Set up the call target, save the current frame ptr, and adjust the frame to access
    -                // locals in native code.
    -                mov eax, tryAddr
    +                    // Set up the call target, save the current frame ptr, and adjust the frame to access
    +                    // locals in native code.
    +                    mov eax, tryAddr
     
     #if 0 && defined(_CONTROL_FLOW_GUARD)
    -                // verify that the call target is valid
    -                mov  ebx, eax; save call target
    -                mov  ecx, eax
    -                call[__guard_check_icall_fptr]
    -                mov  eax, ebx; restore call target
    +                    // verify that the call target is valid
    +                    mov  ebx, eax; save call target
    +                    mov  ecx, eax
    +                    call[__guard_check_icall_fptr]
    +                    mov  eax, ebx; restore call target
     #endif
     
    -                push ebp
    -                mov ebp, framePtr
    -                call eax
    -                pop ebp
    +                    push ebp
    +                    mov ebp, framePtr
    +                    call eax
    +                    pop ebp
     
    -                // The native code gives us the address where execution should continue on exit
    -                // from the region.
    -                mov continuationAddr, eax
    +                    // The native code gives us the address where execution should continue on exit
    +                    // from the region.
    +                    mov continuationAddr, eax
     
    -                // Restore ESP
    -                mov ecx, savedEsp
    -                mov esp, ecx
    +                    // Restore ESP
    +                    mov ecx, savedEsp
    +                    mov esp, ecx
     
    -                pop ebx
    -                pop edi
    -                pop esi
    -            }
    +                    pop ebx
    +                    pop edi
    +                    pop esi
    +                }
     #else
    -            AssertMsg(FALSE, "Unsupported native try-finally handler");
    +                AssertMsg(FALSE, "Unsupported native try-finally handler");
     #endif
    +            }
    +            catch (const Js::JavascriptException& err)
    +            {
    +                pExceptionObject = err.GetAndClear();
    +                tryHandlerAddrOfReturnAddr = scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr();
    +            }
             }
    -        catch (const Js::JavascriptException& err)
    -        {
    -            pExceptionObject = err.GetAndClear();
    -        }
    -
             if (pExceptionObject)
             {
                 // Clone static exception object early in case finally block overwrites it
                 pExceptionObject = pExceptionObject->CloneIfStaticExceptionObject(scriptContext);
    +
    +#if ENABLE_NATIVE_CODEGEN
    +            if (pExceptionObject->GetExceptionContext() && pExceptionObject->GetExceptionContext()->ThrowingFunction())
    +            {
    +                WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr /* start stackwalk from the current frame */, tryHandlerAddrOfReturnAddr);
    +            }
    +#endif
             }
     
             void* newContinuationAddr = NULL;
    @@ -952,6 +976,10 @@ namespace Js
     
             if (pExceptionObject)
             {
    +            if (scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr() != nullptr)
    +            {
    +                WalkStackForCleaningUpInlineeInfo(scriptContext, nullptr, scriptContext->GetThreadContext()->GetTryHandlerAddrOfReturnAddr());
    +            }
                 JavascriptExceptionOperators::DoThrow(pExceptionObject, scriptContext);
             }
     
    

Vulnerability mechanics

Generated on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

9

News mentions

0

No linked articles in our index yet.