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

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

(This may come through twice, I'm having some DNS problems so one copy is
stuck in the sendmail queue.)

On Fri, Jul 26, 2013 at 3:20 AM, <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