************* 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. .. _Wikipedia's list of memory errors: https://en.wikipedia.org/wiki/Memory_safety#Types_of_memory_errors Access errors ============= 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); free(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. .. todo:: figure out if that's the right way to handle that Buffer over-read ---------------- bounds checking again Race condition -------------- uhhhhh idk Page fault ---------- bounds checking, dubious-pointer checking Use after free -------------- ``free(&x);`` will set ``x = NULL;`` ``owned`` and ``borrowed`` keywords Uninitialized variables ======================= forbid them in syntax Null pointer dereference ------------------------ dubious-pointer checking Wild pointers ------------- dubious-pointer checking Memory leak =========== Stack exhaustion ---------------- uhhhhhh idk 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?