Skip to content

Commit ece5527

Browse files
committed
fix(headers): fix stacked borrows for IterMut/ValuesIterMut
1 parent 6e2dd42 commit ece5527

2 files changed

Lines changed: 116 additions & 27 deletions

File tree

src/header/map.rs

Lines changed: 82 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,13 @@ pub struct Iter<'a, T> {
129129
/// yielded more than once if it has more than one associated value.
130130
#[derive(Debug)]
131131
pub struct IterMut<'a, T> {
132-
map: *mut HeaderMap<T>,
132+
// Raw access avoids reborrowing the whole `HeaderMap` on every `next()`,
133+
// which would invalidate previously yielded `&mut T`s.
134+
entries: *mut Bucket<T>,
135+
entries_len: usize,
136+
// This points at the original `HeaderMap::extra_values` allocation for the
137+
// lifetime of the iterator.
138+
extra_values: *mut ExtraValue<T>,
133139
entry: usize,
134140
cursor: Option<Cursor>,
135141
lt: PhantomData<&'a mut HeaderMap<T>>,
@@ -234,7 +240,11 @@ pub struct ValueIter<'a, T> {
234240
/// A mutable iterator of all values associated with a single header name.
235241
#[derive(Debug)]
236242
pub struct ValueIterMut<'a, T> {
237-
map: *mut HeaderMap<T>,
243+
// Raw access avoids reborrowing the whole `HeaderMap` on every step.
244+
entries: *mut Bucket<T>,
245+
// This points at the original `HeaderMap::extra_values` allocation for the
246+
// lifetime of the iterator.
247+
extra_values: *mut ExtraValue<T>,
238248
index: usize,
239249
front: Option<Cursor>,
240250
back: Option<Cursor>,
@@ -951,7 +961,9 @@ impl<T> HeaderMap<T> {
951961
/// ```
952962
pub fn iter_mut(&mut self) -> IterMut<'_, T> {
953963
IterMut {
954-
map: self as *mut _,
964+
entries: self.entries.as_mut_ptr(),
965+
entries_len: self.entries.len(),
966+
extra_values: self.extra_values.as_mut_ptr(),
955967
entry: 0,
956968
cursor: self.entries.first().map(|_| Cursor::Head),
957969
lt: PhantomData,
@@ -1129,7 +1141,8 @@ impl<T> HeaderMap<T> {
11291141
};
11301142

11311143
ValueIterMut {
1132-
map: self as *mut _,
1144+
entries: self.entries.as_mut_ptr(),
1145+
extra_values: self.extra_values.as_mut_ptr(),
11331146
index: idx,
11341147
front: Some(Head),
11351148
back: Some(back),
@@ -2363,34 +2376,58 @@ unsafe impl<'a, T: Sync> Send for Iter<'a, T> {}
23632376
// ===== impl IterMut =====
23642377

23652378
impl<'a, T> IterMut<'a, T> {
2366-
fn next_unsafe(&mut self) -> Option<(&'a HeaderName, *mut T)> {
2379+
fn next_unsafe(&mut self) -> Option<(*const HeaderName, *mut T)> {
23672380
use self::Cursor::*;
23682381

23692382
if self.cursor.is_none() {
2370-
if (self.entry + 1) >= unsafe { &*self.map }.entries.len() {
2383+
if (self.entry + 1) >= self.entries_len {
23712384
return None;
23722385
}
23732386

23742387
self.entry += 1;
23752388
self.cursor = Some(Cursor::Head);
23762389
}
23772390

2378-
let entry = &mut unsafe { &mut *self.map }.entries[self.entry];
2391+
// SAFETY: `self.entry < self.entries_len`, and the iterator has
2392+
// exclusive access to the underlying map for `'a`, so the `entries`
2393+
// allocation remains valid for the lifetime of the iterator.
2394+
let entry = unsafe { self.entries.add(self.entry) };
23792395

23802396
match self.cursor.unwrap() {
23812397
Head => {
2382-
self.cursor = entry.links.map(|l| Values(l.next));
2383-
Some((&entry.key, &mut entry.value as *mut _))
2398+
// SAFETY: `entry` points at a live bucket in `entries`.
2399+
self.cursor = unsafe { (*entry).links }.map(|l| Values(l.next));
2400+
// SAFETY: `entry` points at a live bucket, and the iterator only
2401+
// yields each slot at most once, so materializing these field
2402+
// pointers does not alias another yielded `&mut T`.
2403+
Some(unsafe {
2404+
(
2405+
ptr::addr_of!((*entry).key),
2406+
ptr::addr_of_mut!((*entry).value),
2407+
)
2408+
})
23842409
}
23852410
Values(idx) => {
2386-
let extra = &mut unsafe { &mut (*self.map) }.extra_values[idx];
2411+
// SAFETY: `idx` comes from the `links` chain stored in a live
2412+
// bucket / extra value, so it points at a live `extra_values`
2413+
// slot for the duration of iteration.
2414+
let extra = unsafe { self.extra_values.add(idx) };
23872415

2388-
match extra.next {
2416+
// SAFETY: `extra` points at a live extra value.
2417+
match unsafe { (*extra).next } {
23892418
Link::Entry(_) => self.cursor = None,
23902419
Link::Extra(i) => self.cursor = Some(Values(i)),
23912420
}
23922421

2393-
Some((&entry.key, &mut extra.value as *mut _))
2422+
// SAFETY: `entry` and `extra` both point at live elements in the
2423+
// map backing storage, and the iterator only yields each value
2424+
// slot at most once.
2425+
Some(unsafe {
2426+
(
2427+
ptr::addr_of!((*entry).key),
2428+
ptr::addr_of_mut!((*extra).value),
2429+
)
2430+
})
23942431
}
23952432
}
23962433
}
@@ -2401,14 +2438,13 @@ impl<'a, T> Iterator for IterMut<'a, T> {
24012438

24022439
fn next(&mut self) -> Option<Self::Item> {
24032440
self.next_unsafe()
2404-
.map(|(key, ptr)| (key, unsafe { &mut *ptr }))
2441+
.map(|(key, ptr)| (unsafe { &*key }, unsafe { &mut *ptr }))
24052442
}
24062443

24072444
fn size_hint(&self) -> (usize, Option<usize>) {
2408-
let map = unsafe { &*self.map };
2409-
debug_assert!(map.entries.len() >= self.entry);
2445+
debug_assert!(self.entries_len >= self.entry);
24102446

2411-
let lower = map.entries.len() - self.entry;
2447+
let lower = self.entries_len - self.entry;
24122448
// We could pessimistically guess at the upper bound, saying
24132449
// that its lower + map.extra_values.len(). That could be
24142450
// way over though, such as if we're near the end, and have
@@ -3023,7 +3059,9 @@ impl<'a, T: 'a> Iterator for ValueIterMut<'a, T> {
30233059
fn next(&mut self) -> Option<Self::Item> {
30243060
use self::Cursor::*;
30253061

3026-
let entry = &mut unsafe { &mut *self.map }.entries[self.index];
3062+
// SAFETY: `self.index` was created from a live occupied entry and stays
3063+
// fixed for the lifetime of this iterator.
3064+
let entry = unsafe { self.entries.add(self.index) };
30273065

30283066
match self.front {
30293067
Some(Head) => {
@@ -3032,30 +3070,38 @@ impl<'a, T: 'a> Iterator for ValueIterMut<'a, T> {
30323070
self.back = None;
30333071
} else {
30343072
// Update the iterator state
3035-
match entry.links {
3073+
// SAFETY: `entry` points at a live bucket in `entries`.
3074+
match unsafe { (*entry).links } {
30363075
Some(links) => {
30373076
self.front = Some(Values(links.next));
30383077
}
30393078
None => unreachable!(),
30403079
}
30413080
}
30423081

3043-
Some(&mut entry.value)
3082+
// SAFETY: `entry` points at a live bucket, and `front`/`back`
3083+
// ensure this value slot is yielded at most once.
3084+
Some(unsafe { &mut *ptr::addr_of_mut!((*entry).value) })
30443085
}
30453086
Some(Values(idx)) => {
3046-
let extra = &mut unsafe { &mut *self.map }.extra_values[idx];
3087+
// SAFETY: `idx` comes from the live linked list rooted at
3088+
// `self.index`, so it refers to a live extra value slot.
3089+
let extra = unsafe { self.extra_values.add(idx) };
30473090

30483091
if self.front == self.back {
30493092
self.front = None;
30503093
self.back = None;
30513094
} else {
3052-
match extra.next {
3095+
// SAFETY: `extra` points at a live extra value.
3096+
match unsafe { (*extra).next } {
30533097
Link::Entry(_) => self.front = None,
30543098
Link::Extra(i) => self.front = Some(Values(i)),
30553099
}
30563100
}
30573101

3058-
Some(&mut extra.value)
3102+
// SAFETY: `extra` points at a live extra value, and
3103+
// `front`/`back` ensure this value slot is yielded at most once.
3104+
Some(unsafe { &mut *ptr::addr_of_mut!((*extra).value) })
30593105
}
30603106
None => None,
30613107
}
@@ -3066,28 +3112,37 @@ impl<'a, T: 'a> DoubleEndedIterator for ValueIterMut<'a, T> {
30663112
fn next_back(&mut self) -> Option<Self::Item> {
30673113
use self::Cursor::*;
30683114

3069-
let entry = &mut unsafe { &mut *self.map }.entries[self.index];
3115+
// SAFETY: `self.index` was created from a live occupied entry and stays
3116+
// fixed for the lifetime of this iterator.
3117+
let entry = unsafe { self.entries.add(self.index) };
30703118

30713119
match self.back {
30723120
Some(Head) => {
30733121
self.front = None;
30743122
self.back = None;
3075-
Some(&mut entry.value)
3123+
// SAFETY: `entry` points at a live bucket, and `front`/`back`
3124+
// ensure this value slot is yielded at most once.
3125+
Some(unsafe { &mut *ptr::addr_of_mut!((*entry).value) })
30763126
}
30773127
Some(Values(idx)) => {
3078-
let extra = &mut unsafe { &mut *self.map }.extra_values[idx];
3128+
// SAFETY: `idx` comes from the live linked list rooted at
3129+
// `self.index`, so it refers to a live extra value slot.
3130+
let extra = unsafe { self.extra_values.add(idx) };
30793131

30803132
if self.front == self.back {
30813133
self.front = None;
30823134
self.back = None;
30833135
} else {
3084-
match extra.prev {
3136+
// SAFETY: `extra` points at a live extra value.
3137+
match unsafe { (*extra).prev } {
30853138
Link::Entry(_) => self.back = Some(Head),
30863139
Link::Extra(idx) => self.back = Some(Values(idx)),
30873140
}
30883141
}
30893142

3090-
Some(&mut extra.value)
3143+
// SAFETY: `extra` points at a live extra value, and
3144+
// `front`/`back` ensure this value slot is yielded at most once.
3145+
Some(unsafe { &mut *ptr::addr_of_mut!((*extra).value) })
30913146
}
30923147
None => None,
30933148
}

tests/header_map.rs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -689,3 +689,37 @@ fn ensure_miri_sharedreadonly_not_violated() {
689689

690690
let _foo = &headers.iter().next();
691691
}
692+
693+
#[test]
694+
fn ensure_miri_itermut_not_violated() {
695+
let mut headers = HeaderMap::<u32>::default();
696+
headers.insert(HeaderName::from_static("hello"), 1u32);
697+
headers.insert(HeaderName::from_static("zomg"), 2u32);
698+
699+
let mut iter = headers.iter_mut();
700+
let (_, first) = iter.next().unwrap();
701+
let (_, second) = iter.next().unwrap();
702+
703+
*first += 10;
704+
*second += 20;
705+
}
706+
707+
#[test]
708+
fn ensure_miri_valueitermut_not_violated() {
709+
let mut headers = HeaderMap::<u32>::default();
710+
headers.insert(HeaderName::from_static("hello"), 1u32);
711+
headers.append(HeaderName::from_static("hello"), 2u32);
712+
headers.append(HeaderName::from_static("hello"), 3u32);
713+
714+
let mut entry = match headers.entry(HeaderName::from_static("hello")) {
715+
Entry::Occupied(entry) => entry,
716+
Entry::Vacant(_) => panic!(),
717+
};
718+
719+
let mut iter = entry.iter_mut();
720+
let first = iter.next().unwrap();
721+
let second = iter.next().unwrap();
722+
723+
*first += 10;
724+
*second += 20;
725+
}

0 commit comments

Comments
 (0)