View PDF Abstract:Rust is a modern systems programming language whose type system guarantees memory safety. For the sake of expressivity and performance it allows programmers to relax typing rules temporarily, using unsafe code blocks. Howe...
Rust is a modern systems programming language whose type system guarantees memory safety. For the sake of expressivity and performance it allows programmers to relax typing rules temporarily, using unsafe code blocks. However, in unsafe blocks, the burden of making sure that the code does not end up having undefined behaviour is on the programmer. Even most expert programmers make mistakes and a memory safety bug in an unsafe block renders all the type system guarantees void. To address this problem we are trying to verify soundness of Rust unsafe code applying our Modular Symbolic Execution algorithm. This text outlines our approach and the progress that has been made so far.
Logic in Computer Science
Nima Rahimi Foroushaani, Bart Jacobs
arXiv
2022-12-26
arXiv:2212.12976
Rust's memory safety guarantees, notably ownership and lifetime systems, have driven its widespread adoption. Concurrency bugs still occur in Rust programs, and existing detection approaches exhibit significant limitations: static analyzers suffer from context insensitivity and high false positives, while dynamic methods incur prohibitive runtime costs due to exponential path exploration. This paper presents a Petri net-based method for efficient, precise detection of Rust concurrency bugs. The method rests on three pillars: (1) A syntax-preserving program-to-Petri-net transformation tailored for target bug classes; (2) Semantics-preserving state compression via context-aware slicing; (3) Bug detection through efficient Petri net reachability analysis.
The core innovation is its rigorous, control-flow-driven modeling of Rust's ownership semantics and synchronization primitives within the Petri net structure, with data operations represented as token movements. Integrated pointer analysis automates alias identification during transformation. Experiments on standard Rust concurrency benchmarks demonstrate that our method outperforms the state-of-the-art methods LockBud and Miri that are both tools of detecting concurrency bugs of Rust programs. Compared to LockBud, our approach reduces false positives by 35.7\% and false negatives by 28.3\% , which is obtained through our precise flow-sensitive pointer analysis. Compared with Miri that is a dynamic analysis tool, although Miri can obtain the same detection results, our method achieves 100% faster verification speed since our method takes a state reduce algorithm.
Programming Languages
Kaiwen Zhang, Guanjun Liu
arXiv
2022-12-06
arXiv:2212.02754
Title:Static Information Flow Control Made Simpler View PDF Abstract:Static information flow control (IFC) systems provide the ability to restrict data flows within a program, enabling vulnerable functionality or confidential data to be sta...
View PDF Abstract:Memory-safety bugs introduce critical software-security issues. Rust provides memory-safe mechanisms to avoid memory-safety bugs in programming, while still allowing unsafe escape hatches via unsafe code. However, the unsa...
Memory-safety bugs introduce critical software-security issues. Rust provides memory-safe mechanisms to avoid memory-safety bugs in programming, while still allowing unsafe escape hatches via unsafe code. However, the unsafe code that enhances the usability of Rust provides clear spots for finding memory-safety bugs in Rust source code. In this paper, we claim that these unsafe spots can still be identifiable in Rust binary code via machine learning and be leveraged for finding memory-safety bugs. To support our claim, we propose the tool textttrustspot, that enables reverse engineering to learn an unsafe classifier that proposes a list of functions in Rust binaries for downstream analysis. We empirically show that the function proposals by textttrustspot can recall $92.92\%$ of memory-safety bugs, while it covers only $16.79\%$ of the entire binary code. As an application, we demonstrate that the function proposals are used in targeted fuzzing on Rust packages, which contribute to reducing the fuzzing time compared to non-targeted fuzzing.
Cryptography and Security
Sangdon Park, Xiang Cheng, Taesoo Kim
arXiv
2022-10-31
arXiv:2211.00111
Rust, as an emerging system programming language, introduces $\texttt{unsafe}$ to allow developers to bypass safety checks during compilation. As a result, memory safety bugs are typically confined to the $\texttt{unsafe}$ regions, which have been the primary focus of Rust bug-finding tools. However, such tools rely on the presence of the $\texttt{unsafe}$ keyword in Rust source code; there are no tools available that can examine Rust binaries to pinpoint $\texttt{unsafe}$ areas. Therefore, we propose $\texttt{Ruby}$, the first tool that unmasks $\texttt{unsafe}$ regions in Rust binaries using machine learning. By capturing the subtle differences in the binary instructions, $\texttt{Ruby}$ can identify 91.75% of the total $\texttt{unsafe}$ regions with a false positive rate of 6.16%, beating SOTA LLM models including GPT-5.2, Claude-4.5 and Gemini-3. We further applied $\texttt{Ruby}$ to guide symbolic execution and fuzzing, showing a speed-up of 57.95% and 21.26%, with five bugs confirmed and patched by Google in Android library fuzzing.
Cryptography and Security
Xiang Cheng, Sangdon Park, HyungSeok Han et al.
arXiv
2022-10-31
arXiv:2211.00111
Rust is a relatively new system programming language that has been experiencing a rapid adoption in the past 10 years. Rust incorporates a memory ownership model enforced at a compile time. Since this model involves zero runtime overhead, programs written in Rust are not only memory-safe but also fast, leading to performance comparable to C and C++. Multiple existing benchmarks comparing the performance of Rust with other languages focus on rarely used superficial algorithms, leading to somewhat inconclusive results. In this work, we conduct a comparative performance benchmark of Rust and C++ using commonly used algorithms and data structures rather than exotic ones. Our evaluation shows that the overall performance of Rust is similar to C++, with only minor disadvantage. We also demonstrate that in some Rust routines are slightly faster than the ones of C++.
Programming Languages
Nikolay Ivanov
arXiv
2022-09-19
arXiv:2209.09127
We provide three detailed case studies of vulnerabilities in smart contracts, and show how property-based testing would have found them:
1. the Dexter1 token exchange;
2. the iToken;
3. the ICO of Brave's BAT token.
The last example is, in fact, new, and was missed in the auditing process. We have implemented this testing in ConCert, a general executable model/specification of smart contract execution in the Coq proof assistant. ConCert contracts can be used to generate verified smart contracts in Tezos' LIGO and Concordium's rust language. We thus show the effectiveness of combining formal verification and property-based testing of smart contracts.
Logic in Computer Science
Mikkel Milo, Eske Hoy Nielsen, Danil Annenkov et al.
arXiv
2022-08-01
arXiv:2208.00758
Title:Flux: Liquid Types for Rust View PDF Abstract:We introduce Flux, which shows how logical refinements can work hand in glove with Rust's ownership mechanisms to yield ergonomic type-based verification of low-level pointer manipulating...
We introduce Flux, which shows how logical refinements can work hand in glove with Rust's ownership mechanisms to yield ergonomic type-based verification of low-level pointer manipulating programs. First, we design a novel refined type system for Rust that indexes mutable locations, with pure (immutable) values that can appear in refinements, and then exploits Rust's ownership mechanisms to abstract sub-structural reasoning about locations within Rust's polymorphic type constructors, while supporting strong updates. We formalize the crucial dependency upon Rust's strong aliasing guarantees by exploiting the stacked borrows aliasing model to prove that ``well-borrowed evaluations of well-typed programs do not get stuck''. Second, we implement our type system in Flux, a plug-in to the Rust compiler that exploits the factoring of complex invariants into types and refinements to efficiently synthesize loop annotations -- including complex quantified invariants describing the contents of containers -- via liquid inference. Third, we evaluate Flux with a benchmark suite of vector manipulating programs and parts of a previously verified secure sandboxing library to demonstrate the advantages of refinement types over program logics as implemented in the state-of-the-art Prusti verifier. While Prusti's more expressive program logic can, in general, verify deep functional correctness specifications, for the lightweight but ubiquitous and important verification use-cases covered by our benchmarks, liquid typing makes verification ergonomic by slashing specification lines by a factor of two, verification time by an order of magnitude, and annotation overhead from up to 24% of code size (average 9%) to nothing at all.
Programming Languages
Nico Lehmann, Adam Geller, Niki Vazou et al.
arXiv
2022-07-08
arXiv:2207.04034
In this paper, we leverage low-level compiler intermediate representations (IR) to improve code translation. Traditional transpilers rely on syntactic information and handcrafted rules, which limits their applicability and produces unnatural-looking code. Applying neural machine translation (NMT) approaches to code has successfully broadened the set of programs on which one can get a natural-looking translation. However, they treat the code as sequences of text tokens, and still do not differentiate well enough between similar pieces of code which have different semantics in different languages. The consequence is low quality translation, reducing the practicality of NMT, and stressing the need for an approach significantly increasing its accuracy. Here we propose to augment code translation with IRs, specifically LLVM IR, with results on the C++, Java, Rust, and Go languages. Our method improves upon the state of the art for unsupervised code translation, increasing the number of correct translations by 11% on average, and up to 79% for the Java -> Rust pair with greedy decoding. We extend previous test sets for code translation, by adding hundreds of Go and Rust functions. Additionally, we train models with high performance on the problem of IR decompilation, generating programming source code from IR, and study using IRs as intermediary pivot for translation.
Programming Languages
Marc Szafraniec, Baptiste Roziere, Hugh Leather et al.
arXiv
2022-06-30
arXiv:2207.03578
View PDF Abstract:We present Aeneas, a new verification toolchain for Rust programs based on a lightweight functional translation. We leverage Rust's rich region-based type system to eliminate memory reasoning for many Rust programs, as lon...
As modern software extensively uses free open source packages as dependencies, developers have to regularly pull in new third-party code through frequent updates. However, without a proper review of every incoming change, vulnerable and malicious code can sneak into the codebase through these dependencies. The goal of this study is to aid developers in securely accepting dependency updates by measuring if the code changes in an update have passed through a code review process. We implement Depdive, an update audit tool for packages in Crates.io, npm, PyPI, and RubyGems registry. Depdive first (i) identifies the files and the code changes in an update that cannot be traced back to the package's source repository, i.e., \textit{phantom artifacts}; and then (ii) measures what portion of changes in the update, excluding the phantom artifacts, has passed through a code review process, i.e., \textit{code review coverage}.
Using Depdive, we present an empirical study across the latest ten updates of the most downloaded 1000 packages in each of the four registries. We further evaluated our results through a maintainer agreement survey. We find the updates are typically only partially code-reviewed (52.5\% of the time). Further, only 9.0\% of the packages had all their updates in our data set fully code-reviewed, indicating that even the most used packages can introduce non-reviewed code in the software supply chain. We also observe that updates either tend to have high \textit{CRC} or low \textit{CRC}, suggesting that packages at the opposite end of the spectrum may require a separate set of treatments.
Software Engineering
Nasif Imtiaz, Laurie Williams
arXiv
2022-06-19
arXiv:2206.09422
We present Aeneas, a new verification toolchain for Rust programs based on a lightweight functional translation. We leverage Rust's rich region-based type system to eliminate memory reasoning for many Rust programs, as long as they do not rely on interior mutability or unsafe code. Doing so, we relieve the proof engineer of the burden of memory-based reasoning, allowing them to instead focus on functional properties of their code.
Our first contribution is a new approach to borrows and controlled aliasing. We propose a pure, functional semantics for LLBC, a Low-Level Borrow Calculus that captures a large subset of Rust programs. Our semantics is value-based, meaning there is no notion of memory, addresses or pointer arithmetic. Our semantics is also ownership-centric, meaning that we enforce soundness of borrows via a semantic criterion based on loans rather than through a syntactic type-based lifetime discipline. We claim that our semantics captures the essence of the borrow mechanism rather than its current implementation in the Rust compiler.
Our second contribution is a translation from LLBC to a pure lambda-calculus. This allows the user to reason about the original Rust program through the theorem prover of their choice. To deal with the well-known technical difficulty of terminating a borrow, we rely on a novel approach, in which we approximate the borrow graph in the presence of function calls. This in turn allows us to perform the translation using a new technical device called backward functions.
We implement our toolchain in a mixture of Rust and OCaml. Our evaluation shows significant gains of verification productivity for the programmer.
Rust goes to great lengths to enforce static control of aliasing; the proof engineer should not waste any time on memory reasoning when so much already comes "for free"!
Programming Languages
Son Ho, Jonathan Protzenko
arXiv
2022-06-14
arXiv:2206.07185
Rust is a young programming language gaining increased attention from software developers since it was introduced to the world by Mozilla in 2010. In this study, we attempt to answer several research questions. Does Rust deserve such increased attention? What is there in Rust that is attracting programmers to this new language? Safety and performance were among the very first promises of Rust, as was claimed by its early developers. Is Rust a safe language with high performance? Have these claims been achieved? To answer these questions, we surveyed and analyzed recent research on Rust and research that benchmarks Rust with other available prominent programming languages. The results show that Rust deserves the increased interest by programmers, and recent experimental results in benchmarking research show Rust's overall superiority over other well-established languages in terms of performance, safety, and security. Even though this study was not comprehensive (and more work must be done in this area), it informs the programming and research communities on the promising features of Rust as the language of choice for the future.
Programming Languages
William Bugden, Ayman Alahmar
arXiv
2022-06-11
arXiv:2206.05503
Authors:Gianluca Scopelliti (1 and 2), Sepideh Pouyanrad (2), Job Noorman (2), Fritz Alder (2), Christoph Baumann (1), Frank Piessens (2), Jan Tobias Mühlberg (2 and 3) ((1) Ericsson AB, Sweden, (2) KU Leuven, Belgium, (3) Université Libre...
View PDF Abstract:The Rust programming language has garnered significant interest and use as a modern, type-safe, memory-safe, and potentially formally analyzable programming language. Our interest in Rust stems from its potential as a hard...
The Rust programming language has garnered significant interest and use as a modern, type-safe, memory-safe, and potentially formally analyzable programming language. Our interest in Rust stems from its potential as a hardware/software co-assurance language, with application to critical systems such as autonomous vehicles. We report on the first known use of Rust as a High-Level Synthesis (HLS) language. Most incumbent HLS languages are a subset of C. A Rust-based HLS brings a single modern, type-safe, and memory-safe expression language for both hardware and software realizations with high assurance. As a a study of the suitability of Rust as an HLS, we have crafted a Rust subset, inspired by Russinoff's Restricted Algorithmic C (RAC), which we have imaginatively named Restricted Algorithmic Rust, or RAR. In our first implementation of a RAR toolchain, we simply transpile the RAR source into RAC. By so doing, we leverage a number of existing hardware/software co-assurance tools with a minimum investment of time and effort. In this paper, we describe the RAR Rust subset, detail our prototype RAR toolchain, and describe the implementation and verification of several representative algorithms and data structures written in RAR, with proofs of correctness conducted using the ACL2 theorem prover.
Logic in Computer Science
David Hardin
arXiv
2022-05-24
arXiv:2205.11709
Context: Container data types are ubiquitous in computer programming, enabling developers to efficiently store and process collections of data with an easy-to-use programming interface. Many programming languages offer a variety of container implementations in their standard libraries based on data structures offering different capabilities and performance characteristics.
Inquiry: Choosing the *best* container for an application is not always straightforward, as performance characteristics can change drastically in different scenarios, and as real-world performance is not always correlated to theoretical complexity.
Approach: We present Primrose, a language-agnostic tool for selecting the best performing valid container implementation from a set of container data types that satisfy *properties* given by application developers. Primrose automatically selects the set of valid container implementations for which the *library specifications*, written by the developers of container libraries, satisfies the specified properties. Finally, Primrose ranks the valid library implementations based on their runtime performance.
Knowledge: With Primrose, application developers can specify the expected behaviour of a container as a type refinement with *semantic properties*, e.g., if the container should only contain unique values (such as a `set`) or should satisfy the LIFO property of a `stack`. Semantic properties nicely complement *syntactic properties* (i.e., traits, interfaces, or type classes), together allowing developers to specify a container's programming interface *and* behaviour without committing to a concrete implementation.
Grounding: We present our prototype implementation of Primrose that preprocesses annotated Rust code, selects valid container implementations and ranks them on their performance. The design of Primrose is, however, language-agnostic, and is easy to integrate into other programming languages that support container data types and traits, interfaces, or type classes. Our implementation encodes properties and library specifications into verification conditions in Rosette, an interface for SMT solvers, which determines the set of valid container implementations. We evaluate Primrose by specifying several container implementations, and measuring the time taken to select valid implementations for various combinations of properties with the solver. We automatically validate that container implementations conform to their library specifications via property-based testing.
Importance: This work provides a novel approach to bring abstract modelling and specification of container types directly into the programmer's workflow. Instead of selecting concrete container implementations, application programmers can now work on the level of specification, merely stating the behaviours they require from their container types, and the best implementation can be selected automatically.
Programming Languages
Xueying Qin, Liam O'Connor, Michel Steuwer
arXiv
2022-05-19
arXiv:2205.09655