Skip to content

Commit cd62dac

Browse files
authored
Merge pull request #66 from hg-anssi/work/cyclic_arc
[rule] Cyclic reference counted pointers
2 parents 169d8e7 + f80dd47 commit cd62dac

File tree

2 files changed

+132
-0
lines changed

2 files changed

+132
-0
lines changed

src/en/05_memory.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,3 +178,69 @@ impl Drop for ZU32 {
178178
} // i is freed here
179179
# }
180180
```
181+
182+
## Cyclic reference counted pointers (`Rc` and `Arc`)
183+
184+
Combining [interior mutability](https://doc.rust-lang.org/reference/interior-mutability.html), recurcivity and reference counted pointer into type definitions is unsafe. It can produce memory leaks which can result in DDoS attack or secret leaks.
185+
186+
The following example show such a memory leak in safe Rust:
187+
188+
```rust
189+
use std::{cell::Cell, rc::Rc};
190+
191+
struct LinkedStruct {
192+
other: Cell<Option<Rc<LinkedStruct>>>,
193+
}
194+
195+
fn main() {
196+
println!("Hello, world!");
197+
let a = Rc::new(LinkedStruct {
198+
other: Cell::new(None),
199+
});
200+
let b = Rc::new(LinkedStruct {
201+
other: Cell::new(None),
202+
});
203+
let aa = a.clone();
204+
let bb = b.clone();
205+
a.other.set(Some(bb));
206+
b.other.set(Some(aa));
207+
}
208+
```
209+
210+
Memory leak is shown with `valgrind`:
211+
212+
```
213+
$ valgrind --leak-check=full target/release/safe-rust-leak
214+
==153637== Memcheck, a memory error detector
215+
==153637== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
216+
==153637== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
217+
==153637== Command: target/release/safe-rust-leak
218+
==153637==
219+
Hello, world!
220+
==153637==
221+
==153637== HEAP SUMMARY:
222+
==153637== in use at exit: 48 bytes in 2 blocks
223+
==153637== total heap usage: 10 allocs, 8 frees, 3,144 bytes allocated
224+
==153637==
225+
==153637== 48 (24 direct, 24 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
226+
==153637== at 0x48417B4: malloc (vg_replace_malloc.c:381)
227+
==153637== by 0x10F8D4: safe_rust_leak::main (in /home/toto/src/safe-rust-leak/target/release/safe-rust-leak)
228+
==153637== by 0x10F7E2: std::sys::backtrace::__rust_begin_short_backtrace (in /home/toto/src/safe-rust-leak/target/release/safe-rust-leak)
229+
==153637== by 0x10F7D8: std::rt::lang_start::{{closure}} (in /home/toto/src/safe-rust-leak/target/release/safe-rust-leak)
230+
==153637== by 0x12A90F: std::rt::lang_start_internal (in /home/toto/src/safe-rust-leak/target/release/safe-rust-leak)
231+
==153637== by 0x10FA54: main (in /home/toto/src/safe-rust-leak/target/release/safe-rust-leak)
232+
==153637==
233+
==153637== LEAK SUMMARY:
234+
==153637== definitely lost: 24 bytes in 1 blocks
235+
==153637== indirectly lost: 24 bytes in 1 blocks
236+
==153637== possibly lost: 0 bytes in 0 blocks
237+
==153637== still reachable: 0 bytes in 0 blocks
238+
==153637== suppressed: 0 bytes in 0 blocks
239+
==153637==
240+
==153637== For lists of detected and suppressed errors, rerun with: -s
241+
==153637== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
242+
```
243+
244+
> **Règle {{#check MEM-MUT-REC-RC | Avoid cyclic reference counted pointers}}**
245+
>
246+
> Avoid recursive types whose recursivity use reference counted pointers together with interior mutability.

src/fr/05_memory.md

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,3 +191,69 @@ impl Drop for ZU32 {
191191
} // i est libéré ici
192192
# }
193193
```
194+
195+
## Cycle dans les références comptées (`Rc` et `Arc`)
196+
197+
La **combinaison** de la mutabilité *[intérieure](https://doc.rust-lang.org/reference/interior-mutability.html)*, des références comptées et des types récursifs n'est pas sûre. En effet, elle peut conduire à fuites mémoire, et donc éventuellement à des attaques par déni de service et en des fuites de secrets.
198+
199+
L'exemple non-`unsafe` suivant montre, la création d'une fuite mémoire en utilisant la mutabilité intérieure et les références comptées.
200+
201+
```rust
202+
use std::{cell::Cell, rc::Rc};
203+
204+
struct LinkedStruct {
205+
other: Cell<Option<Rc<LinkedStruct>>>,
206+
}
207+
208+
fn main() {
209+
println!("Hello, world!");
210+
let a = Rc::new(LinkedStruct {
211+
other: Cell::new(None),
212+
});
213+
let b = Rc::new(LinkedStruct {
214+
other: Cell::new(None),
215+
});
216+
let aa = a.clone();
217+
let bb = b.clone();
218+
a.other.set(Some(bb));
219+
b.other.set(Some(aa));
220+
}
221+
```
222+
223+
La fuite peut-être mise en évidence grâce à `valgrind` :
224+
225+
```
226+
$ valgrind --leak-check=full target/release/safe-rust-leak
227+
==153637== Memcheck, a memory error detector
228+
==153637== Copyright (C) 2002-2022, and GNU GPL'd, by Julian Seward et al.
229+
==153637== Using Valgrind-3.19.0 and LibVEX; rerun with -h for copyright info
230+
==153637== Command: target/release/safe-rust-leak
231+
==153637==
232+
Hello, world!
233+
==153637==
234+
==153637== HEAP SUMMARY:
235+
==153637== in use at exit: 48 bytes in 2 blocks
236+
==153637== total heap usage: 10 allocs, 8 frees, 3,144 bytes allocated
237+
==153637==
238+
==153637== 48 (24 direct, 24 indirect) bytes in 1 blocks are definitely lost in loss record 2 of 2
239+
==153637== at 0x48417B4: malloc (vg_replace_malloc.c:381)
240+
==153637== by 0x10F8D4: safe_rust_leak::main (in /home/toto/src/safe-rust-leak/target/release/safe-rust-leak)
241+
==153637== by 0x10F7E2: std::sys::backtrace::__rust_begin_short_backtrace (in /home/toto/src/safe-rust-leak/target/release/safe-rust-leak)
242+
==153637== by 0x10F7D8: std::rt::lang_start::{{closure}} (in /home/toto/src/safe-rust-leak/target/release/safe-rust-leak)
243+
==153637== by 0x12A90F: std::rt::lang_start_internal (in /home/toto/src/safe-rust-leak/target/release/safe-rust-leak)
244+
==153637== by 0x10FA54: main (in /home/toto/src/safe-rust-leak/target/release/safe-rust-leak)
245+
==153637==
246+
==153637== LEAK SUMMARY:
247+
==153637== definitely lost: 24 bytes in 1 blocks
248+
==153637== indirectly lost: 24 bytes in 1 blocks
249+
==153637== possibly lost: 0 bytes in 0 blocks
250+
==153637== still reachable: 0 bytes in 0 blocks
251+
==153637== suppressed: 0 bytes in 0 blocks
252+
==153637==
253+
==153637== For lists of detected and suppressed errors, rerun with: -s
254+
==153637== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 0 from 0)
255+
```
256+
257+
> **Règle {{#check MEM-MUT-REC-RC | Éviter les références comptées récursives mutables}}**
258+
>
259+
> Éviter de définir des types à la fois récursifs, mutables *intérieurement*, et dont la récursion se base sur l'utilisation des références comptées `Rc` ou `Arc`.

0 commit comments

Comments
 (0)