summaryrefslogtreecommitdiffstats
path: root/generic/tclCmdMZ.c
diff options
context:
space:
mode:
authorericm <ericm>2000-04-10 21:08:26 (GMT)
committerericm <ericm>2000-04-10 21:08:26 (GMT)
commit1ca8b9ee3d089e20d6e8603c3b6ce33bac188d6d (patch)
tree969dd778b3f00ae92ec0793ad12d2fb87496794c /generic/tclCmdMZ.c
parenta44349c8166358f92b65f61682ea4a484df881b4 (diff)
downloadtcl-1ca8b9ee3d089e20d6e8603c3b6ce33bac188d6d.zip
tcl-1ca8b9ee3d089e20d6e8603c3b6ce33bac188d6d.tar.gz
tcl-1ca8b9ee3d089e20d6e8603c3b6ce33bac188d6d.tar.bz2
* win/tclWinPipe.c (TclpCreateTempFile): Added conversion of
contents string from UTF to native encoding [Bug: 4030]. * tests/regexp.test: Added tests for infinite looping in [regexp -all]. * generic/tclCmdMZ.c: Fixed infinite loop bug with [regexp -all] [Bug: 4981].
Diffstat (limited to 'generic/tclCmdMZ.c')
-rw-r--r--generic/tclCmdMZ.c30
1 files changed, 27 insertions, 3 deletions
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c
index 16b7522..cbb2f83 100644
--- a/generic/tclCmdMZ.c
+++ b/generic/tclCmdMZ.c
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdMZ.c,v 1.25 2000/02/05 12:08:59 hobbs Exp $
+ * RCS: @(#) $Id: tclCmdMZ.c,v 1.26 2000/04/10 21:08:26 ericm Exp $
*/
#include "tclInt.h"
@@ -127,7 +127,7 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
Tcl_Obj *CONST objv[]; /* Argument objects. */
{
int i, indices, match, about, offset, all, doinline, numMatchesSaved;
- int cflags, eflags;
+ int cflags, eflags, stringLength;
Tcl_RegExp regExpr;
Tcl_Obj *objPtr, *resultPtr;
Tcl_RegExpInfo info;
@@ -274,6 +274,20 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
numMatchesSaved = (objc == 0) ? all : objc;
}
+ /*
+ * Get the length of the string that we are matching against so
+ * we can do the termination test for -all matches.
+ */
+ stringLength = Tcl_GetCharLength(objPtr);
+
+ /*
+ * The following loop is to handle multiple matches within the
+ * same source string; each iteration handles one match. If "-all"
+ * hasn't been specified then the loop body only gets executed once.
+ * We terminate the loop when the starting offset is past the end of the
+ * string.
+ */
+
while (1) {
match = Tcl_RegExpExecObj(interp, regExpr, objPtr,
offset /* offset */, numMatchesSaved, eflags);
@@ -377,10 +391,20 @@ Tcl_RegexpObjCmd(dummy, interp, objc, objv)
/*
* Adjust the offset to the character just after the last one
* in the matchVar and increment all to count how many times
- * we are making a match
+ * we are making a match. We always increment the offset by at least
+ * one to prevent endless looping (as in the case:
+ * regexp -all {a*} a). Otherwise, when we match the NULL string at
+ * the end of the input string, we will loop indefinately (because the
+ * length of the match is 0, so offset never changes).
*/
+ if (info.matches[0].end == 0) {
+ offset++;
+ }
offset += info.matches[0].end;
all++;
+ if (offset >= stringLength) {
+ break;
+ }
}
/*