Detecting Undefined Behavior in Rust with Miri in GitHub Actions
-- 720 WordsRust, CI/CD, Miri, GitHub Actions,
Miri is an interpreter for Rust’s mid-level intermediate representation (MIR), which allows for the detection of undefined behavior and other errors at compile time. Integrating Miri into Continuous Integration (CI) workflows can significantly improve the quality of a Rust codebase by catching errors early in the development process. This can be especially important if your codebase requires the use of unsafe blocks of Rust code which may prevent the Rust compiler from catching bugs that you would normally expect it to.
Warning
This post was drafted by GitHub Copilot Workspaces to experiment with its capabilities. I have reviewed it closely, but am not a Miri expert. In particular, the code examples for various bug types involve subtle use of Rust syntax and may not be entirely accurate.
Types of Errors Detected by Miri
You can find an extensive list of the kinds of errors that Miri can catch in miri’s test suite. Note that many of these examples do not compile, and are used only to explain the bug.
Out-of-Bounds Memory Accesses
Out-of-bounds memory accesses occur when a program tries to read or write memory outside the allocated range. This can lead to unpredictable behavior and security vulnerabilities.
Example
Use-After-Free
Use-after-free errors happen when a program continues to use a pointer after the memory it points to has been freed. This can lead to data corruption or the execution of arbitrary code.
Example
Invalid Use of Uninitialized Data
Using uninitialized data can lead to undefined behavior, as the contents of the uninitialized memory are unknown.
Example
Violation of Intrinsic Preconditions
Certain operations in Rust have preconditions that must be met. Violating these preconditions can cause undefined behavior.
Example
Not Sufficiently Aligned Memory Accesses and References
Memory alignment errors occur when a reference does not meet the alignment requirements for the type it points to.
Example
Violation of Basic Type Invariants
Rust’s type system has certain invariants that must be upheld. Violating these invariants can lead to undefined behavior.
Example
Memory Leaks
While not undefined behavior, memory leaks can lead to resource exhaustion and degraded performance.
Example
|
|
Setting Up GitHub Actions for Automatic PR Runs with Miri
To integrate Miri into your CI workflow with GitHub Actions, follow these steps:
- Create a new file in your repository under
.github/workflows/miri.yml
. - Add the following content to
miri.yml
:
|
|
- Commit and push the changes to your repository.
This GitHub Actions workflow will automatically run Miri on every push and pull request, helping to catch errors early and maintain high code quality.
Conclusion
Integrating Miri into CI workflows offers a powerful way to improve the quality of Rust codebases by detecting a wide range of errors. By setting up GitHub Actions for automatic PR runs with Miri, teams can ensure that their code is robust, safe, and free of common errors before merging changes.