Reputation: 11
does the below code is safe to use? somehow I think this not right way to do. I know a better way is malloc(), realloc(). But I want to understand where this code posses most risk. As compiler does not know the allocation size, how the stack size will be defined ?
int array_call(int k)
{
int temp[k];
int = 0;
int i = 0;
for (i = 0;i<k;i++)
{
temp[i]=i;
}
return k;
}
int main()
{
int n;
scanf("%d", &n);
n=array_call(n);
}
Upvotes: 0
Views: 118
Reputation: 180286
does the below code is safe to use?
No.
somehow I think this not right way to do. I know a better way is malloc(), realloc(). But I want to understand where this code posses most risk.
Risk #1: the feature you are relying upon, variable-length arrays, is optional in C11 and later, and absent (at least not standardized) in C90. Only in C99 is it both standard and mandatory. Many C implementations you will meet implement it, but there are notable ones that do not. Your code will not compile at all on the latter.
Risk #2: C does not specify how automatic VLAs are implemented, but it is common for them to be allocated on the stack. In such implementations it is relatively easy to cause the program to fail with a stack overflow by providing too large a value of n
. There is usually (much) more space available for dynamic allocation with malloc()
&co., but even if there weren't, you can at least detect and recover from a malloc()
failure. Similar applies to the possibility that n
is given as a negative number.
Risk #3: you are using unvalidated user input in a sensitive way. This is a major failing of secure programming protocol.
As compiler does not know the allocation size, how the stack size will be defined ?
You're assuming that there is a stack, and that that's where the VLA will go. Neither is guaranteed. Nor is there a requirement for a particular behavior in those implementations where both of those assumptions hold. In practice, however, the compiler is reasonably likely to allocate VLA members at the top of the stack, above non-VLA members, and simply to adjust the stack pointer appropriately for the value of n
. It's a little trickier if there are multiple VLAs, but totally doable. This is among the least of the problems involved.
Upvotes: 1
Reputation: 123468
This is an example of a variable-length array (VLA), where the array size isn't known until runtime. This feature was introduced in the 1999 revision of the language, but was made optional in the 2011 revision.
So, the first risk is that VLAs are not universally supported - this code may not compile on some platforms. On C2011 and later, you'll want to check if the __STDC_NO_VLA__
feature macro has been defined before trying to use them, something like
#if defined( __STDC_NO_VLA__ )
int *temp = malloc( sizeof *temp * k );
#else
int temp[k];
#endif
/** do stuff with temp **/
#if defined( __STDC_NO_VLA__ )
free( temp );
The second main risk is that VLAs cannot be arbitrarily large - many (if not most) implementations try to allocate VLA space from the stack, and stack space tends to be limited. If k
is too large1 you will likely get some kind of unrecoverable runtime error.
VLAs may not be declared at file scope or with the static
keyword, nor may they be members of struct
or union
types.
Upvotes: 1
Reputation: 1264
If you're using a compiler that doesn't support VLAs (Variable Length Arrays), you might just have that function allocate, and return, an array with the given size.
int *NewInitedArrayWithCount( unsigned int arrayCount )
{
int *array = (int *) malloc( arrayCount * sizeof( int ));
if ( array != NULL )
{
for ( int i = 0; i<arrayCount; i++ )
{
array[i] = (int) i;
}
}
return array;
}
int main()
{
unsigned int arrayCount;
scanf( "%u", &arrayCount );
int *array = NewInitedArrayWithCount( arrayCount );
// Do stuff
if ( array != NULL )
free( array );
return 0;
}
Upvotes: 0