L'Unsafe Rust est une extension du sous-ensemble sûr de Rust, permettant d'effectuer des opérations que le compilateur ne peut pas vérifier en termes de possession, de durée de vie et d'aliasing. Les principales applications incluent : l'interaction avec des bibliothèques bas niveau, FFI, le contrôle manuel de la mémoire, la mise en œuvre d'abstractions ne s'inscrivant pas dans le modèle sûr de Rust.
Les caractéristiques clés de unsafe :
unsafe { ... } ou la fonction : unsafe fn some_func()Exemple :
let x: i32 = 10; let ptr: *const i32 = &x as *const i32; unsafe { println!("Valeur : {}", *ptr); // déréférencement de raw pointer }
Le code à l'intérieur d'un bloc unsafe est-il complètement dangereux et non vérifié par le compilateur, ou le compilateur continue-t-il à appliquer les règles du borrow checker et d'autres vérifications ?
Réponse : Non, à l'intérieur d'un bloc unsafe, le compilateur continue de vérifier de nombreuses règles de Rust (par exemple, typage, règles de possession, syntaxe), mais permet seulement d'exécuter des actions qui autrement ne seraient pas autorisées. On ne peut pas désactiver complètement le borrow checker !
Exemple :
let mut x = 0; let r1 = &mut x as *mut i32; // Interdit : let r2 = &mut x as *mut i32; // même à l'intérieur de unsafe, des erreurs surgiront si la mutabilité est violée
Histoire
Dans une bibliothèque de fichiers asynchrone, un raw pointer a été utilisé pour contrôler un tampon, mais on a oublié de suivre correctement la durée de vie du tampon. En conséquence, lors de la fermeture du fichier, le pointeur est devenu "dangling" et l'accès a conduit à un comportement indéfini (la section unsafe n'a pas sauvé de use-after-free).
Histoire
Dans une implémentation personnelle d'une structure similaire à Vec, le programmeur a élargi manuellement le tampon via unsafe. Une erreur de décalage a conduit à une copie incorrecte des éléments et à une corruption des données, car l'alignement et la disposition des types n'ont pas été pris en compte.
Histoire
Dans un descripteur de threads, un pointeur mutable statique (static mut) a été utilisé sans synchronisation appropriée. En raison de cela, en mode multithread, une data race est survenue accidentellement, entraînant un crash sporadique de l'application, détectable uniquement par fuzzing.