11 ms·
Saying it was fixed in two of the three C++ standard libraries is irrelevant, the language standard itself specifies that the behavior is undefined. This would
by Kranar 3y ago
Saying it was fixed in two of the three C++ standard libraries is irrelevant, the language standard itself specifies that the behavior is undefined.
This would be like saying C++ the language fixed buffer overflows because GCC added bounds checking. Most sensible C++ developers know that you should not depend on undefined behavior to write correct software, and yet your argument that because some implementations (not all) have decided to provide semantics for this, that it's now okay to use it or no longer a problem.
- gpderetta 3y agoMost sensible developers develop software against compiler specifications, not the standard. Very very little useful software can be implemented strictly within what's offered by the standard.
- temac 3y agoThat's very not a reason to justify the critical shortcomings of a standard, especially so when implementations are known to make their practical safeties regress in the name of they are allowed by the letter. In that context the very culture of C++ normalizers and implementers has to change and the introduction of this paper is a step in the wrong direction in that regard.
- gpderetta 3y agoRealistically the only improvement to the spec is changing fs races from undefined behaviour to something less program-invalidating. But to what? Unspecified behaviour would require the standard to give a set of possible outcomes which might not be implementable. Implementation defined would still require the compiler to pick and document a specific behaviour which might also not be possible to guarantee. The only way to provide stronger guarantees is to rigorously define the behaviour of the OS, which is of course not possible. Not even POSIX does that and of course C++ targets beyond POSIX. The reality is that there are a lot of things that are commonly done that are formally undefined (for example mmap, ldopen, openmp) and the user has to look for details beyond the C++ standard and into other documents (other standards, the compiler manual). The alternative is a fully defined isolated sandbox, but that would be pointless for a system language and not even Java attempts that.
- kllrnohj 3y agoOr put another way, find a language, any language, that defines all possible scenarios of a file system race condition in a multi threading & multi process system. It's not possible to do such a thing, and of course nobody does. They just avoid using the term "undefined behavior" even though it absolutely is. Which makes this whole thread absolutely absurd. It's the worst possible example of Rust vs. C++ CVE as the language doesn't get an opinion here at all in the first place
- nindalf 3y agoNo, it's an excellent example. Rust issued a CVE, an immediate point release with a fix for the issue and a blog post explaining the problem and what they did. 2 C++ implementations fixed the issue, but no CVE or blog post. No point release either AFAIK. You harp on the fact that this is undefined in all languages. Yeah sure. But some languages take the report seriously and communicate that to their users. They don't hide behind "spec says UB" or "it's the file system's fault". They take accountability and fix it. Other languages don't because that's the prevailing culture there. That's what you're missing when you're trying to make it seem like there's no difference between Rust and C++. There's a vast difference in how each community takes security. That's why its meaningless to compare the number of CVEs in both languages. Even if C++ reduced the number of CVEs by 90% it still would not be as secure as Rust because 1 C++ CVE is not the same as 1 Rust CVE.
- kllrnohj 3y agoYou're moving the goalposts so fast you could be competing with C++ for prioritizing performance over soundness. Reminder that your original claim was: > The problem definitely exists in C++, but it's not acknowledged as a problem, let alone fixed. Now it's degraded to just "but there wasn't a CVE or blog post!" which isn't even that relevant to the broader argument of Herb's that all the language guarantees don't prevent logic bugs (hence how Rust was able to have this CVE in the first place). There's a point of "good enough" for the language itself. Nobody is making any argument that CVE count is the best or optimal metric for anything
- thfuran 3y agoThat sounds like the hallmark of a defective language to me.
- gpderetta 3y agomost languages don't even have a specification.
- pizlonator 3y agoYes! This is much under appreciated. Usually, it’s just some core calculus of the language that is rigorously specified and the rest is hand waving. There are some exceptions like JS. But even Java has the problem that if you just implement what’s in the spec, you won’t be able to run anything meaningful unless you also do things exactly how the JDK would. You can find out what the JDK does by reading its code and writing test cases and I think that’s what folks do, if they want to be compatible. UB and memory safety are orthogonal. If we specified formally and super rigorously that a pointer is an integer and that memory is an array of bytes, we could have a UB-free language but memory safety would still be on fire.
- gpderetta 3y agoEverything is memory safe if your only datatype is uint8_t /s
- pizlonator 3y agoYup :-)
- tialaramex 3y ago> If we specified formally and super rigorously that a pointer is an integer and that memory is an array of bytes, we could have a UB-free language That's PVI (Provenance Via Integers) and it's a performance disaster. If anything in memory might be pointed to, almost all the nice modern optimisations aren't correct. It is really popular with a certain kind of "Portable assembler" programmer, who typically has no idea how the machine actually works, nor how their language is defined but is very confident the nonsense they're writing ought to do what they wanted it to do. So, the "bad" news is that you can't have this, your compiler vendor won't make it, and the "good" news is that you'd have hated it anyway which is why they won't make it.
- kllrnohj 3y ago> Saying it was fixed in two of the three C++ standard libraries is irrelevant, the language standard itself specifies that the behavior is undefined. Where does it say that? Please point to the spec that says remove_dir is allowed to have TOCTOU security bugs in a system with multiple processes.
- steveklabnik 3y agoThere is a comment below pointing to STL himself saying that it is https://old.reddit.com/r/cpp/comments/151cnlc/a_safety_culture_and_c_we_need_to_talk_about/js8m9sp/ https://old.reddit.com/r/cpp/comments/151cnlc/a_safety_cultu... He doesn't cite it, but if there's anyone I'd trust to have correct information here, it's him.
- tialaramex 3y agoThe UB is actually much broader, the standard just says it's UB if there is other software which touches files while you're also touching them, it's basically just always potential UB to run C++ application software with the filesystem API on a multitasking system. "A file system race is the condition that occurs when multiple threads, processes, or computers interleave access and modification of the same object within a file system. Behavior is undefined if calls to functions provided [...] introduce a file system race."
- kllrnohj 3y agoThat's also UB in Rust, Java, C#, etc... There's no language anywhere where a different process interacting with the file system at the same time isn't UB
- tialaramex 3y agoHow is it UB? The behaviour seems reasonably defined to me in my Rust, my Java, my C#. The people delivering popular implementations of the C++ standard library seemed to feel that not having UB here was a significant Quality of Implementation issue too. The ISO document on the other hand insists it's UB.