tinycc-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Tinycc-devel] Proposal for handling alloca(). Anyone see a problem


From: David A. Wheeler
Subject: Re: [Tinycc-devel] Proposal for handling alloca(). Anyone see a problem with it?
Date: Tue, 08 May 2007 11:16:45 -0400 (EDT)

There lots of interesting alloca() comments, thanks so much! Here are some 
replies...

Fred Weigel:
> But, you may be using alloca() in a parameter sub-expression! (at which
> point later earlier parameters can no longer be correctly retrieved).
> Which is the problem you are thinking about...

Right, that's exactly the problem I was concerned about.  But Daniel Glöckner 
has just enlightened me; it appears that tcc doesn't HAVE anything else on the 
stack when it evaluates a parameter sub-expression.  Stuff always gets moved to 
temp variables instead; I didn't fully appreciate that before.  So this 
problem, which WOULD occur in many other implementation approaches, is a 
non-problem in the tcc case because of how tcc works.

> I suggest that on the each occurrence of alloca() in an expression that
> is a parameter, generate a subtract from SP. Generate a copy of the
> total parameter bytes (to date) to just before the new SP.

If it turns out that there's a special case where this new understanding is 
false, that's an understandable alternative.  Hopefully that won't be necessary.

Dave Dodge:
>Variable length arrays are only guaranteed to persist until the end of the 
>scope of the declaration... You could of course implement variable-length 
>arrays to persist until the end of the function... But then you end up with an 
>implementation that probably can't handle [some constructs]

Fair enough.  Frankly, I think that's an acceptable limitation, and the top 
level of a function declaration that's the same thing (so using alloca() there 
is no different).  But I agree it's probably easy to do better. If it's 
imporant, we could do something like this (not well thought though): On the 
first variable-length array declaration inside a sub-block, store the "previous 
stack location" in a temp variable.  On block exit, if there's been no alloca() 
in that block, just reset the stack location to that temp variable.   I'll bet 
an even better implementation is possible. I haven't worried about the variable 
length array case much yet... as long as I know of ONE way to do it I'm happy.

>POSIX does not require malloc() to be async-signal-safe. So if alloca() 
>invokes malloc(), that makes calling alloca() within a signal handler 
>potentially undefined.

Wow, I hadn't thought about that one.  Thanks. That's a good reason to try to 
do alloca() more "traditionally" (via stack pointer manipulations).  I was 
hoping that this alloca-via-malloc approach would be so obviously easy for ANY 
compiler to implement that a future C standards group would accept alloca().  
But... maybe not.

Philippe Ribet:
>alloca(3), with the extra-byte for bound checking will give you the right 
>alignment. No need to reserve 4 bytes.

Hmm, I explained that poorly.  You're right, you only need ONE extra byte for 
bound checking.

But I want at least a whole 4-byte word of unused allocated space for a 
completely different reason - to reduce stack fragility from buggy code.  It's 
pretty common to have off-by-one loop errors, and many loops write 4-byte-words 
per iteration instead of single characters.  If I reserve at least a 4-byte 
word of unused space at the end of an alloca'ed area, such buggy routines won't 
stomp on something really important.    Debugging those off-by-ones is a royal 
pain, because the failure often only shows up on return but the code that 
actually did the overwrite may be nowhere in sight (the occurrance might be in 
some deeply nested function call).  They're also a quick entry to security 
problems.  This is less of an issue with malloc(), because heap exploits tend 
to be harder to do (though I'd do the same with malloc() were I writing it).  
Yes, the bounds checker will notice such overwrites, but only if that routine 
is running under the bounds checker. Even if the bounds checker is on, the 
allocated memory might be passed to a library routine that doesn't do bounds 
checking.

tcc already wastes a lot of stack space anyway (from temp variables), so in the 
grand scheme wasting a few extra bytes on an alloca() is no big deal.  Beats 
having avoidable debugging sessions and security vulnerabilities.  While the 
code _should_ be right in the first place, having a not-fragile infrastructure 
is a good idea since we're all human.

If you alloca() a value divisible by 4 there's no difference. I want to reserve 
at least one byte for bounds-checking, and if I align by 4 it's the same result.

--- David A. Wheeler




reply via email to

[Prev in Thread] Current Thread [Next in Thread]