Safe from the Fundamentals – The Ethical Case for New Programming Languages

Abstract

Since their invention, C and C++ have dominated computer systems. However, their programmer-controlled memory management scheme has caused great damage globally. It is imperative to create a memory-safe online world. Possible solutions include transitioning to new languages like Rust and Cppfront and deploying external memory checkers like SafeOSL and Memsafe.

Introduction

Sixty years ago, renowned computer scientist Sir Tony Hoare called his creation of the null pointer a “billion-dollar mistake.” The null pointer is a component of almost all programs today [1]. Pointers are variables that hold a location address in computer storage. The null pointer allows programmers to assign nothing to a pointer, essentially leaving the location address blank. Issues arise when computer software attempts to process nothingness as actual values, costing billions of dollars worldwide [1]. Null pointer problems are a common, expensive subset of memory safety issues in languages like C and C++. They are responsible for up to 70% of all security bugs in global computer infrastructure [2][3][4]. Thus, despite the technical difficulties, C and C++ programmers must adopt safety alternatives for a secure online world.

Memory Safety as Real Safety

Despite the devastating consequences, programmers have always overlooked memory safety. For example, a memory safety flaw caused an acceleration incident in 2017, injuring driver Jean Bookout and killing passenger Barbara Schwarz in a 2005 Toyota Camry [5]. Such accidents are not uncommon. Since 2005, over a hundred Toyota cars have had unintended accelerations, causing hundreds of deaths and injuries. Investigations yielded memory safety issues as root causes [6].

After Jean Bookout’s incident, in the Bookout v. Toyota case, expert witness Michael Barr found Toyota’s software to have many memory-related safety issues, such as stack overflow and unsafe casting [6]. These issues accumulated, corrupting the memory of a variable that controls the throttle’s angle [5]. This memory corruption releases the brake for 3 seconds, turning off the throttle and sending the car into unintended, uncontrolled acceleration.

Analysis of Toyota’s code reveals many engineering standard violations. The IEEE and other engineering ethics codes call on engineers to ensure the safety of their work [7]. However, Toyota’s code was “of unreasonable quality”, with “spaghetti” code of 11,000 global variables, “untestable” functions, and “80,000 rule violations” [6]. Despite these issues, Toyota initially blamed the unintended accelerations on sliding floor mats or confused drivers, hiding the bugged monitor chip from NASA’s investigation [5]. 

Why C and C++

Issues like the Toyota accidents are caused by code written in unsafe languages like C and C++. Because they do not automatically check for memory issues, memory bugs tend to remain undetected. However, they remain an industry standard. Since 1972, computers have been built with C due to its high performance and low memory consumption [8]. C and C++ provide extensive low-level controls, such as memory management. This allows programs to reach the high speeds needed for hardware in performance-critical environments like spacecraft [2]. While other languages like Python and Java automatically check for memory issues, they do so with a garbage collector that runs in parallel with the program and slows it down significantly. Execution efficiency is often preferred in exchange for safety risks.

C and C++ are also attractive for their extensive frameworks and community support. Global projects dating back to 1972 have resulted in “a mature ecosystem of libraries and frameworks” [8]. As a result, programmers will likely find an easy solution to their problems in these libraries. Due to their widespread usage, C and C++ also have broad industry support; compilers (for converting the written code to machine code) are available for nearly all computer systems worldwide [8]. This mature ecosystem made C and C++ integral to computer systems. For instance, Google has “hundreds of millions of lines of C++ code” [4]. It would require insurmountable effort to transition to a new language. No suitable alternatives exist.

Alternatives – Rust, Carbon, Cppfront, and More

While replacing C and C++ seems infeasible, several development alternatives show great potential. Microsoft Azure CTO Mark Russinovich said, “The industry should declare those languages as deprecated” [9]. The computer industry should weigh the costs and benefits of alternative languages.

The use of C and C++ causes damage due to memory safety vulnerabilities. For instance, C’s buffer overflow memory bug allows hackers to inject their code into applications [10]. This bug caused viruses like the 4 billion dollar Code Red virus, as well as the internet crippling Nimda and SQL Slammer worms [1][11]. The buffer overflow bug alone caused up to 29% of vulnerabilities in 1978 [12]. Sir Tony Hoare theorized that “we might have had no malware” without these vulnerable memories in C [1]. The cost of keeping C is much higher than the cost of transitioning to a new language.

Rust

Rust is a programming language designed in 2015 to solve memory safety issues. It achieves memory safety comparable to high-level languages like Java and Python while maintaining the speed and memory efficiency of C and C++ [2]. It uses a powerful type system and a new memory management system called ownership. In the ownership system, only one variable can reference a shared computer memory at a time. These two systems ensure that the program’s pointer variables always point to valid memory [14]. These features made Rust “one of the most secure programming languages on the market today” [13] with C’s fast speed.

