I think I said somewhere it would be helpful to have a list of mistakes you can easily accidentally make with unsafe, so I thought I would start one ( partially prompted by a mistake I made myself that I only just noticed today ).
I will be editing this post as I remember more mistakes I made..., or collecting contributions from others in the comments.
(1) Failing to add appropriate trait bounds when implementing an unsafe trait. For example
unsafe impl<'a, K, V, A: Tuning> Send for CursorMutKey<'a, K, V, A> {}
needs to be
unsafe impl<'a, K: Send, V: Send, A: Tuning + Send> Send for CursorMutKey<'a, K, V, A> {}
(2) Failing to allow for trait methods to panic, for example when implementing clone you have to allow for clone to panic, and not lose manually allocated memory (or worse, end up with uninitialized memory). I did this more than once! The solution can involve a struct that implements drop like this.
(3) The raw allocator API has undefined behavior if you pass in 0 for an allocation size.. Yup, I managed to hit this one.
(4) Creating aliased mutable references when trying to implement iteration in a naive way. I don't remember now exactly what I did, but Miri was not happy. Remember that you can use raw pointers to do things that are not valid for references. Generally be careful with the transition between raw pointers and references.
(5) Simply failing to deallocate manually allocated memory. Miri can detect this.