Closed wryun closed 1 month ago
Ahh, I finally got a repro of this. $&.
doesn't work for me but $&foo.
(or any other word besides foo
) does. I've been assuming that something like echo $&.
would also fail and I was wrong about that, since this is an evaluation error, rather than a (simple) parse error.
The panic happens in eval()
because $&foo.
gets parsed as $&foo^.
(in lisptrees terms, (concat (prim foo) (word "."))
). eval()
doesn't expect a tree of nConcat
(I believe the expectation is that those should have been glommed away already). Interestingly, if you do something like $&foo^bar
, something actually reasonable happens (that is, it complains about unknown primitive: foobar
).
Aha, it looks like the difference comes from getclosure()
as called in eval.c:427
. At this point, the shell tries to parse a string term of the form $&foo.
or $&foobar
. The latter just gets parsed as a regular primitive called foobar
. The former, thanks to the magic of free carets, gets parsed as a concatenation of $&foo
and .
. (You also get this bug with $&foo!
or $&foo/
).
The best fix I can think of at the moment is to add a case nConcat
to the switch
at line 379 where we assert that the car of the nConcat
is an nPrim
and then throw an error that what we have is isn't actually valid primitive. I don't feel satisfied about this fix -- it has the vibe of a band-aid "solution" -- but I get quickly dizzy in the glom
/eval
/walk
call stack, so I can't come up with any other behaviors that trigger this. It might just be a symptom of primitives being all three of 1. a word that's fussy to parse, 2. free-caret-able, and 3. evaluated in eval()
rather than walk()
.
I also don't totally understand why this might be flaky (the crashing case crashes 100% of the time for me). Perhaps the command isn't always parsed in the same way? My repro gloms the nConcat
tree to a list containing "$&foo."
back to an nConcat
tree, which is kind of weird and circuitous -- maybe that isn't always how that flow happens.
(Maybe that's the bug in itself? Maybe (concat (prim foo) (word "."))
shouldn't get glommed into a string term "$&foo."
at all?)
I checked out the Aug. 21, 2012 version of es and found the same behavior as I've already observed here -- no problem with $&.
, and failures 100% of the time with $&a.
. I was looking to see if there were two separate bugs, but I guess not. Chalk it up to differences in surrounding OS or something :shrug:
I don't love the fix I've prepared because I keep wanting to find a solution that feels more "fundamental", but I honestly can't come up with anything.
Reproduce: $&. (include the full-stop)
Either es works, quits, or produces the message: es panic: eval: bad closure node kind 3