I'm using alloca() inside a variadic function to allocate stack memory dynamically based on an integer argument. However, I'm concerned about what happens if the argument is mismatched (e.g., passing a non-integer like a string instead of an int).
Since alloca() adjusts the stack pointer dynamically, could this lead to stack corruption, undefined behaviour, or security vulnerabilities if the argument is misinterpreted?
I wrote the following program:
#include <stdio.h>
#include <stdarg.h>
#include <alloca.h>
void my_func(int count, ...)
{
va_list args;
va_start(args, count);
for(int i = 0; i < count; i++){
int size = va_arg(args, int); // Reading size as an int
char *buffer = (char *)alloca(size); // Allocating stack memory
snprintf(buffer, size, "Hello %d", i);
printf("%s\n", buffer);
}
va_end(args);
}
int main(){
my_func(2, 10, "wrong_type");
return 0;
}
Expected Outcome:
- Ideally, the function should handle this gracefully, or the compiler should warn about this issue.
- However, I suspect that alloca() might allocate a random amount of memory (based on an incorrectly interpreted argument) and corrupt the stack).
Observations:
- On some systems, this leads to segmentation fault
- On others, it produces garbage output or unexpected behaviour
- Running with
-fsanitize=undefined
show invalid memory access warning
Questions:
- What exactly happens if a non-integer argument is passed where alloca() expects an int()?
- Could this lead to stack corruption, buffer overflows or undefined behaviour?
- Does alloca() handle such cases differently on various compilers or platform?
- What are the best practice to avoid such issues when using alloca() in variadic functions?
I'm using alloca() inside a variadic function to allocate stack memory dynamically based on an integer argument. However, I'm concerned about what happens if the argument is mismatched (e.g., passing a non-integer like a string instead of an int).
Since alloca() adjusts the stack pointer dynamically, could this lead to stack corruption, undefined behaviour, or security vulnerabilities if the argument is misinterpreted?
I wrote the following program:
#include <stdio.h>
#include <stdarg.h>
#include <alloca.h>
void my_func(int count, ...)
{
va_list args;
va_start(args, count);
for(int i = 0; i < count; i++){
int size = va_arg(args, int); // Reading size as an int
char *buffer = (char *)alloca(size); // Allocating stack memory
snprintf(buffer, size, "Hello %d", i);
printf("%s\n", buffer);
}
va_end(args);
}
int main(){
my_func(2, 10, "wrong_type");
return 0;
}
Expected Outcome:
- Ideally, the function should handle this gracefully, or the compiler should warn about this issue.
- However, I suspect that alloca() might allocate a random amount of memory (based on an incorrectly interpreted argument) and corrupt the stack).
Observations:
- On some systems, this leads to segmentation fault
- On others, it produces garbage output or unexpected behaviour
- Running with
-fsanitize=undefined
show invalid memory access warning
Questions:
- What exactly happens if a non-integer argument is passed where alloca() expects an int()?
- Could this lead to stack corruption, buffer overflows or undefined behaviour?
- Does alloca() handle such cases differently on various compilers or platform?
- What are the best practice to avoid such issues when using alloca() in variadic functions?
- 5 Undefined behavior happens when you try to get va_arg int but it's a char* . When you call alloca, it's already undefined. – KamilCuk Commented Mar 6 at 8:00
- Ideally, the function should handle this gracefully, or the compiler should warn about this issue": how do you expect the compiler to warn you if you pass the wrong arguments to a variadic function? This is impossible by definition. If you use variadic functions it's your responsibility to provide the corrcect argument types. – Jabberwocky Commented Mar 6 at 9:36
2 Answers
Reset to default 4Can alloca() cause stack corruption in a variadic function when arguments are mismatched?
The 2nd call to int size = va_arg(args, int);
is the problem.
The following alloca()
is too late to be the problem with OP's code.
Code has trouble with or without alloca()
.
type va_arg(va_list ap, type);
... The parameter type shall be an object type name. If type is not compatible with the type of the actual next argument (as promoted according to the default argument promotions), the behavior is undefined, except for the following cases: ... (the listed exceptions do not apply to OP's code).
C23 draft § 7.16.1.1 2
int size = va_arg(args, int);
on the 2nd iteration is undefined behavior (UB). Code has gone off the rails.
After that, alloca()
is simply more train wreck.
You're mistaken in what the problem is. The problem isn't with alloca
; all that does is adding to the stack frame pointer and returning the base address of the newly created stack region. In your code alloca
never sees anything other than an int
.
And the reason for that is simple: You use va_arg
to pop a (the next) function argument, as per the rules to apply if that next function argument is an int
. If it's not an int
then you're basically asking 2 + 2 = fish
: It doesn't make sense. However there's no way for a C compiler to generate code that could in any way determined, that a variadic function was not called with parameters that match what the va_…
utilies will then read out. So whatever there would be (according to the calling convention) as per the rules to pop an int
there from the function aruments will end up in the variable. And if you pass a "string" (technically there are no strings in C, only char*
is pointers to buffer regions of char
) it will happily copy the bits that make up the pointer into the int
variable and then pass that to alloca
. And since pointers usually happen to have a lot of high bits set, that value passed to alloca
will likely exceed the stack, causing a (drum roll) stack overflow.
What exactly happens if a non-integer argument is passed where alloca() expects an
int
?
Technically alloca
expects a size_t
, which is a kind of integer type. When passing whatever value to alloca
it will undergo implcit type casting, possibly truncating it.