1 ポイント 投稿者 GN⁺ 3 시간 전 | 1件のコメント | WhatsAppで共有
  • Cpp2Rustはclang ASTベースの構文主導トランスレータで、C++入力を完全に安全なRustコードへ自動変換する
  • 翻訳プロセスでは、clangでC++ファイルをパースしてASTを作成し、ASTを巡回しながらRustコードを文字列として生成した後、rustfmtで単一の.rsファイルとして出力する
  • デフォルトは参照カウントモデルで、デバッグと性能比較のために--model=unsafeでunsafe Rustの生成も可能
  • 生成されたコードはlibcc2rsランタイムライブラリに依存し、Cポインタはnull、算術演算、エイリアスをモデル化するPtr<T>へ変換される
  • プログラム全体の翻訳にはcompile_commands.jsonが必要で、CMakeプロジェクトではCMAKE_EXPORT_COMPILE_COMMANDS=ONフラグで生成できる

C++から安全なRustへの自動変換

  • Cpp2RustはC++を完全に安全なRustへ自動翻訳するツール
  • clangのASTに基づく構文主導トランスレータ
  • 翻訳アルゴリズムはPLDI 2026に掲載された論文Cpp2Rust: Automatic Translation of C++ to Safe Rustで説明されている

翻訳パイプライン

  • 入力C++ファイルをまずclangでパースし、ASTを生成する
  • その後ASTを巡回しながらRustコードを文字列として出力する
  • 必要に応じてlibcc2rsランタイムライブラリ呼び出しを挿入する
    • 例としてはraw pointer semanticsの処理がある
  • 最後にrustfmtを使ってRustコードを単一の.rsファイルに整形する

安全なRustとunsafe Rustモデル

  • デフォルト動作では参照カウントモデルを使用し、完全に安全なRust出力を生成する
  • unsafe Rustジェネレータも提供される
    • コマンドライン引数は--model=unsafe
    • 用途はデバッグと性能比較

libcc2rsランタイムライブラリ

  • 生成されたコードは、翻訳プロセスを単純化するために設計されたランタイムライブラリに依存する
  • Cポインタはlibcc2rsが提供するPtr<T>型へ変換される
  • Ptr<T>はCポインタの意味論をモデル化する
    • null
    • ポインタ算術
    • エイリアス
  • Rustのborrow checkerは検査済みランタイム操作を通じて満たす

ビルドと実行フロー

  • Ubuntuの依存関係インストール例にはlibclang-22-devclang++-22ninja-buildcmakeruffが含まれる
  • ビルドはcmake -GNinja ..ninjaninja checkの順に進める
  • 単一ファイル翻訳コマンドは次の形式
./build/cpp2rust/cpp2rust --file=<file>.cpp -o=<file>.rs
  • unsafe Rustを生成するには次のように実行する
./build/cpp2rust/cpp2rust --file=<file>.cpp -o=<file>.rs --model=unsafe

最小例とプログラム全体の翻訳

  • hello.cppprintf("hello world\n")の例は、Rustのprintln!("hello world")を含むコードへ変換される
  • 変換されたhello.rsは次のようにコンパイルして実行する
rustc hello.rs -L ../libcc2rs/target/debug
./hello
  • プログラム全体の翻訳にはcompile_commands.jsonが必要
  • CMakeでは次のフラグでcompile_commands.jsonを生成する
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
  • プログラム全体の翻訳コマンドは次の形式
./build/cpp2rust/cpp2rust --dir=<dir> -o <output>.rs
  • <dir>compile_commands.jsonが入っているディレクトリでなければならない

テストコマンド

  • 全テストはninja checkで実行する
  • ユニットテストはninja check-unitで実行する
  • libcc2rsのユニットテストはninja check-libcc2rsで実行する
  • libcc2rs-macrosのユニットテストはninja check-libcc2rs-macrosで実行する
  • 意図的に変更した後、期待出力を再生成するにはREPLACE_EXPECTED=1 ninja check-unitを使用する

