Memory Safety

67 pointsposted 16 hours ago
by pmaddams

101 Comments

fweimer

2 hours ago

I find it strange that this web site completely ignores the Java ecosystem, which offers memory-safe implementations for most of the protocols and services listed.

creatonez

37 minutes ago

Java does fine on memory safety, but does not do great on null safety (and overall invariant protection / "make invalid states unrepresentative" ethos), has difficult to harden concurrency primitives, and won't be adopted in many scenarios due to runtime cost and performance pitfalls. Future Valhalla work fixes some of these issues, but leaves many things spiky.

bheadmaster

2 hours ago

Can I use the Java implementations in another language without significant headache?

steelbrain

13 hours ago

The mentions of curl on this website are misleading and/or outdated. Curl is dropping the rust/hyper backend. See https://daniel.haxx.se/blog/2024/12/21/dropping-hyper/

woodruffw

12 hours ago

Is it? Curl dropped the hyper components, but they appear to support rustls as a backend. That work appears to have been done by Prossimo as well, and is conceptually grouped with it on the site.

(In other words: curl is using Rust, just not a specific Rust HTTP/1 backend anymore. But the site doesn’t limit its scope to just that backend.)

codys

14 hours ago

This site is curious in that in incorrectly categorizes go as memory safe.

Perhaps in part because the sponsors are invested in using go and benefit from its inclusion in a list of memory safe languages.

crawshaw

14 hours ago

I am not sure if you are:

1. attempting to retcon garbage collected languages as not memory safe, or

