Bounded array type?

2014-09-02 Thread James Nelson
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?

2014-10-22 Thread Martin Uecker


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?

2014-09-03 Thread Florian Weimer

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?

2014-09-03 Thread Joseph S. Myers
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?

2014-09-03 Thread Florian Weimer

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?

2014-09-03 Thread Joseph S. Myers
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?

2014-10-23 Thread Joseph S. Myers
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