The young programming language Rust can do anything C and C++ can, so what is the difference? Rust guarantees protection against a large number of memory problems. Rust therefore solves a problem with which programmers have been struggling for decades.
Article from Objective 29, 2018
Von Neumann and memory management
The basis for computers and computer programs is the Von Neumann model which is over seventy years old. This architecture has one memory that holds both the instructions as well as program data. Programmers must thus always spend a lot of time on the memory management of their code.
The commonly used programming languages C and C++ offer no support for automatic memory management. The programmer must deal with this himself. An error is easily made. When the programmer reserves a hundred memory locations and the program writes something to location 101, we call it a 'buffer overflow'.
During a buffer overflow, it is often unclear what is going on at that particular moment. The best case scenario is that a piece of memory is being written that was not being used anyway. But the consequences could be much bigger. What if a crucial piece of data, a password for instance, is being overwritten or deleted? Will the deleted data be read by a different application down the line or by the operating system? In that case, sensitive information can end up in the wrong place. Whatever happens, it will occur outside the programmer's control.
Buffer overruns – Heartbleed
Buffer overruns are the cause of many computer problems, such as crashing and vulnerability in terms of attacks. The past years have revealed multiple exploits: vulnerabilities that are the result of these types of errors and which could have significant consequences.
Recently, a vulnerability was discovered that became known as Heartbleed. The total costs for a world-wide update of the systems is estimated at a minimum of five hundred million dollars. The error was included in a component, OpenSSL, that is being used, among other things, in network routers and webservers. This vulnerability allowed encryption keys to be read remotely from these systems. With captured encryption keys, an attacker can read traffic from and to the systems and pretend to be the original owner of the key. When the key of a bank's webserver is discovered, an attacker can pretend to be the webserver of the bank without the user being able to tell the difference in their browser. This vulnerability would not have occurred if OpenSSL had been written in Rust.
The Von Neumann model
Secure programming in Rust
Rust is a relatively new programming language. Like C and C++, it is a system language that is suitable to construct system software, such as operating systems, drivers and compilers. Rust programs compile directly to machine code, enabling the executables to remain small and making maximum performance achievable.
There is one thing that sets Rust apart from most of the other mainstream languages: when it comes to memory management, Rust is very strict. It is an automatic process. Even during compilation, the Borrow Checker (see frame) is checking the memory management. Does the program code run the risk of memory problems during runtime? Borrow Checker will then abort the compilation. The same happens when the code causes data races: parallel processes that access the same memory location simultaneously. Secure programming is thus enforced. For hardcore programmers, programming with Rust is therefore an entirely new experience, despite the similarities to C and C++. They need to get used to the strict Borrow Checker.
Rust is not the only language that offers a solution for memory management. A language like Java does the same but during runtime which results in serious consequences for the performance. A significant disadvantage when software needs to respond as quickly as possible, for instance in medical or industrial applications. Rust does not have this disadvantage. It is also possible to program unsecured in Rust, but this can only be done when the programmer explicitly chooses to do so.
Borrow Checker – automatic memory management
The secret to Rust's automatic memory management, without loss of performance, lies within the Borrow Checker. This bit of software, which is part of the compiler, carefully records how the programmer is using the data in the computer's memory. The Borrow Checker refuses to translate the program code into an executable file when it includes memory errors. The Borrow Checker detects many common errors such as double free, null pointer access, dangling pointer, uninitialized read and data races. Rust can also make sure that the memory is released at exactly the right moment.
The clients' interests
Technolution uses various programming languages and chooses the one that is most suitable for the solution. Most of our clients do not have a preference when it comes to language. They are mostly interested in the finished product and expect an application that is powerful, can be maintained well and does what it is expected to do. The selection of the underlying technology is generally left up to us. The decision regarding which language to use is therefore often made by us.
When do we decide to use Rust? This strongly depends on the context. Various questions play crucial roles. What are the security demands? How important is high performance? Rust and the corresponding ecosystem are still in the developing phase, but the language will certainly be considered for the development of new applications that require high performance, robustness and protection against exploits. The interests of the client are, obviously, the deciding factor amongst these deliberations.
Ecosystem and community
Compared to other programming languages, Rust is still very young. The language started out as a private project of a Mozilla employee; Mozilla being the manufacturers of the open source Internet browser Firefox. Mozilla published the first stable version in 2015. Just for comparison: Java dates from 1996 and the first version of C hit the market in 1972. New programming languages become available on an almost daily basis. Most of these are quick to disappear and fade into oblivion. It takes time for a new language to gain enough credit amongst developers and become a fixture. Nevertheless, there are enough reasons to have faith in Rust's future.
What makes a programming language stand out? And when is a language labeled 'successful'? Firstly, it is important that the language has a proper syntax and can be easily read. Performance is also crucial in many fields of application, just like support for data structures and various operating systems. Rust meets all of these demands. However, a good programming language is not the same as a successful programming language.
In order to be successful in the world of developers it is especially important that a programming language comes with an extensive ecosystem and a strong community. Java is a good example of a language that made it big due to a proper ecosystem with many libraries, supported by a lively and well-organized community. The community is also one of Rust's strong points.
Mozilla has an excellent reputation when it comes to supporting open source. Their Firefox browser has a large community that actively contributes to the safety of the browser, the development of new features and solving bugs. From the very beginning of Rust, Mozilla opted for an insightful update scheme, a flexible and elaborate support for libraries, and a powerful and quickly increasing community. A developer that starts to use Rust will find that excellent documentation is already waiting, a large set of ready-to-go libraries is available and there are many others at hand to help whenever questions or problems occur.
Technolution and Rust
Our introduction to Rust took place in a typical Technolution manner. Most of Technolution's developers have experience with multiple programming languages. One of them needed a well performing language for the development of a videowall application. Java did not offer the desired performance and it had been a long time ago since our colleague had used programming language C. He therefore decided to go with Rust and was pleasantly surprised by the stability, the ecosystem and the ease with which he could work productively in Rust. Other colleagues were soon infected by his enthusiasm. This was enough incentive for us to further explore Rust.
A year has passed since. Rust has proven itself in various projects. The language has gained a lot of momentum and we have started organizing internal and public workshops for developers. The reactions have been promising. There is a lot of interest, both within as well as outside of Technolution.
Trust and investment
We have faith in Rust and are therefore contributing to the Rust community. We are actively involved in several Rust user groups in the Netherlands. We are also working on increasing the applicability of Rust from a content perspective. In a collaboration with the TU Delft, we are, for example, developing a tool that should recognize all possible error conditions in software that have been written in Rust and perform corrective actions accordingly. The software will no longer collapse and is thus continuously available to execute the required functionality.
In addition, we are also looking into the possibilities for the use of Rust in the open source processor architecture RISC-V. This is currently entirely coded in C. Rust compiles to a native executable in machine code, offers automatic memory management and is therefore particularly suitable for this application. Obviously, we also take any disadvantages into account. Is it even possible with Rust? Are there any consequences regarding performance? What limitations do we encounter? We use a softcore version of RISC-V in our security platform JelloPrime which creates quick secured connections based on encryption that is embedded in electronics. We aim for maximum security and believe that Rust can contribute to it.