Unfortunately, the Rust compiler doesn’t give programmers complete memory control like C. They can opt out of its safety using the “unsafe” keyword, circumventing the compiler and writing unchecked memory code. The unsafe keyword appears in 19.11% of Rust’s packages (crates), subduing the safety features that initially made it superior to C++ [13]. 

Still, even in the unsafe mode, Rust maintains its safety standards. Most unsafe usage is used to integrate C++ code into Rust [13]. This means that unsafe is used for bridging external, hazardous code, not compromising native Rust’s safety guarantees. The integration also allows Rust to leverage existing C and C++ libraries to facilitate a successful transition [8]. Moreover, unsafe code in Rust bypasses safety checks and highlights a potential vulnerability, signaling programmers to review that code with extra care. While studies analyzing Rust did find bugs—one in the compiler, 33 in the standard library, 142 in third-party libraries, and 10 in executable programs—these issues only appear in sections with unsafe keywords and will not lead to real-world vulnerabilities [14]. All other code without the “unsafe” label is memory safe.

With a heavy focus on memory safety, Rust’s developer community is more involved in preventing memory risks [14]. This proactive culture motivates Rust’s members to solve memory-related issues.

Carbon and Cppfront

Replacing C++ with a language like Rust offers memory safety but requires massive effort. This barrier keeps programmers and companies in the comfort of C++. Iterations–modernizing C++ dialects–is an easier alternative. Old code need not be deleted; iterations allow intermixing existing code. Carbon and Cppfront are two such dialects meant to improve memory issues while effortlessly integrating with C++ [9]. 

Established in 2022 and 2021,  Carbon and Cppfront are still in early development [9]. Before they are established in the industry, more C/C++ memory bugs can appear and cause greater damage. This wait diminishes their advantage. Furthermore, Carbon and Cppfront do not guarantee complete memory safety like Rust [4]. While these C++ iterations address common memory vulnerabilities, they fail to resolve more intricate ones. For instance, they cannot solve lifetime bugs that occur when a program drops computer memory too early and turns it into garbage data before use, causing unpredictable effects. Although pure Carbon code is memory-safe, C++ code that is gradually intermixed with Carbon is unlikely to achieve complete memory safety [4]. Still, with their cost-effective method to transition large amounts of existing C++ code to new and safer versions, they are promising alternatives. 

External Memory Checking

Another solution is to use external toolboxes to find memory issues in existing C/C++ code. Valgrind, released in 2002, is a toolbox that helps engineers detect memory bugs in their C and C++ code. One of Valgrind’s tools is Memcheck, which scans the code’s manual memory management for possible errors [15]. However, many existing external toolboxes, such as model checking and type systems, are ineffective due to increased runtime and high false positive rates [16].

Several new external toolboxes are being developed to help programmers accurately identify C and C++ memory issues. For example, SafeOSL takes inspiration from Rust’s borrow checker [16]. It translates C code into a temporary intermediate, checking for memory safety using a borrow checking system. Early test results show that SafeOSL effectively finds errors and is adaptable to languages other than C and C++ [16]. Another toolbox is MemSafe, which attempts to find memory errors in running programs through code’s metadata and data flow representation [10]. When added to C code, MemSafe guarantees memory safety with better performance than existing solutions [10].

External toolboxes are the fastest and easiest way to make existing C code memory safe. Toolboxes like Valgrind are being used by many organizations, including NASA, Mozilla, and Python [15]. However, these external checks are optional and won’t force errors if memory bugs exist. Thus, if a programmer neglects their code’s safety, it will risk any other code that uses their code. Memory vulnerabilities will persist.

Ethical Path for the Future

Engineers must follow established codes of ethics to determine the correct future path for memory safety. The IEEE software engineering code states that Software Engineers should “approve software only if they have a well-founded belief that it is safe” [7]. Engineers should not approve software that is not guaranteed memory-safe. This practice requires running external software to check C and C++ code’s memory safety or transitioning to Rust or Cppfront to ensure further safety. Engineers are responsible for the safety of their code and should prevent the use and circulation of unsafe work. 

