Each item in Wikipedia's [list of types of memory errors](https://en.wikipedia.org/wiki/Memory_safety#Types_of_memory_errors) and what Crowbar does to prevent them. # Access errors ## Buffer overflow Crowbar addresses buffer overflow with bounds checking. In C, the type `char *` can point to a single character, a null-terminated string of unknown length, a buffer of fixed size, or nothing at all. In Crowbar, the type `char *` can only point to either a single character or nothing at all. If a buffer is declared as `char[50] name;` then it has type `char[50]`, and can be implicitly converted to `(char[50])*`, a pointer-to-50-chars. If memory is dynamically allocated, it works as follows: ```crowbar void process(size_t bufferSize, char[bufferSize] buffer) { // do some work with buffer, given that we know its size } int main(int argc, (char[1024?])[argc] argv) { size_t bufferSize = getBufferSize(); (char[bufferSize])* buffer = malloc(bufferSize); process(bufferSize, buffer); free(buffer); } ``` Note that `malloc` as part of the Crowbar standard library has signature `(char[size])* malloc(size_t size);` and so no cast is needed above. Note as well that the type of `argv` is complicated. This is because the elements of `argv` have unconstrained size. TODO figure out if that's the right way to handle that ## Buffer over-read bounds checking again ## Race condition uhhhhh 🤷‍♀️ ## Page fault bounds checking, dubious-pointer checking ## Use after free `free(x);` not followed by `x = NULL;` is a compiler error # Uninitialized variables C already warns about these in most cases, so we're good. ## Null pointer dereference dubious-pointer checking ## Wild pointers let C handle it # Memory leak ## Stack exhaustion uhhhhhh 🤷‍♀️ ## Heap exhaustion that counts as error handling, just the `malloc`-shaped kind ## Double free this is just use-after-free but the use is calling free on it ## Invalid free don't do that ## Mismatched free how does that even happen ## Unwanted aliasing uhhh don't do that?