From d87ed61b007bc6ba19a329903dd6c9f6f7e2ec6f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 2 Jan 2016 15:03:17 +0100 Subject: [PATCH] start working on the unsafe post --- personal/_drafts/the-scope-of-unsafe.md | 46 +++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 personal/_drafts/the-scope-of-unsafe.md diff --git a/personal/_drafts/the-scope-of-unsafe.md b/personal/_drafts/the-scope-of-unsafe.md new file mode 100644 index 0000000..f6af9a0 --- /dev/null +++ b/personal/_drafts/the-scope-of-unsafe.md @@ -0,0 +1,46 @@ +--- +title: The scope of unsafe +categories: research rust +--- + +I'd like to talk about an important aspect of dealing with unsafe code, that still regularly seems to catch people on the wrong foot: + +> *When checking unsafe code, it is not enough to just check the contents of every `unsafe` block.* + +It turns out that the underlying reason for this observation is also a nice illustration for the concept of *semantic* types that comes up in my [work on formalizing Rust]({{ site.baseurl }}{% post_url 2015-10-12-formalizing-rust %}) (or rather, its type system). + + + +## An Example + +Before we dive into the deeper reasons for why this is the case, let me start by convincing your that the above statement is actually true. + +Consider the type `Vec`, which is roughly defined as follows: +{% highlight rust %} +pub struct Vec { + ptr: *mut T, + cap: usize, + len: usize, +} +{% endhighlight %} +(I know this definition is not entirely right. If you want to know how the actual `Vec` works, check out the [corresponding section of the Rustonomicon](https://doc.rust-lang.org/nightly/nomicon/vec.html).) + +Roughly speaking, `ptr` points to the heap-allocated block of memory holding the contents of the vector, `cap` holds the size of that memory block (counted in number of `T`), and `len` stores how many elements are actually stored in the vector right now. +`cap` and `len` can be different if the memory block contains some extra (uninitialized) space beyond the end of the vector, which speeds up pushing an element to the end of the vector (at the cost of some extra memory usage). + +It is very easy to add a function to `Vec` that contains no `unsafe` code, and still breaks the safety of the data structure: +{% highlight rust %} +fn evil(&mut self) { + self.cap += 2; +} +{% endhighlight %} + +Why is this bad? +The next time `push` is called, the vector will think that it has space for two more element than it actually does, which will eventually (after sufficiently many calls to `push`) result in using unallocated memory. +Oops. + +So, this example clearly shows that to evaluate the safety of types like `Vec`, we have to look at *every single function* provided by that data structure, even if it does not contain any `unsafe` code. + +## A Reason + +So, why is this the case? -- 2.30.2