From d248b0ce1800a1ebf2c853f205c1947642185c6a Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Mon, 11 Nov 2019 11:34:43 +0100 Subject: [PATCH] Bug 701886: Always create new scope for eval(). Distinguish eval code from script code. --- jsdump.c | 1 + jsfunction.c | 2 +- jsgc.c | 2 +- jsi.h | 2 +- jsobject.c | 1 + jsrepr.c | 1 + jsrun.c | 31 +++++++++++++++++++++++++++++++ jsstate.c | 2 +- jsvalue.c | 4 ++-- jsvalue.h | 3 ++- 10 files changed, 42 insertions(+), 7 deletions(-) diff --git a/jsdump.c b/jsdump.c index 37f84f1..8f0ff69 100644 --- a/jsdump.c +++ b/jsdump.c @@ -885,6 +885,7 @@ void js_dumpvalue(js_State *J, js_Value v) v.u.object->u.f.function->line); break; case JS_CSCRIPT: printf("[Script %s]", v.u.object->u.f.function->filename); break; + case JS_CEVAL: printf("[Eval %s]", v.u.object->u.f.function->filename); break; case JS_CCFUNCTION: printf("[CFunction %s]", v.u.object->u.c.name); break; case JS_CBOOLEAN: printf("[Boolean %d]", v.u.object->u.boolean); break; case JS_CNUMBER: printf("[Number %g]", v.u.object->u.number); break; diff --git a/jsfunction.c b/jsfunction.c index f03e90c..964dc11 100644 --- a/jsfunction.c +++ b/jsfunction.c @@ -56,7 +56,7 @@ static void Fp_toString(js_State *J) if (!js_iscallable(J, 0)) js_typeerror(J, "not a function"); - if (self->type == JS_CFUNCTION || self->type == JS_CSCRIPT) { + if (self->type == JS_CFUNCTION || self->type == JS_CSCRIPT || self->type == JS_CEVAL) { js_Function *F = self->u.f.function; if (js_try(J)) { diff --git a/jsgc.c b/jsgc.c index 8a792ea..ec32009 100644 --- a/jsgc.c +++ b/jsgc.c @@ -97,7 +97,7 @@ static void jsG_markobject(js_State *J, int mark, js_Object *obj) if (obj->type == JS_CITERATOR) { jsG_markobject(J, mark, obj->u.iter.target); } - if (obj->type == JS_CFUNCTION || obj->type == JS_CSCRIPT) { + if (obj->type == JS_CFUNCTION || obj->type == JS_CSCRIPT || obj->type == JS_CEVAL) { if (obj->u.f.scope && obj->u.f.scope->gcmark != mark) jsG_markenvironment(J, mark, obj->u.f.scope); if (obj->u.f.function && obj->u.f.function->gcmark != mark) diff --git a/jsi.h b/jsi.h index 444eb26..e180204 100644 --- a/jsi.h +++ b/jsi.h @@ -110,7 +110,7 @@ double js_strtod(const char *as, char **aas); void js_newarguments(js_State *J); void js_newfunction(js_State *J, js_Function *function, js_Environment *scope); -void js_newscript(js_State *J, js_Function *function, js_Environment *scope); +void js_newscript(js_State *J, js_Function *fun, js_Environment *scope, int type); void js_loadeval(js_State *J, const char *filename, const char *source); js_Regexp *js_toregexp(js_State *J, int idx); diff --git a/jsobject.c b/jsobject.c index 27cdc96..c383956 100644 --- a/jsobject.c +++ b/jsobject.c @@ -31,6 +31,7 @@ static void Op_toString(js_State *J) case JS_CARRAY: js_pushliteral(J, "[object Array]"); break; case JS_CFUNCTION: js_pushliteral(J, "[object Function]"); break; case JS_CSCRIPT: js_pushliteral(J, "[object Function]"); break; + case JS_CEVAL: js_pushliteral(J, "[object Function]"); break; case JS_CCFUNCTION: js_pushliteral(J, "[object Function]"); break; case JS_CERROR: js_pushliteral(J, "[object Error]"); break; case JS_CBOOLEAN: js_pushliteral(J, "[object Boolean]"); break; diff --git a/jsrepr.c b/jsrepr.c index 9844967..ce7087c 100644 --- a/jsrepr.c +++ b/jsrepr.c @@ -161,6 +161,7 @@ static void reprvalue(js_State *J, js_Buffer **sb) break; case JS_CFUNCTION: case JS_CSCRIPT: + case JS_CEVAL: reprfun(J, sb, obj->u.f.function); break; case JS_CCFUNCTION: diff --git a/jsrun.c b/jsrun.c index c2cca8b..113db4a 100644 --- a/jsrun.c +++ b/jsrun.c @@ -200,6 +200,7 @@ int js_iscallable(js_State *J, int idx) if (v->type == JS_TOBJECT) return v->u.object->type == JS_CFUNCTION || v->u.object->type == JS_CSCRIPT || + v->u.object->type == JS_CEVAL || v->u.object->type == JS_CCFUNCTION; return 0; } @@ -1009,6 +1010,32 @@ static void jsR_callfunction(js_State *J, int n, js_Function *F, js_Environment jsR_restorescope(J); } +static void jsR_calleval(js_State *J, int n, js_Function *F, js_Environment *scope) +{ + js_Value v; + int i; + + scope = jsR_newenvironment(J, jsV_newobject(J, JS_COBJECT, NULL), scope); + + jsR_savescope(J, scope); + + /* scripts take no arguments */ + js_pop(J, n); + + for (i = 0; i < F->varlen; ++i) { + js_pushundefined(J); + js_initvar(J, F->vartab[i], -1); + js_pop(J, 1); + } + + jsR_run(J, F); + v = *stackidx(J, -1); + TOP = --BOT; /* clear stack */ + js_pushvalue(J, v); + + jsR_restorescope(J); +} + static void jsR_callscript(js_State *J, int n, js_Function *F, js_Environment *scope) { js_Value v; @@ -1083,6 +1110,10 @@ void js_call(js_State *J, int n) jsR_pushtrace(J, obj->u.f.function->name, obj->u.f.function->filename, obj->u.f.function->line); jsR_callscript(J, n, obj->u.f.function, obj->u.f.scope); --J->tracetop; + } else if (obj->type == JS_CEVAL) { + jsR_pushtrace(J, obj->u.f.function->name, obj->u.f.function->filename, obj->u.f.function->line); + jsR_calleval(J, n, obj->u.f.function, obj->u.f.scope); + --J->tracetop; } else if (obj->type == JS_CCFUNCTION) { jsR_pushtrace(J, obj->u.c.name, "native", 0); jsR_callcfunction(J, n, obj->u.c.length, obj->u.c.function); diff --git a/jsstate.c b/jsstate.c index 2974336..34b703f 100644 --- a/jsstate.c +++ b/jsstate.c @@ -112,7 +112,7 @@ static void js_loadstringx(js_State *J, const char *filename, const char *source P = jsP_parse(J, filename, source); F = jsC_compilescript(J, P, iseval ? J->strict : J->default_strict); jsP_freeparse(J); - js_newscript(J, F, iseval ? (J->strict ? J->E : NULL) : J->GE); + js_newscript(J, F, iseval ? (J->strict ? J->E : NULL) : J->GE, iseval ? JS_CEVAL : JS_CSCRIPT); js_endtry(J); } diff --git a/jsvalue.c b/jsvalue.c index a97dea3..b6245a8 100644 --- a/jsvalue.c +++ b/jsvalue.c @@ -421,9 +421,9 @@ void js_newfunction(js_State *J, js_Function *fun, js_Environment *scope) } } -void js_newscript(js_State *J, js_Function *fun, js_Environment *scope) +void js_newscript(js_State *J, js_Function *fun, js_Environment *scope, int type) { - js_Object *obj = jsV_newobject(J, JS_CSCRIPT, NULL); + js_Object *obj = jsV_newobject(J, type, NULL); obj->u.f.function = fun; obj->u.f.scope = scope; js_pushobject(J, obj); diff --git a/jsvalue.h b/jsvalue.h index 46424fe..adfc6f9 100644 --- a/jsvalue.h +++ b/jsvalue.h @@ -26,7 +26,8 @@ enum js_Class { JS_COBJECT, JS_CARRAY, JS_CFUNCTION, - JS_CSCRIPT, /* function created from global/eval code */ + JS_CSCRIPT, /* function created from global code */ + JS_CEVAL, /* function created from eval code */ JS_CCFUNCTION, /* built-in function */ JS_CERROR, JS_CBOOLEAN,