A rewrite in C++ would not make it any safer. Rewriting it to make it easier to understand could make it safer, but you do not need a different language for that.
If you can change the name_path struct to a standard STL data structure (std::vector<std::string> might work just fine), you can easily rewrite the function such that all memory allocation and all exploitable memory access is delegated to STL containers. If your STL std::string has a buffer overflow issue, you’re of course still in trouble, but the same is true if there are bugs in the STL/implementation of Go/Rust/Python/Java/Haskell…
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.
Right, and you can do the same with C, using libraries providing this functionality wrapped as well. There's plenty of std::string and std::vector like containers, which handle the magic for you. But even then, you can work with struct {len int; void* data;} to get your vector, and replace void* with char* to get a string. A simple vector and simple string is in no way difficult to implement, and many implementations exist.
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.
The difference is that using STL containers such as std::string or std::vector are very much the default in C++ (much the same way ‘safe’ code is the default in Rust), whereas you have to do some manual work in C to get them. The result is that using std::string and std::vector here is the natural solution in C++, whereas likely very experienced C programmers stuck to the manual approach.
Oh, yes, sorry and now it’s too late to fix (both that and the horrible formatting). Though I suppose it would have been a compile-time error, so at least it shouldn’t be exploitable :')
Yes it would, because this is basically string processing where C is the worst possible language one could use. I've detailed in another comment how std::string could be used.
You're talking about naked char[]. You can just as easily make a struct{ int len; char* str; } in C, and combined with the "n" variants of string operations, would work just fine with common tools.
Again, C++ does not make anything safer, and its types can easily be replicated in any other language.
Being possible, doesn't mean the majority of C developers make use of it.
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.