News for hackers. Stuff that matters.
Re:Let’s sunset C/C++ by gizmo on Friday August 14, 2015 @07:54AM (#10059653)
No need to panic, nobody is coming to take your precious pointer arithmetic away. If you want to write unsafe code, go ahead. But we also have to acknowledge that we as a profession are not able to write secure code in C/C++. We're talking about classes of security bugs that just don't exist in managed languages. Bugs that can't happen in languages like Rust either because it forces programmers to indicate ownership and lifetime of memory.

There's always a trade-off between performance and security, but with better tooling support the price for secure code will be very low. Right now security is bad because we look at security as a feature. As something that is added to a project, instead of as something that guides the entire design.

Your suggestion that static analysis can fix this is wildly optimistic, because C/C++ code for a modern browser uses memory pools, pointer arithmetic, just-in-time compilation, and shared memory between object instances, threads and processes and so on. It's hugely complex, and correctness can't be verified with some sort of static analyzer or with added runtime checks.

Re:Let’s sunset C/C++ by carlosrg on Friday August 14, 2015 @08:37AM (#10059780)
> But we also have to acknowledge that we as a profession are not able to write secure code in C/C++.

Wrong. You can write perfectly safe code in C++. You seem to have this ridiculous idea that pointer arithmetic is mandatory on C++. "Pointer arithmetic" is not a feature of C++. It's a feature of how computers work. C++ allows you to do it if you want. Memory pools are not a C++ feature, memory pools are part of how a modern computer and OS works. You know, memory doesn't appear magically in your program.

> Rust forces programmers to indicate ownership and lifetime of memory

So like C++ with unique_ptr, shared_ptr, and RAII?

Also I wanted to say that some of you keep mixing C and C++, calling them "C/C++". They're two different languages.

Re:Let’s sunset C/C++ by pjmlp on Friday August 14, 2015 @09:12AM (#10059921)
I like C++ and dislike its C foundation.

Always written C++ taking advantage of the language features that allow for safer code and bring it closer to Ada linage than C.

Never saw anyone else doing the same in the enterprise codebases I worked on. My team at CERN was the only exception.

Re:Let’s sunset C/C++ by JoeAltmaier on Friday August 14, 2015 @09:18AM (#10059948)
You can even write C++ without linking the runtime, to avoid all that unsafe legacy code. For drivers and such. Done it many times.
Re:Let’s sunset C/C++ by pjmlp on Friday August 14, 2015 @10:05AM (#10060139)
Yes, that is why I find it good that both Mac OS X and Windows allow for kernel code in C++ as a kind of "worse is better" improvement over plain C.

However C++ with teams that haven't drink the safety kool aid, becomes C with a C++ compiler quite fast.

Hence why nowadays I tend to only use it occasionally in side projects.

Re:Let’s sunset C/C++ by steveklabnik on Friday August 14, 2015 @11:01AM (#10060450)

  > So like C++ with unique_ptr, shared_ptr, and RAII?
It is like that, but with stronger guarantees and less overhead.
Re:Let’s sunset C/C++ by pmelendez on Friday August 14, 2015 @11:21AM (#10060586)
> It is like that, but with stronger guarantees and less overhead.

Smart pointers in C++ are very slim, which overhead are you referring to? And which are the stronger guarantees?

Re:Let’s sunset C/C++ by bbatha on Friday August 14, 2015 @11:45AM (#10060755)
shared_ptr uses an atomic counter. In rust you can choose to use an atomic ref count or not. The type system is sufficiently smart to ensure that you do not use the non-atomic one in a thread unsafe context. C++ has no ability to do so, so it does not provide a thread unsafe version.

Additionally, in C++ there's nothing stopping me from wrapping a unique_ptr around a pointer that's aliased else where. This violates the guarantees of a unique_ptr and forces the user to make sure its invariants are held. In Rust the compiler ensures that your Box (Rust's unique_ptr) can never be owned more than once.

Re:Let’s sunset C/C++ by pmelendez on Friday August 14, 2015 @12:27PM (#10061031)
>C++ has no ability to do so, so it does not provide a thread unsafe version.

In which case would you like to enforce a thread unsafe version?

>Additionally, in C++ there's nothing stopping me from wrapping a unique_ptr around a pointer that's aliased else where. This violates the guarantees of a unique_ptr and forces the user to make sure its invariants are held. In Rust the compiler ensures that your Box (Rust's unique_ptr) can never be owned more than once.

True, nothing stops you to do that and it is nice to know it on compile time. But I fail to say how you would do this by accident. If you deliberately want to do this kind of things, then you are asking for trouble and it doesn't matter how awesome your language is, you would find a way to shoot your foot.

Re:Let’s sunset C/C++ by steveklabnik on Friday August 14, 2015 @02:15PM (#10061798)

  > In which case would you like to enforce a thread unsafe version?
Any time you don't use shared_ptr in a multithreaded context, you're paying extra for the overhead of atomics. In Rust, if you need shared ownership, but you're not doing anything with threads, you can remove that overhead. If you then later try to use it across threads, the compiler won't let you, until you switch to using Arc.
Re:Let’s sunset C/C++ by pmelendez on Friday August 14, 2015 @03:26PM (#10062288)
> In Rust, if you need shared ownership, but you're not doing anything with threads, you can remove that overhead.

If I am following you well, then what you are saying is that you if you are in a single thread application you don't need to use a shared_ptr equivalent. Wouldn't that mean that you are using a garbage collected pointer? (Which should have a greater overhead than a shared pointer) because otherwise you would be using plain old raw pointers (with all its problems).

Re:Let’s sunset C/C++ by steveklabnik on Friday August 14, 2015 @04:03PM (#10062565)

  > you don't need to use a shared_ptr equivalent
Well, it's the same thing, but without the atmoics. Rc and Arc only differ in the instructions used to update the count, Rc uses regular increment, Arc uses atomic increment. The code is otherwise the same.
Re:Let’s sunset C/C++ by chadzawistowski on Wednesday August 26, 2015 @03:52AM (#10121677)
How confusing! Rust's Arc is "atomic reference counting" whereas Obj-C/Swift's Arc is "automatic reference counting"
Re:Let’s sunset C/C++ by steveklabnik on Friday August 14, 2015 @11:53AM (#10060798)
Arc<T> vs Rc<T> compared to shared_ptr was what I was going to say for overhead, as well as things like the lack of move constructors, which (should) make Vec<T> faster than std::vec.

For stronger guarantees, I was going to point out that if you std::move a uniq_ptr, it becomes null, but Rust prevents using a Box<T> that's been moved at compile time. Your example is good here too.

Re:Let’s sunset C/C++ by pmelendez on Friday August 14, 2015 @12:17PM (#10060958)
> the lack of move constructors, which (should) make Vec<T> faster than std::vec.

So you are saying that the lack of move constructors (hence copying the structure) will make Vec<T> faster than std::vector? I don't follow that logic, wouldn't it actually be slower?

> I was going to point out that if you std::move a uniq_ptr, it becomes null

The original becames null because the semantic is actually tranfering ownership which might be desirable depending on the case. Also you need it in case you are using custom deleters.

http://stackoverflow.com/questions/13860219/what-are-the-dif...

Re:Let’s sunset C/C++ by steveklabnik on Friday August 14, 2015 @02:14PM (#10061780)

   > I don't follow that logic,
Specifically, I mean that when the vector changes size, the vector needs to reallocate. In Rust, since there are no move constructors, it's just a memcpy of the whole chunk of memory, one big one. Very straightforward and fast. In C++, you need to call all those move constructors.

  > The original becames null because the semantic is actually tranfering ownership
Absolutely. In Rust, this is tracked at compile time, and attempting to use after the move is a compile-time error. In C++, you'll get a null pointer dereference. (I _think_ that technically it's in an 'unspecified' state, not a null one, but on my system, null is what I get).
Re:Let’s sunset C/C++ by pmelendez on Friday August 14, 2015 @03:15PM (#10062199)
> mean that when the vector changes size, the vector needs to reallocate You can control how often the vector changes the size and a lot of times you can even prevent that.

> In Rust, since there are no move constructors, it's just a memcpy.

memcpy is actually slower that move the ownership of a buffer, that's why you avoid copying as much as you can (std::vector also uses memcpy inside).

> In Rust, this is tracked at compile time, and attempting to use after the move is a compile-time error.

It is nice to get a misuse at compile time, but my point is that once you transfer the ownership of the pointer you shouldn't be using that unique_ptr anymore. I'm probably biased but I don't see this "accidental" misuse happening often (tbh I haven't seen it ever and I have seen some horrible things in C++ before)

Re:Let’s sunset C/C++ by steveklabnik on Friday August 14, 2015 @04:05PM (#10062576)

  > (std::vector also uses memcpy inside).
I don't think I am communicating myself clearly, so I'll just bow out about this issue, until I have an example ready. I should write one anyway, I just don't have it at the moment.

  > I'm probably biased but I don't see 
this "accidental" misuse happening > often

While that may be true, as the article points out, all it takes is for someone, anywhere, to slip up once, and then you possibly have a serious security violation. Having the compiler double-check your work is nice.

Re:Let’s sunset C/C++ by monochr on Friday August 14, 2015 @08:07AM (#10059695)
>But we also have to acknowledge that we as a profession are not able to write secure code in C/C++.

You can't write safe code in any Turing complete language. That's the whole point of Turing completeness. The only reason why memory attacks are as common as they are is because C like languages are the most popular ones.

If we replaced everything written with C to a "safe" language like, I don't know Haskell?, we'd have just as many zero day exploits of the monads within programs.

Re:Let’s sunset C/C++ by Nelson69 on Friday August 14, 2015 @12:02PM (#10060872)
You cannot write safe code in any Turing complete language? That's a bold assertion that I don't believe is true. Surely you can use formal methods to develop software and maybe even prove it's correctness and security, it's costly in multiple ways but the language of implementation doesn't prevent you from doing this. It is possible to write secure code.

If we replaced everything in C with Haskell, we'd have an entirely different problem. The attack surface wouldn't involve buffer overflows and stack smashing, it would involve various DoS attacks. Those might be easier to address though.

Re:Let’s sunset C/C++ by gizmo on Friday August 14, 2015 @08:33AM (#10059766)
There is a huge difference between a program that computes the wrong answer and one that corrupts memory, hijacks a shell, and installs a rootkit.

Javascript is turing complete but it's trivial to write a (slow) javascript interpreter in Python that allows anybody to run any javascript program without any risk to their machine. No memory attacks possible. To privilege escalation possible. No unchecked stack overflows. The system would be sandboxed and secure. It will just work or fail gracefully.

It's only when we increase the complexity of our runtimes a thousand fold and when we cut corners to squeeze out higher performance that all the nasty vulnerabilities start to creep in.

Re:Let’s sunset C/C++ by sklogic on Friday August 14, 2015 @09:30AM (#10059996)
It must be really slow in order to avoid attacks like this one: https://github.com/IAIK/rowhammerjs
Re:Let’s sunset C/C++ by JoeAltmaier on Friday August 14, 2015 @09:06AM (#10059897)
For pure Java perhaps. But native code is inevitable, and it has no such protection. So in practice Java is not a lot of protection.
Re:Let’s sunset C/C++ by piva00 on Friday August 14, 2015 @10:23AM (#10060233)
I didn't understand how Java relates to his comment about JavaScript + Python.
Re:Let’s sunset C/C++ by JoeAltmaier on Friday August 14, 2015 @11:47AM (#10060768)
Sorry, its because I'm an idiot. Anyway, secure languages use native code, and that's still a problem.
Re:Let’s sunset C/C++ by chriswarbo on Friday August 14, 2015 @08:15AM (#10059714)
> If we replaced everything written with C to a "safe" language like, I don't know Haskell?, we'd have just as many zero day exploits of the monads within programs.

I disagree. There will always be security issues, due to (ab)uses that developers didn't consider, but there can be different probabilities. Requiring developers to learn about language gotchas, remember those gotchas when coding, and jump through hoops to avoid them, just stacks the odds against us.

Re:Let’s sunset C/C++ by sklogic on Friday August 14, 2015 @09:28AM (#10059983)
> You can't write safe code in any Turing complete language.

Correct. But, a lot of code is written in Turing complete languages which does not really require any Turing completeness at all. And some code should be implemented in non-Turing-complete, verifiable languages.

Re:Let’s sunset C/C++ by iofj on Friday August 14, 2015 @09:18PM (#10063927)
Of course you can. You can, for instance, include an automatically verified proof that your code terminates for finite inputs.

This is in fact where the newest academic languages are going. In dependantly typed languages bounds checks are only done in theory. you have to include a proof that your indexes are within bounds, and the compiler verifies that proof. If it checks out, it compiles. If not, back you go. Far safer than java/go and the like and far faster than c++. These languages tend to allow pointer arithmetic too, for beating it in speed is almost impossible.

Re:Let’s sunset C/C++ by andresmanz on Friday August 14, 2015 @09:30AM (#10059994)
> But we also have to acknowledge that we as a profession are not able to write secure code in C/C++.

Then you've picked the wrong profession. You write that like it was a fact, while it's obviously nothing more than a lack of skill (and maybe knowledge) on your side.

If I chose a language primarily because it's 'safe', that would mean that either I'm pretty bad at writing safe code, or that I'm just unnecessarily lazy.

Re:Let’s sunset C/C++ by dbaupp on Friday August 14, 2015 @11:54AM (#10060805)
Maybe a single developer personally can write C/C++ code that is probably pretty safe (keeping in mind that most personal/small projects never get a proper security analysis/penetration test, so one may have a biased perception), but as soon as you have several people with non-trivial components that interact, it is quite to introduce serious problems accidentally. The evidence is unfortunately against C/C++: even the biggest tech companies in the world developing applications for which security is a critical feature (operating systems, web browsers) still regularly have bugs caused by memory safety issues, and they're almost certainly throwing every tool and a lot of CPU time at the problem.
Re:Let’s sunset C/C++ by pjmlp on Saturday August 15, 2015 @02:13AM (#10064509)
Assuming you work alone maybe yes. However most of us work in teams.

C and C++ have long proven that with average skills teams, the end result is lurking buffer exploits, dangling pointers, corrupted memory somewhere in the code base, that usually take days to sort out.