1 puntos por GN⁺ 3 시간 전 | 1 comentarios | Compartir por WhatsApp
  • Cpp2Rust es un traductor guiado por sintaxis basado en el AST de clang, que convierte automáticamente entradas en C++ a código Rust completamente seguro
  • El proceso de traducción parsea los archivos C++ con clang para crear un AST, recorre el AST generando código Rust como cadenas y luego usa rustfmt para producir un único archivo .rs
  • El valor predeterminado es el modelo de conteo de referencias, y también es posible generar Rust unsafe con --model=unsafe para depuración y comparación de rendimiento
  • El código generado depende de la biblioteca de runtime libcc2rs, y los punteros de C se convierten en Ptr<T>, que modela null, aritmética de punteros y aliasing
  • Para traducir programas completos se requiere compile_commands.json, y en proyectos CMake se puede generar con la bandera CMAKE_EXPORT_COMPILE_COMMANDS=ON

Conversión automática de C++ a Rust seguro

  • Cpp2Rust es una herramienta que traduce automáticamente C++ a Rust completamente seguro
  • Es un traductor guiado por sintaxis basado en el AST de clang
  • El algoritmo de traducción se describe en el artículo Cpp2Rust: Automatic Translation of C++ to Safe Rust, publicado en PLDI 2026

Pipeline de traducción

  • Primero parsea el archivo C++ de entrada con clang para generar un AST
  • Luego recorre el AST y emite el código Rust como una cadena
  • Cuando es necesario, inserta llamadas a la biblioteca de runtime libcc2rs
    • Un ejemplo es el manejo de semántica de raw pointers
  • Por último, usa rustfmt para ordenar el código Rust en un único archivo .rs

Modelos de Rust seguro y Rust unsafe

  • El comportamiento predeterminado usa el modelo de conteo de referencias y genera una salida en Rust completamente seguro
  • También se ofrece un generador de Rust unsafe
    • El argumento de línea de comandos es --model=unsafe
    • Su uso es para depuración y comparación de rendimiento

Biblioteca de runtime libcc2rs

  • El código generado depende de una biblioteca de runtime diseñada para simplificar el proceso de traducción
  • Los punteros de C se convierten al tipo Ptr<T> provisto por libcc2rs
  • Ptr<T> modela la semántica de los punteros de C
    • null
    • aritmética de punteros
    • aliasing
  • El borrow checker de Rust se satisface mediante operaciones de runtime verificadas

Flujo de compilación y ejecución

  • Un ejemplo de instalación de dependencias en Ubuntu incluye libclang-22-dev, clang++-22, ninja-build, cmake y ruff
  • La compilación sigue el orden cmake -GNinja .., ninja, ninja check
  • El comando para traducir un solo archivo tiene la siguiente forma
./build/cpp2rust/cpp2rust --file=<file>.cpp -o=<file>.rs
  • Para generar Rust unsafe, se ejecuta así
./build/cpp2rust/cpp2rust --file=<file>.cpp -o=<file>.rs --model=unsafe

Ejemplo mínimo y traducción de programas completos

  • El ejemplo printf("hello world\n") de hello.cpp se convierte en código que incluye println!("hello world") de Rust
  • El hello.rs convertido se compila y ejecuta así
rustc hello.rs -L ../libcc2rs/target/debug
./hello
  • Para traducir programas completos se requiere compile_commands.json
  • En CMake, compile_commands.json se genera con la siguiente bandera
cmake -DCMAKE_EXPORT_COMPILE_COMMANDS=ON ..
  • El comando para traducir un programa completo tiene la siguiente forma
./build/cpp2rust/cpp2rust --dir=<dir> -o <output>.rs
  • <dir> debe ser el directorio que contiene compile_commands.json

Comandos de prueba

  • Todas las pruebas se ejecutan con ninja check
  • Las pruebas unitarias se ejecutan con ninja check-unit
  • Las pruebas unitarias de libcc2rs se ejecutan con ninja check-libcc2rs
  • Las pruebas unitarias de libcc2rs-macros se ejecutan con ninja check-libcc2rs-macros
  • Para regenerar la salida esperada tras hacer cambios intencionales, se usa REPLACE_EXPECTED=1 ninja check-unit