Situations of severe malpractice, such as the Toyota case, require whistleblowing. However, IEEE and ACM engineering ethics codes state that engineers should not go against their employer or client unless there is a higher ethical concern [7][17]. The engineer is forced to balance between their duty to the public and their loyalty to an employer. Whistleblowing is a complex ethical issue, requiring individuals to balance competing virtues such as loyalty, honesty, duty, and obligation [18]. The Ancient Greek concept of phronesis, or practical wisdom, represents how engineers should approach such virtue issues [19]. Engineers must discern when to whistleblow, what virtues to follow, and to what extent. Before resorting to whistleblowing, engineers are responsible for prioritizing safety in their work and alerting colleagues to any issues. If that fails, whistleblowing is necessary to prevent unsafe systems from causing real harm. In the Toyota case, engineers working on the project should have been honest and blown the whistle.

Virtue ethics can also guide the future of memory safety. The IEEE code of ethics states that software engineers should actively “improve their ability to create safe, reliable, and useful quality software” [7]. Software engineers are obligated to learn and improve constantly. Despite the effort required, transitioning from C to memory-safe options allows engineers to create safer software. A virtuous engineer must accept current costs for greater long-term safety and self-improvement.

By improving programs’ memory safety, engineers contribute to the worldwide common good. Weighing the labor required to ensure memory safety against the benefit to society can help evaluate if it’s worth switching from C and C++. For large corporations like Google, replacing millions of C and C++ code lines is a considerable task [4]. It would be a challenge for engineers, especially those accustomed to C. However, preventing memory bugs would facilitate a safe internet that benefits companies and individual users alike.

For the common good, migration to Rust is preferable over external measures for memory safety. The ACM code of ethics calls for computer scientists to “design and implement systems that are robustly and usably secure” [17]. Specifically, the document states that “security features should be designed to be as intuitive and easy to use as possible” [17]. However, due to their complexities, external solutions like Memsafe and SafeOSL do not satisfy this requirement. These external solutions also fail because of the free rider problem–they rely on voluntary, perfect diligence from every programmer. Inevitably, some individuals will skip costly manual effort while still benefiting from the collective security provided by others. Even if most engineers use external memory safety resources, a few programmers’ negligence can undermine the majority’s collective security efforts [20]. Since programmers distribute and use other code freely, a memory vulnerability in just one computer system can cascade into all systems that use the code. Therefore, it is better to address memory issues directly in programming languages. Memory safety should be mandatory, not just encouraged. 

Ethical frameworks such as utilitarianism, virtue ethics, and the common good can guide the development of memory safety solutions. On an individual level, engineers must ensure projects and employers maintain memory safety and good engineering practices while continuously improving their code. On a structural level, existing programming systems must be modified, migrating C and C++ to new programming language alternatives that are inherently safer. When engineers or companies start new projects, they must choose memory-safe languages to ensure safety by design, while securing existing projects through external toolboxes. The ethical path forward is to move from C/C++ to a safe language like Rust, using Carbon and Cppfront as intermediate steps.

By Stan Weerman, Viterbi School of Engineering, University of Southern California 


About the Author: Stan Weerman

At the time of writing this paper, Stan Weerman was a third-year computer science student at USC. He has made apps and games in several low-level languages and is interested in their fundamental workings.

References

[1] T. Hoare, “Null References: The Billion Dollar Mistake,” InfoQ, Aug. 25, 2009. https://www.infoq.com/presentations/Null-References-The-Billion-Dollar-Mistake-Tony-Hoare/ (accessed Oct. 14, 2024).

[2] “BACK TO THE BUILDING BLOCKS: A PATH TOWARD SECURE AND MEASURABLE SOFTWARE,” The White House, Washington, Feb. 2024. https://www.whitehouse.gov/wp-content/uploads/2024/02/Final-ONCD-Technical-Report.pdf (accessed Oct. 14, 2024).

[3] Catalin Cimpanu, “Microsoft: 70 percent of all security bugs are memory safety issues,” ZDNet, Feb. 11, 2019. https://www.zdnet.com/article/microsoft-70-percent-of-all-security-bugs-are-memory-safety-issues/ (accessed Oct. 14, 2024).

[4] A. Rebert and C. Kern, “Secure by design: Google’s perspective on memory safety,” Technical report, Google Security Engineering, 2024. https://storage.googleapis.com/gweb-research2023-media/pubtools/7665.pdf (accessed Oct. 14, 2024).

[5] K. Twyford, “Bookout v. Toyota Transcript,” District Court of Oklahoma County, Oklahoma, Oct. 2013. https://www.safetyresearch.net/Library/Bookout_v_Toyota_Barr_REDACTED.pdf (accessed Oct. 14, 2024).

[6] M. Dunn, “Toyota’s killer firmware: Bad design and its consequences – EDN,” EDN, Oct. 28, 2013. https://www.edn.com/toyotas-killer-firmware-bad-design-and-its-consequences/ (accessed Oct. 14, 2024).

