RFC: Enforcing Bounds Safety in C (-fbounds-safety)

Summary We propose -fbounds-safety, a C extension to enforce bounds safety to prevent out-of-bounds (OOB) memory accesses, which remain a major source of security vulnerabilities in C. -fbounds-safety aims to eliminate this class of bugs by turning OOB accesses into deterministic traps. The -fbounds-safety extension offers bounds annotations that programmers can use to attach bounds to pointers. For example, programmers can add the __counted_by(N) annotation to parameter ptr, indicating that t...

LLVM Discussion Forums

@fay59 So glad this is hitting the shelves, great job to everyone involved!!

NOW I'M GONNA STANDARDIZE STUFF SO MUCH HARDER FOR SAFETY LET'S GOOOOOOOOOOOOOOOOOOOOO

@thephd @fay59 we're trying to figure out whether this supports array lists (or whatever is the C equivalent of Rust's Vec) and we don't think we understand it...

does it just... not handle those at all?

@SoniEx2 @thephd @fay59 C as a language does not have any form of resizable array at all. C really doesn’t have anything except for pointers and fixed size arrays. When you build your own type, you can add appropriate bounds safety annotations.
@porglezomp @thephd @fay59 what would those look like?
@SoniEx2 @porglezomp @thephd I‘m not fluent enough in rust to be sure what you mean and I’m not sure you’re fluent enough in C to understand the situation? C’s implementation of contiguous storage of the same element are arrays, and if you want it to be resizable you use bare pointers and malloc/realloc/free as needed.
@fay59 @porglezomp @thephd so... you don't get bounds checking on (resizable) pointers?
@SoniEx2 @porglezomp @thephd C doesn’t bounds check anything on its own, which is why we came up with this language extension.
@fay59 @porglezomp @thephd yeah we understand that, but you're saying you can't use this with a resizable pointer? that seems unfortunate, we were really hoping you could...
@SoniEx2 @porglezomp @thephd the proposed extension does bounds check things coming out of malloc/calloc/etc

@fay59 @porglezomp @thephd we saw that but we're confused about how this would work with something like

struct growbuf {
int *data;
int size;
}

where all you have is a struct growbuf *.

(not really a proper size field but we digress)

how do you update the pointer and size when growing?

@SoniEx2 @fay59 @thephd you’d write that type as

struct growbuf {
 int * __counted_by(size) data;
 int size;
}

and then it’s able to check that your grow function correctly updated the pointer and size in sync when you reallocate.

@SoniEx2 @porglezomp @thephd the data field needs to be spelled “int *__counted_by(size) data”: without the annotation, you can only dereference index 0. If you update either the data or size field, you also need to update the other at the same time (without side effects between the two assignments). There is a bounds check at assignment that verifies the assigned pointer has at least size elements. When you use the data pointer, the index is bounds checked against 0..<size.
@fay59 @porglezomp @thephd ooh so you can just update them one by one with normal assignments? that's cool!