Bounded array type?
A recurring error in C (and to a lesser extent C++) is the lack of bounds checking in arrays. One famous instance of this error was the Heartbleed incident (which could also be blamed on messy code). I propose a GCC extension of a bounded array type. A bounded array is an array type that has a variable instead of a constant as its size parameter. For example, a function that writes to a buffer `buf` of size `sz` might have a prototype like this: buf *foo(char *buf, size_t sz); This is error-prone because even though a size parameter is given, the code in the function has no requirement to enforce it. With a bounded array type, the prototype looks like this: buf *foo(char buf[sz], size_t sz); The compiler now knows how large `buf` is, and it can put bounds checks into the code (which may be disabled with -O3). -James
Bounded Array Type?
Sorry for bringing this up again, but this could work: void foo(int x, int (*s)[x]) { (*s)[x] = 1;// <- undefined behaviour } Such an access beyond the specified length means that either 1. the array is accessed out-of-bounds or 2. was accessed using an incompatible pointer and a compiler would be allowed to catch this. Martin
Re: Bounded array type?
On 09/02/2014 11:22 PM, James Nelson wrote: This is error-prone because even though a size parameter is given, the code in the function has no requirement to enforce it. With a bounded array type, the prototype looks like this: buf *foo(char buf[sz], size_t sz); GCC already has a syntax extension to support this: <https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html> The compiler now knows how large `buf` is, and it can put bounds checks into the code (which may be disabled with -O3). We tried this, but it is hard to find information about it, see “Bounded Pointers”. Nowdays, there is -fsanitize=object-size, but I don't know if it uses VLA lengths: <https://gcc.gnu.org/ml/gcc-patches/2014-07/msg00923.html> Historically, propagation of object sizes from malloc and VLAs to __builtin_object_size was rather incomplete. -- Florian Weimer / Red Hat Product Security
Re: Bounded array type?
On Wed, 3 Sep 2014, Florian Weimer wrote: > On 09/02/2014 11:22 PM, James Nelson wrote: > > > This is error-prone because even though a size parameter is given, the code > > in the function has no requirement to enforce it. With a bounded array > > type, the prototype looks like this: > > > > buf *foo(char buf[sz], size_t sz); > > GCC already has a syntax extension to support this: > <https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html> But the size declared in a parameter declaration has no semantic significance; there is no requirement that the pointer passed does point to an array of that size. If you declare the size as [static sz] then that means it points to an array of at least that size, but it could be larger. Thus, any option for any sort of bounds checks based on parameter array sizes (constant or non-constant) would be an option that explicitly produces errors for valid C code. (You could always have a function attribute to enable checking based on parameter array sizes - such an attribute would declare that the function should never access the parameter array outside the bounds given by the size, even if the array passed by the caller is larger, and maybe also that the caller must not pass an array smaller than the size given.) -- Joseph S. Myers jos...@codesourcery.com
Re: Bounded array type?
On 09/03/2014 05:20 PM, Joseph S. Myers wrote: On Wed, 3 Sep 2014, Florian Weimer wrote: On 09/02/2014 11:22 PM, James Nelson wrote: This is error-prone because even though a size parameter is given, the code in the function has no requirement to enforce it. With a bounded array type, the prototype looks like this: buf *foo(char buf[sz], size_t sz); GCC already has a syntax extension to support this: <https://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html> But the size declared in a parameter declaration has no semantic significance; there is no requirement that the pointer passed does point to an array of that size. I believe this was different with the bounded pointer extension. But I might misremember how things worked. I've never used it (I think), I only recall reading some documentation which has now vanished. If you declare the size as [static sz] then that means it points to an array of at least that size, but it could be larger. GCC does not seem to enforce that. This compiles without errors: int foo(char [static 5]); int bar(char *p) { return foo(p); } This could be -- Florian Weimer / Red Hat Product Security
Re: Bounded array type?
On Wed, 3 Sep 2014, Florian Weimer wrote: > > If you declare the size as [static sz] then > > that means it points to an array of at least that size, but it could be > > larger. > > GCC does not seem to enforce that. This compiles without errors: [static] is about optimization (but GCC doesn't optimize using it either). It's only undefined behavior if a call with a too-small array is actually executed. > int foo(char [static 5]); > > int > bar(char *p) > { > return foo(p); > } That's perfectly valid, as long as every call to bar is with an argument that does in fact point to at least 5 chars (if a call doesn't, there's undefined behavior when that call is executed). -- Joseph S. Myers jos...@codesourcery.com
Re: Bounded Array Type?
On Wed, 22 Oct 2014, Martin Uecker wrote: > > > Sorry for bringing this up again, but this could work: > > void foo(int x, int (*s)[x]) > { > (*s)[x] = 1; // <- undefined behaviour Yes, I believe that's undefined (even if the array is part of a larger object, as the same principle as "An array subscript is out of range, even if an object is apparently accessible with the given subscript (as in the lvalue expression a[1][7] given the declaration int a[4][5]) (6.5.6)." (Annex J) applies). -- Joseph S. Myers jos...@codesourcery.com