[7] “Software engineering code of ethics and professional practice: IEEE-CS/ACM Joint Task Force on Software Engineering Ethics and Professional Practices,” Science and engineering ethics, vol. 7, no. 2, pp. 231–238, 2001, doi: 10.1007/s11948-001-0044-4. https://link-springer-com.libproxy2.usc.edu/content/pdf/10.1007/s11948-001-0044-4.pdf (accessed Oct. 14, 2024).

[8] C. Rohlf, “Memory Safety: An Explainer,” Center for Security and Emerging Technology, Sep. 25, 2023. https://cset.georgetown.edu/article/memory-safety-an-explainer/ (accessed Oct. 14, 2024).

[9] M. Heller, “Beyond C++: The promise of Rust, Carbon, and Cppfront,” InfoWorld.com, 2022. https://www.proquest.com/docview/2735904026 (accessed Oct. 14, 2024).

[10] M. S. Simpson and R. K. Barua, “MemSafe: ensuring the spatial and temporal memory safety of C at runtime,” Software, practice & experience, vol. 43, no. 1, pp. 93–128, 2013, doi: 10.1002/spe.2105.

https://onlinelibrary-wiley-com.libproxy2.usc.edu/doi/epdf/10.1002/spe.2105 (accessed Oct. 14, 2024).

[11] J. Kristoff, “Remembering SQL Slammer,” www.netscout.com, Jan. 27, 2023. https://www.netscout.com/blog/asert/remembering-sql-slammer (accessed Dec. 10, 2024).

[12] C. P. Meinel, “How Hackers Break In. . . and how they are Caught,” Scientific American, vol. 279, no. 4, pp. 98–105, Oct. 1998, https://www-jstor-org.libproxy1.usc.edu/stable/26057987?seq=1 (accessed Oct. 21, 2024).

[13] “Unsafe Rust in the Wild: Notes on the Current State of Unsafe Rust,” Rust Foundation, May 21, 2024. https://foundation.rust-lang.org/news/unsafe-rust-in-the-wild-notes-on-the-current-state-of-unsafe-rust/ (accessed Oct. 14, 2024).

[14] H. Xu, Z. Chen, M. Sun, Y. Zhou, and M. R. Lyu, “Memory-Safety Challenge Considered Solved? An In-Depth Study with All Rust CVEs,” ACM transactions on software engineering and methodology, vol. 31, no. 1, pp. 1–25, 2022, doi: 10.1145/3466642. 

[15]“Valgrind: Tool Suite,” valgrind.org, 2024. https://valgrind.org/info/tools.html (accessed Nov. 04, 2024).

[16] X. Yin et al., “SafeOSL: Ensuring memory safety of C via ownership‐based intermediate language,” Software, practice & experience, vol. 52, no. 5, pp. 1114–1142, 2022, doi: 10.1002/spe.3057. https://onlinelibrary-wiley-com.libproxy2.usc.edu/doi/epdf/10.1002/spe.3057 (accessed Oct. 14, 2024).

[17] “ACM code of ethics and professional conduct,” Computers & society, vol. 21, no. 2–4, pp. 6–7, 1991, doi: 10.1145/122652.122653. https://www.acm.org/binaries/content/assets/about/acm-code-of-ethics-and-professional-conduct.pdf (accessed Oct. 14, 2024).

[18] S. R. Paeth, “The Responsibility to Lie and the Obligation to Report: Bonhoeffer’s ‘What Does It Mean to Tell the Truth?’ And the Ethics of Whistleblowing,” Journal of business ethics, vol. 112, no. 4, pp. 559–566, 2013, doi: 10.1007/s10551-012-1557-2. https://link-springer-com.libproxy1.usc.edu/content/pdf/10.1007/s10551-012-1557-2.pdf (accessed Oct. 14, 2024).

[19] R. Hursthouse and G. Pettigrove, “Virtue Ethics,” Stanford Encyclopedia of Philosophy, Oct. 11, 2022. https://plato.stanford.edu/entries/ethics-virtue/ (accessed Nov. 10, 2024).

[20] R. Hardin, “The Free Rider Problem (Stanford Encyclopedia of Philosophy),” Stanford.edu, Oct. 13, 2020. https://plato.stanford.edu/entries/free-rider/ ‌(accessed Nov. 10, 2024).

Further Reading

https://cset.georgetown.edu/article/memory-safety-an-explainer/

https://foundation.rust-lang.org/news/unsafe-rust-in-the-wild-notes-on-the-current-state-of-unsafe-rust

https://storage.googleapis.com/gweb-research2023-media/pubtools/7665.pdf