TLDR: ACToR is an LLM agent-based system that translates C code to memory-safe Rust. Inspired by GANs, it uses a generator (translator) and a discriminator (test-finder) that iteratively improve the translation. The discriminator actively seeks out behavioral differences between the C and Rust code, feeding these ‘adversarial’ tests back to the translator for refinement. This approach successfully translates large C codebases (average 485 LoC) with over 90% test pass rate and zero human intervention, significantly outperforming previous non-adversarial methods.
Memory safety vulnerabilities in C and C++ code are a significant concern in the software industry, accounting for a large percentage of security issues annually. To address this, there’s a growing demand to translate legacy C code into modern, memory-safe languages like Rust. Rust is designed to prevent these critical vulnerabilities by ensuring memory safety at compile time, avoiding the runtime overhead often associated with C memory safety checks.
However, manually translating millions of lines of existing C code is a monumental and often impractical task. Automated translation approaches have emerged, broadly categorized into rule-based and LLM-assisted methods. Rule-based translators, while systematic, often produce Rust code that is not idiomatic or entirely safe. LLM-assisted translators, while capable of generating more idiomatic and safe Rust, have struggled to generalize to larger C projects (over 500 lines of code) and frequently require human intervention due to their reliance on complex program analyses that can break down.
Introducing ACToR: An Adversarial Approach to C to Rust Translation
A new research paper introduces ACToR (Adversarial C To Rust translator), a novel LLM agent-based approach designed to overcome the limitations of existing translation methods. Inspired by Generative Adversarial Networks (GANs), ACToR employs two collaborating AI agents: a generator agent (the ‘Translator’) and a discriminator agent (the ‘Discriminator’). These agents work together in an iterative process to refine and improve the Rust translation.
The core idea behind ACToR is a continuous feedback loop. In each iteration, the Translator agent synthesizes and refines a Rust translation, aiming to pass an existing suite of tests. Following this, the Discriminator agent steps in to find new failing tests, specifically looking for inputs where the translated Rust code behaves differently from the original C code. These newly discovered ‘adversarial’ test cases are then fed back to the Translator, which uses them to further refine its translation. This iterative process ensures that the Translator learns to produce Rust programs that are not only correct on initial tests but also robust against challenging, adversarial inputs.
How ACToR Works in Detail
ACToR begins with an initial translation by the Translator agent, ensuring it passes a set of seed tests. Then, the adversarial loop starts. The Discriminator agent, given the C code and the current Rust translation, generates new test cases. These tests are designed to be valid for the C program and, crucially, to expose mismatches between the C and Rust outputs. The Discriminator is prompted to retry until it finds such discriminating tests. Once found, these new tests are added to the growing test suite. The Translator agent then takes this updated, more challenging test set and works to improve the Rust translation until it passes all current tests. This cycle repeats for a fixed number of iterations, leading to a progressively more correct and robust translation.
To enhance the Discriminator’s ability to find subtle errors, ACToR also incorporates a fuzzing script. This fuzzer helps the Discriminator explore corner cases and accelerate the discovery of mismatches, making the overall translation process more effective.
Impressive Results and Scalability
ACToR was evaluated on two sets of benchmarks: a micro-benchmark of 6 C programs and a larger macro-benchmark of 57 real-world command-line utilities from BSDCoreUtils. These programs ranged from 7 to 5,469 lines of code, with an average size of 485 lines. The results were highly promising:
- ACToR successfully translated all 63 real-world command-line utilities.
- It achieved over a 90% test pass rate with zero human intervention, a significant advancement for C to Rust translation at this scale.
- Compared to baseline, non-adversarial approaches, ACToR improved translation correctness by up to 18.9%.
The adversarial design proved crucial. When compared against a ‘coverage baseline’ (where the discriminator only aimed to increase code coverage, not find mismatches), ACToR consistently outperformed, demonstrating that actively seeking behavioral differences is more effective than simply increasing test coverage for improving translation correctness. The inclusion of the fuzzing tool further strengthened ACToR’s ability to uncover challenging bugs.
Also Read:
- Enhancing Automated Program Repair with Intelligent Filtering Policies
- A-MemGuard: Securing AI Agent Memory Against Subtle Attacks
Conclusion
ACToR represents a significant step forward in automated C to Rust translation. By leveraging an adversarial collaboration between a translator and a discriminator agent, it produces functionally correct and memory-safe Rust code from large C programs with high accuracy and minimal human involvement. This approach holds immense potential for migrating legacy C codebases to safer, more modern programming environments. You can read the full research paper for more details here: ACToR Research Paper.


