Rust is promising for addressing memory safety issues. Improving existing C/C++ toolchains will take time, but these steps help set a realistic path forward.
December 9, 2024
Rust offers powerful tools for addressing memory safety issues, but rewriting all C and C++ applications in Rust isn’t feasible due to the sheer volume of legacy code and the challenges of reimplementation. Instead, improving existing C/C++ toolchains and retrofitting secure practices can make current codebases safer. Developers should choose memory-safe languages like Rust for new projects and adopt modular migration strategies for existing software. Achieving widespread memory safety will take time, with significant progress likely decades away, but these steps help set a realistic path forward.
RIIR — “rewrite it in Rust” — is a common refrain for addressing memory safety issues in C and C++ applications. Like many other pithy sayings, it’s not exactly wrong, but it doesn’t tell the whole story. The “Product Security Bad Practices” report issued by the U.S. Cybersecurity & Infrastructure Security Agency (CISA) calls for building software in a way that avoids introducing memory safety vulnerabilities. This makes sense: the best way to address a vulnerability is to not introduce it in the first place.
C and C++ are two of the top five languages in the November 2024 TIOBE Index, a measure of programming language popularity. Unfortunately, they also have no default protections against memory safety errors. The combination of popularity and unsafety is bad for software security. Rust has gone from 20th in the November 2023 TIOBE index to 14th in November 2024. The Linux Foundation’s Census III of Free and Open Source Software reported a 500% in Rust components compared to the 2022 Census II. Developers are clearly paying attention to memory safety and writing more Rust code in order to avoid introducing memory safety vulnerabilities.
You might interpret this as “take all projects written in C and C++ and rewrite them in Rust.” Mike loves Rust, but that’s not the answer. Any other considerations aside, the sheer volume of C/C++ code is huge. The amount of developer time that would be spent converting the code would be significant on its own. And anyone who has ever rewritten an application or library knows that the process often introduces as many bugs as it fixes. As an example, the gitoxide project is reimplementing git in Rust. The project is still working toward feature parity. We don’t doubt that it will get there, but these things take years. Now imagine that for the Linux kernel, Apache HTTPD, and countless other code bases large and small.
So if we can’t simply rewrite it in Rust, what can we do? Well, there’s been a lot of work in improving toolchains so that C and C++ can be more memory safe. Sean Baxter wrote the Circle compiler to do things like borrow checks for C++ code which improves memory at compile time. Improvements like that to the toolchain can improve the safety of binaries without changing the code itself. Google researchers have recently shared work that shows the ability to retrofit secure design approaches to C/C++ code bases without incurring a significant performance penalty. As the industry pays more attention to memory safety, work will continue toward reducing the risk for existing code bases.
Another issue is that Rust’s compile times are often significantly longer for large code bases than in languages like Go or Zig. This often means longer iteration loops when developing software, however the tradeoff might be worth it because Rust’s compile time checks can catch many bugs during compilation instead of during runtime. Would it be faster to write tests for the issues that Rust avoids — and other potential issues — than to iterate in Rust? It depends on your use case. If we’re writing something that requires a high level of safety and security, the answer is often Rust. However, you might write something you need to quickly prototype or with more relaxed safety and security requirements in another language.
Notes: be clearer on the tradeoffs. Iteration time versus safety. If it’s a safety-critical application, you might want to use Rust but if rapid iteration is more important, you might want to pick something like Go.
C and C++ won’t disappear on January 1, 2026. Fortran and COBOL are over 60 years old and are still used in some places. Do we think that new projects should be written in C/C++? No. Write new projects in Rust or another language that meets your business and security needs. Modularly-developed projects can shift to Rust piecemeal. This won’t happen overnight.
Software vendors are asked to provide a roadmap to memory safety by January 1, 2026. But that requirement is unclear. Roadmaps aren’t guarantees, they’re estimates. Software vendors will put dates far beyond 2026 in the roadmap because, as we discussed above, this work is hard. It’s likely that achieving a majority of code being memory-safe will happen closer to 2036.
CISA’s report gets the ball rolling. Now that we’re having the conversation, we can work toward the goal of eliminating memory safety vulnerabilities.
No older posts
No newer posts