Earlier quoted context omitted.
VLAs are no more unsafe than standard C is for stack corruption.
Just one additional attack vector more to add to the list, who's still counting them?
C99 doesn't need function bodies, or 'VLAs are Turing complete'
241–250 of 257 posts
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#242Earlier quoted context omitted.
Tip: if writing new functions that take things that are not strings, try to avoid C’s mistakes with strncpy and putting “str” in the name.
Those are strings! Null-terminated strings are not special.
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#243Earlier quoted context omitted.
Overflowing the stack gives you a segfault. Smashing the stack lets hackers pop a shell on your computer. They are incredibly different. VLAs can crash your program, but they do not give attackers the ability to scribble all over the stack.
Unless they happen to be enjoying kernel space.
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#244Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#245Earlier quoted context omitted.
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.
An attacker could trigger a large VLA allocation that jumps over the guard page, and a write to that allocation. That write would start _below_ the guard page, so damage would be done before the page fault occurs (ideally, that write wouldn’t touch the guard page and there wouldn’t be a page fault but that typically is harder to do; the VLA memory allocation typically is done to be fully used) Triggering use of the i…
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#246Earlier quoted context omitted.
This is simply nonsense. In cases with highly complex recursive algorithms, "unrecursing" would make the code a completely unmaintainable mess, requiring an immensely complicated state machine, which is why something like Stockfish doesn't do that in its recursive search function even though the code base is extremely optimised. And yes, some algorithms are inherently recursive, and don't gain any meaningfull perform…
> In cases with highly complex recursive algorithms, "unrecursing" would make the code a completely unmaintainable mess, requiring an immensely complicated state machine Nothing about it is "immensely complicated". Rather than store your recursion state in a call stack, you can store it in a stack of your own, i.e. a heap-allocated container. The state of a cycle of foo(a,b,c) -> bar(d,e,f) -> baz(g,h) -> foo(...) be…
1. This is often irrelevant, depending on your priorities. Taking stockfish as an example again, memory is not what's at a premium, search nodes is. The search space is inherently intractable. You're never gonna be able to recurse meaningfully deeper by shaving off some stack space, because the breadth of the tree grows exponentially in the number of plies. The only form of optimisation that helps here is caching and various heuristics to avoid searching certain nodes at all
2. You know you can change the stack size, right? This is what Stockfish does for its search threads. No need for fancy dynamic allocation here. Also, have fun watching shit get interesting interesting when you have to realloc() ncpu huge chunks of contiguous memory balls deep into a search, when the engine is in time trouble... Sometimes resizing allocated memory is simply not an option.
3. Again this is not always relevant. Stockfish needs its big stacks all the time. So big whoop.
4. This Stockfish does need to do, which is why it keeps an array of structs(never resized) for that purpose. But Stockfish also needs to make decisions about when things move between the different stacks, which is why it uses recursive calls despite having a stack on the heap also.
5. It's obvious I am aware of this. My original comment literally said that banning recursion would force you to implement recursion manually anyway using a state machine. Like, dude, you're literally repeating my own comment back at me as if I didn't already know it. What's up with that?
The point here is: yes, in some specialised cases it might be preferable to implement the recursion yourself if the problem calls for it. But other times, and I'd argue most of the time, this is not necessary. So just use the already available abstraction provided by language. Your line of reasoning is a bit like arguing for not using C at all, because it will be slower than assembly in some cases. sure, write hand optimised assembly in your hot paths if you need to, but most people don't. Abstractions are generally our friends, they help us write clearer, more consise code.
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#247Earlier quoted context omitted.
Useless semantic pedantry at best, but arguable wrong as there isn't some sort of ISO standard on dumb hacking terms.
Overflowing the stack gives you a segfault. Smashing the stack lets hackers pop a shell on your computer. They are incredibly different. VLAs can crash your program, but they do not give attackers the ability to scribble all over the stack.
Maybe. If the architecture supports protected memory and the compiler has placed an appropriately sized guard page below the stack. If it doesn't then overflowing the stack via a VLA gives you easy read and write access to any byte in program memory.
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#248Earlier quoted context omitted.
Overflowing the stack gives you a segfault. Smashing the stack lets hackers pop a shell on your computer. They are incredibly different. VLAs can crash your program, but they do not give attackers the ability to scribble all over the stack.
> Overflowing the stack gives you a segfault. Maybe. If the architecture supports protected memory and the compiler has placed an appropriately sized guard page below the stack. If it doesn't then overflowing the stack via a VLA gives you easy read and write access to any byte in program memory.
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#249Earlier quoted context omitted.
`size_t` is defined as > the unsigned integer type of the result of the sizeof operator ( https://port70.net/~nsz/c/c11/n1570.html#7.19p2 ) `sizeof` returns the following: > If the type of the operand is a variable length array type, the operand is evaluated; otherwise, the operand is not evaluated and the result is an integer constant. ( https://port70.net/~nsz/c/c11/n1570.html#6.5.3.4p2 ) So `sizeof(size_t)` must b…
> So `sizeof(size_t)` must be a concrete integer constant for any given C implementation, it can't change at runtime. I didn't say it has to change at runtime, I said that there is no upper limit on it in theory , because the upper limit is specified in terms of the implementation, and a a theoretical implementation with no upper limit on memory means that there is no upper limit on size_t. Besides, I also said: > Su…
Re: C99 doesn't need function bodies, or 'VLAs are Turing complete'
#250Earlier quoted context omitted.
> Overflowing the stack gives you a segfault. Maybe. If the architecture supports protected memory and the compiler has placed an appropriately sized guard page below the stack. If it doesn't then overflowing the stack via a VLA gives you easy read and write access to any byte in program memory.
If your architecture does not support this then you’re at risk whenever you make a function call.