shithub: libmujs

Download patch

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