Mercurial > public > mercurial-scm > hg
comparison rust/hg-core/src/dirstate_tree/owning.rs @ 48999:cfd270d83169 stable
rust: explain why the current `OwningDirstateMap` is unsound
See inline comments.
Differential Revision: https://phab.mercurial-scm.org/D12428
author | Rapha?l Gom?s <rgomes@octobus.net> |
---|---|
date | Tue, 05 Apr 2022 10:55:27 +0200 |
parents | d1210d56008b |
children | dd6b67d5c256 |
comparison
equal
deleted
inserted
replaced
48998:91a60031aba2 | 48999:cfd270d83169 |
---|---|
1 use super::dirstate_map::DirstateMap; | 1 use super::dirstate_map::DirstateMap; |
2 use stable_deref_trait::StableDeref; | 2 use stable_deref_trait::StableDeref; |
3 use std::ops::Deref; | 3 use std::ops::Deref; |
4 | |
5 /* | |
6 // /!\ This is unsound and can cause use after free. It will be fixed in the | |
7 // next patch | |
8 | |
9 // If we change `value` from its current use of `HgPathBuf` to `&HgPath`, | |
10 // nothing here tells that `value` will outlive `OwningDirstateMap` | |
11 pub fn copy_map_insert<'a,'owned>( | |
12 &'owned mut self, | |
13 key: &HgPath, | |
14 value: &'a HgPath, | |
15 ) -> Result<Option<HgPathBuf>, DirstateV2ParseError> { | |
16 // `'local` is smaller than `'a` here | |
17 let map: &'local mut DirstateMap<'local> = self.get_map_mut(); | |
18 let node: &'local mut Node<'local> = DirstateMap::get_or_insert_node( | |
19 map.on_disk, | |
20 &mut map.unreachable_bytes, | |
21 &mut map.root, | |
22 &key, | |
23 WithBasename::to_cow_owned, | |
24 |_ancestor| {}, | |
25 )?; | |
26 if node.copy_source.is_none() { | |
27 map.nodes_with_copy_source_count += 1 | |
28 } | |
29 Ok(node.copy_source.replace(value.into()).map(Cow::into_owned)) | |
30 // and right here ----------^^^^^^^^^^^^ | |
31 // we are storing `&'a HgPath` in `Node<'local>` which is possible | |
32 // because to the compiler, `'a` is longer than ``local`. | |
33 // It is wrong because nothing proves that `&'a HgPath` will outlive `self`. | |
34 } | |
35 | |
36 // All of this is caused by the wrong cast of the DirstateMap pointer that | |
37 // fakes the lifetime of `DirstateMap` and ensures the compiler that it lives | |
38 // as long as `on_disk`, which is only true for its immutable data. | |
39 // This will be fixed in the next commit. | |
40 */ | |
4 | 41 |
5 /// Keep a `DirstateMap<'on_disk>` next to the `on_disk` buffer that it | 42 /// Keep a `DirstateMap<'on_disk>` next to the `on_disk` buffer that it |
6 /// borrows. | 43 /// borrows. |
7 /// | 44 /// |
8 /// This is similar to [`OwningRef`] which is more limited because it | 45 /// This is similar to [`OwningRef`] which is more limited because it |