gcc -E -traditional broken

Neil Booth neil@daikokuya.demon.co.uk
Mon Dec 11 15:15:00 GMT 2000


Zack Weinberg wrote:-

> As long as you're sure that that's sufficient.  The code path I saw it
> going through was like this:
> 
> 	rescan sees 'defined'
> 	rescan calls macroexpand
> 	macroexpand calls special_symbol
> 	special_symbol advances past '[(] macroname [)]'
> 		and inserts " 0 " or " 1 " into the output

Here is where it went wrong - it does a SKIP_WHITE_SPACE regardless of
whether it's looking for the ')' or not.  That's where the buffer
overflow occurred:-

    while (is_idchar (*ip->bufp))
      ++ip->bufp;
    SKIP_WHITE_SPACE (ip->bufp);
    if (paren) {
      if (*ip->bufp != ')')
	goto oops;
      ++ip->bufp;
    }

> 	macroexpand returns without stacking a new buffer
> 	rescan assumes that if macroexpand didn't stack a new buffer,
> 		it didn't move ibp either, so it need not recheck
> 		against limit
> 	rescan walks past the end of the buffer.
> 
> However, rescan is a steaming pile of spaghetti

You can say that again, but extend to the whole code :-) If I'm
*really* bored one day I might try and clean up tradcpp.c, but that
would be a sad day indeed.  A good reason I'm not keen on reworking it
is a complete lack of testcases, and the fact that I don't know the
traditional rules.

> I just discovered that tradcpp silently ignores #error, which means
> that tr-defined.c can give false passes.  On the #assert argument, it
> probably makes sense to add #error to tradcpp; this should be
> relatively easy.

Ugh.  Yes, I'll add that to my todo list before committing your
testcases.

Neil.


More information about the Gcc-bugs mailing list