Many hyperlinks are disabled.
Use anonymous login
to enable hyperlinks.
Overview
Comment: | Fix problems with break and continue in for-step clauses, triggered by reporting of Coverity CID 1251203. Some of these were originally bugs in Tcl 8.0. |
---|---|
Downloads: | Tarball | ZIP archive | SQL archive |
Timelines: | family | ancestors | descendants | both | trunk |
Files: | files | file ages | folders |
SHA1: |
0db7a63c31f78537c2da67872f28dbe1 |
User & Date: | dkf 2015-08-03 07:21:29 |
Context
2015-08-03
| ||
09:57 | merge mark check-in: 2c8fc45c70 user: dkf tags: trunk | |
09:55 | merge mark Closed-Leaf check-in: b28720a3d7 user: dkf tags: mistake | |
07:21 | Fix problems with break and continue in for-step clauses, triggered by reporting of Coverity CID 125... check-in: 0db7a63c31 user: dkf tags: trunk | |
07:18 | Fix the documentation comment. Closed-Leaf check-in: 77a5609058 user: dkf tags: Coverity CID 1251203 | |
2015-08-01
| ||
19:00 | explicitly ignore Tcl_PushCallFrame and TclPushStackFrame return value - it is always TCL_OK. Incons... check-in: 7448dc7ef9 user: msofer tags: trunk | |
Changes
Changes to generic/tclCompile.c.
︙ | ︙ | |||
4079 4080 4081 4082 4083 4084 4085 | * special handling exception range (so that we can correctly unwind the * stack). * * These must be done separately; they can be different (especially for * calls from inside a [for] increment clause). */ | < < < < < < < < < < > > > > > > > > > > > | | 4079 4080 4081 4082 4083 4084 4085 4086 4087 4088 4089 4090 4091 4092 4093 4094 4095 4096 4097 4098 4099 4100 4101 4102 4103 4104 4105 4106 4107 4108 4109 4110 4111 4112 | * special handling exception range (so that we can correctly unwind the * stack). * * These must be done separately; they can be different (especially for * calls from inside a [for] increment clause). */ rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_CONTINUE, &auxContinuePtr); if (rangePtr == NULL || rangePtr->type != LOOP_EXCEPTION_RANGE) { auxContinuePtr = NULL; } else if (auxContinuePtr->stackDepth == envPtr->currStackDepth-wordCount && auxContinuePtr->expandTarget == envPtr->expandCount-expandCount) { auxContinuePtr = NULL; } else { continueRange = auxContinuePtr - envPtr->exceptAuxArrayPtr; } rangePtr = TclGetInnermostExceptionRange(envPtr, TCL_BREAK, &auxBreakPtr); if (rangePtr == NULL || rangePtr->type != LOOP_EXCEPTION_RANGE) { auxBreakPtr = NULL; } else if (auxContinuePtr == NULL && auxBreakPtr->stackDepth == envPtr->currStackDepth-wordCount && auxBreakPtr->expandTarget == envPtr->expandCount-expandCount) { auxBreakPtr = NULL; } else { breakRange = auxBreakPtr - envPtr->exceptAuxArrayPtr; } if (auxBreakPtr != NULL || auxContinuePtr != NULL) { loopRange = TclCreateExceptRange(LOOP_EXCEPTION_RANGE, envPtr); ExceptionRangeStarts(envPtr, loopRange); } |
︙ | ︙ |
Changes to generic/tclExecute.c.
︙ | ︙ | |||
754 755 756 757 758 759 760 | static Tcl_Obj * ExecuteExtendedBinaryMathOp(Tcl_Interp *interp, int opcode, Tcl_Obj **constants, Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr); static Tcl_Obj * ExecuteExtendedUnaryMathOp(int opcode, Tcl_Obj *valuePtr); static void FreeExprCodeInternalRep(Tcl_Obj *objPtr); static ExceptionRange * GetExceptRangeForPc(const unsigned char *pc, | | | 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 | static Tcl_Obj * ExecuteExtendedBinaryMathOp(Tcl_Interp *interp, int opcode, Tcl_Obj **constants, Tcl_Obj *valuePtr, Tcl_Obj *value2Ptr); static Tcl_Obj * ExecuteExtendedUnaryMathOp(int opcode, Tcl_Obj *valuePtr); static void FreeExprCodeInternalRep(Tcl_Obj *objPtr); static ExceptionRange * GetExceptRangeForPc(const unsigned char *pc, int searchMode, ByteCode *codePtr); static const char * GetSrcInfoForPc(const unsigned char *pc, ByteCode *codePtr, int *lengthPtr, const unsigned char **pcBeg, int *cmdIdxPtr); static Tcl_Obj ** GrowEvaluationStack(ExecEnv *eePtr, int growth, int move); static void IllegalExprOperandType(Tcl_Interp *interp, const unsigned char *pc, Tcl_Obj *opndPtr); |
︙ | ︙ | |||
7951 7952 7953 7954 7955 7956 7957 | TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS))); break; default: TRACE(("=> ")); } #endif if ((result == TCL_CONTINUE) || (result == TCL_BREAK)) { | | | 7951 7952 7953 7954 7955 7956 7957 7958 7959 7960 7961 7962 7963 7964 7965 | TRACE(("\"%.30s\" => ", O2S(OBJ_AT_TOS))); break; default: TRACE(("=> ")); } #endif if ((result == TCL_CONTINUE) || (result == TCL_BREAK)) { rangePtr = GetExceptRangeForPc(pc, result, codePtr); if (rangePtr == NULL) { TRACE_APPEND(("no encl. loop or catch, returning %s\n", StringForResultCode(result))); goto abnormalReturn; } if (rangePtr->type == CATCH_EXCEPTION_RANGE) { TRACE_APPEND(("%s ...\n", StringForResultCode(result))); |
︙ | ︙ | |||
8112 8113 8114 8115 8116 8117 8118 | if (traceInstructions) { fprintf(stdout, " ... no enclosing catch, returning %s\n", StringForResultCode(result)); } #endif goto abnormalReturn; } | | | 8112 8113 8114 8115 8116 8117 8118 8119 8120 8121 8122 8123 8124 8125 8126 | if (traceInstructions) { fprintf(stdout, " ... no enclosing catch, returning %s\n", StringForResultCode(result)); } #endif goto abnormalReturn; } rangePtr = GetExceptRangeForPc(pc, TCL_ERROR, codePtr); if (rangePtr == NULL) { /* * This is only possible when compiling a [catch] that sends its * script to INST_EVAL. Cannot correct the compiler without * breaking compat with previous .tbc compiled scripts. */ |
︙ | ︙ | |||
10108 10109 10110 10111 10112 10113 10114 | * * GetExceptRangeForPc -- * * Given a program counter value, return the closest enclosing * ExceptionRange. * * Results: | > > | | | < < > | | | | | | > > | 10108 10109 10110 10111 10112 10113 10114 10115 10116 10117 10118 10119 10120 10121 10122 10123 10124 10125 10126 10127 10128 10129 10130 10131 10132 10133 10134 10135 10136 10137 10138 10139 10140 10141 10142 10143 10144 10145 10146 10147 10148 10149 | * * GetExceptRangeForPc -- * * Given a program counter value, return the closest enclosing * ExceptionRange. * * Results: * If the searchMode is TCL_ERROR, this procedure ignores loop exception * ranges and returns a pointer to the closest catch range. If the * searchMode is TCL_BREAK, this procedure returns a pointer to the most * closely enclosing ExceptionRange regardless of whether it is a loop or * catch exception range. If the searchMode is TCL_CONTINUE, this * procedure returns a pointer to the most closely enclosing * ExceptionRange (of any type) skipping only loop exception ranges if * they don't have a sensible continueOffset defined. If no matching * ExceptionRange is found that encloses pc, a NULL is returned. * * Side effects: * None. * *---------------------------------------------------------------------- */ static ExceptionRange * GetExceptRangeForPc( const unsigned char *pc, /* The program counter value for which to * search for a closest enclosing exception * range. This points to a bytecode * instruction in codePtr's code. */ int searchMode, /* If TCL_BREAK, consider either loop or catch * ExceptionRanges in search. If TCL_ERROR * consider only catch ranges (and ignore any * closer loop ranges). If TCL_CONTINUE, look * for loop ranges that define a continue * point or a catch range. */ ByteCode *codePtr) /* Points to the ByteCode in which to search * for the enclosing ExceptionRange. */ { ExceptionRange *rangeArrayPtr; int numRanges = codePtr->numExceptRanges; register ExceptionRange *rangePtr; int pcOffset = pc - codePtr->codeStart; |
︙ | ︙ | |||
10158 10159 10160 10161 10162 10163 10164 | rangeArrayPtr = codePtr->exceptArrayPtr; rangePtr = rangeArrayPtr + numRanges; while (--rangePtr >= rangeArrayPtr) { start = rangePtr->codeOffset; if ((start <= pcOffset) && (pcOffset < (start + rangePtr->numCodeBytes))) { | < | > > > > > > | 10161 10162 10163 10164 10165 10166 10167 10168 10169 10170 10171 10172 10173 10174 10175 10176 10177 10178 10179 10180 10181 | rangeArrayPtr = codePtr->exceptArrayPtr; rangePtr = rangeArrayPtr + numRanges; while (--rangePtr >= rangeArrayPtr) { start = rangePtr->codeOffset; if ((start <= pcOffset) && (pcOffset < (start + rangePtr->numCodeBytes))) { if (rangePtr->type == CATCH_EXCEPTION_RANGE) { return rangePtr; } if (searchMode == TCL_BREAK) { return rangePtr; } if (searchMode == TCL_CONTINUE && rangePtr->continueOffset != -1){ return rangePtr; } } } return NULL; } |
︙ | ︙ |
Changes to tests/for.test.
︙ | ︙ | |||
1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 | }] set tmp $end set end [meminfo] } expr {$end - $tmp} }} {return -level 0 -code continue} } 0 # cleanup ::tcltest::cleanupTests return # Local Variables: # mode: tcl | > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > > | 1180 1181 1182 1183 1184 1185 1186 1187 1188 1189 1190 1191 1192 1193 1194 1195 1196 1197 1198 1199 1200 1201 1202 1203 1204 1205 1206 1207 1208 1209 1210 1211 1212 1213 1214 1215 1216 1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238 1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302 1303 1304 1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338 1339 1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 | }] set tmp $end set end [meminfo] } expr {$end - $tmp} }} {return -level 0 -code continue} } 0 test for-8.0 {Coverity CID 1251203: break vs continue in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 list a [\ for {set i 0} {$i < 5} {incr i; list a [eval {}]} { incr j }] incr i } list $i $j $k }} } {6 5 3} test for-8.1 {Coverity CID 1251203: break vs continue in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 list a [\ for {set i 0} {$i < 5} {incr i;list a [eval break]} { incr j }] incr i } list $i $j $k }} } {2 1 3} test for-8.2 {Coverity CID 1251203: break vs continue in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 list a [\ for {set i 0} {$i < 5} {incr i;list a [eval continue]} { incr j }] incr i } list $i $j $k }} } {1 1 3} test for-8.3 {break in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 list a [\ for {set i 0} {$i < 5} {incr i; break} { incr j }] incr i } list $i $j $k }} } {2 1 3} test for-8.4 {continue in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 list a [\ for {set i 0} {$i < 5} {incr i; continue} { incr j }] incr i } list $i $j $k }} } {1 1 3} test for-8.5 {break in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 list a [\ for {set i 0} {$i < 5} {incr i; list a [break]} { incr j }] incr i } list $i $j $k }} } {2 1 3} test for-8.6 {continue in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 list a [\ for {set i 0} {$i < 5} {incr i; list a [continue]} { incr j }] incr i } list $i $j $k }} } {1 1 3} test for-8.7 {break in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 list a [\ for {set i 0} {$i < 5} {incr i;eval break} { incr j }] incr i } list $i $j $k }} } {2 1 3} test for-8.8 {continue in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 list a [\ for {set i 0} {$i < 5} {incr i;eval continue} { incr j }] incr i } list $i $j $k }} } {1 1 3} test for-8.9 {break in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 for {set i 0} {$i < 5} {incr i;eval break} { incr j } incr i } list $i $j $k }} } {2 1 3} test for-8.10 {continue in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 for {set i 0} {$i < 5} {incr i;eval continue} { incr j } incr i } list $i $j $k }} } {1 1 3} test for-8.11 {break in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 for {set i 0} {$i < 5} {incr i;break} { incr j } incr i } list $i $j $k }} } {2 1 3} test for-8.12 {continue in for-step clause} { apply {{} { for {set k 0} {$k < 3} {incr k} { set j 0 for {set i 0} {$i < 5} {incr i;continue} { incr j } incr i } list $i $j $k }} } {1 1 3} # cleanup ::tcltest::cleanupTests return # Local Variables: # mode: tcl |
︙ | ︙ |