1use super::{
4 ArchivedBTreeMap, ClassifiedNode, InnerNode, InnerNodeEntry, LeafNode, LeafNodeEntry, Node,
5 NodeHeader, MIN_ENTRIES_PER_INNER_NODE, MIN_ENTRIES_PER_LEAF_NODE,
6};
7use crate::{
8 rel_ptr::RelPtr,
9 validation::{ArchiveContext, LayoutRaw},
10 Archived, Fallible,
11};
12use bytecheck::{CheckBytes, Error};
13use core::{
14 alloc::{Layout, LayoutError},
15 convert::{Infallible, TryFrom},
16 fmt,
17 hint::unreachable_unchecked,
18 ptr,
19};
20use ptr_meta::Pointee;
21
22impl<K, C> CheckBytes<C> for InnerNodeEntry<K>
23where
24 K: CheckBytes<C>,
25 C: ArchiveContext + ?Sized,
26 C::Error: Error,
27{
28 type Error = K::Error;
29
30 #[inline]
31 unsafe fn check_bytes<'a>(
32 value: *const Self,
33 context: &mut C,
34 ) -> Result<&'a Self, Self::Error> {
35 RelPtr::manual_check_bytes(ptr::addr_of!((*value).ptr), context)
36 .unwrap_or_else(|_| core::hint::unreachable_unchecked());
37 K::check_bytes(ptr::addr_of!((*value).key), context)?;
38
39 Ok(&*value)
40 }
41}
42
43#[derive(Debug)]
45pub enum LeafNodeEntryError<K, V> {
46 KeyCheckError(K),
48 ValueCheckError(V),
50}
51
52impl<K: fmt::Display, V: fmt::Display> fmt::Display for LeafNodeEntryError<K, V> {
53 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
54 match self {
55 LeafNodeEntryError::KeyCheckError(e) => write!(f, "key check error: {}", e),
56 LeafNodeEntryError::ValueCheckError(e) => write!(f, "value check error: {}", e),
57 }
58 }
59}
60
61#[cfg(feature = "std")]
62const _: () = {
63 use std::error::Error;
64
65 impl<K: Error + 'static, V: Error + 'static> Error for LeafNodeEntryError<K, V> {
66 fn source(&self) -> Option<&(dyn Error + 'static)> {
67 match self {
68 Self::KeyCheckError(e) => Some(e as &dyn Error),
69 Self::ValueCheckError(e) => Some(e as &dyn Error),
70 }
71 }
72 }
73};
74
75impl<K, V, C> CheckBytes<C> for LeafNodeEntry<K, V>
76where
77 K: CheckBytes<C>,
78 V: CheckBytes<C>,
79 C: Fallible + ?Sized,
80 C::Error: Error,
81{
82 type Error = LeafNodeEntryError<K::Error, V::Error>;
83
84 #[inline]
85 unsafe fn check_bytes<'a>(
86 value: *const Self,
87 context: &mut C,
88 ) -> Result<&'a Self, Self::Error> {
89 K::check_bytes(ptr::addr_of!((*value).key), context)
90 .map_err(LeafNodeEntryError::KeyCheckError)?;
91 V::check_bytes(ptr::addr_of!((*value).value), context)
92 .map_err(LeafNodeEntryError::ValueCheckError)?;
93 Ok(&*value)
94 }
95}
96
97#[derive(Debug)]
99pub enum ArchivedBTreeMapError<K, V, C> {
100 KeyCheckError(K),
102 ValueCheckError(V),
104 TooFewInnerNodeEntries(usize),
106 TooFewLeafNodeEntries(usize),
108 CheckInnerNodeEntryError {
110 index: usize,
112 inner: K,
114 },
115 CheckLeafNodeEntryError {
117 index: usize,
119 inner: LeafNodeEntryError<K, V>,
121 },
122 InvalidNodeSize(usize),
124 MismatchedInnerChildKey,
126 InnerNodeInLeafLevel,
128 InvalidLeafNodeDepth {
130 expected: usize,
132 actual: usize,
134 },
135 UnsortedLeafNodeEntries,
137 UnlinkedLeafNode,
139 UnsortedLeafNode,
141 LastLeafForwardPointerNotNull,
143 LengthMismatch {
145 expected: usize,
147 actual: usize,
149 },
150 IncorrectChildKey,
152 ContextError(C),
154}
155
156impl<K, V, C> From<Infallible> for ArchivedBTreeMapError<K, V, C> {
157 fn from(_: Infallible) -> Self {
158 unsafe { core::hint::unreachable_unchecked() }
159 }
160}
161
162impl<K, V, C> fmt::Display for ArchivedBTreeMapError<K, V, C>
163where
164 K: fmt::Display,
165 V: fmt::Display,
166 C: fmt::Display,
167{
168 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
169 match self {
170 Self::KeyCheckError(e) => write!(f, "key check error: {}", e),
171 Self::ValueCheckError(e) => write!(f, "value check error: {}", e),
172 Self::TooFewInnerNodeEntries(n) => write!(
173 f,
174 "too few inner node entries (expected at least {}): {}",
175 MIN_ENTRIES_PER_INNER_NODE, n
176 ),
177 Self::TooFewLeafNodeEntries(n) => write!(
178 f,
179 "too few leaf node entries (expected at least {}): {}",
180 MIN_ENTRIES_PER_LEAF_NODE, n,
181 ),
182 Self::CheckInnerNodeEntryError { index, inner } => write!(
183 f,
184 "inner node entry check error: index {}, error {}",
185 index, inner
186 ),
187 Self::CheckLeafNodeEntryError { index, inner } => write!(
188 f,
189 "leaf node entry check error: index {}, error {}",
190 index, inner
191 ),
192 Self::InvalidNodeSize(n) => write!(f, "invalid node size: {}", n),
193 Self::MismatchedInnerChildKey => write!(f, "mismatched inner child key"),
194 Self::InnerNodeInLeafLevel => write!(f, "inner node in leaf level"),
195 Self::InvalidLeafNodeDepth { expected, actual } => write!(
196 f,
197 "expected leaf node depth {} but found leaf node depth {}",
198 expected, actual,
199 ),
200 Self::UnsortedLeafNodeEntries => write!(f, "leaf node contains keys in unsorted order"),
201 Self::UnlinkedLeafNode => write!(f, "leaf nodes are not linked in the sorted order"),
202 Self::UnsortedLeafNode => write!(f, "leaf nodes are not linked in sorted order"),
203 Self::LastLeafForwardPointerNotNull => {
204 write!(f, "the forward pointer of the last leaf was not null")
205 }
206 Self::LengthMismatch { expected, actual } => write!(
207 f,
208 "expected {} entries but there were actually {} entries",
209 expected, actual,
210 ),
211 Self::IncorrectChildKey => write!(f, "incorrect child key in inner node"),
212 Self::ContextError(e) => write!(f, "context error: {}", e),
213 }
214 }
215}
216
217#[cfg(feature = "std")]
218const _: () = {
219 use std::error::Error;
220
221 impl<K, V, C> Error for ArchivedBTreeMapError<K, V, C>
222 where
223 K: Error + 'static,
224 V: Error + 'static,
225 C: Error + 'static,
226 {
227 fn source(&self) -> Option<&(dyn Error + 'static)> {
228 match self {
229 Self::KeyCheckError(e) => Some(e as &dyn Error),
230 Self::ValueCheckError(e) => Some(e as &dyn Error),
231 Self::TooFewInnerNodeEntries(_) => None,
232 Self::TooFewLeafNodeEntries(_) => None,
233 Self::CheckInnerNodeEntryError { inner, .. } => Some(inner as &dyn Error),
234 Self::CheckLeafNodeEntryError { inner, .. } => Some(inner as &dyn Error),
235 Self::InvalidNodeSize(_) => None,
236 Self::MismatchedInnerChildKey => None,
237 Self::InnerNodeInLeafLevel => None,
238 Self::InvalidLeafNodeDepth { .. } => None,
239 Self::UnsortedLeafNodeEntries => None,
240 Self::UnlinkedLeafNode => None,
241 Self::UnsortedLeafNode => None,
242 Self::LastLeafForwardPointerNotNull => None,
243 Self::LengthMismatch { .. } => None,
244 Self::IncorrectChildKey => None,
245 Self::ContextError(e) => Some(e as &dyn Error),
246 }
247 }
248 }
249};
250
251impl<T> LayoutRaw for Node<[T]> {
252 fn layout_raw(metadata: <Self as Pointee>::Metadata) -> Result<Layout, LayoutError> {
253 let result = Layout::new::<NodeHeader>()
254 .extend(Layout::array::<T>(metadata).unwrap())?
255 .0;
256 #[cfg(not(feature = "strict"))]
257 {
258 Ok(result)
259 }
260 #[cfg(feature = "strict")]
261 {
262 Ok(result.pad_to_align())
263 }
264 }
265}
266
267type ABTMError<K, V, C> = ArchivedBTreeMapError<
268 <K as CheckBytes<C>>::Error,
269 <V as CheckBytes<C>>::Error,
270 <C as Fallible>::Error,
271>;
272
273impl NodeHeader {
274 #[inline]
275 unsafe fn manual_check_bytes<'a, K, V, C>(
276 value: *const Self,
277 context: &mut C,
278 ) -> Result<&'a Self, ABTMError<K, V, C>>
279 where
280 K: CheckBytes<C>,
281 V: CheckBytes<C>,
282 C: ArchiveContext + ?Sized,
283 C::Error: Error,
284 {
285 let raw_node = Self::manual_check_header(value, context)
286 .map_err(ArchivedBTreeMapError::ContextError)?;
287
288 let node_layout = if raw_node.is_inner() {
289 InnerNode::<K>::layout_raw(ptr_meta::metadata(raw_node.classify_inner_ptr::<K>()))
290 .map_err(C::wrap_layout_error)
291 .map_err(ArchivedBTreeMapError::ContextError)?
292 } else {
293 LeafNode::<K, V>::layout_raw(ptr_meta::metadata(raw_node.classify_leaf_ptr::<K, V>()))
294 .map_err(C::wrap_layout_error)
295 .map_err(ArchivedBTreeMapError::ContextError)?
296 };
297
298 context
299 .bounds_check_subtree_ptr_layout((raw_node as *const NodeHeader).cast(), &node_layout)
300 .map_err(ArchivedBTreeMapError::ContextError)?;
301
302 Self::manual_check_contents::<K, V, C>(raw_node, context)?;
303
304 Ok(raw_node)
305 }
306
307 #[inline]
308 unsafe fn manual_check_header<'a, C>(
309 value: *const Self,
310 context: &mut C,
311 ) -> Result<&'a Self, C::Error>
312 where
313 C: ArchiveContext + ?Sized,
314 C::Error: Error,
315 {
316 CheckBytes::check_bytes(ptr::addr_of!((*value).meta), context).map_err(
317 |_: Infallible| unreachable_unchecked(),
319 )?;
320 CheckBytes::check_bytes(ptr::addr_of!((*value).size), context).map_err(
321 |_: Infallible| unreachable_unchecked(),
323 )?;
324 RelPtr::manual_check_bytes(ptr::addr_of!((*value).ptr), context).map_err(
325 |_: Infallible| unreachable_unchecked(),
327 )?;
328
329 Ok(&*value)
331 }
332
333 #[inline]
334 unsafe fn manual_check_contents<K, V, C>(
335 raw_node: &Self,
336 context: &mut C,
337 ) -> Result<(), ABTMError<K, V, C>>
338 where
339 K: CheckBytes<C>,
340 V: CheckBytes<C>,
341 C: ArchiveContext + ?Sized,
342 C::Error: Error,
343 {
344 let root = (raw_node as *const Self).cast();
346 let size = from_archived!(raw_node.size) as usize;
347 let offset =
348 -isize::try_from(size).map_err(|_| ArchivedBTreeMapError::InvalidNodeSize(size))?;
349 let start = context
350 .check_ptr(root, offset, ())
351 .map_err(ArchivedBTreeMapError::ContextError)?;
352
353 let range = context
355 .push_suffix_subtree_range(start, root)
356 .map_err(ArchivedBTreeMapError::ContextError)?;
357 if raw_node.is_inner() {
358 InnerNode::manual_check_bytes::<V, C>(raw_node.classify_inner_ptr::<K>(), context)?;
359 } else {
360 CheckBytes::check_bytes(raw_node.classify_leaf_ptr::<K, V>(), context)?;
361 }
362 context
363 .pop_suffix_range(range)
364 .map_err(ArchivedBTreeMapError::ContextError)?;
365
366 Ok(())
367 }
368}
369
370impl<K> InnerNode<K> {
371 #[allow(clippy::type_complexity)]
372 fn verify_integrity<'a, V, C>(
373 &'a self,
374 ) -> Result<&K, ArchivedBTreeMapError<K::Error, V::Error, C::Error>>
375 where
376 K: CheckBytes<C> + PartialEq,
377 V: CheckBytes<C> + 'a,
378 C: Fallible + ?Sized,
379 {
380 for entry in self.tail.iter() {
381 let child = unsafe { &*entry.ptr.as_ptr() }.classify::<K, V>();
382 let first_key = match child {
383 ClassifiedNode::Inner(c) => c.verify_integrity::<V, C>()?,
384 ClassifiedNode::Leaf(c) => &c.tail[0].key,
385 };
386 if !entry.key.eq(first_key) {
387 return Err(ArchivedBTreeMapError::IncorrectChildKey);
388 }
389 }
390
391 let least_child = unsafe { &*self.header.ptr.as_ptr() }.classify::<K, V>();
392 let first_key = match least_child {
393 ClassifiedNode::Inner(c) => c.verify_integrity::<V, C>()?,
394 ClassifiedNode::Leaf(c) => &c.tail[0].key,
395 };
396
397 Ok(first_key)
398 }
399
400 #[inline]
401 unsafe fn manual_check_bytes<'a, V, C>(
402 value: *const Self,
403 context: &mut C,
404 ) -> Result<&'a Self, ABTMError<K, V, C>>
405 where
406 K: CheckBytes<C>,
407 V: CheckBytes<C>,
408 C: ArchiveContext + ?Sized,
409 C::Error: Error,
410 {
411 let len = ptr_meta::metadata(value);
413
414 if len + 1 < MIN_ENTRIES_PER_INNER_NODE {
417 return Err(ArchivedBTreeMapError::TooFewInnerNodeEntries(len + 1));
418 }
419
420 let tail_ptr = ptr::addr_of!((*value).tail) as *const InnerNodeEntry<K>;
422 for index in (0..len).rev() {
423 CheckBytes::check_bytes(tail_ptr.add(index), context).map_err(|inner| {
424 ArchivedBTreeMapError::CheckInnerNodeEntryError { index, inner }
425 })?;
426 }
427
428 Ok(&*value)
429 }
430}
431
432impl<K, V, C> CheckBytes<C> for LeafNode<K, V>
433where
434 K: CheckBytes<C>,
435 V: CheckBytes<C>,
436 C: ArchiveContext + ?Sized,
437 C::Error: Error,
438{
439 type Error = ArchivedBTreeMapError<K::Error, V::Error, C::Error>;
440
441 #[inline]
442 unsafe fn check_bytes<'a>(
443 value: *const Self,
444 context: &mut C,
445 ) -> Result<&'a Self, Self::Error> {
446 let len = ptr_meta::metadata(value);
448
449 if len < MIN_ENTRIES_PER_LEAF_NODE {
450 return Err(ArchivedBTreeMapError::TooFewLeafNodeEntries(len));
451 }
452
453 let tail_ptr = ptr::addr_of!((*value).tail) as *const LeafNodeEntry<K, V>;
455 for index in (0..len).rev() {
456 CheckBytes::check_bytes(tail_ptr.add(index), context)
457 .map_err(|inner| ArchivedBTreeMapError::CheckLeafNodeEntryError { index, inner })?;
458 }
459
460 Ok(&*value)
461 }
462}
463
464#[cfg(feature = "alloc")]
465const _: () = {
466 #[cfg(not(feature = "std"))]
467 use alloc::collections::VecDeque;
468 #[cfg(feature = "std")]
469 use std::collections::VecDeque;
470
471 impl<K, V, C> CheckBytes<C> for ArchivedBTreeMap<K, V>
472 where
473 K: CheckBytes<C> + Ord,
474 V: CheckBytes<C>,
475 C: ArchiveContext + ?Sized,
476 C::Error: Error,
477 {
478 type Error = ArchivedBTreeMapError<K::Error, V::Error, C::Error>;
479
480 unsafe fn check_bytes<'a>(
481 value: *const Self,
482 context: &mut C,
483 ) -> Result<&'a Self, Self::Error> {
484 let len = from_archived!(*Archived::<usize>::check_bytes(
485 ptr::addr_of!((*value).len),
486 context,
487 )?) as usize;
488
489 if len > 0 {
490 let root_rel_ptr =
491 RelPtr::manual_check_bytes(ptr::addr_of!((*value).root), context)?;
492
493 let mut nodes = VecDeque::new();
495 let root_ptr = context
496 .check_subtree_rel_ptr(root_rel_ptr)
497 .map_err(ArchivedBTreeMapError::ContextError)?;
498
499 let root = NodeHeader::manual_check_header(root_ptr, context)
504 .map_err(ArchivedBTreeMapError::ContextError)?;
505
506 let root_layout = if root.is_inner() {
509 InnerNode::<K>::layout_raw(ptr_meta::metadata(root.classify_inner_ptr::<K>()))
510 .map_err(C::wrap_layout_error)
511 .map_err(ArchivedBTreeMapError::ContextError)?
512 } else {
513 LeafNode::<K, V>::layout_raw(ptr_meta::metadata(
514 root.classify_leaf_ptr::<K, V>(),
515 ))
516 .map_err(C::wrap_layout_error)
517 .map_err(ArchivedBTreeMapError::ContextError)?
518 };
519
520 context
523 .bounds_check_subtree_ptr_layout(root_ptr.cast(), &root_layout)
524 .map_err(ArchivedBTreeMapError::ContextError)?;
525
526 let nodes_range = context
528 .push_prefix_subtree_range(
529 root_ptr.cast(),
530 root_ptr.cast::<u8>().add(root_layout.size()),
531 )
532 .map_err(ArchivedBTreeMapError::ContextError)?;
533
534 NodeHeader::manual_check_contents::<K, V, C>(root, context)?;
536
537 nodes.push_back((root, 0));
538
539 while let Some(&(node, depth)) = nodes.front() {
540 if !node.is_inner() {
542 break;
543 }
544 nodes.pop_front();
545 let inner = node.classify_inner::<K>();
546
547 let child_ptr = context
548 .check_subtree_rel_ptr(&inner.header.ptr)
549 .map_err(ArchivedBTreeMapError::ContextError)?;
550 let child = NodeHeader::manual_check_bytes::<K, V, C>(child_ptr, context)?;
551 nodes.push_back((child, depth + 1));
552
553 for entry in inner.tail.iter() {
556 let child_ptr = context
557 .check_subtree_rel_ptr(&entry.ptr)
558 .map_err(ArchivedBTreeMapError::ContextError)?;
559 let child = NodeHeader::manual_check_bytes::<K, V, C>(child_ptr, context)?;
560 nodes.push_back((child, depth + 1));
561 }
562 }
563
564 context
566 .pop_prefix_range(nodes_range)
567 .map_err(ArchivedBTreeMapError::ContextError)?;
568
569 let mut entry_count = 0;
571 for (node, depth) in nodes.iter() {
572 if !node.is_leaf() {
573 return Err(ArchivedBTreeMapError::InnerNodeInLeafLevel);
574 }
575 let leaf = node.classify_leaf::<K, V>();
576
577 let expected_depth = nodes.front().unwrap().1;
579 if *depth != expected_depth {
580 return Err(ArchivedBTreeMapError::InvalidLeafNodeDepth {
581 expected: expected_depth,
582 actual: *depth,
583 });
584 }
585
586 for (prev, next) in leaf.tail.iter().zip(leaf.tail.iter().skip(1)) {
588 if next.key < prev.key {
589 return Err(ArchivedBTreeMapError::UnsortedLeafNodeEntries);
590 }
591 }
592
593 entry_count += leaf.tail.len();
595 }
596
597 for (i, (node, _)) in nodes.iter().enumerate() {
598 let leaf = node.classify_leaf::<K, V>();
599
600 if i < nodes.len() - 1 {
602 let next_ptr = context
603 .check_rel_ptr(&leaf.header.ptr)
604 .map_err(ArchivedBTreeMapError::ContextError)?;
605 let next_node = nodes[i + 1].0.classify_leaf();
606
607 if next_ptr != (next_node as *const LeafNode<K, V>).cast() {
608 return Err(ArchivedBTreeMapError::UnlinkedLeafNode);
609 }
610 if next_node.tail[0].key < leaf.tail[leaf.tail.len() - 1].key {
611 return Err(ArchivedBTreeMapError::UnsortedLeafNode);
612 }
613 } else {
614 if !leaf.header.ptr.is_null() {
616 return Err(ArchivedBTreeMapError::LastLeafForwardPointerNotNull);
617 }
618 }
619 }
620
621 if entry_count != len {
623 return Err(ArchivedBTreeMapError::LengthMismatch {
624 expected: len,
625 actual: entry_count,
626 });
627 }
628
629 if root.is_inner() {
631 root.classify_inner::<K>().verify_integrity::<V, C>()?;
632 }
633 }
634
635 Ok(&*value)
636 }
637 }
638};