为什么 Tcler 建议支持你的“表达"? [英] Why do Tcler suggest to brace your `expr`essions?
问题描述
我们可以用两种可能的方式评估这两个表达式:
We can evaluate the two expression in two possible ways:
set a 1
set b 1
puts [expr $a + $b ]
puts [expr {$a + $b } ]
但是为什么讨厌有经验的 Tclers 第一个,并将其视为不好的做法?expr
的第一次使用是否有一些安全问题?
But why hate experienced Tclers the first one, and consider it as bad practice?
Does the first usage of expr
has some security concern?
推荐答案
expr
的问题"在于它实现了自己的迷你语言",其中包括变量替换等(用它们的值替换那些 $a
-s)和命令替换(用运行 command
[command ...] 东西>s),所以基本上计算 expr $a + $b
的过程是这样的:
The "problem" with expr
is that it implements its own "mini language", which includes, among other things, variable substitution (replacing those $a
-s with their values) and command substitution (replacing those [command ...]
things with the results of running command
s), so basically the process of evaluating expr $a + $b
goes like this:
- Tcl 解释器解析出四个单词 —
expr
、$a
、+
和$b
在源字符串之外.由于其中两个词以$
开头,因此会发生变量替换,因此实际上会有expr
,1
,+
> 和2
. - 通常,第一个单词是命令的名称,其他单词是它的参数,因此 Tcl 解释器查找名为
expr
的命令,并执行它并传递给它三个参数:1
、+
和2
. - 实现 if
expr
then concatenates 所有传递给它的参数,将它们解释为字符串,得到一个字符串1 + 2
.立> - 然后这个字符串被再次解析 —这次由
expr
机器根据自己的规则,包括变量和命令替换,如前所述.
- The Tcl interpreter parses out four words —
expr
,$a
,+
and$b
out of the source string. Since two of these words begin with$
, variable substitution takes place so really there will beexpr
,1
,+
, and2
. - As usually, the first word is taken to be the name of a command, and others are arguments to it, so the Tcl interpreter looks up a command named
expr
, and executes it passing it the three arguments:1
,+
, and2
. - The implementation if
expr
then concatenates all the arguments passed to it interpreting them as strings, obtaining a string1 + 2
. - This string is then parsed again — this time by the
expr
machinery, according to its own rules which include variable- and command substitutions, as already mentioned.
以下内容:
- 如果你支持你的
expr
会话,就像在expr{$a + $b}
,这些花括号提供的分组禁止 Tcl 解释器1 解释旨在由expr
本身解析的脚本.这意味着在我们的玩具示例中,expr
命令只会看到一个参数,$a + $b
,并且会自行执行替换. 上面解释的双重解析"可能会导致安全问题.
- If you brace your
expr
essions, like inexpr {$a + $b}
, grouping provided by those curly braces inhibits interpretation by the Tcl interpreter1 of the script intended to be parsed byexpr
itself. This means in our toy example theexpr
command would see exactly one argument,$a + $b
, and will perform substitutions itself. "Double parsing" explained above might lead to security problems.
例如在下面的代码中
set a {[exec echo rm -rf $::env(HOME)]}
set b 2
expr $a + $b
expr
命令本身会解析一个字符串 [exec echo rm -rf $::env(HOME)] + 2
.它的评估将失败,但到那时,您的主目录的内容应该已经消失了.(请注意,在稍后对我的答案进行编辑时,一位好心的 Tcler 将 echo
放在了 rm
前面,以试图挽救随机复制者的脖子,因此所写的命令赢得了't call rm
但如果你从中删除 echo
,它会.)
The expr
command will itself parse a string [exec echo rm -rf $::env(HOME)] + 2
. Its evaluation will fail, but by that time, the contents of your home directory will be supposedly gone. (Note that a kind Tcler placed echo
in front of rm
in a later edit to my answer in an attempt to save the necks of random copypasters, so the command as written won't call rm
but if you remove echo
from it, it will.)
1 好吧,几乎是—"backslash+newline" 序列即使在 {...}
块.
1 Well, almost — "backslash+newline" sequences are still processed even inside {...}
blocks.
这篇关于为什么 Tcler 建议支持你的“表达"?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!