Comment by remram

Comment by remram 9 days ago

5 replies

How safe is it? It has pointers and they are widely used (more than Rust where pointers are unsafe, but there are other reference types). Are those safe?

dfawcus 9 days ago

Generally.

That is as it does not have pointer arithmetic, unlike C, and arrays / slices are bounds checked. So one will get a crash from a null pointer deref.

The other risk with null pointer access is struct member access via such a pointer, but again due to lack of pointer arithmetic, that can't be easily triggered. The one way would be to have a massive struct, say much greater than the page size, and deref through that - fairly unlikely.

The other reference types (slices, maps, interface values, channels) are safe unless subject to data race issues (multi goroutine update). However channels are safe there, as their role is to be used from multiple goroutines.

So the path to lack of memory safety would be a data race, leading to type misinterpretation, hence type unsafety, then incorrect access and/or spatial and temporal unsafety as a consequence.

Apart from poor design / implementation of explicit multi threaded apps, the most likely data race strikes me as accidental lexical capture by a goroutine, hence movement to the heap, and a resultant race. The sort of thing which was mentioned in a paper (by Uber?). Those should be amiable to detection by linters.

The other case of races from poor threading design would be harder to automatically detect, but also harder to trigger. Probably avoidable by correct use of mutexes around access to the shared types (slices and maps), or simply by following an Actor or CSP design model.

  • remram 9 days ago

    Thanks for the summary, that is very helpful.

    At a language level though, it is either safe or unsafe. If it is "generally safe" provided you use it correctly, I would say it is not safe, in the strict sense.

    I don't think data races on pointers are allowed (looking at the memory model: https://go.dev/ref/mem) but I am not sure I have understood your scenario fully. Maybe I should read that paper you mention.

    Thanks again for the detailed response!

    • dfawcus 9 days ago

      That is an absolutist position, which some of us don't agree with. Taking the view that in practice there are degrees of "memory safety". That is generally my position, and that the largest benefits come from spatial safety, then temporal safety, in that order.

      On that absolute position, there possibly are no "memory safe" languages, not even Rust as until it's borrow checker "bug" is fixed, it fails the absolutist position. If such a bug is left unfixed for long enough, one can deem it as de-facto "won't fix".

      The Go example code provided elsewhere in the thread included a memory race on an "interface value", that being a form of "fat pointer". It was that I was referring to, updating only half of value, so making it internally inconsistent.

      • [removed] 8 days ago
        [deleted]