Ridurre il peso del codice C storico senza affrontare costose riscritture manuali è una delle sfide più concrete per chi si occupa della manutenzione di software di sistema, componenti di sicurezza e infrastrutture mature. Canonical vuole capire se sia possibile automatizzare una parte consistente di questo lavoro: non limitandosi a convertire la sintassi, ma arrivando a produrre codice Rust realmente sicuro, leggibile e soprattutto fedele al comportamento dell’originale C.
Per farlo ha avviato con la University of Bristol un progetto di ricerca triennale che combina machine learning, analisi dei programmi, testing e metodi formali.
L’obiettivo è costruire strumenti capaci di affrontare repository C di grandi dimensioni, con centinaia di migliaia di righe, e trasformarli in Rust riducendo al minimo l’uso di unsafe senza introdurre regressioni funzionali difficili da individuare.
Canonical vuole automatizzare la migrazione dal C senza riscrivere tutto a mano
Una parte enorme del software critico ancora oggi poggia su C e C++, linguaggi che offrono un controllo molto preciso su memoria e hardware ma lasciano al programmatore la responsabilità di evitare errori come use-after-free, buffer overflow, dereferenziazioni non valide e race condition.
Rust nasce proprio per impedire molte di queste classi di bug già in fase di compilazione ed è infatti ritenuto la scelta numero uno per guardare alla sicurezza della memoria delle applicazioni evitando la fetta più importante degli errori storici che hanno introdotto gravi vulnerabilità.
Il problema è che riscrivere da zero applicazioni mature significa spesso spendere anni di lavoro e rischiare di perdere comportamenti consolidati, ottimizzazioni e correzioni accumulate nel tempo.
Canonical prova quindi a percorrere una strada diversa: preservare il valore del codice esistente trasformandone gradualmente il modello di sicurezza. AppArmor e snap-confine saranno utilizzati come casi di studio reali per valutare quanto lontano possa arrivare il metodo. La società precisa però un punto importante: la loro presenza nel progetto non equivale a un annuncio della loro riscrittura in Rust: serviranno soprattutto come banco di prova per misurare difficoltà, limiti e affidabilità dell’approccio.
Ubuntu ha già adottato implementazioni Rust di strumenti storicamente associati al mondo Unix: un esempio è uutils coreutils, reimplementazione multipiattaforma delle GNU Core Utilities; un altro è sudo-rs. Sono però progetti sviluppati e mantenuti come implementazioni autonome: tradurre automaticamente un repository C esistente introduce una valanga di potenziali problemi.
Perché cresce l’impegno a migrare codice C verso Rust
Il progetto accademico che coinvolge direttamente Canonical arriva in una fase in cui Rust ha ormai superato da tempo lo status di linguaggio sperimentale.
La versione 1.0 risale al 15 maggio 2015 e il linguaggio ha trovato spazio proprio dove C e C++ dominano da decenni: sistemi operativi, componenti di sicurezza, firmware, browser e software vicino all’hardware.
La ragione principale è nota: Rust consente di controllare memoria e risorse senza garbage collector, ma il compilatore applica regole che impediscono in Safe Rust molte categorie di errori legati a puntatori, durata degli oggetti e accessi concorrenti.
I numeri aiutano a capire perché il tema interessa sempre più aziende. Google ha riferito che in Android la quota delle vulnerabilità legate alla sicurezza della memoria è scesa dal 76% nel 2019 al 24% nel 2024, parallelamente all’aumento del codice scritto con linguaggi memory-safe. Gli stessi tecnici Google stimano che circa il 70% delle vulnerabilità gravi nei grandi codebase basati su linguaggi non memory-safe appartenga storicamente a questa famiglia.
Il codice generato dovrà dimostrare di comportarsi come l’originale
Canonical e Università di Bristol (Regno Unito) spiegano che il codice Rust generato sarà trattato come non attendibile finché strumenti indipendenti non raccoglieranno prove sufficienti della sua correttezza. Il compilatore Rust può dimostrare molte proprietà sulla gestione sicura della memoria, ma non può sapere se una funzione convertita calcoli esattamente ciò che calcolava quella C.
Per verificare l’equivalenza comportamentale, i ricercatori intendono combinare fuzz testing e tecniche formali. Con il fuzzing si generano grandi quantità di input, compresi valori insoliti e combinazioni progettate per raggiungere percorsi raramente esercitati. Si eseguono quindi la versione C e quella Rust confrontandone risultati e comportamento osservabile.
C2Rust ha già sperimentato un’idea simile con il suo sistema di cross-checking: le versioni C e Rust possono produrre tracce di esecuzione che il sistema confronta per individuare divergenze. La ricerca Canonical-Bristol vuole andare oltre, affiancando ai test anche modalità di controllo ancora più rigorose.
La ricerca di Canonical e dell’università britannica non ha come obiettivo quello di far scrivere Rust a un’AI, cosa che i modelli generativi sanno già fare discretamente, ma come stabilire con prove tecniche che centinaia di migliaia di righe generate automaticamente possano davvero sostituire codice C maturo senza cambiarne il comportamento. Ed è anche il motivo per cui il progetto durerà 3 anni.