Hacker News new | past | comments | ask | show | jobs | submit login

> I'm confused

Thanks, I've tried to clarify that Zig provides spatial memory safety but not temporal memory safety, so hopefully it's less confusing.

> "Simplicity" does not mean safety.

Ceteris parabus, complexity breeds bugs and simplicity improves the probability of safety. For example, if I were auditing a piece of code for security, I would prefer the simplest correct program to the most complex correct program. Reduced surface area means reduced area for attack.

When I say that Zig pursues simplicity, I also mean this as high praise, that Zig is highly "orthogonal". In other words, able to solve difficult problems with a minimum of overlapping features. For example, Zig's comptime gives you generics, but also gives you so much more, plus there is also type safety throughout Zig's comptime, yet it eliminates the need for macros, and is more versatile, powerful and flexible at the same time. It's incredibly elegant. Nothing left to add, nothing left to take away.

> Zig does exactly what Rust does in this case.

Things like checked arithmetic matter and should be enabled by default in safe builds, yet Rust does not actually do this in safe release builds. Zig does and I hope that Rust one day will.

> What are you trying to argue here? Buffer bleeds can't happen in safe rust.

By definition, buffer bleeds can in fact happen in safe Rust. The borrow checker can protect against UAF and overflow, but the borrow checker can't protect against all kinds of underflow, which is what a buffer bleed is. You can even pull them off in JavaScript.

No language is actually 100% memory safe, not with respect to buffer bleeds.




> Things like checked arithmetic matter and should be enabled by default in safe builds, yet Rust does not actually do this in safe release builds. Zig does and I hope that Rust one day will.

The entire origin of unchecked arithmetic being a problem originates from their use as indexes to buffers. If you solve the indexing buffer issue you don't need to completely expand every single mathematical operation to a checked one which slows down the code. If people want checked artihmetic for some reason in the rare case that it matters in a non-buffer case, then they can used things like checked_add.


> Reduced surface area means reduced area for attack.

First of all, that's security, not safety. Lots of software exists in an environment where it isn't going to be attacked.

> Things like checked arithmetic matter and should be enabled by default in safe builds.

Rust offers actual checked arithmetic - for example, suppose I have a 32-bit signed integer (i32) and I want to add something to it, in Rust I can choose the most appropriate of:

add - also presented as the + operator, in debug this will panic on overflow, but in production I can choose, either panic or just have it wrap silently

checked_add - at runtime check for overflow and get either None or Some(i32)

overflowing_add - this time instead of Option we get a pair back, with our (wrapped if necessary) numeric answer and a boolean saying if we overflowed

saturating_add - addition saturates at the minimum and maximum thresholds

unchecked_add - even in debug builds this is not checked (yes it's unsafe)

wrapping_add - this performs the most likely native hardware behaviour, wrapping numbers around at the limits

You might also realise your variable should inherently have certain arithmetic, for example a 16-bit PCM sample should always have saturating arithmetic (getting this wrong is one reason badly written older audio software can sound bad) so you can make them Saturating<i16> or maybe you actually want wrapping arithmetic on the simulated 32-bit CPU registers in your Motorola 68000 simulator, so you use Wrapping<u32> for them.

The debug behaviour for the trivial + operator is not intended to be your best defence, if you're sure you want wrapping, write that down, if you're sure you want to check, write the check. But sure, if you somehow want your release code to panic, but don't want to write the panics out by hand, you can tell the compiler you want this in release builds.

> By definition, buffer bleeds can happen in safe Rust.

Nope.

> The borrow checker can protect against UAF and overflow, but it can't protect against all kinds of underflow

And it doesn't, in safe Rust the actual bounds checks are emitted, and they only get elided in most cases because in idiomatic Rust it's clear to the compiler that the checks are unnecessary (e.g. iterating over items in a vector, the compiler knows how long the vector is, and it can see we're starting at the beginning and stopping at the end, so, we don't need the bounds check and it won't actually be emitted in the machine code). thing[index] is bounds checked in safe Rust.

> No language is actually 100% memory safe, not with respect to buffer bleeds.

Many languages are 100% memory safe. Most fascinating here is WUFFS which - in exchange for its restricted purpose - gets to be both entirely safe and faster than the C (or C++, or Rust) you'd actually write.

You literally can't write a "buffer bleed" type goof in WUFFS. I don't mean "You won't because it's so easy to get it right" or even "It will warn you about the problem at runtime so you can fix it". I mean code which can exhibit that bug does not compile.


> First of all, that's security, not safety. Lots of software exists in an environment where it isn't going to be attacked.

I use the terms interchangeably on purpose, because safety and security are really two sides of the same coin. In the past, I've worked in security and I now work in a domain where safety is critical. It's my experience that the two fields have considerable overlap.

We can always get better at interdisciplinary sharing of knowledge.




Consider applying for YC's Spring batch! Applications are open till Feb 11.

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

Search: