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

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.