Zsh Mailing List Archive
Messages sorted by: Reverse Date, Date, Thread, Author

Re: Segfault completing: for f in 1; do <[here] x

On Jul 26, 11:20am, solo-zsh@xxxxxxxxxxxxx wrote:
} I'm getting a segfault when trying to complete after the "<" in:
} for f in 1; do < x

Hmm.  Line numbers below refer to zle_tricky.c.

Both of the cases you backtraced indicate that get_comp_string() has
run off the end of [it's internal copy of] the input line.  Stepping
through in the debugger, it correctly determines that it's in a "for"
loop, which is recorded by the mysteriously-named variable "ins", but
then that information is discarded at line 1243 when the ";" is found.

This in turn means that "do" is not treated as a keyword on the next pass
around the loop at line 1224.  Thus it is believed the command word has
been found, and tt0 is assigned NULLTOK.

Next the "<" token is found, but because "do" appeared to be the command
word, redirpos is NOT incremented at line 1216.  It's actually a bit more
complicated than this because wordpos is incremented at line 1353 even
when the word is a separator, so I think the test on 1215 is valid only
for very simple command lines.

In any case the NULLTOK branch at 1257 is now taken, which is correctly
identifying that the word under the cursor has been reached, which
happens to be the dummy string "x" that was added at line 1136 (or in
the second example, the word "pom").  The dummy x is removed and the
result is recorded as the word to be completed (either the empty string
or "pom").

Here's where things get weird.  Because the end of the input line has
not yet been reached, the loop starts again even though the word to be
completed has been found.  (This isn't by itself wrong, we have to fill
in the whole $words array even though CURRENT is going to point into
the middle of it.)  The two examples diverge at this point because of
the number of words that follow the "<".

Because the relative positions of the command word and the redirection
have become confused ("do" not recognized), the code ends up arriving in
the "Check if we are in an array subscript" block at line 1476.  In the
first example no value has ever been assigned to the local variable "s",
so itype_end() derefs a null pointer and segfaults.

In the second example two more passes are done to reach the word "-O".
At this point, zlemetacs_qsub == 36 and wb == 33, so the "for" loop
at line 1485 spins forever trying to step forward three characters in a
two-character string.  The infinite loop could be fixed by breaking
when *tt == 0 in the loop condition or when nclen == 0 at line 1495,
and probably that should get fixed just for sanity, but it doesn't help
with the underlying problem.

That's as far as I've had time to get today.  If someone else wants to
pick up from here, have at it.

Messages sorted by: Reverse Date, Date, Thread, Author