1
votes

CERT's Secure Coding Standard includes an item (API05-C) which encourages the use of conformant array parameters, which is a recommendation I've implemented in a lot of my code (hidden behind a macro for compilers which don't support them).

For those who don't know, a conformant array parameter is something like:

void foo(int length, char data[length]);

API05-C provides more information.

Lots of compilers don't like variable-length arrays (for good reason). C11 demotes them from required (as they were in C99) to optional (compilers should define __STDC_NO_VLA__ if they're not implemented). MSVC flat out doesn't support them. IAR hides them behind a switch (--vla). GCC and clang will warn you about them if you ask (with -Wvla, or -Werror=vla if you want an error).

Conformant array parameters don't suffer from the same problems as "normal" variable-length arrays; they don't result in variable stack usage. They just tell the compiler how big an existing array, which could be on the stack or heap, is.

My issue is that every compiler I'm aware of treats conformant array parameters as VLAs. This isn't such a big deal for compilers like MSVC since I can just define my macro to nothing, but for compilers like GCC and clang I want to use conformant array parameters but don't want to trigger -Wvla diagnostics.

According to API05-C (emphasis added):

Consequently, an array declaration that serves as a function argument may have an index that is a variable or an expression. The array argument is demoted to a pointer and is consequently not a variable length array (VLA). Conformant array parameters can be used by developers to indicate the expected bounds of the array. This information may be used by compilers, or it may be ignored. However, such declarations are useful to developers because they serve to document relationships between array sizes and pointers. This information can also be used by static analysis tools to diagnose potential defects.

I desperately want this to be true, but I can't seem to find the relevant parts of the C99 or C11 standards.

So, based strictly on the C99/C11 standards, are conformant array parameters VLAs? Or, to put it another way, does passing an array as an argument really demote it to a pointer?

Obviously, please cite the relevant parts of the specification(s).

2
If I understand your question, and you are asking about a function like type funcname (int a, int array[a]) { ... }, then yes, array is a VLA (it can't be anything else by definition, 'a' is not a constant). Also, you may prefer C11 Standard (n1570 draft) over the .pdf form.David C. Rankin
does passing an array as an argument really demote it to a pointer? Yes. It would be pretty heavy not to do so.Alceste_
David: Yes, that's what I'm asking; edited to make that clearer. As I mentioned (and Alceste_ alluded to), it's not clear that it's actually an array, in which case it can't very well be a variable length array.nemequ
Alceste_: the question here isn't how it's implemented by the compiler, but rather how the C spec handles it.nemequ
Examples aren't normative, but Example 4 from 6.7.6.2p10 calls C in the declaration void fvla(int m, int C[m][m]); a "VLA". The (normative) language in 6.7.6.2 indicates that yes, these array parameters are considered variable length arrays.Cornstalks

2 Answers

1
votes

All parameters declared as array types are transformed to pointer types. VLAs are no exception.

N1256 (C99+TC1+TC2+TC3):

6.7.5.3 Function declarators (including prototypes)

7 A declaration of a parameter as "array of type" shall be adjusted to "qualified pointer to type", where the type qualifiers (if any) are those specified within the [ and ] of the array type derivation. If the keyword static also appears within the [ and ] of the array type derivation, then for each call to the function, the value of the corresponding actual argument shall provide access to the first element of an array with at least as many elements as specified by the size expression.

A function declared void f(int a[10]); takes any int *. A function declared void f(int length, int array[length]); takes an int and a int *.

However, you write:

My issue is that every compiler I'm aware of treats conformant array parameters as VLAs. This isn't such a big deal for compilers like MSVC since I can just define my macro to nothing, but for compilers like GCC and clang I want to use conformant array parameters but don't want to trigger -Wvla diagnostics.

Well, it's tricky. It is a VLA before it is transformed to a pointer, and the point of -Wvla was to warn about code that would fail to compile on compilers that do not support VLAs. As you've seen, MSVC doesn't like the code.

Conformant array parameters don't suffer from the same problems as "normal" variable-length arrays; they don't result in variable stack usage. They just tell the compiler how big an existing array, which could be on the stack or heap, is.

No, they do not do that. Given void f(int a[10]);, it is perfectly valid to call f with a null pointer, with a pointer to an array of length 1, etc. The compiler must support that. They only serve as a hint to human readers. The same applies to transformed VLAs.

0
votes

They are not VLA, but just pointers. If you extend that rule to more than one dimension you obtain a variably modified type, VM, still not a VLA.

If you want to indicate that the pointer should not be 0, there is static as in

void Toto(size_t n, double vec [static n]);

which indicates that vec must have at least n elements, and in particular can't be null.