ref: e431170dae07e32179b8234d9af699f4491294db
parent: 0d595bd6cf4efb2aa32837cd542a13d1ebbdb150
author: Tor Andersson <[email protected]>
date: Fri Jan 17 16:10:54 EST 2014
Improve stackidx function to return "undefined" for out-of-bounds accesses.
--- a/jsbuiltin.c
+++ b/jsbuiltin.c
@@ -28,7 +28,7 @@
if (jsR_loadscript(J, "(eval)", s))
jsR_error(J, "SyntaxError (eval)");
- js_dup(J, 0); /* copy this */
+ js_copy(J, 0); /* copy this */
js_call(J, 0);
return 1;
}
--- a/jsrun.c
+++ b/jsrun.c
@@ -40,15 +40,8 @@
return toint32(n);
}
-/* Push and read stack values stack */
+/* Push values on stack */
-static int stackidx(js_State *J, int idx)
-{
- if (idx < 0)
- return top + idx;
- return bot + idx;
-}
-
static void js_pushvalue(js_State *J, js_Value v)
{
stack[top] = v;
@@ -133,52 +126,55 @@
js_pushobject(J, jsR_newcfunction(J, v));
}
+/* Read values from stack */
+
+static const js_Value *stackidx(js_State *J, int idx)
+{
+ static js_Value undefined = { JS_TUNDEFINED, { 0 } };
+ idx = idx < 0 ? top + idx : bot + idx;
+ if (idx < 0 || idx >= top)
+ return &undefined;
+ return stack + idx;
+}
+
int js_isundefined(js_State *J, int idx)
{
- idx = stackidx(J, idx);
- return stack[idx].type == JS_TUNDEFINED;
+ return stackidx(J, idx)->type == JS_TUNDEFINED;
}
int js_isstring(js_State *J, int idx)
{
- idx = stackidx(J, idx);
- return stack[idx].type == JS_TSTRING;
+ return stackidx(J, idx)->type == JS_TSTRING;
}
js_Value js_tovalue(js_State *J, int idx)
{
- idx = stackidx(J, idx);
- return stack[idx];
+ return *stackidx(J, idx);
}
int js_toboolean(js_State *J, int idx)
{
- idx = stackidx(J, idx);
- return jsR_toboolean(J, &stack[idx]);
+ return jsR_toboolean(J, stackidx(J, idx));
}
double js_tonumber(js_State *J, int idx)
{
- idx = stackidx(J, idx);
- return jsR_tonumber(J, &stack[idx]);
+ return jsR_tonumber(J, stackidx(J, idx));
}
const char *js_tostring(js_State *J, int idx)
{
- idx = stackidx(J, idx);
- return jsR_tostring(J, &stack[idx]);
+ return jsR_tostring(J, stackidx(J, idx));
}
js_Object *js_toobject(js_State *J, int idx)
{
- idx = stackidx(J, idx);
- return jsR_toobject(J, &stack[idx]);
+ return jsR_toobject(J, stackidx(J, idx));
}
js_Value js_toprimitive(js_State *J, int idx, int hint)
{
- idx = stackidx(J, idx);
- return jsR_toprimitive(J, &stack[idx], hint);
+ return jsR_toprimitive(J, stackidx(J, idx), hint);
}
/* Stack manipulation */
@@ -188,13 +184,18 @@
top -= n;
}
-void js_dup(js_State *J, int idx)
+void js_copy(js_State *J, int idx)
{
- idx = stackidx(J, idx);
- stack[top] = stack[idx];
+ stack[top] = *stackidx(J, idx);
++top;
}
+void js_dup(js_State *J)
+{
+ stack[top] = stack[top-1];
+ ++top;
+}
+
void js_dup2(js_State *J)
{
stack[top] = stack[top-2];
@@ -446,7 +447,7 @@
opcode = *pc++;
switch (opcode) {
case OP_POP: js_pop(J, 1); break;
- case OP_DUP: js_dup(J, -1); break;
+ case OP_DUP: js_dup(J); break;
case OP_DUP2: js_dup2(J); break;
case OP_ROT2: js_rot2(J); break;
case OP_ROT3: js_rot3(J); break;
@@ -467,7 +468,7 @@
case OP_TRUE: js_pushboolean(J, 1); break;
case OP_FALSE: js_pushboolean(J, 0); break;
- case OP_THIS: js_dup(J, 0); break;
+ case OP_THIS: js_copy(J, 0); break;
case OP_GLOBAL: js_pushobject(J, J->G); break;
case OP_FUNDEC:
--- a/jsrun.h
+++ b/jsrun.h
@@ -44,6 +44,7 @@
const char *js_tostring(js_State *J, int idx);
void js_pop(js_State *J, int n);
-void js_dup(js_State *J, int idx);
+void js_dup(js_State *J);
+void js_copy(js_State *J, int idx);
#endif