From e558d912a7e3583d700aa42261ef1fa17e5d0d55 Mon Sep 17 00:00:00 2001 From: Melody Horn Date: Wed, 28 Oct 2020 22:17:02 -0600 Subject: syntax highlight Crowbar code --- safety.rst | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 109 insertions(+) create mode 100644 safety.rst (limited to 'safety.rst') diff --git a/safety.rst b/safety.rst new file mode 100644 index 0000000..61cca97 --- /dev/null +++ b/safety.rst @@ -0,0 +1,109 @@ +************* +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 ``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:: + + 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 ``(void[size])* malloc(size_t 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? -- cgit v1.2.3