Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

Suppose I have a self-contained Zig project and it has a nasty memory safety bug - how can I identify where the cause might be? What parts of my project source are potentially unsafe ?

You've said it's not everything, so, what's excluded? What can I rule out?



You can rule out a bounds violations from all but specifically marked unsafe code.


The same useless claim could be made for C and with the same effect.

The trick Rust is doing here that Zig is not is that Rust's safe contracts are always what we would call wide contracts. As a safe Rust programmer it's never your fault because you were "holding it wrong". For example If you insist on sorting a Vec<Foozle> even though Foozles all claim they're greater even than themselves, Rust doesn't say (as C and C++ do) too bad, you broke it so now all bets are off, sorting won't be useful in Rust because Foozles don't have a coherent ordering, but your program is fine. In fact today it's quite fast to uselessly "sort" that container.

Zig has numerous narrow contracts, which means when you write Zig touching any of those contracts it is your responsibility as a Zig programmer to ensure all their requirements were upheld, and when you in turn create code or types you will likely find you add yet further narrowness - so you can be and in practice often are, "holding it wrong".


> The same useless claim could be made for C and with the same effect

It really can't be.

Memory safety is problematic because it's a common cause of some dangerous bugs. Of the two main kinds of memory safety, Rust generally eliminates both, leaving only unsafe Rust and foreign code as possible sites of memory unsafety. Zig, on the other hand, generally eliminates only the more dangerous kind, leaving only unsafe Zig and foreign code as possible sites of that.

Mind you, the vast majority of horrific, catastrophic bugs are not due to UAF. So if we get a horrific, catastrophic bug in Rust, we can eliminate UAF as a cause leaving us only with most possible causes, just as in most programming languages used to write most of the software in the world already.

This point of ha-ha, you also got a segfault while I only got all other bugs doesn't make sense from a software correctness perspective.

There is no binary line between Rust and Zig that makes Zig's superior safety to C that couldn't also be put between Rust and languages that make far stronger guarantees, putting Rust in the same bucket as C. If you think that the argument, "Rust, just like C, is unable to guarantee the vast majority of correctness properties that ATS can, therefore it is equally useless" is silly, then so is trying to put Zig and C in the same bucket.

If you believe that eliminating certain classes of bugs is important for correctness even when you don't eliminate most bugs, then I don't see how a language that eliminates the more dangerous class of the two that Rust eliminates is "just as useless" as a language that eliminates neither.

I have been programming in both C++ and Java for a very long time, and while I appreciate Java's safety, the main difference between the two languages for me hasn't been a different in correctness but in productivity. That productivity comes from Java's superior abstraction - I can make many different kinds of local changes without affecting other code at all, and that is not the case in a low-level language, be it C, C++, Zig, or Rust. I think it's good that Zig and Rust offer bounds ("spatial") safety. I also think it's good that Rust offers UAF ("temporal") safety, but I find the price of that too high for my liking.

Of course, my experience is not universal because I use C++ only for really low-level stuff (mostly when working on the HotSpot VM these days) where both Zig and Rust would have been used in their unsafe flavours anyway, because I'm more than happy to pay the increased memory footprint for higher productivity in other cases.


> It really can't be.

I just did it.


Fair enough :)

I guess one could claim that some feature is useful because it eliminates certain classes of bugs while another is useless because it eliminates certain classes of bugs (which happens to be the more impactful subset of the former class), it's just not a very compelling claim, especially the way you presented it, which is:

Something bad happens, say an attacker steals my data. Rust is useful because I can eliminate spatial and temporal safety as the cause, leaving only all others, while in Zig I can eliminate spatial unsafety as the cause (leaving all others), but that's just as useless as C, where I can eliminate neither spatial nor temporal unsafety as the cause.

I can see how it may be reasonable to argue that all are equally useless, but given that spatial unsafety is the largest subclass of unsafety that causes security vulnerabilities, I'm not convinced by the argument that eliminating it is completely useless while eliminating a somewhat larger class (i.e. adding a smaller marginal benefit than the first step) becomes very useful.