2. discussing a particular implementation choice of the standard Go runtime that was made because it is not a practical source of bugs (see https://research.swtch.com/gorace, it is not an inherent feature of the language, just the implementation, and it is the right practical choice)

But either way: this is the sort of thing I have seen again and again in the Rust "community" that I find deeply off-putting. Build good things, do not play snooty word games.

AnthonyMouse

11 hours ago

The thing that annoys me more is the singular focus on memory safety as if nothing else matters. For example, by most definitions PHP is a "memory safe" language, but it's also full of poor design choices and the things written in it have a disproportionate number of security vulnerabilities. JavaScript is also classically modeled as a gelatinous mass of smoldering tires and npm seems to have been designed for the purpose of carrying out supply chain attacks.

So then we see an enormous amount of effort being spent to try to replace everything written in C with Rust when that level of effort should have been able to e.g. come up with something which is easy enough for ordinary people to use that it could plausibly displace WordPress but has a better security posture. Or improve the various legacy issues with distribution package managers so that people stop avoiding them even for popular packages in favor of perilous kludges like npm and Docker.

aw1621107

8 hours ago

> JavaScript is also classically modeled as a gelatinous mass of smoldering tires

TypeScript exists? So I'm not too sure that everyone is focusing entirely on memory safety...

> So then we see an enormous amount of effort being spent to try to replace everything written in C with Rust when that level of effort should have been able to e.g. come up with something which is easy enough for ordinary people to use that it could plausibly displace WordPress but has a better security posture.

I feel like this is somewhat... inconsistent? At the risk of oversimplifying a bit (or more), Rust is "something which is easy enough for ordinary people to use that it could plausibly displace [C/C++] but has a better security posture" (not saying that it's the only option, of course). So now that all that effort has been expended in producing Rust, you want to just... forgo applying the solution and redirect that effort to working on solutions to other problems? What happens when you come up with solutions to those? Drop those solutions on the floor as well in favor of solving yet other issues?

I think another explanation for allocation of effort here is due to the difference between creating a solution and applying a solution. At the risk of oversimplifying yet again, "replace C with Rust" is applying a known solution with known benefits/drawbacks to a known problem. Can you say the same about "[i]mprov[ing] the various legacy issues with distribution package managers so that people stop avoiding them even for popular packages in favor of perilous kludges like npm and Docker", let alone coming up with an easy-to-use more secure WordPress replacement?

AnthonyMouse

7 hours ago

> TypeScript exists?

TypeScript is JavaScript with a moderate improvement to one of its many flaws. An actual solution would look like choosing/developing a decent modern scripting language and getting the web standards people to add it to browsers and have access to the DOM, which would in turn cause that to be the first language novices learn and temper the undesirably common practice of people using JavaScript on the back end because it's what they know.

> Rust is "something which is easy enough for ordinary people to use that it could plausibly displace [C/C++] but has a better security posture"

It's kind of the opposite of that. It's something that imposes strict constraints which enables professional programmers to improve the correctness of their software without sacrificing performance. But it does that by getting in your way on purpose. It's not an easy thing if you're new. And there's a place for that, but it's an entirely different thing.

The problem with WordPress isn't that it's designed for performance over security. It's not fast, and a replacement with a better design could easily improve performance while doing significantly more validation. And it's full of low-hanging fruit in terms of just removing a lot of the legacy footguns.

> So now that all that effort has been expended in producing Rust, you want to just... forgo applying the solution and redirect that effort to working on solutions to other problems?

In general when you come up with some new construction methods that are better able to withstand earthquakes, you apply them whenever you build a new building, and maybe to some specific buildings that are especially important or susceptible to the problem, but it's not worth it to raze every building in the city just to build them again with the new thing. After all, what happens when you get the new new thing? Start all over again, again?

aw1621107

6 hours ago

> TypeScript is JavaScript with a moderate improvement to one of its many flaws.

I'm certainly not going to say that nothing better could emerge, but nevertheless it's effort towards improving something that isn't memory safety.

In other words, I don't really agree that there's a "singular focus" on memory safety. Memory safety rewrites/projects get headlines, absolutely, but that doesn't mean everyone else has dropped what they were doing. Generally speaking, different groups, different projects, etc.

> It's kind of the opposite of that.

I don't think I quite agree? What I was thinking is that there have been efforts to make memory-safe dialects/variants/etc. of C/C++, but none of them really got significant traction in the domains Rust is now finding so much success in. I'm not saying this is because Rust is easy, but (at least partially) because it took concepts from those previous efforts and made them easy enough to be accessible to ordinary devs, and as a result Rust could become a plausible more-secure replacement for C/C++ where those earlier efforts could not.

> The problem with WordPress isn't that it's designed for performance over security. It's not fast, and a replacement with a better design could easily improve performance while doing significantly more validation. And it's full of low-hanging fruit in terms of just removing a lot of the legacy footguns.

Sure, and I'm not denying that. My point is just that unlike Rust vs. C/C++, as of this moment we don't know what an analogous plausible replacement for WordPress could be (or at least I don't know; perhaps you're more in-the-know than I am). Again, it's the difference between having a plausible solution for a problem in hand vs. sitting at the drafting desk with some sketches.

> In general when you come up with some new construction methods that are better able to withstand earthquakes, you apply them whenever you build a new building, and maybe to some specific buildings that are especially important or susceptible to the problem, but it's not worth it to raze every building in the city just to build them again with the new thing.

I feel like perhaps where the analogy breaks down is that unlike rebuilding a building, the Rust version of something can be built while the old version is still being used. Rust 4 Linux didn't require Linux and/or driver development to halt or for existing drivers to be removed in order to start and/or continue its development, Dropbox didn't have to tear out its old sync engine before starting work on the new one, etc.

And because of that, I feel like in general Rust is already mostly being used for new/important things? Or at the very least, I don't think "raze every building in the city just to build them again with the new thing" is an apt description of what is going on; it's more akin to building a "shadow" copy of a building in the same space using the new techniques with the possibility of swapping the "shadow" copy in at some point.

Or maybe I'm just too charitable here. Wouldn't be the first time.

> After all, what happens when you get the new new thing? Start all over again, again?

If the cost-benefit analysis points in that direction, sure, why not?

AnthonyMouse

5 hours ago

> Generally speaking, different groups, different projects, etc.

Well yes, but we're talking about the Rust people, which is why Typescript was a red herring to begin with. The complaint is that they've got a new hammer and then start seeing nails everywhere.

> What I was thinking is that there have been efforts to make memory-safe dialects/variants/etc. of C/C++, but none of them really got significant traction in the domains Rust is now finding so much success in.

This was mostly because they didn't solve the performance problem. In the domains where that matters less, other languages did make significant inroads. Java, Python, etc. have significant usage in domains that before them were often C or C++.

> My point is just that unlike Rust vs. C/C++, as of this moment we don't know what an analogous plausible replacement for WordPress could be (or at least I don't know; perhaps you're more in-the-know than I am). Again, it's the difference between having a plausible solution for a problem in hand vs. sitting at the drafting desk with some sketches.

The primary thing WordPress needs is a fresh implementation that takes into account sound design principals the original never did and which at this point would be compatibility-breaking changes. Give each plugin its own namespace by default, have a sane permissions model etc.

It doesn't require any great novelty, it's just a lot of work to re-implement a complex piece of software from scratch in a different language. But that's the analogous thing, with an analogous level of effort, being proposed for rewriting a lot of software in Rust whose predecessors have significantly fewer vulnerabilities than WordPress.

> I feel like perhaps where the analogy breaks down is that unlike rebuilding a building, the Rust version of something can be built while the old version is still being used.

That has little to do with it. If you really wanted to rebuild every building in the city, you could build a new building on every available empty lot, move the people from existing buildings into the new buildings, raze the buildings they just moved out of to turn them into empty lots and then repeat until every building is replaced.

The reason that isn't done is that building a new thing from scratch requires a significant amount of resources, so it's something you only force outside of its natural replacement cycle if the incremental improvement is very large.

> If the cost-benefit analysis points in that direction, sure, why not?

The point is that it doesn't. Rewriting a large amount of old C code, especially if it doesn't have a lot of attack surface exposed to begin with, is a major cost with a smaller benefit. Meanwhile there are many other things that have medium costs and medium benefits, or large costs and large benefits, and those might be a better use of scarce resources.

aw1621107

3 hours ago

> The complaint is that they've got a new hammer and then start seeing nails everywhere.

Ah, my apologies for misreading the original comment I replied to then.

> This was mostly because they didn't solve the performance problem. In the domains where that matters less, other languages did make significant inroads. Java, Python, etc. have significant usage in domains that before them were often C or C++.

Which is true! But even after Java/Python/etc. made their inroads the memory-safe dialects/variants/etc. of C/C++ still didn't attract much attention, since while Java/Python/etc. made memory safety easy enough for devs, as you said they didn't make performant memory safety easy enough, which left C/C++ their niche. While Rust is far from a perfect solution, it seems to have made performant memory safety easy enough to get to where it is today.

> If you really wanted to rebuild every building in the city, you could build a new building on every available empty lot, move the people from existing buildings into the new buildings, raze the buildings they just moved out of to turn them into empty lots and then repeat until every building is replaced.

I took "raze every building in the city just to build them again with the new thing" as specifically implying a destroy -> rebuild order of operations, as opposed to something more like "replace every building with the new thing". Too literal of a reading on my end, I guess?

> The reason that isn't done is that building a new thing from scratch requires a significant amount of resources, so it's something you only force outside of its natural replacement cycle if the incremental improvement is very large.

I mean, that's... arguably what is being done? Obviously different people will disagree on the size of the improvement, and the existence of hobbyists kind of throws a wrench into this as well since their resources are not necessarily put towards an "optimal" use pretty much by definition.

> The point is that it doesn't. Rewriting a large amount of old C code, especially if it doesn't have a lot of attack surface exposed to begin with, is a major cost with a smaller benefit. Meanwhile there are many other things that have medium costs and medium benefits, or large costs and large benefits, and those might be a better use of scarce resources.

That's a fair conclusion to come to, though it's evidently one where different people can come to different conclusions. Whether one stance or the other will be proven right (if the situation can even be summed up as such), only time will tell.

And again, I feel like I should circle back again to the "solution in hand vs. sitting at the drafting table" thing. Maybe an analogy to moonshot research a la Xerox PARC/Bell Labs might be better? One can argue that more resources into a WordPress replacement might yield more benefits than rewriting something from C to Rust, but there are much larger uncertainty bars attached to the former than the latter. It's easier to get resources for something with more concrete benefits than something more nebulous.

Gibbon1

3 hours ago

My heresy is that processor ISA's aren't memory safe and so it's sort of foolish to pretend a systems language is safe. I feel things like pointer tagging are more likely to provide real returns.

Also remember a conversation with someone at netscape about JS. The idea was partly as an interpreted language it could be safe unlike binaries. Considering binaries on pre 2000 hardware, running an arbitrary binary oof. But that it wasn't as easy as assumed.

saagarjha

11 hours ago

Why do you think data races are not a practical source of bugs?

pjmlp

2 hours ago

They are, pity that Rust type system has nothing to prevent them outside a very specific use case of in-memory data structures and threads.

Make those in-memory data structures writable via OS IPC and all bets are open, regarding what other processes, or kernel extensions, do to the memory segment.

Fearless concurrency is welcomed, but lets not overlook the fine print in systems programming.

saagarjha

2 hours ago

If you have both sides cooperating, then it's perfectly reasonable to write a safe interface on top of shared memory. If not…well, what do you suggest? Also, pointing at the overwhelming majority of code and going "this is a very specific use case" is also kind of wild, because even in IPC scenarios there will be in-memory data that needs protection.

pjmlp

2 hours ago

What I suggest is getting the marketing message correctly.

SkiFire13

2 hours ago

Are you perhaps confusing data races with race conditions?

pjmlp

2 hours ago

Nope, because it depends on how memory storage is mapped on the process, linker scripts and other fun tricks in systems programming, outside Rust's type system.

crawshaw

11 hours ago

Data races are a source of bugs. They are not a noticeable fraction of the security issues that face memory unsafe languages, which is the practical argument for memory safety.

saagarjha

10 hours ago

No they’re pretty important these days now that basic linear overflows and the like are harder to exploit

testdelacc1

3 hours ago

While we’re on the subject of what’s deeply off-putting - how did you generalise to a “community” based on one persons comment. When did Codys become representative of such a large group?

By the same token can I say your comment here is representative of all HN comments?

AlotOfReading

14 hours ago

If we're being extremely strict, Python probably also shouldn't be on that list because the CPython runtime is written in C and has had issues with memory safety in the past.

Ultimately, "memory safety" is a conversation about what a program is intended to do and what semantics the language guarantees that program will have when executed. For the vast majority of programs, you can be just as confident that your Go and Python code will do the right things at runtime as your safe Rust. It's good enough.

vlovich123

13 hours ago

No, because then no language would be included, including Rust. Implementation bugs are not treated the same as integral parts of the language as defined by the standard. Python is defined as memory safe.

AlotOfReading

13 hours ago

I understand this website as focusing on unsafety in a more practical sense of writing your stack in memory safe ways, not in the sense of discussing what's theoretically possible within the language specs. After all, Fil-C is standard compliant, but "run everything under Fil-C" is not the argument it's making. The most common language runtime being memory unsafe is absolutely an applicable argument here, mitigated only by the fact that it's a mature enough runtime that memory issues are vanishingly rare.

vlovich123

8 hours ago

Fil-C is super new and while it is memory safe, a lot of work is still ongoing in terms of getting existing programs to run under it and currently it only supports Linux which is nowhere near being “c and C++ can now be memory safe”.

hackermailman

12 hours ago

Sometimes except I learned the hard way that if you write everyday Python math code it's actually variable-time arithmetic and totally unsuitable for applied cryptography, oops

rurban

an hour ago

And they are also promoting rust as memory safe, whilst ignoring the true memory safe languages (the ones with a GC), which is kinda hilarious.

Politicians

websiteapi

14 hours ago

is go not memory safe? other than unsafe and other contrived goroutine scenarios, isn't it? I'm actually really curious - I've been writing go for just a couple years now and my understanding is the only ways for it to be unsafe are the two scenarios I described earlier.

K0nserv

14 hours ago

Changes to multi-word pointers can cause UB due to race conditions in Go because only changes at the word level are atomic.

See: https://blog.stalkr.net/2015/04/golang-data-races-to-break-m...

lomase

13 hours ago

Does Rust not have race conditions?

tekne

13 hours ago

One of Rust's core guarantees is that a race condition in safe code will never cause UB. It might return a nondeterministic result, but that result will be safe and well-typed (for example, if it's a Vec, it will be a valid Vec that will behave as expected and, once you have a unique reference, is guaranteed not to change out from under you).

Dylan16807

13 hours ago

When talking about the kind that lead to torn memory writes, no it doesn't have those. To share between threads you need to go through atomics or mutexes or other protection methods.

steveklabnik

13 hours ago

Rust prevents data races, but not race conditions.

muricula

14 hours ago

Usually people are talking about race conditions. When you say contrived you're thinking races conditions are difficult to win and unrealistic but attackers who have a lot of money on the line spend the time to win all sorts of wild race conditions consistently.

websiteapi

14 hours ago

is there actually a programming language that makes race conditions impossible (I am not being facetious, I actually do not know)? if the existence of races makes a language unsafe, then aren't all languages unsafe?

Yoric

13 hours ago

It's not that race conditions are generally memory-unsafe. The same race conditions would not be memory-unsafe in, say, Java or Python.

Go has a memory model that basically guarantees that the language is memory-safe except with a few marked "unsafe" functions or in case of race conditions involving interfaces or arrays. It's pretty easy to come up with an example of such a race condition that will cause reads or writes from/to unpredictable memory addresses. I imagine it's quite feasible to turn this into reads or writes from/to crafted memory addresses, which would be a mean to defeat pretty much any security measure implemented in the language.

The Rust community caters to people who are a bit obsessive about safety (including myself) and Rust developers tend to consider this a bug in the design of the Go language (there are a few, albeit much harder to achieve, issues that are vaguely comparable in Rust and they are considered bugs in the current design of Rust). The Go community tends to attract people who are more interested in shipping than in guarantees, and Go developers who are aware of this issue tend not care and assume that this is never going to happen in practice (which may or may not be true, I haven't checked).

torginus

12 hours ago

>is there actually a programming language that makes race conditions impossible

It'd be very hard to make something that offers that guarantee in the real world. One of the most common, IRL exploitable race conditions are ones that involve multiple services/databases, and even if your programming language would have such a feature, your production system would not.

muricula

11 hours ago

Python has that property when you don't bring C extensions into the conversation. Data races exist, but can never cause memory corruption due to the GIL.

i_am_a_peasant

13 hours ago

isn’t that the point of languages that have first class actor models something something?

SkiFire13

an hour ago

Even in those languages you can easily have the equivalent of race conditions simply due to the order messages are received.

awesome_dude

13 hours ago

> is there actually a programming language that makes race conditions impossible

To my knowledge, no.

> if the existence of races makes a language unsafe, then aren't all languages unsafe?

Are we talking about "data races" or "race conditions" One can lead to the other, but race conditions are a much bigger set.

AIUI It's impossible for any language level controls to prevent any and all race conditions, because some are happening outside of the binary/process/computer.

Data races, OTOH are almost trivial to protect against - a contestable thing must have a guard that ensures a writer has exclusive access to that thing for the duration of the write.

Some languages do this with mutually exclusive locks (mutex/semaphore/go channels), some languages/paradigms do this by never having shareable objects (Functional Programming/Pass by Value), and some (Rust) are doing this with the compile time checks and firm rules on a single writer.

Edit: Never having shareable objects should really be "never allowing an outside thread/coroutine/process/whatever mutate your copy of an object" meaning that an object is immutable to them, and they have to have a copy that they can mutate to their heart's content. They have to communicate any changes back, and then you choose whether to integrate those changes, or not

fweimer

3 hours ago

I'm not involved in Go development, only watching from the sidelines. I think it's very likely due to the project dynamics that after the first (published) exploit against real software, the compiler will be changed so that low-level data races can no longer result in type confusion. There will be some overhead, but it's going to be quite modest. I think this is realistic because there's already a garbage collector. Indirection to fresh heap allocations can be used to make writes to multiple fields to appear as atomic.

So I think Go is absolutely not in the same bucket as C, C++, or unsafe Rust.

woodruffw

12 hours ago

I think Go is effectively memory safe. The relevant test is for the presence of exploitable memory corruption, and to my understanding that’s never been a real issue with Go.

codys

11 hours ago

Go can have memory unsafety leading to arbitrary memory reads and writes by having an interface replaced by another thread (go interfaces use 2 words, one for the vtable and another for the data. It does not replace these in a thread safe way, so one can use a vtable to work with an unexpected data pointer.

Folks have shown this allows the kinds of arbitrary memory reads/writes that folks normally ban in their definition of memory safe (and this post's website has a definition does as well):

https://research.swtch.com/gorace

https://blog.stalkr.net/2015/04/golang-data-races-to-break-m...

https://www.ralfj.de/blog/2025/07/24/memory-safety.html

aw1621107

10 hours ago

"Effectively" is the key word in GP's comment - i.e., there are no known real-world vulnerabilities in Go code that are attributable to tearing on data races, so the claim is that that particular memory safety flaw does not exist in practice.

codys

10 hours ago

Interesting interpretation of that phrase. I think saying "probabilistically memory safe" would be more accurate (and more clearly communicate that idea), because we're betting on when a known case of memory unsafety in the language will show up in some piece of software.

aw1621107

9 hours ago

I don't know if I'd agree that "probabilistically memory safe" is better because it also fits a hypothetical implementation which catches out-of-bounds accesses /etc. 50% of the time regardless of whether in-the-wild exploits exist.

Maybe something like "Go is effectively/practically memory safe at the moment" would be better? Or if you want to put on your lawyer hat "Go is not known to be memory unsafe at this time", but that's rather cumbersome at best.

codys

9 hours ago

"at the moment" implies that Go would need to change for that statement to change, but instead we're waiting on a programer to make a mistake (A mistake that memory safe languages prevent).

Which does get us to why defining the properties of a language based on what people have written in that language _so far_ is weird. It's not really a property of the language that no one has screwed up yet. It's perhaps an indication that it might be less likely that folks will screw up, which is where the "probabilistic" comes in. It assumes that given the lack of a counter example (a screw up) so far, and given the time that Go has existed, it _appears_ that it's low-likelyhood to screw up go programs in that particular way.

Agreed that the word is non-targeted in one way, but it's better than the alternate (implying go would have to change to become memory unsafe), if one wants to talk about how-memory-safe-is-go.

aw1621107

8 hours ago

> "at the moment" implies that Go would need to change for that statement to change

I agree that "at the moment" could imply that Go would need to change for that statement to change, but I think it could also imply that "effectively/practically" could change as well since "effectively/practically" in this context implies a particular state of knowledge about known exploits (i.e., that there are none). If someone releases a practical data race exploit for real-world Go codebases tomorrow, "effectively/practically" would no longer hold, and therefore the statement would no longer hold despite Go not changing. The representation of the state of knowledge is part of why I suggested the lawyer-y version :P

pjmlp

3 hours ago

Because it is, from point of view of what memory corruption issues are there in C and C++.

Waiting for the traditional Rust reply.

llmslave2

13 hours ago

Or perhaps because you are using an uncommon definition for "memory safety".

codys

10 hours ago

One can evaluate Go using the extent of the definition from the site itself, which uses out of bounds reads and writes as a sign of memory unsafety.

Go's implementation allows torn writes for interfaces (which are 2 words in size). These torn writes allow arbitrary memory reads/writes (a superset of out of bounds reads/writes)

llmslave2

10 hours ago

Has this problem (which is really a race condition problem) ever been shown to be exploitable or lead to issues?

codys

10 hours ago

It sounds like you have a definition of memory safety you aren't disclosing.

Please fully provide your definition of memory safety. Not interested in trying to figure out what it is in a 20-questions-over-hn way.

llmslave2

9 hours ago

The definition from the posted website seems sufficient to me.

codys

8 hours ago

In that case, I can just refer back to my original comment: https://news.ycombinator.com/item?id=46388948

And then note that memorysafety.org says this (in case folks haven't read it):

> Memory safety is a property of some programming languages that prevents programmers from introducing certain types of bugs related to how memory is used.

They then provide an examine of out-of-bounds read/write. Which is the exact example I noted in my linked comment.

(Note: memorysafety.org does not provide a concrete definition of memory safety, but we get enough from what it says in this case)

The site does not require the known existence of an exploit in popular software (and does not require that _any_ exploit be possible, a bug is sufficient), merely that the language fails to block "certain types of bugs".

llmslave2

8 hours ago

Can you point to a single instance of this causing an issue?

codys

7 hours ago

Here's an example where a bug could exist in go due torn writes in a real program.

I found this by searching for places where folks reload there config at runtime, as they are generally a place where people forget to synchronize correctly in go.

1. A viper.OnConfigChange callback is set up to call readConfig(): https://github.com/OdyseeTeam/chainquery/blob/48c092515dea5c...

2. Inside readConfig(), we assign to a slice `twillio.RecipientList` (https://github.com/OdyseeTeam/chainquery/blob/48c092515dea5c...

3. Note that in Go, slices are objects composed of 3 words (https://go.dev/blog/slices-intro#slice-internals) And there isn't syncronization built-in over updating them. As a result, if something reads the slice while it's being updated we will mix together a data pointer & length & capacity that correspond to different real slice objects. If the length we read is from a slice that has real length 10, but the data pointer we read is from a slice with real length 1, when iterating we'll read memory out of bounds.

4. in the context of this particular program, we may send SMSs to recipients who were never in the configured list if a config change occurs at the right time. Or a segfault. Entirely unclear if reading the memory will result in reasonable behavior.

Note: I'm not familiar with this repo otherwise. This is from a quick search.

jkdjfdsnjsdf

14 hours ago

By that standard it also incorrectly categorizes rust as memory safe.

Dylan16807

13 hours ago

> By that standard

What standard?

pizlonator

14 hours ago

> Languages that are not memory safe include C, C++, and assembly.

False.

C and C++ are not memory safe if you use the most common and most performant implementations, sure.

At some point these folks are going to have to accept that caveat

roblabla

14 hours ago

C and C++ as defined by their current standards are memory unsafe. You may argue that some specific implementations manage to stay as memory safe as they can get away with, but even then, features like union prevents a fully memory-safe implementation.

pizlonator

13 hours ago

> C and C++ as defined by their current standards are memory unsafe.

I don’t think the spec says one way or another (but please correct me if you find verbiage indicating that the language must be memory unsafe).

It’s possible to make the whole language memory safe, including unions. It’s tricky, but possible.

Someone else mentioned Fil-C but Fil-C builds on a lot of prior art. The fact that C and C++ can be memory safe is no secret to those who understand language implementation.

vlovich123

13 hours ago

By definition, C and C++ are memory safe as long as you follow the rules. The problem is that the rules cannot be automatically checked and in practice are the source of unenumerable issues from straight up bugs to subtle standards violations that trigger the optimizer to rewrite your code into what you didn’t intend.

But yes, fil-c is a huge improvement (afaik though it doesn’t solve the UB problem - it just guarantees you can’t have a memory safety issue as a result)

pizlonator

12 hours ago

> By definition, C and C++ are memory safe as long as you follow the rules.

This statement doesn't make sense to me.

Memory safety is a property of language implementations, which is all about what happens when the programmer does not follow the rules.

> The problem is that the rules cannot be automatically checked and in practice are the source of unenumerable issues from straight up bugs to subtle standards violations that trigger the optimizer to rewrite your code into what you didn’t intend.

They can be automatically checked and Fil-C proves this. The prior art had already proved it before Fil-C existed.

> But yes, fil-c is a huge improvement (afaik though it doesn’t solve the UB problem - it just guarantees you can’t have a memory safety issue as a result)

Fil-C doesn't have UB. If you find anything that looks like UB to you, please file a GH issue.

Let's also be clear that you're referring to nasal demons specifically, not UB generally. In some contexts, like CPU ISAs, UB means a trap, rather than nasal demons. So let's use the term "nasal demons".

C and C++ only have nasal demons because:

- Policy decisions. For example, making signed integer addition have nasal demons is because someone wanted to cook a benchmark.

- Lack of memory safety in most implementations, combined with a refusal to acknowledge what happens when the wrong kind of memory access occurs. (Note that CPU ISAs like x86 and ARM are not memory safe, but have no nasal demons, because they do define what happens when any kind of memory access occurs.)

So anyway, Fil-C has no nasal demons, because:

- I turned off all of those silly policy decisions for cooking benchmarks.

- The memory safety means that I define what happens when the wrong kind of memory access occurs: the program gets killed with a panic.

vlovich123

7 hours ago

First, let me say that I really respect the work you’re doing in fil-c. Nothing I say is intended as a knock and you’re doing fantastic engineering work moving the field forward and I hope you find success.

That’s good to know about nasal demons. Are you saying you somehow inhibit the optimizer from injecting a security vulnerability due to UB ala https://www.cve.org/CVERecord?id=CVE-2009-1897 ? I’m kinda curious how you trick LLVM into not optimizing through UB since it’s UB model is so tuned to the C/C++ standard.

Anyway, Fil-C is only currently working on (a lot of, but not all yet I think right?) Linux userspace while C and C++ as a standard language definition span a lot more environments. I agree the website should call out Fil-C as memory safe but I think it’s also fair to say that Fil-C is more an independent dialect of C/C++ (eg you do have to patch some existing software) - IMHO it’s too confusing for communicating out to say that C/C++ is memory safe and I’d rather it say something like Fil-C is memory safe or C/C++ code running under Fil-C is memory safe.

> Memory safety is a property of language implementations, which is all about what happens when the programmer does not follow the rules.

By this argument no language is memory safe because every language has bugs that can result in memory safety issues. Certainly rustc definitely has soundness issues that haven’t been fixed and I believe this is also true of Python, JavaScript, etc but I think it’s an unhelpful bar or framing of the problem. The language itself is memory safe and any safety issues within the language spec or implementation are a bug to be fixed. That isn’t true of C/C++ where there’s going to always exist environments where it’s impossible to even have a memory safe implementation (eg microcontrollers) let alone mandate one in the spec. And also fil-C does have a performance impact so some software may not ever be a good fit for it (eg video encoders/decoders). For example, a non memory safe conforming implementation of JavaScript is not possible. Same goes for safe rust, Python or Java. By comparison that isn’t true for c/c++.

fweimer

2 hours ago

At a certain point, it's a trade-off. A systems language will offer facilities that can be used to break encapsulation and abstractions, and access memory as a sequences of bytes. (Anything capable of file I/O on stock Linux can write to /proc/self/mem, for example.) The difference to (typical) C and C++ is that these facilities are less likely to be invoked by accident.

Reasonable people will disagree about what memory safety (and type safety) mean to them. Personally, bounds checking for arrays and strings, some solution for safe deallocation of memory, and an obviously correct way to write manual bounds checks is more interesting than (for example) no access to machine addresses and no FFI.

Regarding bounds checking, GNAT offers some interesting (non-standard) options: https://gcc.gnu.org/onlinedocs/gnat_ugn/Management-of-Overfl... Basically, you can write a bounds check in the most natural way, and the compiler will evaluate the check with infinite precision (or almost, to improve performance). In standard, you might end up with an exception in some corner cases where the check should pass. I wish more languages would offer something like this. Among widely used languages, only Python offers this capability because it uses infinite-precision integers.

II2II

12 hours ago

Question: why is a union memory unsafe?

My meager understanding of unions is that they allow data of different types to be overlayed in the same area of memory, with the typical use case being for data structures that may contain different types of data (and the union typically being embedded in a struct that identifies the data type). This certainly presents problems with the interpretation of data stored in the union, but it also strikes me that the union object would have a clearly defined sized and the compiler would be able to flag any memory accesses outside of the bounds of the union. While this is clearly problematic, especially if at least one of the elements is a pointer, it also seems like the sort of problem that a compiler can catch (which is the benefit of Rust on this front).

Please correct me if I'm wrong. This sort of software development is a hobby for me (anything that I do for work is done in languages like Python).

woodruffw

11 hours ago

A trivial example of this would be a tagged union that represents variants with control structures of different sizes; if the attacker can induce a confusion between the tag and the union member at runtime, they can (typically) perform a controlled read of memory outside of the intended range.

Rust avoids this by having sum types, as well as preventing the user from constructing a tag that’s inconsistent with the union member. So it’s not that a union is inherent unsafe, but that the language’s design needs to control the construction and invariants of a union.

pizlonator

11 hours ago

Canonical example:

    union {
        char* p;
        long i;
    };
Then say that the attacker can write arbitrary integers into `i` and then trigger dereferences on `p`.

fweimer

3 hours ago

The standard does not assign meaning to this sequence of execution, so an implementation can detect this and abort. This is not just hypothetical: existing implementations with pointer capabilities (Fil-C, CHERI targets, possibly even compilers for IBM i) already do this. Of course, such C implementations are not widely used.

The union example is not particularly problematic in this regard. Much more challenging is pointer arithmetic through uintptr_t because it's quite common. It's probably still solvable, but at a certain point, changes the sources becomes easier, even at at scale (say if something uses the %p format specifier with sprintf/sscanf).

llmslave2

13 hours ago

He's talking about Fil-c

checker659

3 hours ago

I never understood why software has to pay for the lack of memory safety primitives in the hardware.

fweimer

2 hours ago

People have tried, and so far, achieving safety through trusted compilers and (fairly complicated) run-time support has been much more efficient. A small team could probably design a RISC-V CPU with extensions for hardware-assisted bounds checking and garbage collection, but any real CPU that they can built would likely have performance levels that are typical for research-oriented RISC-V CPUs. Doing the same thing in software on a contemporary commercially established CPU is going to be much, much faster.

grumbelbart

3 hours ago

Can you say what hardware could do better? I.e. which kind of primitives do you miss, or would make it easier to develop safer software?

pjmlp

3 hours ago

Bounds checking of pointers, C Machine kind of.

Solaris and Linux SPARC since 2015, for example.

https://docs.oracle.com/en/operating-systems/solaris/oracle-...

https://docs.kernel.org/arch/sparc/adi.html

ARM MTE, as another one,

https://learn.arm.com/learning-paths/mobile-graphics-and-gam...

fweimer

2 hours ago

These approaches can only detect linear overflows deterministically. Use-after-frees (temporal safety violations) are only detected with some probability. It's mostly a debugging tool. And MTE requires special firmware, which is usually not available in the cloud because the tag memory reservation is a boot-time decision.

pjmlp

2 hours ago

Still better than status quo on most systems.

It is kind of interesting how all attempts to improve security are akin to arguing about usefulness of seatbelts when people still die wearing them.

checker659

3 hours ago

CHERI, but that's just one example.

llmslave2

10 hours ago

Nothing beats arguing about memory safety and Rust on the internet on Christmas.

bgwalter

12 hours ago

The annual report of this org is pretty underspecified. There are numerous directors. Are they getting paid under "ops & admin" (11%)? Is "advancement" (12.3%) marketing?

Prossimo gets 6.8%. Does that money go to programmers? Are people whose works are being rewritten and plagiarized offered money to do the rewrite themselves or does it go to friends and family?

Why does an org that takes donations not produce a proper report?

ece

14 hours ago

Now do type safety.

rurban

an hour ago

Or better concurrency safety. The real deal

squirrellous

13 hours ago

[flagged]

dang

12 hours ago

Please don't start flamewars on HN. It's not what this site is for, and destroys what it is for.

https://news.ycombinator.com/newsguidelines.html

squirrellous

12 hours ago

Apologies. Please feel free to delete it. That was not the intention.

dang

8 hours ago

I believe you of course. These things do generally start unintentionally.

sealeck

13 hours ago

This is a bit like saying everyone would be a bit less jaded if the plane staying in the air wasn't hung over the Boeing 737 MAX 8 designer's heads by certain communities and used as an existential threat to the company.

II2II

12 hours ago

Commenting from the sidelines:

Doesn't modern C++ offer the ability to write memory safe code? The primary distinguishing difference from Rust, on this front, is that Rust is memory safe by default (and allows them to override memory safety with code that is explicitly declared as unsafe) while C++ requires the developer to make a conscious effort to avoid unsafe code (without providing facilities to declare code as safe or unsafe). While this means that C++ is problematic, it does not make Rust automagically safer - particularly when interfacing with C/C++ code (as would be the case when interfacing with Linux syscalls or most C or C++ based libraries).

I guess what I'm saying is that Rust is great when dealing exclusively with Rust libraries since it is either memory safe by default or because it is easier to audit (since it is either declared explicitly or implicitly as unsafe). On the other hand, it is not guaranteed to be memory safe. While this may sound like nitpicking, the distinction is important from the perspective of the end user who is unlikely to ever audit the code yet may be swayed by being told that it is written in a memory safe language.

ChadNauseam

12 hours ago

All languages offer the ability to write memory-safe code. It's just that doing so is very difficult in C and C++. The benefit of Rust isn't really the assurance of safety that's provided by not using the `unsafe` keyword. After all, pretty much all Rust programs do use the `unsafe` keyword. The benefit of Rust is a combination of many design decisions that make it easy to write safe code.

For example, everyday operations in Rust are almost all defined. But in C++, it is extremely easy to run into undefined behavior by accident and make your code do something bizarre. On the practical side, I have never ever gotten a segfault when writing rust, but have many times in C++.

coffeeaddict1

12 hours ago

> C++ requires the developer to make a conscious effort to avoid unsafe code

The problem is much worse than how you put it. I've written C++ for more than a decade and it's painful to constantly having to worry about memory safety due to enormous complexity of the language. Even if you are super diligent, you will make a mistake and it will bite you when you expect it the least. Relying on clang-tidy, non-default compiler flags, sanitizers and other tools is not only not enough, but a constant source of headache on how to integrate them with your build systems and project requirements.

II2II

11 hours ago

Admittedly, I am more of a hobbiest when it comes to C++ development. I try to keep track of things, but I started learning the language before it was standardized and I switched to other languages shortly after it was standardized (never mind the introduction of memory safe option in the standard libraries, which occurred in the 2000's). That said, memory safety has been a consideration, and a feature, for nearly 20 years now. It seems to me that people should have been taught how to approach it for nearly 20 years now. Sure, you can break the rules. Sure, anyone working with older code would have been exposed to bad code. Yet it shouldn't be a universal problem unless people are deliberately seeking out shortcuts (since writing memory safe code in C++ is messier than writing unsafe code).

torginus

12 hours ago

I think one of the fundamental differences in the SOTA C++ approach to memory safety (eg. extending unique/shared_ptr) and Rust is that C++ doesn't try to enforce having a single mutable reference to a variable and it still relies on strict aliasing heuristics, and so cannot claim to be fully deterministic. Still, use after free, and memory leaks should be impossible.

It'll still let you do a bunch of stuff Rust doesn't, which is up to the programmer to decide whether this is good or not.

aw1621107

12 hours ago

> Still, use after free, and memory leaks should be impossible.

Use-after-free is still possible in modern C++ via std::span/std::string_view/etc. outliving the backing object.

AlotOfReading

12 hours ago

    Doesn't modern C++ offer the ability to write memory safe code?
Can you name an example of a non-trivial C++ program that's memory safe? The only examples I can think of went to extraordinary lengths with formal methods and none of them are widely used.

adapower

12 hours ago

A better analogy might be how Ada was hung over the heads of those using C and C++, to the point of Ada being mandated by law in certain niches.

And then Ada software caused the loss of US$370 million with Ariane 5.

aw1621107

11 hours ago

> to the point of Ada being mandated by law in certain niches.

> And then Ada software caused the loss of US$370 million with Ariane 5.

This seems like a bit of a non-sequitur? Ariane is an EU rocket and the flight you're referring to was carrying an EU payload, and I don't think it was ever subject to the US DoD Ada mandate or an EU equivalent (which I'm not sure ever existed?).

(Also a bit of a nitpick, but I don't think the US DoD Ada Mandate was a law per se; it was a DoD policy and not something the US Congress passed).

It's probably somewhat disputable as to whether the Ariane failure was "due to Ada" or whether other higher-level concerns were responsible (e.g., reusing the Ariane 4 software without revalidation)

AlotOfReading

13 hours ago

If you're writing C/C++ and you don't care about memory safety, you're taking one of a few possible positions:

1. "I don't care what my program does."

Why write it though?

2. "I don't care what the standard says, I've put text into a compiler and it gave me a binary that does the thing."

What if you want to put the same text into a different compiler in the future, or the same compiler again? Are you certain the binary is going to continue doing the thing? Have you even fully tested the binary?

3. "I use a special runtime that makes memory unsafety defined again."

One, I don't believe you unless you're part of a very small group of people and two, why are you accepting the serious drawbacks (performance, process death, all the broader issues of UB) that come with this?

It's genuinely hard for me to understand why you wouldn't think memory safety is important Don't you want to write code that's portable and correct? Don't you want to execute other people's programs and trust they won't segfault? Doesn't it frustrate you that the language committees have spent years refusing to address even the lowest-hanging fruit?