News for hackers. Stuff that matters.
Re:Would Rust have prevented Heartbleed? Another look by Someone1234 on Tuesday March 17, 2015 @02:41PM (#9220260)
I have a question: How do Rust and Go compare in terms of security? Or are they both very similar in terms of mitigating certain classic C vulnerability classes.
Re:Would Rust have prevented Heartbleed? Another look by slimsag on Tuesday March 17, 2015 @02:57PM (#9220368)
Background: I have been developing in Go for ~5 years, and Rust for probably less than 2 months.

- Both Go and Rust use bounds checking on arrays/slices (which means out-of-bounds accesses are not allowed).

- Go is garbage collected, so memory leaks cannot occur.

- Rust encourages an ownership/lifetime model, so memory leaks cannot occur.

- Go can still have data races between multiple concurrent threads. To catch them, you must use the race detector _at run time_. Note however that Go encourages communicating information over channels, and if idiomatic code is being written the chance of data races is next to none.

- Rust cannot have data races in most cases, as it's ownership/lifetime model allows for catching them _at compile-time_.

- Both of these assumptions are based on no external C or unsafe code being in the picture.

TL;DR: Very similar.

EDIT: I used the wrong terminology -- sorry. Instead of _memory leak_ I should have said _dangling pointers_ (memory leaks can occur in _any_ language, Go/Rust/Java/JS/etc).

Re:Would Rust have prevented Heartbleed? Another look by rdtsc on Tuesday March 17, 2015 @03:24PM (#9220593)
> Go is garbage collected, so memory leaks cannot occur.

Well it depends on how you define memory leaks. Memory leaks can of course occur logically. Like say you create objects in a cache and never remove them. It is still a memory leak.

But at the level that you define the memory leak, it seems Rust can be just as good as Go because memory ownership is tracked by the compiler. One can say it is even better because of compile time checks and no need to have a GC @ runtime present.

Re:Would Rust have prevented Heartbleed? Another look by comex on Tuesday March 17, 2015 @03:41PM (#9220742)
If you're worried about memory leaks, an obvious downside of Rust is that it encourages reference counting over GC (more accurately: has no GC, but that might change in the future), and reference counting can leak via cycles.

However, in practice most values can be neither Rc nor Gc but single-owner, like unique_ptr in C++, which is easier to reason about than either.

Re:Would Rust have prevented Heartbleed? Another look by steveklabnik on Tuesday March 17, 2015 @03:54PM (#9220870)
Yes, it's important to note that Rust isn't 'refcounting but not GC,' but single ownership + borrowing over all else, and then using refcounting if you find yourself in a situation where you need multiple ownership.
Re:Would Rust have prevented Heartbleed? Another look by readymade on Tuesday March 17, 2015 @03:14PM (#9220494)
Memory leaks are still possible when using GC, of course, unless one operates with a strict definition that only includes unreferenced objects.
Re:Would Rust have prevented Heartbleed? Another look by osn on Tuesday March 17, 2015 @03:24PM (#9220587)
GC doesn't preven all the memory leaks. En easy example is a stack class backeed by an array. If you need more members, you allocate a bigger array and copy members. (The GC takes care of the smaller old array).

So far so good. But You forget to allocate smaller array (and copy members) when you consume too much memory. So 1000000* push(something) followed by 1000000*pop() keeps plenty allocated memory not in usage.

(It's not as brutal as malloc() and forget the result but still pretty awfull situation in a large project.)

Re:Would Rust have prevented Heartbleed? Another look by Dewie on Tuesday March 17, 2015 @03:41PM (#9220739)
According to that definition of memory leak, I guess you can call anything that doesn't eagerly free memory for memory leak. And the term gets quite weak and vague in that case.
Re:Would Rust have prevented Heartbleed? Another look by osn on Wednesday March 18, 2015 @05:13AM (#9224337)
The issue with this code is not that it isn't eager enough. It deoesn't free the memory ever (for value of ever "till the whole stack is not freed, that can be the whole runtime of the program").
Re:Would Rust have prevented Heartbleed? Another look by azth on Tuesday March 17, 2015 @04:15PM (#9221078)
> - Go can still have data races ... To catch them, you must use the race detector...

To catch _some of_ them :) No guarantee that they will all be caught.

Re:Would Rust have prevented Heartbleed? Another look by slimsag on Tuesday March 17, 2015 @04:27PM (#9221169)
To be specific, the ones _that occur_ at run-time. It's not a "will maybe kinda sorta detect data race conditions" situation.
Re:Would Rust have prevented Heartbleed? Another look by azth on Tuesday March 17, 2015 @04:54PM (#9221377)
Ah, fair enough! I thought it was a heuristic one. What sort of performance impact does it have?
Re:Would Rust have prevented Heartbleed? Another look by kibwen on Tuesday March 17, 2015 @08:50PM (#9222801)
See https://golang.org/doc/articles/race_detector.html

  > The cost of race detection varies by program, but for a 
  > typical program, memory usage may increase by 5-10x and 
  > execution time by 2-20x.
Re:Would Rust have prevented Heartbleed? Another look by nothrabannosir on Tuesday March 17, 2015 @02:54PM (#9220349)
Zero experience with Rust beyond watching tutorials and talks, please please correct me if Im wrong.

Rust has one killer feature that Go does not have: the typesystem has semantics for memory sharing. You can declare how a pointer can be used: is it accessed concurrently, is it local to me, &c. This helps the typesystem detect race conditions where two threads access a block of memory in an unsafe way.

Go does not have this. In Go, you "share memory by communicating", instead of "communicating by sharing memory." But if you do want to share memory, you are back to using locks and your own conventions and mechanics to prevent concurrent access. The language doesn't help you.

So it's a different programming paradigm. And if you use Go like you would use Rust (memory sharing), then Go is less safe.

(...right?)

EDIT: This sounds one-sided, but I'm only talking about sharing memory, here. If you don't do that, and stick to communicating, then Go can blow you away. I don't know how Rust deals with coroutines, but Go has super light threads (goroutines) that make concurrent behavior pure joy. All your threads can so easily talk to eachother, and wait for eachother, and it's all so light and native and good!

E.g. you have a handler for a POST, but you only want to close the connection when another thread has finished doing something. And you don't want to tie up an entire OS thread, because it could take a while and that's just too expensive. In go: super easy, just do a blocking channel read. In another language? Wow, where would I start...

(How does rust do that?)

Re:Would Rust have prevented Heartbleed? Another look by slimsag on Tuesday March 17, 2015 @03:07PM (#9220448)
Using a plain-old mutex in Go isn't encouraged. As you said, the memory model is _share by communicating_.

Sometimes, yes, using a mutex makes more sense -- and that does introduce the possibility of a data race.

If you follow effective Go code -- I imagine the code is on average about just as safe as Rust code is. It is partially comparable to using `unsafe` blocks in Rust -- don't do it, unless you know what you're doing. Stick with channels.

Re:Would Rust have prevented Heartbleed? Another look by steveklabnik on Tuesday March 17, 2015 @04:00PM (#9220930)
While channels are awesome, and are a good pattern, what's important about Rust is that it lets you do channels, but if you need to share mutable memory for some reason, Rust still has your back in that use-case. We can guarantee no data races, even with shared mutable memory, at compile time. It's pretty huge.

That said, channels in Rust are also nice to use, and you shouldn't not choose channels. Rust just enables other use-cases too.

Re:Would Rust have prevented Heartbleed? Another look by nothrabannosir on Tuesday March 17, 2015 @03:14PM (#9220496)
Example from personal experience: I'm working on an audio app right now, and I have high bandwidth, low latency data. I'm CPU bound, allocations and the GC are my enemy. It's just not feasible to constantly copy those buffers around. :(

Don't take this the wrong way, I'm not complaining about Go. Just know that sometimes, there are real reasons to share memory. And when you do: Rust has got your back, but in Go you're on your own.

Re:Would Rust have prevented Heartbleed? Another look by giovannibajo1 on Tuesday March 17, 2015 @03:30PM (#9220638)
Not sure what you mean; channels don't force you to copy buffers, you can simply pass the pointer/slice through the channel, but the point is that the paradigm encourages you to pass the ownership of that buffer through the channel.
Re:Would Rust have prevented Heartbleed? Another look by Animats on Tuesday March 17, 2015 @10:07PM (#9223160)
"the paradigm encourages you to pass the ownership of that buffer through the channel."

Rust transfers ownership when you send a single-owner reference over a channel. The sender can no longer access the referenced object; the compiler prevents that. That's the safe way to do it. This is a significant advance in multi-thread programming. The rules that make this work are strikingly simple. Somebody should have thought of this 20 or 30 years ago, but as far as I know, nobody did. Rust pushes the single-owner model hard, and it seems to work. The C++ crowd beat their head against the wall on this for decades, through three generations of auto_ptr, then unique_ptr. Really getting it right requires something like the Rust borrow checker, which C++ does not have.

Go does not do anything to prevent sharing data between threads. It's very easy in Go to unwittingly create shared data, because slices are references. After you've sent a reference, the sender still has access to the shared data, as does the receiver, so there's a potential race condition. Go does nothing to prevent this. There's a lot of dancing around this issue in "(In)effective Go", and long discussions of "is this a race condition" in Go forums. Go is a useful language, but it's in spite of Go's concurrency system, not because of it.

Re:Would Rust have prevented Heartbleed? Another look by rdtsc on Wednesday March 18, 2015 @02:24AM (#9223919)
Not sure there is a great advantage for that use case than from using C/C++ with threads and lockless queue of some sort.
Re:Would Rust have prevented Heartbleed? Another look by slimsag on Tuesday March 17, 2015 @03:33PM (#9220660)
Why can't you transfer buffers as []byte or []float32 etc to another goroutine over a channel? Hint: that doesn't copy the buffer, it just transfers "ownership" of it.
Re:Would Rust have prevented Heartbleed? Another look by surrealize on Tuesday March 17, 2015 @04:41PM (#9221294)
What if the buffer is aliased? In rust, when you transfer ownership, you can statically guarantee that there's no aliasing. But AFAIK that's not possible in go.
Re:Would Rust have prevented Heartbleed? Another look by TheDong on Tuesday March 17, 2015 @09:46PM (#9223064)
"ownership" was in quotes because what he really means is "logical, but not language guaranteed, ownership". Both sides of the channel still can touch the underlying data and cause races.
Re:Would Rust have prevented Heartbleed? Another look by Rapzid on Wednesday March 18, 2015 @04:09AM (#9224186)
It's not discouraged.. It's right there in the sync package. You can use channels where it makes sense, you can use RWMutex where it makes sense.
Re:Would Rust have prevented Heartbleed? Another look by azth on Tuesday March 17, 2015 @04:24PM (#9221144)
> I imagine the code is on average about just as safe as Rust code is.

The same claim can be made for C++ (with uniqe_ptr<T>), but we know how that faired. It is telling enough that there is a race detector tool for Go.

Re:Would Rust have prevented Heartbleed? Another look by Veedrac on Tuesday March 17, 2015 @07:49PM (#9222479)
Not really; Go is GC'd. C++ isn't memory safe.
Re:Would Rust have prevented Heartbleed? Another look by rdtsc on Wednesday March 18, 2015 @02:36AM (#9223956)
Using unique_ptr correctly is memory safe. For example:

  std::unique_ptr<int> p(new int(1));
  std::unique_ptr<int> q = p;
Should fail.

You can strong arm it into break but you can also reuse a pointer locally in Go after it was sent over a channel.

Re:Would Rust have prevented Heartbleed? Another look by Veedrac on Wednesday March 18, 2015 @09:39AM (#9225334)
C++ really isn't memory safe. It's trivial to think of an example:

    #include <iostream>

    auto f() {
        int x = 1;
        return [&] () { return x; };
    }

    int main(int, char **) {
        std::cout << f()() << std::endl;
    }
Of course "using <x> correctly" prevents bugs as long as - as C++ does - you define "correctly" as generously as possible. I agree Go isn't totally memory safe, but the level of memory safety is insanely less than in C++.

If you want something particularly involving unique_ptr, consider that best practices are to give non-owning sharing as raw pointers: you could say they're safe as long as you use them correctly but again that misses the point. I can also give an example (stolen from a talk) directly involving shared_ptr even when used with traditional "best practices" although I'm sure the best practices will update themselves to include this.

In some sense, Rust has been described as merely formalizing and automatically enforcing the best practices that people were already using in C++; it's the formality and automaticity that turns it from a dangerous language to a safe one.

Re:Would Rust have prevented Heartbleed? Another look by jamii on Tuesday March 17, 2015 @03:28PM (#9220627)
> (How does rust do that?)

My first thought would be to attach the connection object to the data the other thread is working on. When it is done it processing your message it drops the whole thing, closing the connection. If you want to hold it open for multiple workers you could make it an Arc<Connection> so it doesn't close until they all drop it.

Re:Would Rust have prevented Heartbleed? Another look by pcwalton on Tuesday March 17, 2015 @03:19PM (#9220536)
I can't speak to security as a whole, since security encompasses more than memory safety. But regarding memory safety, they're similar. Rust has an edge in that it can use hardware parallelism while remaining memory safe, while Go is not memory safe if GOMAXPROCS > 1. However, the memory-unsafe part of Go is a corner (racing on a map or slice) that hasn't caused any real-world security problems I'm aware of.

(Disclaimer: I'm a Rust developer.)

Re:Would Rust have prevented Heartbleed? Another look by slimsag on Tuesday March 17, 2015 @03:42PM (#9220751)
I generally agree with what you're saying here. The difference appears to be that Rust forces you on a compiler level to be safe of any potential race-condition.

Go doesn't enforce this on a compiler level -- but instead it encourages the use of sharing by communicating (over channels, where data races cannot occur), instead of sharing memory e.g. via a mutex (where you can run into a data race).

Re:Would Rust have prevented Heartbleed? Another look by steveklabnik on Tuesday March 17, 2015 @03:50PM (#9220825)
Important distinction: Rust forces you to be free of data races, which are a subset of race conditions. A very important subset, mind you, but they're different. It's not really possible to prevent general race conditions, like any form of logic error.
Re:Would Rust have prevented Heartbleed? Another look by zmanian on Tuesday March 17, 2015 @03:06PM (#9220438)
Rust is one of rare class of memory safe languages that are

- easily callable from other languages because of the C ABI

- runtime free and not Posix dependent

- portable across CPU architectures.

Rust will provide you memory safety where other languages can't even run.

Re:Would Rust have prevented Heartbleed? Another look by ngrilly on Wednesday March 18, 2015 @11:40AM (#9226242)
Rust is not "runtime free". Rust needs a "minimal runtime", as stated on the project home page. You need at least a memory allocator. Even C programs are usually linked to a runtime library (like glibc).
Re:Would Rust have prevented Heartbleed? Another look by Jweb_Guru on Wednesday March 18, 2015 @02:21PM (#9227552)
Rust is usable with an extremely minimal runtime that approximates having no runtime at all (with #[no_std]). There are a few intrinsics you have to define, but none of them involve memory allocation. It also has a core crate that does not expose anything that requires allocation.
Re:Would Rust have prevented Heartbleed? Another look by ngrilly on Tuesday March 24, 2015 @11:38AM (#9257256)
Interesting! I was unaware of the existence of #[no_std]. My mistake. Thanks for putting it right :)
Re:Would Rust have prevented Heartbleed? Another look by bjwbell on Tuesday March 17, 2015 @08:43PM (#9222775)
- easily call C libraries, practically trivial. I hated using the FFI's in Java & C#.

There's many things I don't like about rust but the above list make it very hard to beat.

Re:Would Rust have prevented Heartbleed? Another look by mavdi on Tuesday March 17, 2015 @03:01PM (#9220404)
I've played around with both languages and to my limited knowledge Go just seems like a more modern C language with a GC and easy multithreading.

Rust on the other hand is a completely different animal to anything I've used before. It has one of the most annoying compilers but that is for a reason, if your code compiles then it's memory safe (with a few exceptions, like 'unsafe' block)

Re:Would Rust have prevented Heartbleed? Another look by plq on Tuesday March 17, 2015 @03:13PM (#9220486)
They're practically same, but rust pulled it off without a gc.
Re:Would Rust have prevented Heartbleed? Another look by Symmetry on Tuesday March 17, 2015 @03:25PM (#9220596)
Exactly. I can easily see someone re-implementing OpenSSL in Rust. Not so much with Go.
Re:Would Rust have prevented Heartbleed? Another look by tptacek on Tuesday March 17, 2015 @05:30PM (#9221662)
Golang has possibly the best TLS library implemented in any language. Maybe you instead mean that nobody would drop a Golang TLS library into a C program, but that they might do that with a Rust TLS library? That's truey, but not particularly interesting. Most languages can't be dropped easily into C programs.
Re:Would Rust have prevented Heartbleed? Another look by pcwalton on Tuesday March 17, 2015 @06:43PM (#9222154)
> That's truey, but not particularly interesting. Most languages can't be dropped easily into C programs.

I don't see how the fact that most languages can't be dropped into C programs makes the fact that Rust can not interesting. It seems to me to imply the opposite.

Re:Would Rust have prevented Heartbleed? Another look by tptacek on Tuesday March 17, 2015 @10:28PM (#9223228)
Fair enough! I just get itchy at this refrain about Rust rewriting OpenSSL because again: Golang crypto/tls is an achievement. It is a seriously nice piece of code. It didn't need a uniquely great language (golang isn't that), just a uniquely talented TLS implementor.
Re:Would Rust have prevented Heartbleed? Another look by tsuraan on Tuesday March 17, 2015 @05:56PM (#9221846)
Making a library that can be linked into a C program is interesting because it can also be linked into a program written in pretty much any language. OpenSSL is awful, but it has bindings to pretty much any language that you want, so it's very commonly used. Go's TLS will never have that, but one implemented in Rust could.
Re:Would Rust have prevented Heartbleed? Another look by slimsag on Tuesday March 17, 2015 @04:29PM (#9221189)
Rust does not yet have a SSL library implemented as far as I am aware of. Go, however, does indeed have it's own pure-Go SSL library[1] and does not use OpenSSL at all.

[1] http://golang.org/pkg/crypto/tls/

Re:Would Rust have prevented Heartbleed? Another look by Symmetry on Tuesday March 17, 2015 @04:49PM (#9221336)
I should have been more clear. By "re-implementing OpenSSL in Rust" I meant making an implementation of SSL that would be used the same way as OpenSSL is, dynamically linked from C or various other programming languages. If you want a static library to compile into your Go application then of course doing it in Go is the most straightforward way to do it.