> So, what's the big deal? Crappy C code gets exploited every day, and we upgrade it, and then we're "safe" until the next huge hole that's been there forever is reported. (In the meantime, people party with their private stash of vulnerabilities.)
> So, what's the big deal? Crappy C code gets exploited every day, and we upgrade it, and then we're "safe" until the next huge hole that's been there forever is reported. (In the meantime, people party with their private stash of vulnerabilities.)
A lot of Linux C utilities would benefit from such a treatment.
My impression is that some projects are already experimenting with or using C++ in their C code bases, so C to C++ is quite likely.
However, using C and C++ together in a project is especially easy. If I were to do this, I would first get the code base compiling with a C++ compiler (this already brings some extra type safety) and is not particularly difficult.
Then I'd start replacing C code blocks with safer C++ code. This could mean changing a function, some parameter-passing conventions, replacing char* with std::string, etc.
This has the biggest chance of success I feel, and there's already success stories and strategies available that describe this method. E.g: GCC.
I'm not suggesting that C -> Rust is easier than or quite as easy as C -> C++, just that it is much easier than C -> most other languages, and that it is close enough to C -> C++ that it is worth investigating. It is definitely more robust than the minimal definition of "incremental."
When it comes to memory safe languages, your choices do not boil down to "Rust or nothing".
Of course, Mercurial gives lie to this assumption.
It takes a lot more than a toolchain to write fast code.
What it matters is if it is fast enough for the use case being targeted.
As side note I remember when C compilers for home computers generated worser code than junior Assembly programmers.
Even then, Mercurial is implemented in Python and quite usable
The fact that a Java rewrite of git actually exists demonstrates the falsity of this statement.
Otherwise yes, it could even be rewritten in Ruby, as falcolas suggested...
Many other languages support C linkage in a way that's comparable to C++.
The point is that code like in that function is a nightmare to write correctly and test in plain C.
The real way out is to eventually change to a language where safety is opt-out and not opt-in, like in C++.
I have always been on the C++, in the C vs C++ wars, but I am also aware of all those developers that just code C with a C++ compiler, hence opt-in.
If it makes you happy I can use the ANSI C++ section number instead.
So any place that is against templates and exceptions, usually rules out the standard library on those arguments.
Then you have the software houses, whose C++ code is actually C with a C++ compiler that use the bloat and slow arguments against the library.
I don't remember them by heart, but there were a couple CppCon 2014 talks where this type of arguments was discussed.
I do like to use C++ a lot on personal projects, but there I can make full use of C++ best practices.
At work, I tend to avoid using it, because most C++ developers I have met on my career, actually use it as Better C, keeping all safety loopholes from C.
I had my share of spending weeks tracking down memory corruption issues.
Argument 2 is valid, but only applies to kernels, and also only applies to 1992 (it works a lot better now).
(That's probably why I misunderstoood your statement an argument against C++ on its own merits.)
Something like:
std::string path_name(std::vector<std::string> const& dirs, std::string const& name) { std::string p; for(auto const& dir : dirs) { p += (dirs + "/"); } p += name; return p; }
should work. If you feel like it, you can also add something like:
std::size_t len = name.size();
for(auto const& dir : dirs) { len += dir.size(); }
p.reserve(len);
Of course, len may overflow, but even if it does, all the harm that causes is that the string will have to reallocate memory during growth until running in a segfault when further memory allocation fails.I'm just trying to point out that the convenience of some C++ standard library features is not isolated to C++, and C++ is not a "memory safe" language by meaning of the word.
p += (dir + "/");
Again, C++ does not make anything safer, and its types can easily be replicated in any other language.
The "n" variants are a joke in terms of security, even the C99 annex, that was demoted to optional in C11.
I call them a joke, because tracking the pointer and length separately is hardly an improvement in terms of security.
The only improvement that the "n" variants added is that the null character is always added to the end, instead of how strncpy does it, by only adding the character if there is enough space.
(EDIT: Some stuff has changed since February, so some of these claims are now out of date. But not all of them, the overall situation is still similar.)
The solution here is actually quite trivial: just restrict filenames to 255 bytes and nesting to 255 levels, which limits paths to 64KB at most. Anyone trying to use git repositories exceeding either of those limits should be considered insane.
I think that using std::string would prevent the bug, because it would throw length_error on append. string::resize can be used to avoid excessive allocations.
Sanity checks would provide extra safety, but the code should fail cleanly even without them.
Funny, because I've actually been locked up for being insane five times. Speaking from experience, they'd only consider me insane if I said something like 255 was an important number because there are two sides to every problem and five fingers on each hand, and the path, which two feet take, is six one way / half a dozen the other, to the four corners of the earth, which is the natural limit.
So... you don't really know what insane is. Jus' sayin'.