diff options
| -rw-r--r-- | generic/tclUtil.c | 8 | ||||
| -rw-r--r-- | tests/split.test | 15 |
2 files changed, 23 insertions, 0 deletions
diff --git a/generic/tclUtil.c b/generic/tclUtil.c index d0cca71..55c7212 100644 --- a/generic/tclUtil.c +++ b/generic/tclUtil.c @@ -869,6 +869,14 @@ Tcl_SplitList( size = TclMaxListLength(list, -1, &end) + 1; length = end - list; + if (size >= (INT_MAX/sizeof(char *)) || + length > (INT_MAX - 1 - (size * sizeof(char *)))) { + if (interp) { + Tcl_SetResult( + interp, "memory allocation limit exceeded", TCL_STATIC); + } + return TCL_ERROR; + } argv = (const char **)ckalloc((size * sizeof(char *)) + length + 1); for (i = 0, p = ((char *) argv) + size*sizeof(char *); diff --git a/tests/split.test b/tests/split.test index efd4323..2862291 100644 --- a/tests/split.test +++ b/tests/split.test @@ -80,6 +80,21 @@ test split-2.1 {split errors} { test split-2.2 {split errors} { list [catch {split a b c} msg] $msg $errorCode } {1 {wrong # args: should be "split string ?splitChars?"} {TCL WRONGARGS}} + +test bug-c9f0520f7e "Bug c9f0520f7e Tcl_SplitList memory overflow crash" -body { + # [dict for] compilation calls Tcl_SplitList, thus its use. Not + # a bug in dict. + proc p {} [list dict for $str {} {}] + p +} -constraints slowTest -setup { + set limit 26 + set str "0 1 2 3 4 5 6 7 8 9 " + for { set i 0 } { $i < $limit } { incr i } { + set str "$str $str" + } +} -cleanup { + catch {rename p {}} +} -result {max length of a Tcl list * exceeded} -match glob -returnCodes error # cleanup catch {rename foo {}} |
