How memory safety CVEs differ between Rust and C/C++

Rust’s promise of memory safety compared with C and C++ is examined through real CVEs, undefined behavior pitfalls, and how each ecosystem treats “unsafe” code and API misuse. Commenters argue that Rust’s borrow checker and safety culture materially reduce whole classes of vulnerabilities, while critics highlight its complexity, inconsistent overflow behavior between debug and release, and growing supply‑chain risk from deep dependency trees. Others counter that “modern C++” with hardened libraries, sanitizers, and safer idioms can close much of the gap in theory, but note that large real‑world C/C++ codebases still routinely ship serious memory bugs, which is driving adoption of Rust in projects like Android and the Linux kernel.

Rust, undefined behavior, and unsafe

  • Some argue UB can occur in Rust without directly using unsafe in your crate: via no_std, language soundness holes, UB in dependencies or the standard library, or compiler/LLVM bugs.
  • Others emphasize Rust’s model: UB must originate in some unsafe somewhere (including in dependencies or std); the benefit is that unsafe is localized and reviewable.

Integer overflow semantics

  • Dispute over Rust’s “panic in debug, wrap in release” behavior.
  • Critics say having two behaviors makes overflow practically as unreliable as UB and wish overflow always panicked.
  • Others stress this is implementation-defined, not UB: behavior is bounded and configurable (overflow-checks = true), unlike C/C++ UB that can lead to extreme misoptimizations.

How to interpret Rust CVEs

  • Rust libraries tend to treat any misuse that can cause UB as a CVE, even if exploitation is unrealistic.
  • C/C++ ecosystems rarely classify such issues as CVEs, so raw “number of CVEs” is viewed as a misleading metric for language safety.
  • Some worry this could extend to panics being treated as DoS vulnerabilities; others see it as part of a culture that prioritizes correctness.

Prevalence and importance of memory safety bugs

  • One commenter claims memory bugs are a tiny fraction of “average” vulnerabilities; others dispute this and cite data (within the thread) that memory safety issues dominate high‑impact zero-days.
  • There’s debate whether porting broad codebases to Rust is over‑optimization versus justified for high‑value, heavily attacked software (browsers, OS components, Android).

Rust vs modern C++ safety strategies

  • One side argues modern C++ plus hardened libraries, sanitizers, and guidelines can largely solve memory bugs if used consistently.
  • Counterpoints:
    • In practice many large C/C++ codebases remain unsafe (Android, Chromium, system libraries).
    • Rust’s safety is the default; in C++ safety often requires opting in, careful discipline, and toolchains that teams frequently relax under delivery pressure.
    • Real‑world reports (e.g., Android) are cited as evidence Rust yields large reductions in memory vulnerabilities compared to legacy C/C++ code.

Nulls, assertions, and contracts

  • Discussion around functions like curl_getenv and whether to assert on null inputs.
  • Some advocate pervasive precondition checks; others argue that in C this becomes noisy and often devolves to “crash anyway on null deref.”
  • Rust’s Option<T> and non‑nullable references are contrasted: APIs must explicitly opt into None, and misuse leads to panics with clear backtraces rather than UB.

Performance and adoption trends

  • Examples like Ladybird’s HTML parser rewrite show Rust replacing C++ with equal or better performance.
  • Debate whether speed gains come from Rust itself or from redesign opportunities during rewrites.
  • C and C++ are seen as losing ground in some domains (browsers, kernels), though many domains (HPC, HFT, standards‑driven stacks) still revolve around C/C++.

Rust complexity and dependency concerns

  • Critics highlight Rust’s conceptual complexity (ownership, lifetimes, advanced types) and the effort spent shaping types to satisfy the borrow checker.
  • Supporters frame this as “making complexity explicit” instead of hiding it, yielding safer, more debuggable code.
  • There’s broad concern about large, deep dependency trees in Rust (thin stdlib, many crates, build.rs, GitHub‑tied publishing) and corresponding supply‑chain risk.
  • Defenders note that C/C++ often “solve” this by vendoring or copy‑pasting code, which obscures dependencies rather than eliminating them.