diff --git a/src/en/04_language.md b/src/en/04_language.md
index 8491118..a213031 100644
--- a/src/en/04_language.md
+++ b/src/en/04_language.md
@@ -204,3 +204,116 @@ the process.
TODO: cyclomatic complexity of the macro expanded code, recursion
limits, ...
-->
+
+## Value displacement
+
+Values in Rust may have three distinct semantics when considering value displacement:
+
+- Either it has _move_ semantics, this behavior is the default one.
+- Or it has move _move_ semantics plus the _drop_ semantics, i.e. its type has [_drop glue_](https://doc.rust-lang.org/core/mem/fn.needs_drop.html) (by directly implementing `Drop` or by containing a field with _drop glue_).
+- Or it has copy semantics, by having its type implementing the `Copy` trait.
+
+However, some problem may appear when using the `std::ptr::read` function.
+According to the [documentation](https://doc.rust-lang.org/std/ptr/fn.read.html), the function:
+> Reads the value from src without moving it. This leaves the memory in src unchanged.
+
+To be clear, this function is performing a bit-wise (shallow) copy of the pointee (value pointed to by the raw pointer), regardless of its type semantics.
+This is a dangerous behavior as it can lead to double-drop and, in some cases, to double-free.
+
+To illustrate the copy on a type having the move semantics let's consider the following snippet:
+
+```rust
+# use std::ops::Drop;
+#
+#[derive(Debug)]
+struct MyStruct(u8);
+
+impl Drop for MyStruct {
+ fn drop(&mut self) {
+# println!("---Dropping an object---\nBefore zeroing: {} @ {:p}", self.0, &self.0 as *const u8);
+ self.0 = 0;
+# println!("After zeroing: {} @ {:p}", self.0, &self.0 as *const u8);
+ }
+}
+
+fn main(){
+ let obj: MyStruct = MyStruct(42);
+ let ptr: *const MyStruct = &obj as *const MyStruct;
+ println!("{:?} @ {:p}", unsafe { std::ptr::read(ptr) }, ptr);
+}
+```
+Output (may vary):
+```
+MyStruct(42) @ 0x7ffcb01ec737
+---Dropping an object---
+Before zeroing: 42 @ 0x7ffcb01ec7a7
+After zeroing: 0 @ 0x7ffcb01ec7a7
+Before zeroing: 42 @ 0x7ffcb01ec737
+---Dropping an object---
+After zeroing: 0 @ 0x7ffcb01ec737
+```
+
+We can see that a second object is created by the call to `std::ptr::read`, i.e. a copy of a _non-copy_ object is performed.
+
+This causes problems of varying severity:
+
+ - In some _rare_ cases (no _drop glue_, no non-aliasing guarantees, no _safety invariants_ attached to the type; basically when the type should have been `Copy` itself), it can be harmless.
+
+ - In most cases, there may be _safety_ or _validity_ invariants (such as pointer aliasing, or rather, lack thereof) which make one instance become `unsafe` to use, or even UB to use, the moment the other instance is.
+
+ - Example:
+
+ ```rust,no_run
+ # use ::core::mem;
+ #
+ let box_1: Box = Box::new(42);
+ let at_box_1: *const Box = &box_1;
+ let box_2: Box = unsafe { at_box_1.read() };
+ mem::forget(box_1); // `Box` non-aliasing guarantees invalidates the pointer in `box_2`
+ drop(box_2); // UB: "usage" of invalidated pointer.
+ ```
+ See [Stacked Borrows](https://plv.mpi-sws.org/rustbelt/stacked-borrows/) for more info.
+
+ - If the type has drop glue, then, when one of the two instances is dropped, any usage of the other may cause a use-after-free, the most notable example being that the second instance will be, in and of itself, freed, causing a double-free.
+
+ **This is Undefined Behavior, and is a source of major vulnerabilities**.
+
+The following snippet showcases this double-free bug:
+```rust
+# use std::boxed::Box;
+# use std::ops::Drop;
+#
+#[derive(Debug)]
+struct MyStructBoxed(Box);
+
+impl Drop for MyStructBoxed {
+ fn drop(&mut self) {
+# println!("---Dropping an object---\nBefore zeroing: {} @ {:p}", self.0, self.0);
+ let value: &mut u8 = self.0.as_mut();
+ *value = 0;
+# println!("After zeroing: {} @ {:p}", self.0, self.0);
+ }
+}
+
+fn main(){
+ let obj: MyStructBoxed = MyStructBoxed(Box::new(42));
+ let ptr: *const MyStructBoxed = &obj as *const MyStructBoxed;
+ println!("{:?} @ {:p}", unsafe { std::ptr::read(ptr) }, unsafe { &*ptr }.0 );
+}
+```
+Output (may vary):
+```
+MyStructBoxed(42) @ 0x55fe454b3c10
+Before zeroing: 42 @ 0x55fe454b3c10
+After zeroing: 0 @ 0x55fe454b3c10
+Before zeroing: 179 @ 0x55fe454b3c10
+After zeroing: 0 @ 0x55fe454b3c10
+free(): double free detected in tcache 2
+```
+
+> ### Rule {{#check LANG-RAW-PTR | Avoid the use of `std::ptr::read` }}
+>
+> `std::ptr::read` might have undesired side effect depending on the way the type of the raw pointer is moving through different context.
+> It is preferable to use the operation of referencing/dereferencing (`&*`) to avoid those side effect.
+>
+> Moreover, if pointee `T` is `Copy`, the `*`-dereference operator should be used.
diff --git a/src/fr/04_language.md b/src/fr/04_language.md
index 27b52a1..663512c 100644
--- a/src/fr/04_language.md
+++ b/src/fr/04_language.md
@@ -223,3 +223,98 @@ d'autres raisons.
TODO : complexité cyclomatique du code macro-expansé, limites de
récursion, ...
-->
+
+## Déplacement de valeurs
+
+Rust propose trois différents modes de déplacement de valeur:
+
+- Soit par *déplacement*, qui est le comportement par défaut.
+- Ou par *déplacement* plus un *drop* si `mem::needs_drop::()` renvoie `true`.
+- Ou par *copie*, si son type implémente le trait `Copy`
+
+Cependant, des problèmes peuvent être constater lors de l'utilisation de la fonction `std::ptr::read`.
+Selon la [documentation](https://doc.rust-lang.org/std/ptr/fn.read.html), cette fonction:
+> Lis la valeur pointée par src sans la déplacer. Ce qui laisse la mémoire pointée intact.
+
+Cette fonction est donc responsable d'effectuer une copie de la valeur pointée, indépendamment du mode de déplacement du type en question.
+Ce comportement peut être dangereux car il peut mener à des *double-free* et/ou des *double-drop*.
+
+Pour illustrer ce comportement, considérons le code suivant :
+
+```rust
+# use std::ops::Drop;
+#
+#[derive(Debug)]
+struct MyStruct(u8);
+
+impl Drop for MyStruct {
+ fn drop(&mut self) {
+# println!("---Dropping an object---\nBefore zeroing: {} @ {:p}", self.0, &self.0 as *const u8);
+ self.0 = 0;
+# println!("After zeroing: {} @ {:p}", self.0, &self.0 as *const u8);
+ }
+}
+
+fn main(){
+ let obj: MyStruct = MyStruct(100);
+ let ptr: *const MyStruct = &test as *const MyStruct;
+ println!("{:?} @ {:p}", unsafe { std::ptr::read(ptr) }, ptr);
+}
+```
+
+On peut observer qu'un deuxième objet a implicitement été créé lors de l'appel à `std::ptr::read`, i.e. une copie d'un objet *non copiable* est effectuée.
+
+Cela peut poser différents problèmes :
+
+ - Dans certains _rares_ cas (pas de _drop glue_, ni de guarantie de non-aliasing, ni d'invariants de sûreté reliés au type; i.e. quand le type aurait dû être `Copy`), cela peut être sans danger.
+
+ - Dans la plupart des cas, il pourrait y avoir des invariants de sûreté ou de validité (tel que l'aliasing de pointeur) ce qui rend une instance `unsafe` à utilisé, voire même UB, au moment où l'autre instance est utilisée.
+
+ - Exemple:
+
+ ```rust,no_run
+ # use ::core::mem;
+ #
+ let box_1: Box = Box::new(42);
+ let at_box_1: *const Box = &box_1;
+ let box_2: Box = unsafe { at_box_1.read() };
+ mem::forget(box_1); // `Box` non-aliasing guarantees invalidates the pointer in `box_2`
+ drop(box_2); // UB: "usage" of invalidated pointer.
+ ```
+ Cf. [Stacked Borrows](https://plv.mpi-sws.org/rustbelt/stacked-borrows/) pour plus d'informations.
+
+ - Si le type doit être *drop* (i.e. `mem::needs_drop::()` renvoie vraie), alors quand une des deux instances est *drop*, toute utilisation de l'autre peu causer un *use-after-free*, l'exemple le plus notable étant que la seconde instance sera également *drop*, ce qui causera un *double-free*.
+
+ **Ceci est un Comportement Non Défini (*Undefined Behavior*), et est responsable de vulnérabilités majeures**.
+
+Le code suivant illustre ce problème :
+
+```rust
+# use std::boxed::Box;
+# use std::ops::Drop;
+#
+#[derive(Debug)]
+struct MyStructBoxed(Box);
+
+impl Drop for MyStructBoxed {
+ fn drop(&mut self) {
+# println!("---Dropping an object---\nBefore zeroing: {} @ {:p}", self.0, self.0);
+ let value: &mut u8 = self.0.as_mut();
+ *value = 0;
+# println!("After zeroing: {} @ {:p}", self.0, self.0);
+ }
+}
+
+fn main(){
+ let test: MyStructBoxed = MyStructBoxed(Box::new(100));
+ let ptr: *const MyStructBoxed = &test as *const MyStructBoxed;
+ println!("{:?} @ {:p}", unsafe { std::ptr::read(ptr) }, unsafe { &*ptr }.0 );
+}
+```
+
+> ### Règle {{#check LANG-RAW-PTR | Éviter d'utiliser `std::ptr::read`}}
+>
+> `std::ptr::read` peut avoir des effets de bords indésirables en fonction du mode déplacement du type pointé par le *raw pointer* source.
+> Il est donc préférable d'utiliser l'opération de référencement/déréférencement (`&*`) pour les éviter.
+>
+> De plus, si le la valeur `T` pointée est `Copy`, l'opérateur de `*`-déréférencement doit être utilisé.