On 1/29/21 4:01 PM, Jakub Jelinek via Gcc-patches wrote:
> Hi!
>
> GCC 11 ICEs on all -fdirectives-only preprocessing when the files don't end
> with a newline.
>
> The problem is in the assertion, for empty TUs buffer->cur == buffer->rlimit
> and so buffer->rlimit[-1] access triggers UB in the preprocessor, for
> non-empty TUs it refers to the last character in the file, which can be
> anything.
> The preprocessor adds a '\n' character (or '\r', in particular if the
> user file ends with '\r' then it adds another '\r' rather than '\n'), but
> that is added after the limit, i.e. at buffer->rlimit[0].
>
> Now, if the routine handles occassional bumping of pos to buffer->rlimit + 1,
> I think it is just the assert that needs changing, usually we read from *pos
> if pos < limit and then e.g. if it is '\r', look at the following character
> (which could be one of those '\n' or '\r' at buffer->rlimit[0]). There is
> also the case where for '\\' before the limit we read following character
> and if it is '\n', do one thing, if it is '\r' read another character.
> But in that case if '\\' was the last char in the TU, the limit char will be
> '\n', so we are ok.
>
> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
>
> 2021-01-29 Jakub Jelinek <ja...@redhat.com>
>
> PR preprocessor/98882
> * lex.c (cpp_directive_only_process): Don't assert that rlimit[-1]
> is a newline, instead assert that rlimit[0] is either newline or
> carriage return. When seeing '\\' followed by '\r', check limit
> before accessing pos[1].
OK
jeff