Have you noticed how zero is categorically different from the other numbers, even the very small ones? It's an additive identity. No matter how often we sum together zeroes, the answer is still zero and that won't work for other values. Being the additive identity is categorically different, even though it might seem as though zero is just even smaller than a tenth or a millionth, it's different.

In (safe) Rust we categorically don't have type unsafety. Safe Rust function A doesn't have unsafety, and function B which calls it doesn't have unsafety, and function C which calls that doesn't either and so on forever. So in the exercise we talked about the answer is that the fault won't be anywhere in the safe Rust. But because we don't have this in "safe" Zig even though you say there's spatial safety, oops the lack of temporal safety means our apparently OK code might induce the spatial safety issues we thought couldn't exist.

It's OK, the C++ Convener is absolutely convinced of the same line of thinking as you. Surely if they can just keep finding adjustments to make C++ fractionally safer it'll be as safe as Rust. Right? If every three years they make it 10% less unsafe, surely in thirty years it's... oh right, about 65% less unsafe. Huh.


> In (safe) Rust we categorically don't have type unsafety

This is very inaccurate. Simple (i.e. non-dependent) types can describe very, very few properties. 99% of correctness properties cannot be described with simple types at all. That is exactly why, from ATS's vantage point, Rust is about as "safe" as Assembly; its types can guarantee almost nothing, while ATS can guarantee virtually everything.

So now the question is, with what little simple types give us (which is still useful), how much are we willing to pay for what confidence in their soundness. After all, Rust doesn't actually give us 100% safety, because we interact with C code etc.. But it does give us some higher confidence than the one given to us by Zig. So now the question is, since we don't have 100% confidence anyway - there are no zeros or ones here, neither on cost nor on the benefit side - how much are we willing to pay for what amount of added confidence?

Some people find the cost of Rust to be worth the added confidence; some don't. There is no binary line here.

> It's OK, the C++ Convener is absolutely convinced of the same line of thinking as you. Surely if they can just keep finding adjustments to make C++ fractionally safer it'll be as safe as Rust.

I'm not interested in making C++ as safe as Rust. For applications programming I use Java, which is somewhat safer than Rust, and for low-level code, I'm much more interested in other correctness properties than just safety. Safety gives me some small portion of the correctness I want, and it's great when that small portion is mostly free, but the bang-for-the-buck that I get from Rust is too low for me. I pay for all this complication in exchange for only guaranteeing no UAF? For that effort, I want a lot more.


> After all, Rust doesn't actually give us 100% safety, because we interact with C code etc..

And so, after all this long thread you're back to just saying you weren't actually talking about safe Rust in the conversation about safe Rust. It was all a big waste of my time.


No, I was talking about safe Rust, which also interacts with potentially unsafe C code, you know. What do you think schedules the threads running your safe code? How do you think your safe code reads from a socket?


Which as long as no new functionality is added keeps getting safer.

https://security.googleblog.com/2024/09/eliminating-memory-s...


I thought there's no such thing as "safer". There's only whatever guarantees Rust happens to make that can prevent almost 1% of the bugs a language like ATS can prevent, which is safe, and anything that doesn't make those exact same guarantees, which is unsafe and completely worthless.

Anyway, you help prove my point, which is that even those who claim to believe in a binary distinction between what Rust happens to guarantee and anything else don't actually believe that, and understand that it's all about numbers and risks. There are many measures to reduce bugs - some through guarantees in the language, others without guarantees - that each have some level of effectiveness and some cost, and the goal is to balance those costs and reduce bugs as much as possible.

Anyone who follows the research in software correctness over the past five decades should know that in the seventies we thought we had the answers, but since the nineties we've known that there is no one right answer to correctness, and that there's no way to tell in advance which methods will be more or less effective.


And quite evidently the design and community for both C and C++ leads to design with massive amounts of very high severity bugs.

Of course ignoring how Rust also helps against logic bugs by managing null values and having an expressive type system.

You seem to be the one completely focused on the binary question since that is the only thing that allows C , C++ etc. to still be part of the conversation.


And then we forget about all other types of undefined behavior?

I would say that a cursory search on ”segfault” in the Bun repo tells a different story.

https://github.com/oven-sh/bun/issues?q=is%3Aissue%20state%3...




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: