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 _______________________________________________ Tinycc-devel mailing list [email protected] http://lists.nongnu.org/mailman/listinfo/tinycc-devel
