Earlier quoted context omitted.
That's not really a fair comparison though. Recursion is strictly necessary to implement several algorithms. Even if "banned" from the language, you would have to simulate it using a heap allocated stack or something to do certain things. None of this applies to VLA arguments.
It's not strictly necessary precisely because all recursions can be "simulated" with a heap allocated stack. And in fact, the "simulated" approach is almost always better, from both a performance and a maintenance perspective.
C99 doesn't need function bodies, or 'VLAs are Turing complete'
201–210 of 257 posts
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#202Earlier quoted context omitted.
It's not strictly necessary precisely because all recursions can be "simulated" with a heap allocated stack. And in fact, the "simulated" approach is almost always better, from both a performance and a maintenance perspective.
Definitely not.
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#203Earlier quoted context omitted.
Welcome to the world of undefined behavior. Anything can happen....
I think this is a common misunderstanding about UB. It's not that anything can happen, just that the standard doesn't specify what happens, meaning whatever happens is compiler/architecture/OS dependent. So you can't depend on UB in portable code. But something definite will happen, given the current state of the system. After all, if it didn't, these things wouldn't be exploitable either.
Avoiding UB (edit: in general) doesn't have anything to do with the code being portable and everything with the code not being buggy [1][2].
[0] https://en.cppreference.com/w/c/language/behavior
[1] https://blog.regehr.org/archives/213
[2] http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#204Earlier quoted context omitted.
I think this is a common misunderstanding about UB. It's not that anything can happen, just that the standard doesn't specify what happens, meaning whatever happens is compiler/architecture/OS dependent. So you can't depend on UB in portable code. But something definite will happen, given the current state of the system. After all, if it didn't, these things wouldn't be exploitable either.
> But something definite will happen, given the current state of the system. This is only true in the very loose and more or less useless sense that the compiler is definitely going to emit some machine code. What does that machine code do in the UB case? It might be absolutely anything . One direction you could go here is you insist that surely the machine code has a defined meaning for all possible machine states,…
I once had a bug like that in a piece of AVR C code where the stack corruption would happen in the same place every time and the code would pathologically jump to the same places in the same order every time. It's worth noting though that when there's an OS, usually what will happen is just a SIGABRT. See the OpenBSD libc allocator for a masterclass in making misbehaving programs crash.
I was never advocating to rely on UB, btw. But yes, UB can be understood in many cases.
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#205Earlier quoted context omitted.
I think this is a common misunderstanding about UB. It's not that anything can happen, just that the standard doesn't specify what happens, meaning whatever happens is compiler/architecture/OS dependent. So you can't depend on UB in portable code. But something definite will happen, given the current state of the system. After all, if it didn't, these things wouldn't be exploitable either.
What you are describing is unspecified and implementation-defined behavior [0]. Avoiding UB (edit: in general) doesn't have anything to do with the code being portable and everything with the code not being buggy [1][2]. [0] https://en.cppreference.com/w/c/language/behavior [1] https://blog.regehr.org/archives/213 [2] http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
You cite to a source that contradicts you. In the llvm blog post: "It is also worth pointing out that both Clang and GCC nail down a few behaviors that the C standard leaves undefined."
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#206Earlier quoted context omitted.
With VLAs: 1. The stack-smashing pattern is simple, straightforward and sure to be used often. Other ways to smash the stack require some more "effort"... 2. It's not just _you_ who can smash the stack. It's the fact that anyone who calls your function will smash the stack if they pass some large numeric value.
They can overflow the stack. They cannot smash the stack.
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#207Earlier quoted context omitted.
They can overflow the stack. They cannot smash the stack.
Useless semantic pedantry at best, but arguable wrong as there isn't some sort of ISO standard on dumb hacking terms.
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#208Earlier quoted context omitted.
What you are describing is unspecified and implementation-defined behavior [0]. Avoiding UB (edit: in general) doesn't have anything to do with the code being portable and everything with the code not being buggy [1][2]. [0] https://en.cppreference.com/w/c/language/behavior [1] https://blog.regehr.org/archives/213 [2] http://blog.llvm.org/2011/05/what-every-c-programmer-should-...
Oh really? Then why does every compiler I use have a parameter to turn off strict aliasing? You cite to a source that contradicts you. In the llvm blog post: "It is also worth pointing out that both Clang and GCC nail down a few behaviors that the C standard leaves undefined."
Added 'in general' to my comment to make this explicit.
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#209Earlier quoted context omitted.
VLAs make it a lot easier to corrupt the stack by accident. Unless you're quite a careful coder, stuff like: f (size_t n) { char str[n]; leads to a possible exploit where the input is manipulated so n is large, causing a DoS attack (at best) or full exploit at worse. I'm not saying that banning VLAs solves every problem though. However the main reason we forbid VLAs in all our code is because thread stacks (particula…
> stuff like ... leads to a possible exploit where the input is manipulated so n is large The same is true for most recursive calls, should recursion be also banned in programming languages?
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#210Earlier quoted context omitted.
> What exactly are you doing there, in kernel code? In kernel code? What you're doing is triggering the guard page over and over if the stack is pushing into new territory. > Do what exactly? Just reject stack allocations that are larger than the cluster of guard pages? And keep book of past allocations? A lot of that needs to happen at runtime, since the compiler doesn't know the size with VLAs. Just hit the guard p…
An attacker would first trigger a large VLA-allocation that puts the stack pointer within a few bytes of the guard page. Then they would just have the kernel put a return address or two on the stack and that would be enough to cause a page fault. The only way to guard against that would be to check that every CALL instruction has enough stack space which is infeasible.
Triggering use of the injected code may require another call timed precisely to hit the changed code before the page fault occurs.
Of course, the compiler could and should check for stack allocations that may jump over guard pages and abort the program (or, if in a syscall, the OS) or grow the stack when needed. Also, VLAs aren’t needed for this. If the programmer creates a multi-megabyte local array, this happens, too (and that can happen accidentally, for example when increasing a #define and recompiling)
The lesson is, though, that guard pages alone don’t fully protect against such attacks. The compiler must check total stack space allocated by a function, and, if it can’t determine that that’s under the size of your guard page, insert code to do additional runtime checks.
I don’t see that as a reason to outright ban VLAs, though.