|
Between C++ and Rust, my bet would be that you decide Rust. But—also learn Zig in addition to Rust. Having seen first-hand how so many threat vectors these days are now supply chain attacks, having reported CVEs and earned P1 bounties in memory safe languages, and having worked on static analysis systems to detect zero day exploits—I'm also impressed by Zig's overall approach towards safety, as being more than only memory safety. For example, this comes through in Zig's extreme simplicity and explicitness, and also how Zig enables checked arithmetic by default for safe builds. For people who haven't worked in security, integer overflow and wraparound may seem like small things, but they increase the probability of exploits such as buffer bleeds, i.e. attacks like OpenSSL's Heartbleed, which are often remotely accessible and easier to pull off than a UAF. In fact, no language is 100% memory safe, i.e. able to prevent a memory buffer bleed, because these are logic errors with respect to the protocol. However, explicit control flow and checked arithmetic do help to close semantic gaps and minimize ambiguity, which is what good security comes down to. Of course, Zig only offers spatial memory safety, and not temporal memory safety like Rust. So Zig is more memory safe than C, and less memory safe than Rust or JavaScript. Nevertheless, Zig is safer than Rust when it comes to being able to handle memory allocation failure. Again, Rust's borrow checker is also valuable for concurrency safety, i.e. for multithreaded systems, but if you're using io_uring for fast I/O, then multithreading is less of the necessary evil that it used to be a few years ago. Zig is something you can pick up in a week, with state of the art tooling, and fantastic C-ABI interop for libraries. So... learn both! |
> For example, this comes through in little things like Zig's extreme simplicity and explicitness
"Simplicity" does not mean safety. In fact simplicity means you can't describe hard problems easily without being overly verbose, which means more code and more attack surfaces. Problems are what can be simple or complex. If your language advertises "simplicity" it just means it can't solve complex problems in straight forward ways. Zig is just repeating the mistakes of C++ as well as all the mistakes of Go.
> or people who haven't worked in security, integer overflow and wraparound may seem like a small thing, but they increase the probability of buffer bleeds, i.e. attacks like OpenSSL's Heartbleed, which are often remotely accessible and easier to pull off than a UAF.
Zig does exactly what Rust does in this case.
> In fact, no language is 100% memory safe, i.e. able to prevent a memory buffer bleed, because these are logic errors with respect to the file or protocol format.
What are you trying to argue here? Buffer bleeds can't happen in safe rust.
> The borrow checker is obviously great for multithreaded systems, but if you're using io_uring for fast I/O, then multithreading is less of the necessary evil that it used to be a few years ago.
Syncronization is a problem in any kind of multitasking. Whether that happens inside or outside the language is the only question. The OS can have all the same problems your code can have. https://mobile.twitter.com/axboe/status/1505335772706091011 Also io_uring assumes you're only ever writing for Linux.
> Nevertheless, Zig is safer than Rust when it comes to checked arithmetic or being able to handle memory allocation failure.
This is simply incorrect. Most of the problem with unchecked overflow is for buffer overflows, which are fully caught. Rust gives options to handle memory allocation failure if you want to handle it. Generally though for most applications simply crashing is completely fine.