Index: library/nx/nx.tcl =================================================================== diff -u -rf177ffa3fb3583ff5e9879b1770f2cb23391b634 -rdc801eacd9d3d6f63b53830aef0fec2e0b71134c --- library/nx/nx.tcl (.../nx.tcl) (revision f177ffa3fb3583ff5e9879b1770f2cb23391b634) +++ library/nx/nx.tcl (.../nx.tcl) (revision dc801eacd9d3d6f63b53830aef0fec2e0b71134c) @@ -1227,7 +1227,7 @@ set options [list] if {[info exists :default]} { if {[string match {*\[*\]*} ${:default}]} { - append options substdefault + lappend options substdefault } set :parameterSpec [list [list [:namedParameterSpec $prefix $name $options]] ${:default}] } else { @@ -1485,7 +1485,7 @@ # Only add implicit substdefault, when default is given and # substdefault is allowed via substdefault slot property. # - if {[string match {*\[*\]*} ${:default}] && ${:substdefault}} { + if {${:substdefault}} { lappend options substdefault } set :parameterSpec [list [:namedParameterSpec $prefix ${:name} $options] ${:default}] @@ -2255,10 +2255,17 @@ set trace ${:trace} } - if {$parameterOptions ne "" && "substdefault" in [split $parameterOptions ,]} { + if {[info exists defaultValue] && "substdefault" in [split $parameterOptions ,] && + [string match {*\[*\]*} $defaultValue]} { + if {![info complete $defaultValue]} { + return -code error "substdefault: default '$defaultValue' is not a complete script" + } + # TODO: This should be -novariables, and protected by + # [apply]. For now, untouched, as ArgumentDefaults() has no + # substitution restrictions. set defaultValue [subst $defaultValue] } - + if {$initblock eq "" && !$configurable && !$incremental && $accessor eq "none" && ![info exists trace]} { # @@ -2383,6 +2390,24 @@ } lappend defaultopts -trace $trace } + + lassign [::nx::MetaSlot parseParameterSpec -class $class [self] $spec] \ + pname parameterOptions _ _ + + set paramOptsList [split $parameterOptions ,] + if {[info exists defaultValue] && "substdefault" in [split $paramOptsList ,]} { + + if {![info complete $defaultValue]} { + return -code error "substdefault: default '$defaultValue' is not a complete script" + } + + if {![string match {*\[*\]*} $defaultValue]} { + set paramOptsList [lsearch -exact -inline -all -not $paramOptsList "substdefault"] + set spec [string trimright $pname:[join $paramOptsList ,] :] + } + + } + set slot [::nx::MetaSlot createFromParameterSpec [::nsf::self] \ -class $class \ -initblock $initblock \ Index: tests/parameters.test =================================================================== diff -u -refd3c005e70839815fa89aa36e896bc8ada59315 -rdc801eacd9d3d6f63b53830aef0fec2e0b71134c --- tests/parameters.test (.../parameters.test) (revision efd3c005e70839815fa89aa36e896bc8ada59315) +++ tests/parameters.test (.../parameters.test) (revision dc801eacd9d3d6f63b53830aef0fec2e0b71134c) @@ -3416,12 +3416,29 @@ } ? {catch {::ns1::B create b1 -b1 [::ns1::A new] -b2 [::ns1::ns2::A new]}} 0 +} +nx::test case substdefault-hardening { + nx::Class create K { + :object property {p2:substdefault "$x"} + :property {p4:substdefault "$y"} + :create k + } + + ? {::K cget -p2} {$x} + ? {::k cget -p4} {$y} + + ? {::K object property {p3:substdefault "[[set _ 1]"}} {substdefault: default '[[set _ 1]' is not a complete script} + ? {::K property {p5:substdefault "[[set _ 2]"}} {substdefault: default '[[set _ 2]' is not a complete script} + ::K property {p6:substdefault "[set _ 2]]"} + ? {[::K new] cget -p6} {2]} + ::K object property {p7:substdefault "[set _ 7]]"} + ? {::K cget -p7} {7]} + } - # # Local variables: # mode: tcl