Earlier quoted context omitted.
It does not invalidate an argument that you do not want to talk about it. Regarding the second point: yes, you can then blame the "unsafe" part but the issue is that the problem might not be so localized as the notion of "only auditing unsafe blocks is sufficient" implies. You may need to understand the subtle interaction of unsafe blocks with the rest of the program.
> the problem might not be so localized as the notion of "only auditing unsafe blocks is sufficient" implies It depends on what you consider "problem" can mean. An unsafe function needs someone to write unsafe in order to call it, and it's on that calling code to make sure the conditions needed to call the unsafe function are met. If that function itself is safe, but still let's you trigger the unsafe function unsafe…
Smart pointers for the kernel
91–100 of 120 posts
Re: Smart pointers for the kernel
#92Earlier quoted context omitted.
It does not invalidate an argument that you do not want to talk about it. Regarding the second point: yes, you can then blame the "unsafe" part but the issue is that the problem might not be so localized as the notion of "only auditing unsafe blocks is sufficient" implies. You may need to understand the subtle interaction of unsafe blocks with the rest of the program.
Unsafe blocks have a specific set of requirements they have to abide by. Assuming they successfully do so, it is then guaranteed that no safe code is able to trigger undefined behaviour by calling the unsafe code. Importantly, this can be checked without ever reading any of the safe code.
https://github.com/ejmahler/transpose/blob/e70dd159f1881d86a...
The code is buggy. Where is the bug?
Re: Smart pointers for the kernel
#93Earlier quoted context omitted.
Rust’s whole premise of guaranteed memory safety through compiletime checks has always been undermined when confronted with the reality that certain foundational operations must still be implemented using unsafe. Inevitably folks concede that lower level libraries will have these unsafe blocks and still expect higher level code to trust them, and at that point we’ve essentially recreated the core paradigm of C: trust…
I don't think you're giving Rust enough credit here. For those projects that don't use any unsafe, we can say -- absent compiler bugs or type system unsoundness -- that there will be no memory leaks or data races or undefined behavior. That's useful! Very useful! For projects that do need unsafe, that unsafe code can be cordoned off into a corner where it can be made as small as possible, and can be audited. The rest…
It's very useful indeed, I've been programming in Rust daily for the past 7 years (wow time flies) and the times when I've needed unsafe code can still be counted on my two hands.
Re: Smart pointers for the kernel
#94"could break the guarantees" is a weak guarantee then.
Re: Smart pointers for the kernel
#95Earlier quoted context omitted.
I don't think you're giving Rust enough credit here. For those projects that don't use any unsafe, we can say -- absent compiler bugs or type system unsoundness -- that there will be no memory leaks or data races or undefined behavior. That's useful! Very useful! For projects that do need unsafe, that unsafe code can be cordoned off into a corner where it can be made as small as possible, and can be audited. The rest…
This is giving Rust a bit too much credit though. - Memory leaks are not just possible in Rust, they're easy to write and mildly encouraged by the constraints the language places on you. IME I see more leaks in Rust in the wild than in C, C#, Python, C++, ... - You can absolutely have data races in a colloquial sense in Rust, just not in the sense of the narrower definition they created to be able to say they don't h…
Re: Smart pointers for the kernel
#96Earlier quoted context omitted.
Rust’s whole premise of guaranteed memory safety through compiletime checks has always been undermined when confronted with the reality that certain foundational operations must still be implemented using unsafe. Inevitably folks concede that lower level libraries will have these unsafe blocks and still expect higher level code to trust them, and at that point we’ve essentially recreated the core paradigm of C: trust…
I don't think you're giving Rust enough credit here. For those projects that don't use any unsafe, we can say -- absent compiler bugs or type system unsoundness -- that there will be no memory leaks or data races or undefined behavior. That's useful! Very useful! For projects that do need unsafe, that unsafe code can be cordoned off into a corner where it can be made as small as possible, and can be audited. The rest…
Re: Smart pointers for the kernel
#97Earlier quoted context omitted.
Unsafe blocks have a specific set of requirements they have to abide by. Assuming they successfully do so, it is then guaranteed that no safe code is able to trigger undefined behaviour by calling the unsafe code. Importantly, this can be checked without ever reading any of the safe code.
Let's discuss this example: https://github.com/ejmahler/transpose/blob/e70dd159f1881d86a... The code is buggy. Where is the bug?
I don't get the argumentshere. In practice, Rust lowers the risk of most of your codebase. Yeah, it doesn't handle every logic bug, but mostly you can code with confidence, and only pay extra attention when you're coding something intricate.
A language which catches even these bugs would be incredible, and I would definitely try it out. Rust ain't that language, but it still does give you more robust programs.
Re: Smart pointers for the kernel
#98Earlier quoted context omitted.
> the problem might not be so localized as the notion of "only auditing unsafe blocks is sufficient" implies It depends on what you consider "problem" can mean. An unsafe function needs someone to write unsafe in order to call it, and it's on that calling code to make sure the conditions needed to call the unsafe function are met. If that function itself is safe, but still let's you trigger the unsafe function unsafe…
In other words, somebody made an error somewhere.
Re: Smart pointers for the kernel
#99Earlier quoted context omitted.
Unsafe blocks have a specific set of requirements they have to abide by. Assuming they successfully do so, it is then guaranteed that no safe code is able to trigger undefined behaviour by calling the unsafe code. Importantly, this can be checked without ever reading any of the safe code.
Let's discuss this example: https://github.com/ejmahler/transpose/blob/e70dd159f1881d86a... The code is buggy. Where is the bug?
To answer the question of "where is the bug" -- by definition, it is where the programmer wrote an `unsafe` block that assumes an invariant which does not necessarily hold. Which I assume is the point you're trying to make -- that a buggy assert in "safe" code broke an invariant assumed by unsafe code. And indeed, that's part of the danger of `unsafe` -- by using an `unsafe` block, you are asserting that there is no possible path that could be taken, even by safe code you're interacting with, that would break one of your assumed invariants. The use of an `unsafe` block is not just an assertion that the programmer has verified the contents of the block to be sound given a set of invariants, but also that any inputs that go into the block uphold those invariants.
And indeed, I spotted this bug by thinking about the invariants in that way. I started by reading the innermost `unsafe` functions like `transpose_small` to make sure that they can't ever access an index outside of the bounds provided. Then, I looked at all the `unsafe` blocks that call those functions, and read the surrounding code to see if I could spot any errors in the bounds calculations. I observed that `transpose_recursive` and `transpose_tiled` did not check to ensure the bounds provided were actually valid before handing them off to `unsafe` code, which meant I also had to check any safe code that called those functions to see how the bounds were calculated; and there I found the integer overflow.
So you're right that this is a case of "subtle interaction of unsafe blocks with the rest of the program", but the wonderful part of `unsafe` is that you can reduce the surface area of interaction with the rest of the program to an absolute minimum. The module you linked exposes a single function with a public, safe interface; and by convention, a safe API visible outside of its module is expected to be sound regardless of the behavior of safe code in other modules. This meant I only had to check a handful of lines of code behind the safe public interface where issues like integer overflows could break invariants. Whereas if Rust had no concept of `unsafe`, I would have to worry about potentially every single call to `transpose` across a very large codebase.
Re: Smart pointers for the kernel
#100Earlier quoted context omitted.
> If you limited wrong to "memory safe" Yes, because this is a discussion about the value of "unsafe", so we're only talking about the wrongs that are enabled by "unsafe". > and also ignore that unsafe parts violating invariants can make safe parts of Rust to be wrong. If I run a line of code that corrupts memory, and the program crashes 400 lines later, I don't say the spot where it crashes is wrong, I say the memor…
It does not invalidate an argument that you do not want to talk about it. Regarding the second point: yes, you can then blame the "unsafe" part but the issue is that the problem might not be so localized as the notion of "only auditing unsafe blocks is sufficient" implies. You may need to understand the subtle interaction of unsafe blocks with the rest of the program.
If done properly, you can and should write out all the invariants, and a third party could create a proof that your code upholds them and they prevent memory errors. That involves checking interactions between connected unsafe blocks as a combined proof, but it won't extend to "the rest of the program" outside unsafe blocks.