1use crate::{validation::ArchiveContext, Fallible};
4use core::{
5 alloc::{Layout, LayoutError},
6 fmt,
7 ops::Range,
8};
9
10#[derive(Debug)]
12pub enum ArchiveError {
13 Overflow {
15 base: *const u8,
17 offset: isize,
19 },
20 Underaligned {
22 expected_align: usize,
24 actual_align: usize,
26 },
27 OutOfBounds {
29 base: *const u8,
31 offset: isize,
33 range: Range<*const u8>,
35 },
36 Overrun {
38 ptr: *const u8,
40 size: usize,
42 range: Range<*const u8>,
44 },
45 Unaligned {
47 ptr: *const u8,
49 align: usize,
51 },
52 SubtreePointerOutOfBounds {
54 ptr: *const u8,
56 subtree_range: Range<*const u8>,
58 },
59 SubtreePointerOverrun {
61 ptr: *const u8,
63 size: usize,
65 subtree_range: Range<*const u8>,
67 },
68 RangePoppedOutOfOrder {
72 expected_depth: usize,
74 actual_depth: usize,
76 },
77 UnpoppedSubtreeRanges {
79 last_range: usize,
81 },
82 ExceededMaximumSubtreeDepth {
84 max_subtree_depth: usize,
86 },
87 LayoutError {
89 layout_error: LayoutError,
91 },
92}
93
94unsafe impl Send for ArchiveError {}
97
98unsafe impl Sync for ArchiveError {}
101
102impl fmt::Display for ArchiveError {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 match *self {
105 ArchiveError::Overflow { base, offset } => write!(
106 f,
107 "relative pointer overflowed: base {:p} offset {}",
108 base, offset
109 ),
110 ArchiveError::Underaligned {
111 expected_align,
112 actual_align,
113 } => write!(
114 f,
115 "archive underaligned: need alignment {} but have alignment {}",
116 expected_align, actual_align
117 ),
118 ArchiveError::OutOfBounds {
119 base,
120 offset,
121 ref range,
122 } => write!(
123 f,
124 "pointer out of bounds: base {:p} offset {} not in range {:p}..{:p}",
125 base, offset, range.start, range.end
126 ),
127 ArchiveError::Overrun {
128 ptr,
129 size,
130 ref range,
131 } => write!(
132 f,
133 "pointer overran buffer: ptr {:p} size {} in range {:p}..{:p}",
134 ptr, size, range.start, range.end
135 ),
136 ArchiveError::Unaligned { ptr, align } => {
137 write!(
138 f,
139 "unaligned pointer: ptr {:p} unaligned for alignment {}",
140 ptr, align
141 )
142 }
143 ArchiveError::SubtreePointerOutOfBounds {
144 ptr,
145 ref subtree_range,
146 } => write!(
147 f,
148 "subtree pointer out of bounds: ptr {:p} not in range {:p}..{:p}",
149 ptr, subtree_range.start, subtree_range.end
150 ),
151 ArchiveError::SubtreePointerOverrun {
152 ptr,
153 size,
154 ref subtree_range,
155 } => write!(
156 f,
157 "subtree pointer overran range: ptr {:p} size {} in range {:p}..{:p}",
158 ptr, size, subtree_range.start, subtree_range.end
159 ),
160 ArchiveError::RangePoppedOutOfOrder {
161 expected_depth,
162 actual_depth,
163 } => write!(
164 f,
165 "subtree range popped out of order: expected depth {}, actual depth {}",
166 expected_depth, actual_depth
167 ),
168 ArchiveError::UnpoppedSubtreeRanges { ref last_range } => {
169 write!(f, "unpopped subtree ranges: last range {}", last_range)
170 }
171 ArchiveError::ExceededMaximumSubtreeDepth { max_subtree_depth } => write!(
172 f,
173 "pushed a subtree range that exceeded the maximum subtree depth of {}",
174 max_subtree_depth
175 ),
176 ArchiveError::LayoutError { ref layout_error } => {
177 write!(f, "a layout error occurred: {}", layout_error)
178 }
179 }
180 }
181}
182
183#[cfg(feature = "std")]
184impl std::error::Error for ArchiveError {}
185
186#[derive(Debug)]
188pub struct PrefixRange {
189 range: Range<*const u8>,
190 depth: usize,
191}
192
193unsafe impl Send for PrefixRange {}
196
197unsafe impl Sync for PrefixRange {}
200
201#[derive(Debug)]
203pub struct SuffixRange {
204 start: *const u8,
205 depth: usize,
206}
207
208unsafe impl Send for SuffixRange {}
211
212unsafe impl Sync for SuffixRange {}
215
216#[derive(Debug)]
218pub struct ArchiveValidator<'a> {
219 bytes: &'a [u8],
220 subtree_range: Range<*const u8>,
221 subtree_depth: usize,
222 max_subtree_depth: usize,
223}
224
225unsafe impl<'a> Send for ArchiveValidator<'a> {}
228
229unsafe impl<'a> Sync for ArchiveValidator<'a> {}
232
233impl<'a> ArchiveValidator<'a> {
234 #[inline]
236 pub fn new(bytes: &'a [u8]) -> Self {
237 Self::with_max_depth(bytes, usize::MAX)
238 }
239
240 #[inline]
242 pub fn with_max_depth(bytes: &'a [u8], max_subtree_depth: usize) -> Self {
243 Self {
244 bytes,
245 subtree_range: bytes.as_ptr_range(),
246 subtree_depth: 0,
247 max_subtree_depth,
248 }
249 }
250
251 #[inline]
256 pub fn log_alignment(&self) -> usize {
257 (self.bytes.as_ptr() as usize).trailing_zeros() as usize
258 }
259
260 #[inline]
262 pub fn alignment(&self) -> usize {
263 1 << self.log_alignment()
264 }
265}
266
267impl<'a> Fallible for ArchiveValidator<'a> {
268 type Error = ArchiveError;
269}
270
271impl<'a> ArchiveContext for ArchiveValidator<'a> {
272 type PrefixRange = PrefixRange;
273 type SuffixRange = SuffixRange;
274
275 #[inline]
276 unsafe fn bounds_check_ptr(
277 &mut self,
278 base: *const u8,
279 offset: isize,
280 ) -> Result<*const u8, Self::Error> {
281 let base_pos = base.offset_from(self.bytes.as_ptr());
282 let target_pos = base_pos
283 .checked_add(offset)
284 .ok_or(ArchiveError::Overflow { base, offset })?;
285 if target_pos < 0 || target_pos as usize > self.bytes.len() {
286 Err(ArchiveError::OutOfBounds {
287 base,
288 offset,
289 range: self.bytes.as_ptr_range(),
290 })
291 } else {
292 Ok(base.offset(offset))
293 }
294 }
295
296 #[inline]
297 unsafe fn bounds_check_layout(
298 &mut self,
299 data_address: *const u8,
300 layout: &Layout,
301 ) -> Result<(), Self::Error> {
302 if self.alignment() < layout.align() {
303 Err(ArchiveError::Underaligned {
304 expected_align: layout.align(),
305 actual_align: self.alignment(),
306 })
307 } else if (data_address as usize) & (layout.align() - 1) != 0 {
308 Err(ArchiveError::Unaligned {
309 ptr: data_address,
310 align: layout.align(),
311 })
312 } else {
313 let available_space = self.bytes.as_ptr_range().end.offset_from(data_address) as usize;
314 if available_space < layout.size() {
315 Err(ArchiveError::Overrun {
316 ptr: data_address,
317 size: layout.size(),
318 range: self.bytes.as_ptr_range(),
319 })
320 } else {
321 Ok(())
322 }
323 }
324 }
325
326 #[inline]
327 unsafe fn bounds_check_subtree_ptr_layout(
328 &mut self,
329 data_address: *const u8,
330 layout: &Layout,
331 ) -> Result<(), Self::Error> {
332 if layout.size() == 0 {
333 if data_address < self.subtree_range.start || data_address > self.subtree_range.end {
334 Err(ArchiveError::SubtreePointerOutOfBounds {
335 ptr: data_address,
336 subtree_range: self.subtree_range.clone(),
337 })
338 } else {
339 Ok(())
340 }
341 } else if !self.subtree_range.contains(&data_address) {
342 Err(ArchiveError::SubtreePointerOutOfBounds {
343 ptr: data_address,
344 subtree_range: self.subtree_range.clone(),
345 })
346 } else {
347 let available_space = self.subtree_range.end.offset_from(data_address) as usize;
348 if available_space < layout.size() {
349 Err(ArchiveError::SubtreePointerOverrun {
350 ptr: data_address,
351 size: layout.size(),
352 subtree_range: self.subtree_range.clone(),
353 })
354 } else {
355 Ok(())
356 }
357 }
358 }
359
360 #[inline]
361 unsafe fn push_prefix_subtree_range(
362 &mut self,
363 root: *const u8,
364 end: *const u8,
365 ) -> Result<PrefixRange, Self::Error> {
366 if self.subtree_depth >= self.max_subtree_depth {
367 Err(ArchiveError::ExceededMaximumSubtreeDepth {
368 max_subtree_depth: self.max_subtree_depth,
369 })
370 } else {
371 let result = PrefixRange {
372 range: Range {
373 start: end,
374 end: self.subtree_range.end,
375 },
376 depth: self.subtree_depth,
377 };
378 self.subtree_depth += 1;
379 self.subtree_range.end = root;
380 Ok(result)
381 }
382 }
383
384 #[inline]
385 fn pop_prefix_range(&mut self, range: PrefixRange) -> Result<(), Self::Error> {
386 if self.subtree_depth - 1 != range.depth {
387 Err(ArchiveError::RangePoppedOutOfOrder {
388 expected_depth: self.subtree_depth - 1,
389 actual_depth: range.depth,
390 })
391 } else {
392 self.subtree_range = range.range;
393 self.subtree_depth = range.depth;
394 Ok(())
395 }
396 }
397
398 #[inline]
399 unsafe fn push_suffix_subtree_range(
400 &mut self,
401 start: *const u8,
402 root: *const u8,
403 ) -> Result<SuffixRange, Self::Error> {
404 let result = SuffixRange {
405 start: self.subtree_range.start,
406 depth: self.subtree_depth,
407 };
408 self.subtree_depth += 1;
409 self.subtree_range.start = start;
410 self.subtree_range.end = root;
411 Ok(result)
412 }
413
414 #[inline]
415 fn pop_suffix_range(&mut self, range: SuffixRange) -> Result<(), Self::Error> {
416 if self.subtree_depth - 1 != range.depth {
417 Err(ArchiveError::RangePoppedOutOfOrder {
418 expected_depth: self.subtree_depth - 1,
419 actual_depth: range.depth,
420 })
421 } else {
422 self.subtree_range.end = self.subtree_range.start;
423 self.subtree_range.start = range.start;
424 self.subtree_depth = range.depth;
425 Ok(())
426 }
427 }
428
429 #[inline]
430 fn finish(&mut self) -> Result<(), Self::Error> {
431 if self.subtree_depth != 0 {
432 Err(ArchiveError::UnpoppedSubtreeRanges {
433 last_range: self.subtree_depth - 1,
434 })
435 } else {
436 Ok(())
437 }
438 }
439
440 fn wrap_layout_error(layout_error: core::alloc::LayoutError) -> Self::Error {
441 ArchiveError::LayoutError { layout_error }
442 }
443}