summaryrefslogtreecommitdiffstats
path: root/generic/tclAssembly.c
diff options
context:
space:
mode:
authorKevin B Kenny <kennykb@acm.org>2010-09-29 03:10:31 (GMT)
committerKevin B Kenny <kennykb@acm.org>2010-09-29 03:10:31 (GMT)
commitd99cc083620428efefa6cbe365862a1744e29920 (patch)
treeb825a803d1e226f2f8f09e663d3143690d16a2e3 /generic/tclAssembly.c
parented1a39674bcefde95dc18068ce7e17ae293fe9e3 (diff)
downloadtcl-d99cc083620428efefa6cbe365862a1744e29920.zip
tcl-d99cc083620428efefa6cbe365862a1744e29920.tar.gz
tcl-d99cc083620428efefa6cbe365862a1744e29920.tar.bz2
* tests/assemble.test: Completed conversion of tests to a
* generic/tclAssemble.c: "white box" structure that follows the C code. Added missing safety checks on the operands of 'over' and 'reverse' so that negative operand counts don't smash the stack.
Diffstat (limited to 'generic/tclAssembly.c')
-rw-r--r--generic/tclAssembly.c39
1 files changed, 37 insertions, 2 deletions
diff --git a/generic/tclAssembly.c b/generic/tclAssembly.c
index 899d419..d6916fa 100644
--- a/generic/tclAssembly.c
+++ b/generic/tclAssembly.c
@@ -18,6 +18,7 @@ static void BBEmitInst1or4(AssembleEnv* assemEnvPtr, int tblind, int param,
int count);
static void BBEmitOpcode(AssembleEnv* assemEnvPtr, int tblind, int count);
static int CheckNamespaceQualifiers(Tcl_Interp*, const char*, int);
+static int CheckNonNegative(Tcl_Interp*, int);
static int CheckOneByte(Tcl_Interp*, int);
static int CheckSignedOneByte(Tcl_Interp*, int);
static int CheckStack(AssembleEnv*);
@@ -1170,7 +1171,8 @@ AssembleOneLine(AssembleEnv* assemEnvPtr)
Tcl_WrongNumArgs(interp, 1, &instNameObj, "count");
goto cleanup;
}
- if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) {
+ if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK
+ || CheckNonNegative(interp, opnd) != TCL_OK) {
goto cleanup;
}
BBEmitInstInt4(assemEnvPtr, tblind, opnd, opnd+1);
@@ -1181,7 +1183,8 @@ AssembleOneLine(AssembleEnv* assemEnvPtr)
Tcl_WrongNumArgs(interp, 1, &instNameObj, "count");
goto cleanup;
}
- if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK) {
+ if (GetIntegerOperand(assemEnvPtr, &tokenPtr, &opnd) != TCL_OK
+ || CheckNonNegative(interp, opnd) != TCL_OK) {
goto cleanup;
}
BBEmitInstInt4(assemEnvPtr, tblind, opnd, opnd);
@@ -1582,6 +1585,38 @@ CheckSignedOneByte(Tcl_Interp* interp,
/*
*-----------------------------------------------------------------------------
*
+ * CheckNonNegative --
+ *
+ * Verify that a constant is nonnegative
+ *
+ * Results:
+ * On success, returns TCL_OK. On failure, returns TCL_ERROR and
+ * stores an error message in the interpreter result.
+ *
+ * This code is here primarily to verify that instructions like INCR_INVOKE
+ * are consuming a positive number of operands
+ *
+ *-----------------------------------------------------------------------------
+ */
+
+static int
+CheckNonNegative(Tcl_Interp* interp,
+ /* Tcl interpreter for error reporting */
+ int value) /* Value to check */
+{
+ Tcl_Obj* result; /* Error message */
+ if (value < 0) {
+ result = Tcl_NewStringObj("operand must be nonnegative", -1);
+ Tcl_SetObjResult(interp, result);
+ Tcl_SetErrorCode(interp, "TCL", "ASSEM", "NONNEGATIVE", NULL);
+ return TCL_ERROR;
+ }
+ return TCL_OK;
+}
+
+/*
+ *-----------------------------------------------------------------------------
+ *
* CheckStrictlyPositive --
*
* Verify that a constant is positive