diff --git a/CHANGELOG.md b/CHANGELOG.md
index 3de372b8..62fd3ebe 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 0.2.11 (November 13, 2023)
+
+* Fix MIRI error in `header::Iter`.
+
 # 0.2.10 (November 10, 2023)
 
 * Fix parsing of `Authority` to handle square brackets in incorrect order.
diff --git a/Cargo.toml b/Cargo.toml
index 3672249b..25ca5011 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -4,7 +4,7 @@ name = "http"
 # - Update html_root_url in lib.rs.
 # - Update CHANGELOG.md.
 # - Create git tag
-version = "0.2.10"
+version = "0.2.11"
 readme = "README.md"
 documentation = "https://docs.rs/http"
 repository = "https://github.com/hyperium/http"
diff --git a/src/header/map.rs b/src/header/map.rs
index dd0f262a..0290160e 100644
--- a/src/header/map.rs
+++ b/src/header/map.rs
@@ -82,7 +82,9 @@ pub struct HeaderMap<T = HeaderValue> {
 /// more than once if it has more than one associated value.
 #[derive(Debug)]
 pub struct Iter<'a, T> {
-    inner: IterMut<'a, T>,
+    map: &'a HeaderMap<T>,
+    entry: usize,
+    cursor: Option<Cursor>,
 }
 
 /// `HeaderMap` mutable entry iterator
@@ -811,12 +813,9 @@ impl<T> HeaderMap<T> {
     /// ```
     pub fn iter(&self) -> Iter<'_, T> {
         Iter {
-            inner: IterMut {
-                map: self as *const _ as *mut _,
-                entry: 0,
-                cursor: self.entries.first().map(|_| Cursor::Head),
-                lt: PhantomData,
-            },
+            map: self,
+            entry: 0,
+            cursor: self.entries.first().map(|_| Cursor::Head),
         }
     }
 
@@ -2078,13 +2077,47 @@ impl<'a, T> Iterator for Iter<'a, T> {
     type Item = (&'a HeaderName, &'a T);
 
     fn next(&mut self) -> Option<Self::Item> {
-        self.inner
-            .next_unsafe()
-            .map(|(key, ptr)| (key, unsafe { &*ptr }))
+        use self::Cursor::*;
+
+        if self.cursor.is_none() {
+            if (self.entry + 1) >= self.map.entries.len() {
+                return None;
+            }
+
+            self.entry += 1;
+            self.cursor = Some(Cursor::Head);
+        }
+
+        let entry = &self.map.entries[self.entry];
+
+        match self.cursor.unwrap() {
+            Head => {
+                self.cursor = entry.links.map(|l| Values(l.next));
+                Some((&entry.key, &entry.value))
+            }
+            Values(idx) => {
+                let extra = &self.map.extra_values[idx];
+
+                match extra.next {
+                    Link::Entry(_) => self.cursor = None,
+                    Link::Extra(i) => self.cursor = Some(Values(i)),
+                }
+
+                Some((&entry.key, &extra.value))
+            }
+        }
     }
 
     fn size_hint(&self) -> (usize, Option<usize>) {
-        self.inner.size_hint()
+        let map = self.map;
+        debug_assert!(map.entries.len() >= self.entry);
+
+        let lower = map.entries.len() - self.entry;
+        // We could pessimistically guess at the upper bound, saying
+        // that its lower + map.extra_values.len(). That could be
+        // way over though, such as if we're near the end, and have
+        // already gone through several extra values...
+        (lower, None)
     }
 }
 
diff --git a/src/lib.rs b/src/lib.rs
index 22901438..ed570e1f 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,4 +1,4 @@
-#![doc(html_root_url = "https://docs.rs/http/0.2.10")]
+#![doc(html_root_url = "https://docs.rs/http/0.2.11")]
 
 //! A general purpose library of common HTTP types
 //!
diff --git a/tests/header_map_fuzz.rs b/tests/header_map_fuzz.rs
index 68a8604f..c3af2e52 100644
--- a/tests/header_map_fuzz.rs
+++ b/tests/header_map_fuzz.rs
@@ -8,6 +8,7 @@ use rand::{Rng, SeedableRng};
 
 use std::collections::HashMap;
 
+#[cfg(not(miri))]
 #[test]
 fn header_map_fuzz() {
     fn prop(fuzz: Fuzz) -> TestResult {