1件のコメント

 
GN⁺ 3 시간 전
Lobste.rsの意見
  • 今年2月にDan Wallachの発表を聞いたが、DARPAの**TRACTOR(Translating All C to Rust)**プロジェクトを紹介していた [1] [2] [3]
    研究プログラムの試験・評価はMIT Lincoln Laboratoryのチームが担当しているとのこと
    まだ研究段階だと理解しているが、このテーマにはとても関心があり、こうしたツールやアイデアが今後どう発展するのかかなり気になる
    メモリ管理に起因する多くの「些細な」バグを実際になくせるかもしれない
    [1] https://www.darpa.mil/research/programs/translating-all-c-to-rust
    [2] https://github.com/DARPA-TRACTOR-Program
    [3] https://ll.mit.edu/r-d/projects/…

  • 興味深い。著者らがこれで変換し、自分たちでも面白いと考えているライブラリやアプリのデモを1つか2つ見られたら本当にうれしい

  • なぜ変換ステップが必要なのかよくわからない。メモリ安全なRustへ変換できるだけの十分な情報があるなら、C++についても静的解析で安全だと保証できるだけの情報があるのではないか?

    • 変換過程で新しい検査を入れる方式なので、「元のコードが安全だった」というよりは、「新しいコードはメモリを壊す代わりに大きく失敗して終了する」という折衷案に近い
    • READMEにリンクされている論文の冒頭にこの話がある
      広く配布されているソフトウェアのセキュリティ脆弱性の約70%は、CやC++のような言語におけるメモリ安全性バグに由来し、静的解析・サニタイザー・ハードウェア隔離といった緩和策に数十年投資してきたにもかかわらず、攻撃者は依然として安全でないメモリ操作を悪用しているという
      長期的に有望な解決策は既存のC++コードベースをRustのようなメモリ安全な言語へ移行することだが、手作業ではコストが高すぎ、しかもエラーが起きやすいと説明している
      Cpp2Rustは、C++プログラムを機能的に等価でメモリ安全なRustコードへ自動変換できる最初のシステムだと主張している
      パフォーマンスの一部をセキュリティと引き換えにしつつ、C++の無制限なエイリアス参照とRustの所有権モデルの根本的な不一致を、ランタイムの所有権・可変性チェックの挿入によって解決し、意味を保ったまま安全性を保証するという
      動的検査のオーバーヘッドを減らすためにRustコード向けのソース間最適化も作成しており、冗長な所有権操作を取り除くことで失われた性能のかなりの部分を回復するとしている
      したがって動機は単に安全性を証明することではなく、Rustへ移植し、その後の開発もRustへ移しやすくすることにある
    • 十分な情報はなく、ライスの定理によれば今後も得られない
      この種のプロジェクトの発想は、より慣用的なRustへさらにリファクタリングするための出発点を作ることであり、そうなればコードを解析可能にできる
      できれば変換後のコードからランタイム検査やunsafeな部分も取り除けるようになる
      C++を「Rustっぽい形」にリファクタリングして同じように解析可能にすればよいのでは、と言えるかもしれないが、C++はより多くの柔軟性を許す異なる意味論を持つため、解析すべき経路が指数的に増えたり、静的解析が曖昧な行き止まりに陥ったりしうる
      静的解析器に難しいことをさせず、境界ケースを悪用しないと約束する必要があり、そのためにはより制約の強い意味論と追加アノテーションを備えたC++方言を作ることになる
      Circle/Safe C++は可能性を示したが、C++ WGがその方向を強く拒否したため、サポートされないRust風C++方言を自分で使うか、単にRustを使うかしか残らない
  • 入力コード自体が安全でない場合には、正確にはどう動作するのだろうか?

    • ランタイム検査で処理する。したがって違反が発生した瞬間、メモリを壊す代わりに安全かつ決定的にクラッシュできる