Unsafe Rust è un'estensione del sottoinsieme sicuro di Rust che consente di eseguire operazioni che il compilatore non può verificare per quanto riguarda la gestione, la durata e l'aliasing. Le principali aree di utilizzo includono: interazione con librerie a basso livello, FFI, controllo manuale della memoria, implementazione di astrazioni che non rientrano nel modello di Rust sicuro.
Caratteristiche chiave di unsafe:
unsafe { ... } o una funzione: unsafe fn some_func()Esempio:
let x: i32 = 10; let ptr: *const i32 = &x as *const i32; unsafe { println!("Valore: {}", *ptr); // dereferenziazione di raw pointer }
Il codice all'interno di un blocco unsafe è completamente non sicuro e non controllato dal compilatore, o il compilatore continua ad applicare le regole del borrow checker e altre verifiche?
Risposta: No, all'interno di un blocco unsafe il compilatore continua a controllare molte regole di Rust (ad esempio, tipizzazione, regole di proprietà, sintassi), ma consente di eseguire solo azioni che altrimenti non sarebbero consentite. Non è possibile disattivare completamente il borrow checker!
Esempio:
let mut x = 0; let r1 = &mut x as *mut i32; // Vietato: let r2 = &mut x as *mut i32; // anche all'interno di unsafe appariranno errori se si viola la mutabilità
Storia
In una libreria di file asincroni è stato utilizzato un raw pointer per controllare un buffer, ma è stato dimenticato di tenere traccia correttamente della durata del buffer. Di conseguenza, alla chiusura del file, il pointer è diventato "appeso" e l'accesso ha portato a undefined behavior (la sezione unsafe non ha salvato da use-after-free).
Storia
Nella propria implementazione di una struttura simile a Vec, il programmatore ha ampliato manualmente il buffer tramite unsafe. Un errore di offset ha portato a una copia errata degli elementi e alla corruzione dei dati, poiché non sono stati considerati l'allineamento e il layout dei tipi.
Storia
In un descrittore di thread è stato utilizzato un puntatore statico mutabile (static mut) senza una corretta sincronizzazione. A causa di ciò, in modalità multithreading è emerso accidentalmente un data race, causando un crash sporadico dell'applicazione, catturato solo con fuzzing.