1 comentarios

 
GN⁺ 3 시간 전
Opiniones en Lobste.rs
  • Escuché una charla de Dan Wallach en febrero de este año, donde presentó el proyecto TRACTOR (Translating All C to Rust) de DARPA [1] [2] [3]
    Al parecer, el equipo de MIT Lincoln Laboratory está realizando las pruebas y evaluaciones del programa de investigación
    Entiendo que todavía está en etapa de investigación, pero me interesa mucho este tema y tengo bastante curiosidad por ver qué tipo de herramientas e ideas salen de aquí
    Parece que realmente podría eliminar muchos de esos bugs “menores” que vienen del manejo de memoria
    [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/…

  • Interesante. Estaría muy bien poder ver una o dos demos de librerías o apps que los autores hayan convertido con esto y que ellos mismos consideren interesantes

  • No termino de entender por qué hace falta una etapa de conversión. Si hay suficiente información como para convertirlo a Rust con seguridad de memoria, ¿no significa eso que también habría suficiente información como para garantizar por análisis estático que el C++ es seguro?

    • Lo resuelven metiendo nuevas verificaciones durante la conversión, así que es más bien una concesión del tipo “el código original era seguro” vs. “el código nuevo falla de forma contundente y termina en vez de corromper memoria”
    • Esto aparece al principio del paper enlazado en el README
      Dice que alrededor del 70% de las vulnerabilidades de seguridad en software ampliamente distribuido provienen de bugs de seguridad de memoria en lenguajes como C y C++, y que, pese a décadas de inversión en mitigaciones como análisis estático, sanitizers y aislamiento por hardware, los atacantes siguen explotando operaciones de memoria inseguras
      Explica que una solución prometedora a largo plazo es migrar los codebases existentes de C++ a un lenguaje con seguridad de memoria como Rust, pero hacerlo a mano es demasiado costoso y propenso a errores
      Cpp2Rust afirma ser el primer sistema capaz de traducir automáticamente programas en C++ a código Rust funcionalmente equivalente y con seguridad de memoria
      A cambio de sacrificar algo de rendimiento por seguridad, resuelve la incompatibilidad fundamental entre las referencias con alias sin restricciones de C++ y el modelo de ownership de Rust insertando verificaciones en runtime de ownership y mutabilidad, preservando la semántica y garantizando la seguridad
      Para reducir el overhead de las verificaciones dinámicas, también crearon optimizaciones interprocedimentales para el código Rust, eliminando operaciones de ownership redundantes y recuperando buena parte del rendimiento perdido
      Así que la motivación no es simplemente demostrar seguridad, sino migrarlo a Rust y facilitar que el desarrollo futuro también se mueva a Rust
    • No hay suficiente información y, según el teorema de Rice, tampoco la habrá en el futuro
      La idea de proyectos como este es crear un punto de partida para seguir refactorizando hacia Rust idiomático, y así volver el código analizable
      Con suerte, eso también permitirá eliminar verificaciones en runtime o partes inseguras del código traducido
      Se podría decir que bastaría con refactorizar C++ para que tenga “forma de Rust” y así hacerlo igual de analizable, pero C++ tiene otra semántica que permite mucha más flexibilidad, así que las rutas a analizar pueden crecer exponencialmente o el análisis estático puede terminar en callejones ambiguos
      Habría que prometer no hacer cosas difíciles para los analizadores estáticos ni explotar casos límite, y para eso podrías crear un dialecto de C++ con semántica más restringida y anotaciones extra
      Circle/Safe C++ mostró que eso tenía potencial, pero el WG de C++ rechazó con fuerza esa dirección, así que solo queda elegir entre usar por tu cuenta un dialecto de C++ parecido a Rust pero sin respaldo, o simplemente usar Rust
  • ¿Cómo funciona exactamente si el código de entrada en sí no es seguro?

    • Se maneja con verificaciones en runtime. Así, en el momento en que ocurre una violación, en vez de corromper memoria puede fallar de forma segura y determinista