ENCRUST: Encapsulated Substitution and Agentic Refinement on a Live Scaffold for Safe C-to-Rust Translation
Organizations: Korea University, South Korea · University of Houston, United States · State University of New York Korea, South Korea · Virginia Tech, United States
Abstract
We present Encapsulated Substitution and Agentic Refinement on a Live Scaffold for Safe C-to-Rust Translation, a two-phase pipeline for translating real-world C projects to safe Rust. Existing approaches either produce unsafe output without memory-safety guarantees or translate functions in isolation, failing to detect cross-unit type mismatches or handle unsafe constructs requiring whole-program reasoning. Furthermore, function-level LLM pipelines require coordinated caller updates when type signatures change, while project-scale systems often fail to produce compilable output under real-world dependency complexity. Encrust addresses these limitations by decoupling boundary adaptation from function logic via an Application Binary Interface (ABI)-preserving wrapper pattern and validating each intermediate state against the integrated codebase. Phase 1 (Encapsulated Substitution) translates each function using an ABI-preserving wrapper that splits it into two components: a caller-transparent shim retaining the original raw-pointer signature, and a safe inner function targeted by the LLM with a clean, scope-limited prompt. This enables independent per-function type changes with automatic rollback on failure, without coordinated caller updates. A deterministic, type-directed wrapper elimination pass then removes wrappers after successful translation. Phase 2 (Agentic Refinement) resolves unsafe constructs beyond per-function scope, including static mut globals, skipped wrapper pairs, and failed translations, using an LLM agent operating on the whole codebase under a baseline-aware verification gate. We evaluate Encrust on 7 GNU Coreutils programs and 8 libraries from the Laertes benchmark, showing substantial unsafe-construct reduction across all 15 programs while maintaining full test-vector correctness.
Figures & tables
| Category | Tool | Description |
| Navigation | grep | Regex search across the workspace; returns matching file:line pairs with surrounding context |
| read_file | Read file contents with an optional start/end line range | |
| read_function | Extract a complete function body by brace-depth counting | |
| get_function_signatures | List all function signatures declared in a given file | |
| list_files | Enumerate all .rs source files in the workspace | |
| Modification | replace | Exact-match replacement of a unique string in a single file |
| Program | LoC | Functions | Covered | Test scripts |
| split | 13,848 | 207 | 73 | 12 |
| pwd | 5,859 | 127 | 16 | 2 |
| cat | 7,460 | 166 | 37 | 4 |
| truncate | 7,181 | 124 | 33 | 8 |
| uniq | 8,299 | 167 | 34 | 3 |
| tail | 14,423 | 266 | 76 | 30 |
| Library | LoC | Functions | Covered | Test inputs |
| tulipindicators | 12,565 | 270 | 211 | 1,000 |
| optipng | 106,123 | 495 | 224 | 1,000 |
| bzip2 | 4,417 | 65 | 31 | 1,000 |
| snudown | 5,426 | 140 | 72 | 1,000 |
| lil | 3,565 | 148 | 72 | 1,000 |
| genann | 410 | 13 | 7 | 1,000 |
| Program | System | Ptr.Decl | Ptr.Deref | Unsafe LoC | Unsafe Cast | Unsafe Call | Comp.Rate | Correct. | Clippy |
| cat | C2Rust | 192 | 317 | 5,625 | 3,116 | 1,038 | N/A | 100% | 546 |
| C2SaferRust | 120 | 240 | 4,189 | 1,992 | 912 | 75.3% | 100% | 239 | |
| EvoC2Rust | 81 | 231 | 2,338 | 1,082 | 525 | 64% | 0% | N/A | |
| Encrust | 95 | 170 | 3,407 | 1,463 | 1,076 | 95.8% | 100% | 211 | |
| head | C2Rust | 192 | 442 | 6,245 | 3,488 | 1,378 | N/A | 100% | 410 |
| C2SaferRust | 141 | 351 | 4,699 | 2,464 | 1,189 | 69.9% | 100% | 247 |
| Library | System | Ptr.Decl | Ptr.Deref | Unsafe LoC | Unsafe Cast | Unsafe Call | Comp.Rate | Correct. | Clippy |
| bzip2 | C2Rust | 147 | 3,614 | 9,304 | 6,601 | 1,686 | N/A | 100% | 254 |
| C2SaferRust | 85 | 2,217 | 7,688 | 3,397 | 1,252 | 57.58 | 100% | 417 | |
| EvoC2Rust | 65 | 391 | 1,459 | 548 | 327 | 83.00 | 0% | N/A | |
| Encrust | 79 | 384 | 1,907 | 886 | 572 | 93.94 | 100% | 146 | |
| genann | C2Rust | 48 | 158 | 557 | 231 | 116 | N/A | 100% | 32 |
| C2SaferRust | 38 | 127 | 479 | 174 | 102 | 57.14 | 100% | 29 |
| Suite | Configuration | Ptr.Decl | Ptr.Deref | Unsafe LoC | Unsafe Cast | Unsafe Call | Clippy |
| Coreutils | C2Rust | 1,572 | 3,471 | 50,668 | 27,647 | 10,414 | 2,951 |
| Encrust Phase 1 | 886 | 1,585 | 27,424 | 11,227 | 9,659 | 1,463 | |
| Encrust (Phase 1+2) | 829 | 1,489 | 25,724 | 10,626 | 9,336 | 1,495 | |
| Laertes | C2Rust | 2,991 | 14,177 | 87,501 | 50,652 | 15,213 | 7,174 |
| Encrust Phase 1 | 2,269 | 8,278 | 69,009 | 36,107 | 13,795 | 6,465 | |
| Encrust (Phase 1+2) | 2,081 | 4,729 | 60,190 | 30,041 | 12,482 | 6,453 |
| Task type | Disc. | Compl. | Failed | Rate | Avg. iters |
| static_mut | 363 | 227 | 136 | 62.5% | 21.8 |
| wrapper_removal | 454 | 347 | 107 | 76.4% | 20.6 |
| struct_migration | 23 | 21 | 2 | 91.3% | 10.7 |
| struct_use_migrate | 15 | 14 | 1 | 93.3% | 3.8 |
| function_translate | 263 | 174 | 89 | 66.2% | 23.7 |
| dead_code | 15 | 7 | 8 | 46.7% | 18.3 |
Code Translation
Code translation converts programs between languages, frameworks, and representations while aiming to preserve behavior and sometimes improve safety or performance.
See all 41 papers