Where is this modern C++ culture that has resulted in large-scale codebases free of memory safety vulnerabilities? I've never seen even one, much less a "widespread culture".
> The majority of C++ programmers make use of:
None of this, empirically, results in safe code.
> Most of the unsafe C++ code is written by the "C with C++" sub-community that are mostly C refugees forced to use a C++ compiler.
I haven't seen any evidence for this. A lot of vulnerabilities are found in modern C++11.
> Also while the C++ community is pushing for safety with activities like the C++ Core Guidelines and reducing the amount of UB in the standard, the C standard community doesn't care at all.
I don't see any way that the C++ Core Guidelines are going to be able to succeed in creating a usable language that is memory-safe. Robert O'Callahan and I have elaborated why in other posts.
In any large scale C++ conference like CppCon.
In tooling from Microsoft and Apple.
> I haven't seen any evidence for this. A lot of vulnerabilities are found in modern C++11.
Using C++11 idioms, or C with classes?
> I don't see any way that the C++ Core Guidelines are going to be able to succeed in creating a usable language that is memory-safe. Robert O'Callahan and I have elaborated why in other posts.
Rust will become a sound alternative to C++ when:
- Libraries stop using nightly
- Rust developers can call OS APIs like COM on Windows without gymnastics. I mean with the same ease that Delphi, C++ Builder and Visual C++ integrate with COM.
- Rust developers can call OS X and iOS APIs with the same ease than Swift and Objective-C
- Has IDE support that can match what QtCreator, Clion, XCode, Visual Studio, C++ Builder, Keil MDK, ...
I really would like to see Rust one day supersede C++, but in what concerns C family of the languages, C++ is the safest option we currently have.
I have been part of the C++ community since the early days as Turbo Pascal and strong type refugee, and have followed how hard it has been for a language that is almost copy-paste compatible with C to earn the position it holds in the industry.
So until Rust gets some OS SDK love, bashing C++ community efforts to improve security won't get many adopters.
I keep on playing with Rust, but I get to write production code it still is JVM, .NET languages, Swift or C++.
> In tooling from Microsoft and Apple.
Microsoft and Apple regularly ship memory safety vulnerabilities in their codebases that are written in modern C++. Their browser engines, for example.
> Using C++11 idioms, or C with classes?
Using C++11 idioms. C++11 doesn't actually do anything to mitigate use after free, for example. In fact, I think there's a reasonable argument to be made that C++11 is less safe than C++03 in terms of use after free, because of features like move semantics and lambdas.
And I'm not intending to argue "use Rust" here. There are plenty of other memory safe languages out there. I'm simply arguing that C++ is not memory safe, and it cannot be while preserving any semblance of backwards compatibility. The specific technical reasons for this have been elaborated in posts that I've sure you've seen. I'd like to see proponents of the idea that modern C++ is memory safe actually try to rebut those.
Personally I would rather be using Ada or Modula-3 for the few use cases I still use C++.
However in the context of security minded developers that can only choose between C, Objective-C, C++ and nothing else, C++ is the only one providing the features to write safer code.
Of course if not all team members play ball it doesn't work, but it is better than not having an option at all.
One point of note is that O'Callahan's "Vapourware" post points out a problem that's solvable, it isn't some big blocker the way he claims it is. Your comment 162 days ago describes the real problem, or at least one of them.
Edit, because fuck:
> Where is this modern C++ culture that has resulted in large-scale codebases free of memory safety vulnerabilities? I've never seen even one, much less a "widespread culture".
The rest of your post shifts the question from "is there a culture of secure, maintainable, and understandable software" to "Is C++ software free of memory flaws." Are these concepts not distinct to you?
Why even bother replying, if you're going to drag the discussion into some corner like that?
No, it is a big blocker. In fact, it's the same as the problem I pointed out, just with global variables instead of shared ptr. Aliasable mutable data is the fundamental unsolvable problem; whether it arises through global variables or shared ptr is just a detail.
> The rest of your post shifts the question from "is there a culture of secure, maintainable, and understandable software" to "Is C++ software free of memory flaws." Are these concepts not distinct to you?
Software that has memory flaws that enable remote code execution is not secure.
Imagine refactoring a program to not use globals but instead pass them up by const or mutable reference to where they're used. The checker can do the same imagining with an effect system.
> Software that has memory flaws that enable remote code execution is not secure.
Words have meaning.
Not at all. This requires higher order control flow analysis, which is pretty much guaranteed to fall down in all sorts of cases.
[1] Edit: A mechanism for annotating that a class or method does not get implicitly passed globals would be very useful for things like std::function<>::operator() so that std::function objects are forced to access globals by capturing them, because totally unrelated uses of a std::function could stomp over the same type instantiation for this ultra-dumb analysis.
Edit: Here's the tl;dr version. One solution to the global variables problem is for the CppCoreGuidelines to say, "Don't use globals." Another is for them to say, "Don't use globals, but for the 90%-case we won't be dicks about it, we won't blindly pretend that every function could use globals when they obviously don't."
No, you wouldn't. Try writing such an analysis. Either I will be able to break your analysis or it will return "yes, this might mutate a global" for so much of any reasonably sized program that the analysis will be useless.
This is basic, basic stuff to anyone who is in the sound static analysis field.
The point is, you can write functioning programs even with that -- you can copy construct out of a global, for example, but you obviously can't pass string literals to functions that touch stdout or errno. If you want to make a legitimate disagreement, argue against the more practical version where you treat different global variables as different things.
> This is basic, basic stuff to anyone who is in the sound static analysis field.
Do people in that field also nitpick pieces of rhetoric and deliberately ignore the main point?
I don't think any intelligent person in that field would argue that C++ programs can't be written or refactored in such a way so as to get rigid enough use of globals so as to pass a relatively conservative analysis. I mean, that would imply you couldn't get anything useful done in a language without globals.
Copy construction out of a global is actually still unsafe, because some other thread (for example) might mutate the global, invalidating the this pointer. Or the copy constructor might call a function that can't be proven to not access the global, causing the same problem.
> If you want to make a legitimate disagreement, argue against the more practical version where you treat different global variables as different things.
That isn't meaningfully more precise. You are still going to require higher order control flow analysis. Think about how you would analyze functions like std::transform() and prove that the function passed in doesn't destroy the container being mapped over (or call a function that does, etc.)
> I don't think any intelligent person in that field would argue that C++ programs can't be written or refactored in such a way so as to get rigid enough use of globals so as to pass a relatively conservative analysis. I mean, that would imply you couldn't get anything useful done in a language without globals.
Well, sure, but that's not C++ anymore. Neither roc nor I have argued that you can't write some subset of C++ that is sound. In fact, there are subsets of C used for avionics and the like that are provably type-safe and memory-safe, because they disallow dynamic allocation entirely and are extremely restrictive with what pointer operations they support. But the entire value proposition of these C++ static analyses is to be compatible with the C++ ecosystem. When you start adding restrictions that rule out most C++ libraries and, worse, that you can't get around without massively rewriting their logic, then you're essentially a different language.
It's not unsafe, that code wouldn't pass the check. Other threads would have to not access globals at all, or all threads have to access them read-only.
As for doing things on a variable by variable basis, just imagine a rote refactoring from a global variable to non-global variable passed up from main. For example:
https://github.com/srh/memcached/compare/65da75f...235db6
We eliminate the global variable "as" by passing a struct assoc pointer parameter up from main.
The parts of this that isn't a rote refactoring is where, instead of adding another parameter to functions like event_handler and event_set, modifying libevent to pass through the struct assoc pointer, we instead put the struct assoc pointer into a closure (because this is C, whatever homespun kludge is most convenient). The other situation where it's put into a closure is some calls to pthread_create.
We know that this refactoring retains identical behavior -- every access to the global as now accesses the same as object -- because only one instance of struct assoc has been constructed. (And the kludges with C-style closures here are correct merely by inspection, i.e. the right variables are initialized, type safety would handle that.)
Now, if we have some tool for checking use of globals, it can do the same thing, and then analyze memory safety using the rules it uses for non-globals. What it needs from the user are annotations to help it know when and how a global reference should be captured by a closure instead of passed as an extra parameter to the closure. Of course, it would be perfectly valid to thread a struct assoc pointer parameter through the internals of libevent, if that was sufficient to check the program.
Now, memcached would have other problems to deal with, because the struct assoc is shared across threads. The point is, the problem is not that it's a global variable, it's other structure inherent to how the program is designed. And examples like
unique_ptr<Foo> p;
void bar() {
p = make_unique<Foo>(...);
Foo xyz(*p); // Forbidden! (NOT)
}
are easily dealt with.Can you name one C++ program with the same track record as postfix or qmail?
http://web.archive.org/web/20160401021400/http://www.guninsk...
djb is a smart and motivated guy and even he isn't quite capable of writing correct C code; how much chance does anyone else have?
Again, which C++ program has been even analyzed to that level?
What I do see is hubris. They are overconfident and pretend that one can use C++ like Haskell, i.e. one can safely go ahead and pile one abstraction onto another.
C programmers at least know the limitations of their language.
This is the just impression that I and many others get. I'm sure there are counterexamples.
The majority of C++ programmers make use of:
- RAII
- String classes instead of char* überall
- Vector classes instead of char* überall
- new and delete instead of malloc()/free() and casts
- References for out parameters instead of pointers
- Real enums, specially since C++11, instead of #define
- Smart pointers for memory management
- Type based programming to reduce errors
- Minimize the use of the pre-processor to #include and macros, only when they cannot be expressed via templates, const, constexpr and inline.
Most of the unsafe C++ code is written by the "C with C++" sub-community that are mostly C refugees forced to use a C++ compiler.
Also while the C++ community is pushing for safety with activities like the C++ Core Guidelines and reducing the amount of UB in the standard, the C standard community doesn't care at all.
The only thing that the C community has done regarding security was the Annex K in C99, which was proven so good that it became an optional feature in C11.