Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

eval accessed via global.eval not caught #51

Open
overlookmotel opened this issue Jan 4, 2021 · 2 comments
Open

eval accessed via global.eval not caught #51

overlookmotel opened this issue Jan 4, 2021 · 2 comments
Labels
bug Something isn't working eval Issue related to `eval` instrumentation Relates to instrumentation

Comments

@overlookmotel
Copy link
Owner

Livepack Babel plugin converts indirect use of eval var to evalShim. evalShim is an livepack internal function which injects scope-tracker code before evaluating the code with (0, eval)().

eval can also be accessed as global.eval. This would act as indirect eval.

module.exports = global.eval('() => 123');

Currently, Livepack does not recognise this usage and so the function created by eval is not tracked.

Babel plugin needs to convert global.eval to evalShim to fix this.

Remaining problems

The following would still not be recognised:

const g = global;
const e = g.eval;
const val = 'val'
const e = global['e' + val];

Cannot patch global.eval to catch this as that would render direct calls to eval() indirect.

Not sure if possible to solve this.

@overlookmotel overlookmotel added the feature New feature or request label Jan 31, 2021
@overlookmotel overlookmotel added optimization Improvement to performance or output bug Something isn't working and removed feature New feature or request optimization Improvement to performance or output labels Feb 10, 2021
@overlookmotel
Copy link
Owner Author

overlookmotel commented Mar 6, 2021

Actually, it is possible to solve. Livepack would keep a reference to global eval internally and replace global.eval with the shim.

Any direct eval() calls would need to be patched to restore the original global.eval before eval() is called and swap global.eval back to the shim again immediately after it's called.

export default () => eval('x') would be Babel-transformed to:

const [ livepack_swapEval ] = require('livepack/lib/init/eval.js');

export default () => ( () => {
  livepack_swapEval(1);
  try {
    return eval('livepack_swapEval(); x');
  } catch (err) {
    livepack_swapEval();
    throw err;
  }
} )();

livepack_swapEval() called with a truthy value sets global.eval back to the original, and when called with a falsy value, returns global.eval to the shim. livepack_swapEval() needs to be invoked at start of the eval-ed expression so the shim is restored before the eval code is executed. The catch {} block is in case the evaluated code causes a syntax error.

This approach would also remove the need for replacing eval with livepack_eval, as it'd be defined universally.

See also #137.

@overlookmotel
Copy link
Owner Author

See #137 (comment) for a better solution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working eval Issue related to `eval` instrumentation Relates to instrumentation
Projects
None yet
Development

No branches or pull requests

1 participant