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

Re: input.c and here documents bugfixes



Bart Schaefer wrote:
> } The problem with the original file is that is can exit from the for loop on
> } two conditions.  If it exits when the buffer is filled up, the l counter is
> } one more than otherwise.
> 
> But that's the right thing to do, unless ingetc() has changed a lot from
> hgetch().  Originally, hgetch() would return a space that wasn't really
> in the input stream whenever lexstop was true; and hgets() [which became
> ingets() recently] would have to trim that space off to return the real
> input.  If the buffer is filled up, then the last character returned by
> ingetc() is a real part of the stream, and the counter should be one
> greater so that the '\0' string-terminator will be inserted after the
> last character read.
> 
> Your loop is completely equivalent as far as I can tell, except that if
> n <= 1 and lexstop happens to already be true before ingets() is called,
> you'll write a '\0' into buf[-1].

Here is the original:

!     for (l = 0; l < n - 1; l++)
!       if ((buf[l] = ingetc()) == '\n' || lexstop)
!           break;
!     buf[l + (lexstop ? 0 : 1)] = 0;


If it exit on the l < n - 1 condition, buf[l-1] is the last character it
wrote, but in all other cases it is buf[l].  The (lexstop ? 0 : 1) hack does
what you said but if l = n - 1 (the buffer filled up) and lexstop is not yes
true (more to come) then buf[n] will be written, which is one byte over the
end of the buffer.  This means that it overwrites the next element on the
stack which may be a return address, a frame pointer or anything else.  And
here is the fixed version:

!     for (l = 0; l < n - 1 && (buf[l++] = ingetc()) != '\n' && !lexstop;);
!     if (lexstop)
!       l--;
!     buf[l] = '\0';

Note that here in all cases, buf[l-1] was the last character written.  This
means that in most cases the terminating null must be written to buf[l], but
if lexstop is one, I decrement l to delete the additional space returned by
ingetc().

The exit condition guarantees that l < n on exit from the loop, and l is not
incremented after the exit from the loop, so buf[l] is always in the usable
address range (unless n = 1 but htegs() never called with this value).

Zoltan



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