6 ms·
It's statistically inevitable: many eyes also means many fingers, and you'd need a lot of nines on programmer perfection to avoid any use-after-frees in a proje
by gue5t 10y ago
It's statistically inevitable: many eyes also means many fingers, and you'd need a lot of nines on programmer perfection to avoid any use-after-frees in a project as big and frequently-changing as Linux. This is why people are so hype about memory safety recently--get a computer to do something perfectly, rather than trying to push every human up the asymptotic slope to perfection (when they have much more important things to spend their time on!).
- milesrout 10y agoExcept compilers are also big MLOC+ projects with their own bugs, and every compiler bug is a potential source of memory errors. Plus (at least in Rust) in order to ever do anything useful, you have to use unsafe anyway, usually in the most complex bits of code that have the most potential for subtle memory errors. Personally that's the biggest problem I have with it: it seems like it helps avoid issues a lot, but only in the easy cases where I'm very confident I can avoid them anyway. In the really tricky subtle cases (or even fairly basic things like cyclic data structures, which are not niche) the compiler throws up its hands. Those, honestly, are the cases where I want compiler help. That's not to say I don't think it's useful. In fact, making all the easy cases trivial does mean you can focus your effort, analysis, thought, design, whiteboard space, etc. on the trickier cases. But it's not anywhere near as useful as it is sometimes claimed to be.
- vitiral 10y agoThe easy cases... Like 99% of your entire project including checking for data races? Until we have perfect AI writing all our code, it's going to be pretty difficult to fix the other cases. That's what code reviews and extensive unit tests are for.
- milesrout 10y agoIf you're going to respond to my post with such trivial rubbish I'm not going to respond to yours with anything other than this comment.
- i336_ 10y agoHang on. That's not ideal. Could you possibly go into further detail? I feel that Rust is envisioned by its followers as the just-unveiled never-before-known perfect solution to memory safety and related problems, when in reality C and other languages continue to have similar issues because the issues themselves are not solved problems. So I'm holding Rust at arm's length until someone can thoroughly and objectively debunk the views that I have. But I'd love to be able to argue effectively. I agree with all the statements you made two levels up. Can you provide further detail to counter the parent comment?
- gue5t 10y agoI think the problem you see in Rust evangelism is a conflation of overall program correctness (aka "security"; any bug can be considered a security bug in a contrived-enough threat model) with memory safety. The C programs I encounter in the wild tend to be both insecure and not memory-safe. The difference between regular bugs in memory-safe programs and memory-safety bugs is that with a regular bug your program is still evaluating the code you wrote; perhaps you forgot a permission check, or you made a silly mistake in code that you didn't think was security-relevant but which a user might be using to keep their house doors locked. These are frustrating, but can usually be understood once found by established debugging techniques like bisecting a codebase with a test case. With a memory-safety bug, your program runs the buggy code and, if you're unlucky, will diverge from the semantics you associate with its source code. Whereas a C programmer thinks of "x->name = foo;" as making an assignment of a struct field, if "x" is an invalid pointer, this code might write to an unrelated integer variable, modify 4 or 8 bytes of a string buffer, cause a segfault (this is nice, since we find out our program is buggy), alter a function pointer (to produce a segfault muuch later in code which is itself correct), or have any number of other effects. This is much more hard to debug, and it's effectively impossible to mitigate the impact on your code of memory safety bugs outside your code. If you're working in a memory-safe language and call a function which you do not know to be implemented correctly, the worst thing it can do is issue an unexpected system call, which shows up very quickly in debugging. It can't mangle unrelated variables to make the program crash in correct, bug-free portions of code. As noted, Rust is not, as a whole, memory-safe. Unsafe code can set up bombs that will cause segfaults and other mischief in safe code, just like the situation in C if we substitute 'unsafe' for 'incorrect' and 'safe' for correct. But, in Rust, if you see misbehavior you do not have to audit your entire codebase. You only need to audit the code explicitly marked as unsafe. The vast majority of computation in Rust is outside of unsafe blocks, and using unsafe in the middle of a complicated, subtle algorithm raises big warning bells in code review. With respect to "C and other languages [having] similar issues", I don't think this is the case. Remote native code execution is a security issue only present in memory-unsafe programs. We do see remote (high-level) code execution vulnerabilities in programming languages with "eval"-like faculties, but it's not hard to audit your code and all its dependencies for calls to the built-in "eval", whereas auditing C code for memory safety is incredibly difficult. All of this is in some sense a consequence of the principle of least privilege: we want to make the world more secure by avoiding having an omnipresent "do absolutely anything" escape hatch, so that we can trust modules in proportion to the privileges they need. Rust and memory safety aren't a silver bullet, but I believe they're a cost-effective step toward correctness. The other half of Rust is that having algrebraic datatypes and a good typesystem helps you help yourself avoid many logic mistakes, and having an expressive language with generics helps you write less code (which correlates with having fewer bugs). This is why Haskell programmers like to claim they see fewer bugs than other languages. It's much harder to make an objective argument here, because availability of tools for preventing bugs isn't the same as lack of bugs. There are C codebases with fewer bugs than Haskell codebases; pure bug count depends on a multitude of factors in the development process and only formal verification can prove your program to be correct relative to its specification. And then your specification still might not mean what you wanted it to mean! There aren't any silver bullets, but Rust is a useful tool that you should consider making part of your toolkit, and there's been a lot of work to try to make it able to do all the things people do in C.