Why do Tcler suggest to brace your `expr`essions?

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 commands), so basically the process of evaluating expr $a + $b goes like this:

  1. 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 be expr, 1, +, and 2.
  2. 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, +, and 2.
  3. The implementation if expr then concatenates all the arguments passed to it interpreting them as strings, obtaining a string 1 + 2.
  4. 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.

What follows:

  • If you brace your expressions, 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.
  • “Double parsing” explained above might lead to security problems.

    For example, in the following code

    set a {[exec echo rm -rf $::env(HOME)]}
    set b 2
    expr $a + $b
    

    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.)

  • Double parsing inhibits certain optimisations the Tcl engine can do when dealing with calls to expr.

1 Well, almost — “backslash+newline” sequences are still processed even inside {...} blocks.

Leave a Comment