Is this macro safe or should I make sure alloca never returns NULL?
#define DO_COPY(x) strcpy(alloca(strlen((x)) + 1), x)
Is this macro safe or should I make sure alloca never returns NULL?
#define DO_COPY(x) strcpy(alloca(strlen((x)) + 1), x)
If the string is user controlled I'd say that alloca is not safe. The way alloca is implemented in many compilers it doesn't do any kind of sanity checking on the amount it subtracts from (or adds to if your stack grows that way) the stack pointer. Even with large red zones around the stack it would be relatively easy to make the alloca():ed string to point way outside the stack.
Especially in a threaded environment the thread stacks can be quite small and close to each other.
On the linux machines I could test this on it would require a 10MB string to do start scribbling on some other threads stack with this. On MacOS 512kB seems to be enough.
Here's a quick hack to see how close you can end up (notice that this doesn't really tell you much if the stack allocation is done using some randomizing allocator like in OpenBSD or some other system that takes their allocator safety seriously).
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <stdint.h>
void *
x(void *v)
{
int x;
return &x;
}
int
main(int argc, char **argv)
{
pthread_t ta, tb;
char *va, *vb;
pthread_create(&ta, NULL, x, NULL);
pthread_create(&tb, NULL, x, NULL);
pthread_join(ta, (void **)&va);
pthread_join(tb, (void **)&vb);
printf("diff: %d\n", abs((intptr_t)vb-(intptr_t)va));
return 0;
}
And here is what strcpy(alloca(strlen(s) + 1), s) gets compiled to:
movq %rbx, %rdi
call _strlen
addq $31, %rax
andq $-16, %rax
subq %rax, %rsp
movq %rsp, %rdi
movq %rbx, %rsi
call _strcpy
Notice how there's no sanity checking other than quick alignment before subtracting the return value from strlen (in %rax) from the stack pointer.