tablacus / TablacusScriptControl

Script Control for 64-bit platforms
https://tablacus.github.io/scriptcontrol_en.html
MIT License
62 stars 17 forks source link

fix memory corruption in OnScriptError() #9

Closed quension-gh closed 7 years ago

quension-gh commented 7 years ago

Fix memory corruption when CteActiveScriptSite::OnScriptError() is called by the engine outside of a CTScriptControl::Invoke() context.

An example situation where this can occur is when a script contains code that will generate an exception: JScript function test() { throw new Error("Test Exception") } and this function is passed outside the ScriptControl, as a callback or through the CodeObject property. External code can then call the function directly, and CteActiveScriptSite::OnScriptError() will be called with a stale m_pEI pointer, which can lead to stack or heap corruption when it is filled in.

This change ensures m_pEI is only used while CTScriptControl::Invoke() is in progress.

SReject commented 7 years ago

This fixes cases where the stack/heap is corrupted from later calls to a dispatched pointer. Compare stack traces between 32bit MSScriptControl and 64bit tsc:

Run with c:\windows\sysWOW64\cscript.exe

// setup sc
var sc = new ActiveXObject("MSScriptControl.ScriptControl");
sc.Language = "jscript";

// add something to the global object for illistrative purposes
sc.ExecuteStatement('this.example = function () { throw new Error("woops"); };');

// attempt to get a pointer to the js script's global object
var jsGlobal = sc.Eval('this');

// perform some asynchronous processing
var xhr = new ActiveXObject("Msxml2.ServerXMLHTTP.6.0");
xhr.open("GET", "http://example.com", true);
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {

        // this results in the stack/heap being corrupted
        jsGlobal.example()

    }
};

vs

After registering tsc, run with cscript.exe

// setup tsc
var tsc = new ActiveXObject("ScriptControl");
tsc.Language = "jscript";

// add something to the global object for illistrative purposes
tsc.ExecuteStatement('this.example = function () { throw new Error("woops"); };');

// attempt to get a pointer to the js script's global object
var jsGlobal = tsc.Eval('this');

// perform some asynchronous processing
var xhr = new ActiveXObject("Msxml2.ServerXMLHTTP.6.0");
xhr.open("GET", "http://example.com", true);
xhr.onreadystatechange = function () {
    if (xhr.readyState == 4) {

        // this results in the stack/heap being corrupted
        jsGlobal.example()

    }
};
tablacus commented 7 years ago

Thank you so much!