From 7682f9c4cd7dfb3439a27d03b4531358798ff443 Mon Sep 17 00:00:00 2001 From: dgp Date: Wed, 24 Jul 2013 16:51:04 +0000 Subject: Demonstrate and fix memory leak in Tcl_ParseVar(). --- generic/tclParse.c | 1 + tests/parse.test | 21 +++++++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/generic/tclParse.c b/generic/tclParse.c index 96c2a10..e475fb8 100644 --- a/generic/tclParse.c +++ b/generic/tclParse.c @@ -1566,6 +1566,7 @@ Tcl_ParseVar( code = TclSubstTokens(interp, parsePtr->tokenPtr, parsePtr->numTokens, NULL, 1, NULL, NULL); + Tcl_FreeParse(parsePtr); TclStackFree(interp, parsePtr); if (code != TCL_OK) { return NULL; diff --git a/tests/parse.test b/tests/parse.test index 4605914..d7de5ff 100644 --- a/tests/parse.test +++ b/tests/parse.test @@ -23,6 +23,7 @@ testConstraint testparsevarname [llength [info commands testparsevarname]] testConstraint testparsevar [llength [info commands testparsevar]] testConstraint testasync [llength [info commands testasync]] testConstraint testcmdtrace [llength [info commands testcmdtrace]] +testConstraint memory [llength [info commands memory]] test parse-1.1 {Tcl_ParseCommand procedure, computing string length} testparser { testparser [bytestring "foo\0 bar"] -1 @@ -674,6 +675,26 @@ test parse-13.5 {Tcl_ParseVar procedure, error looking up variable} testparsevar unset -nocomplain abc list [catch {testparsevar {$abc([bogus x y z])}} msg] $msg } {1 {invalid command name "bogus"}} +test parse-13.6 {Tcl_ParseVar memory leak} -constraints memory -setup { + proc getbytes {} { + return [lindex [split [memory info] \n] 3 3] + } +} -body { + set a() foo + set end [getbytes] + for {set i 0} {$i < 5} {incr i} { + set vn {} + set res [testparsevar [append vn $ a([string repeat {[]} 19]) bar]] + if {$res ne {foo bar}} {error "Unexpected result: $res"} + + set tmp $end + set end [getbytes] + } + expr {$end - $tmp} +} -cleanup { + unset -nocomplain a end i vn res tmp + rename getbytes {} +} -result 0 test parse-14.1 {Tcl_ParseBraces procedure, computing string length} testparser { testparser [bytestring "foo\0 bar"] -1 -- cgit v0.12