From Raw Pointers to Memory Safety: A Modular Demand-Driven Typestate Analysis for Rust
Rust combines high performance with strong memory safety through strict ownership and borrowing rules. However, its unsafe mode reintroduces vulnerabilities by allowing raw-pointer manipulation—a major source of memory-safety bugs. Existing whole-program analyses for Rust often suffer from low recall and high false positives. Since unsafe code is typically small and isolated, we propose a demand-driven alternative. We present Pincer, a flow-, field-, and context-sensitive dataflow analysis framework built on IFDS. Pincer performs mutually bidirectional analysis—backward to trace raw-pointer origins and forward to explore their aliases—adapting this strategy to Rust’s ownership model and low-level semantics. On this foundation, Pincer performs a modular, bottom-up vulnerability-oriented typestate analysis to detect use-after-free and double-free bugs. It tracks aliases and nullness states of raw pointers while exploiting new strong-update opportunities at function returns of container-manipulating calls and leveraging Rust’s safety invariants to prune safe regions early through aliasing XOR mutability checking. The modular design enables controlled exploration—optionally under a budget—to improve scalability. Controlled unsoundness further boosts efficiency while maintaining high recall and precision. We evaluate Pincer on vulnerable programs and large Rust projects. The results demonstrate that Pincer detects memory-safety errors with higher accuracy than state-of-the-art analyses while offering practical efficiency, confirming its effectiveness in securing Rust’s unsafe code.