diff options
author | Kevin B Kenny <kennykb@acm.org> | 2010-09-29 03:10:31 (GMT) |
---|---|---|
committer | Kevin B Kenny <kennykb@acm.org> | 2010-09-29 03:10:31 (GMT) |
commit | d99cc083620428efefa6cbe365862a1744e29920 (patch) | |
tree | b825a803d1e226f2f8f09e663d3143690d16a2e3 /generic/tclAssembly.c | |
parent | ed1a39674bcefde95dc18068ce7e17ae293fe9e3 (diff) | |
download | tcl-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.c | 39 |
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 |