it only works because you're skipping over environment variables:
char **argv = &stack;
char **envp = __environ = argv + ( 1 * sizeof( void* ) );
let's say argv = 0x8, then according to this code, on x86_64, envp = 0x48 (0x8 + sizeof(void * ) * sizeof(char *)). here's a sample stack where argc = 1: stack:
[0x0] = 1 (argc)
[0x8] = "program path"
[0x10] = 0
[0x18] = "FOO1=FOO1"
[0x20] = "FOO2=FOO2"
[0x28] = "FOO3=FOO3"
[0x30] = "FOO4=FOO4"
[0x38] = "FOO5=FOO5"
[0x40] = "FOO6=FOO6"
[0x48] = "FOO7=FOO7"
...
since you set envp to 0x48 it now points to FOO7=FOO7, you've inadvertently skipped FOO1-FOO6. if argc = 2, then envp would point to FOO6 and you skipped FOO1-FOO5.try this with your code, pass 8 arguments to your test. the environment will point to the last element in argv and then terminate, completely missing the actual environment. again, that's only the behavior on x86, on x86_64, passing any argument will cause a segfault.