我们可以用两种可能的方式评估两个表达式:
set a 1
set b 1
puts [expr $a + $b ]
puts [expr {$a + $b } ]
但为什么讨厌经验丰富的 Tclers 第一个,并认为这是不好的做法呢?
第一次使用是否expr
有一些安全问题吗?
“问题”与expr
是它实现了自己的“迷你语言”,其中包括变量替换(替换那些$a
-s 及其值)和命令替换(替换那些[command ...]
与运行结果有关的事情command
s),所以基本上评估的过程expr $a + $b
是这样的:
- Tcl 解释器解析出四个单词 -
expr
, $a
, +
and $b
超出源字符串。由于其中两个词开头为$
,变量替换发生,所以真的会有expr
, 1
, +
, and 2
.
- 通常,第一个单词被视为命令的名称,其他单词是它的参数,因此 Tcl 解释器会查找名为的命令
expr
,并传递三个参数来执行它:1
, +
, and 2
.
- 实施如果
expr
then 连接起来所有传递给它的参数将它们解释为字符串,获得一个字符串1 + 2
.
- 那么这个字符串就是再次解析——这一次由
expr
机器,根据它自己的规则,包括变量和命令替换,如已经提到的。
接下来是:
- If you brace your expressions http://wiki.tcl.tk/10225, like in
expr {$a + $b}
, grouping provided by those curly braces inhibits interpretation by the Tcl interpreter1 of the script intended to be parsed by expr
itself. This means in our toy example the expr
command would see exactly one argument, $a + $b
, and will perform substitutions itself.
-
上面解释的“双重解析”可能会导致安全问题。
例如,在下面的代码中
set a {[exec echo rm -rf $::env(HOME)]}
set b 2
expr $a + $b
The expr
命令本身会解析一个字符串[exec echo rm -rf $::env(HOME)] + 2
。它的评估将会失败,但到那时,您的主目录的内容将会消失。 (请注意,一种 Tcler 放置echo
在...前面rm
在稍后编辑我的答案时,试图拯救随机复制者的脖子,因此所写的命令不会调用rm
但如果你删除echo
从它开始,它就会。)
- 双重解析抑制了 Tcl 引擎在处理调用时可以进行的某些优化
expr
.
1 Well, almost — "backslash+newline" sequences are still processed even inside {...} blocks http://www.tcl.tk/man/tcl8.6/TclCmd/Tcl.htm#M16.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)