5 ms·
There is no conflict between (auto)cxx and the view that `unsafe` blocks assert the soundness of their contents. Using cxx does not, in fact, remove any `unsafe
by Rusky 6y ago
There is no conflict between (auto)cxx and the view that `unsafe` blocks assert the soundness of their contents. Using cxx does not, in fact, remove any `unsafe` blocks- thus it is not "lying," nor is it "the ultimate evil." (Such hyperbole makes productive discussion in this space rather difficult...)
Consider the (completely and utterly standard) practice of writing a safe Rust library wrapping a C++ library. To be sound, this crate has two obligations: First, its `extern {}` function signatures must match the C++ library's. Second, its public API must enforce any additional soundness invariants from the C++ library.
Ensuring that signatures match is tedious and entirely mechanical- automating it increases confidence that a program is sound! Crucially, there is more to signature matching than mere arity and type layout- C++ vocabulary types express ownership information that bindgen alone does not capture!
Cxx isolates all the auditing work related to C++ vocabulary types, like `std::vector` or `std::unique_ptr`. A single audit of cxx covers this aspect of all cxx-using crates. This is an enormous win if your goal is to integrate Rust with a large C++ codebase like Gecko or Chromium!
The kernel of truth to your argument lies only in that second obligation. As Ralf concludes in that same issue thread, the problem of generated `unsafe` blocks is not new to cxx, but a near-universal aspect of Rust/C++ bindings. The solution is not, and never was, to give up and hand-write a bunch of `unsafe` blocks.
Instead, the solution is simply to ensure that auditors can easily locate generated `unsafe` blocks and the soundness assertions they represent. A typical solution here (also mentioned in that thread) is to add "unsafe" to the macro name or input. (Dtolnay already plans to do this for cxx.) Personally, I would argue that this is not even cxx's failing, but a tooling issue- if we're going to use macros to generate bindings, then our auditing tools should see through those macros.
- fluffything 6y ago> Using cxx does not, in fact, remove any `unsafe` blocks- thus it is not "lying," nor is it "the ultimate evil." (Such hyperbole makes productive discussion in this space rather difficult...) If I can write an unsound Rust program using autocxx or cxx safe Rust APIs, then these APIs are unsound. Whether these APIs are macros or function calls does not matter. There is no distinction at the API level about whether incorrect unsafe code is expanded, or called into. The API is safe, and for these crates, the currently-safe API introduces undefined behavior. cxx will be fixed to require unsafe, but AFAICT autocxx usecase is to satisfy Chromiums requirements which require completely avoiding unsafe.
- Rusky 6y agoThere is no such thing as a "safe macro" or an "unsafe macro," so you can't make the usual argument there. Macros (and other forms of code generation) all exist before and outside the "safety system," and so must be inspected in an audit regardless. Putting "unsafe" in the name or input of cxx/autocxx/etc. is a great tweak that improves local readability, but it's not a fundamental change. The actual generated wrapper functions would still be safe, after all. If you're generating `unsafe` blocks, good tooling will point them out to you just the same as if they were hand-written. Nobody is trying to sweep that responsibility under the rug- not cxx, not Chromium, not autocxx. That is, Chromium's requirement is notably not "completely avoiding unsafe." (This is another piece of hyperbole that derails productive discussion.) Their actual requirement is perfectly reasonable: restrict manual per-function unsafe to exceptional scenarios that deserve extra attention, above and beyond the usual check that a function is always safe to call with arguments that match its type. Updating autocxx to require surface-level `unsafe` in the same way as cxx does not conflict with this requirement. However, it's also relevant that autocxx is a) rather new, and b) not (yet?) an official Google project: https://github.com/google/autocxx#license-and-usage-notes https://github.com/google/autocxx#license-and-usage-notes. It would be unwise to blindly infer any sort of Chromium policy from it at this point, especially when they have just published a rather detailed document that contradicts your inference. Overall, the problem we should be trying to solve here is not simply "how do we prevent people from generating unsound code," but "how can we enable people to correctly bind to large C++ APIs?"
- fluffything 6y ago> There is no such thing as a "safe macro" or an "unsafe macro," so you can't make the usual argument there From all the soundness issues that have been filled on macros that were not safe in the past, the impression I have is that all exported Rust macros must be safe. > but "how can we enable people to correctly bind to large C++ APIs?" This is a solved problem: rust-bindgen, it correctly generates unsafe Rust FFI wrappers for all C++ code. What the Chromium devs actually want is what I pointed out in my root comment: to automatically generate correct soundness proofs for their C++ code / APIs, so that they can automatically generate safe Rust FFI wrappers for them. This is an unsolved problem, which is probably impossible to solve. So I think this is an absurd requirement from the part of the Chromium project, that deserves the absurd solution proposed by the `autocxx` crate, which is to just assume that these proofs exist. The disclaimer "You can only use `autocxx` on those APIs for which those proofs actually exist" isn't very reassuring TBH. They don't appear interested in finding out whether those proofs actually exist, so what's the point really. They will just start using Rust, continue getting CVEs because "oh, I guess we shouldn't have blidnly wrapped those thousands of APIs", and conclude that Rust isn't more secure than C++.