Returning variable-sized stack data
IchorDev
zxinsworld at gmail.com
Wed Jul 17 10:56:28 UTC 2024
On Wednesday, 17 July 2024 at 09:31:37 UTC, Nick Treleaven wrote:
> Isn't that a stack overflow footgun?
How so?
> Wouldn't that allocate on `foo`'s stack? It needs to be on the
> caller's stack.
Depends on whether you place the alloca call in the caller or the
callee.
This brings us to an important implementation question: what if
there's 3 layers of function calls, and all of them each want to
return a variadic stack allocation? The example in my OP could
certainly be chained with many returns, but perhaps there's a
better way? What if we just return a pointer to the stack memory,
use alloca, and then copy the data to the newly allocated
pointer? Granted, the newly allocated memory will overlap the old
memory if it's sufficiently large, but this shouldn't be a
problem under any calling conventions that I'm familiar with.
This example works with dmd >= 2.084.1, but fails with ldc2/old
dmd for some reason:
```d
import std.typecons;
struct A{ int a,b,c,d,e,f,g; }
struct B{ int a,b,c; }
void[] myFn(int n){
import core.stdc.stdlib: alloca;
auto nSqr = n * n;
if(nSqr == 0){
auto __returnPtr = alloca(A.sizeof);
*cast(A*)__returnPtr = A(nSqr+1,2,3,4,5,6,7);
return __returnPtr[0..A.sizeof];
}else{
auto __returnPtr = alloca(B.sizeof);
*cast(B*)__returnPtr = B(nSqr,2,7);
return __returnPtr[0..B.sizeof];
}
}
void main(){
int n = 0; //<—— can be any number
void[] myMem;
{
import core.stdc.stdlib: alloca;
void[] __returnMemory = myFn(n);
myMem = alloca(__returnMemory.length)[0..__returnMemory.length];
myMem[] = __returnMemory[];
}
import std.stdio;
writeln(cast(int[])myMem);
}
```
More information about the dip.ideas
mailing list