2. Memory Safety

In general, Crowbar does its best to ensure that code will not exhibit any of the following memory errors (pulled from Wikipedia’s list of memory errors. However, sometimes the compiler knows less than the programmer, and so code that looks dangerous is actually fine. Crowbar allows programmers to suspend the memory safety checks with the fragile keyword.

2.1. Access errors

2.1.1. Buffer overflow

Crowbar addresses buffer overflow with bounds checking. In C, the type uint8_t * can point to a single byte, a null-terminated string of unknown length, a buffer of fixed size, or nothing at all. In Crowbar, the type uint8 * can only point to either a single byte or nothing at all. If a buffer is declared as uint8[50] name; then it has type uint8[50], and can be implicitly converted to (uint8[50])*, a pointer-to-50-bytes. If memory is dynamically allocated, it works as follows:

void process(uintsize bufferSize, uint8[bufferSize] buffer) {
    // do some work with buffer, given that we know its size

int8 main(uintsize argc, (uint8[1024?])[argc] argv) {
    uintsize bufferSize = getBufferSize();
    (uint8[bufferSize])* buffer = malloc(bufferSize);
    process(bufferSize, buffer);

Note that malloc as part of the Crowbar standard library has signature (void[size])* malloc(uintsize size); and so no cast is needed above. In C, buffer in main would have type pointer-to-VLA-of-char, but buffer in process would have type VLA-of-char, and this conversion would emit a compiler warning. However, in Crowbar, a (T[N])* is always implicitly convertible to T[N], so no warning exists.

Note as well that the type of argv is complicated. This is because the elements of argv have unconstrained size.


figure out if that’s the right way to handle that

2.1.2. Buffer over-read

bounds checking again

2.1.3. Race condition

uhhhhh idk

2.1.4. Page fault

bounds checking, dubious-pointer checking

2.1.5. Use after free

free(&x); will set x = NULL; owned and borrowed keywords

2.2. Uninitialized variables

forbid them in syntax

2.2.1. Null pointer dereference

dubious-pointer checking

2.2.2. Wild pointers

dubious-pointer checking

2.3. Memory leak

2.3.1. Stack exhaustion

uhhhhhh idk

2.3.2. Heap exhaustion

that counts as error handling, just the malloc-shaped kind

2.3.3. Double free

this is just use-after-free but the use is calling free on it

2.3.4. Invalid free

don’t do that

2.3.5. Mismatched free

how does that even happen

2.3.6. Unwanted aliasing

uhhh don’t do that?