rkyv_test/validation/validators/
archive.rs1use crate::{validation::ArchiveContext, Fallible};
4use core::{alloc::Layout, fmt, ops::Range};
5
6#[derive(Debug)]
8pub enum ArchiveError {
9 Overflow {
11 base: *const u8,
13 offset: isize,
15 },
16 Underaligned {
18 expected_align: usize,
20 actual_align: usize,
22 },
23 OutOfBounds {
25 base: *const u8,
27 offset: isize,
29 range: Range<*const u8>,
31 },
32 Overrun {
34 ptr: *const u8,
36 size: usize,
38 range: Range<*const u8>,
40 },
41 Unaligned {
43 ptr: *const u8,
45 align: usize,
47 },
48 SubtreePointerOutOfBounds {
50 ptr: *const u8,
52 subtree_range: Range<*const u8>,
54 },
55 SubtreePointerOverrun {
57 ptr: *const u8,
59 size: usize,
61 subtree_range: Range<*const u8>,
63 },
64 RangePoppedOutOfOrder {
68 expected_depth: usize,
70 actual_depth: usize,
72 },
73 UnpoppedSubtreeRanges {
75 last_range: usize,
77 },
78 ExceededMaximumSubtreeDepth {
80 max_subtree_depth: usize,
82 },
83}
84
85unsafe impl Send for ArchiveError {}
88
89unsafe impl Sync for ArchiveError {}
92
93impl fmt::Display for ArchiveError {
94 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
95 match self {
96 ArchiveError::Overflow { base, offset } => write!(
97 f,
98 "relative pointer overflowed: base {:p} offset {}",
99 base, offset
100 ),
101 ArchiveError::Underaligned {
102 expected_align,
103 actual_align,
104 } => write!(
105 f,
106 "archive underaligned: need alignment {} but have alignment {}",
107 expected_align, actual_align
108 ),
109 ArchiveError::OutOfBounds {
110 base,
111 offset,
112 range,
113 } => write!(
114 f,
115 "pointer out of bounds: base {:p} offset {} not in range {:p}..{:p}",
116 base, offset, range.start, range.end
117 ),
118 ArchiveError::Overrun { ptr, size, range } => write!(
119 f,
120 "pointer overran buffer: ptr {:p} size {} in range {:p}..{:p}",
121 ptr, size, range.start, range.end
122 ),
123 ArchiveError::Unaligned { ptr, align } => write!(
124 f,
125 "unaligned pointer: ptr {:p} unaligned for alignment {}",
126 ptr, align
127 ),
128 ArchiveError::SubtreePointerOutOfBounds { ptr, subtree_range } => write!(
129 f,
130 "subtree pointer out of bounds: ptr {:p} not in range {:p}..{:p}",
131 ptr, subtree_range.start, subtree_range.end
132 ),
133 ArchiveError::SubtreePointerOverrun {
134 ptr,
135 size,
136 subtree_range,
137 } => write!(
138 f,
139 "subtree pointer overran range: ptr {:p} size {} in range {:p}..{:p}",
140 ptr, size, subtree_range.start, subtree_range.end
141 ),
142 ArchiveError::RangePoppedOutOfOrder {
143 expected_depth,
144 actual_depth,
145 } => write!(
146 f,
147 "subtree range popped out of order: expected depth {}, actual depth {}",
148 expected_depth, actual_depth
149 ),
150 ArchiveError::UnpoppedSubtreeRanges { last_range } => {
151 write!(f, "unpopped subtree ranges: last range {}", last_range)
152 }
153 ArchiveError::ExceededMaximumSubtreeDepth { max_subtree_depth } => write!(
154 f,
155 "pushed a subtree range that exceeded the maximum subtree depth of {}",
156 max_subtree_depth
157 ),
158 }
159 }
160}
161
162#[cfg(feature = "std")]
163impl std::error::Error for ArchiveError {}
164
165#[derive(Debug)]
167pub struct PrefixRange {
168 range: Range<*const u8>,
169 depth: usize,
170}
171
172unsafe impl<'a> Send for PrefixRange {}
175
176unsafe impl Sync for PrefixRange {}
179
180#[derive(Debug)]
182pub struct SuffixRange {
183 start: *const u8,
184 depth: usize,
185}
186
187unsafe impl<'a> Send for SuffixRange {}
190
191unsafe impl Sync for SuffixRange {}
194
195#[derive(Debug)]
197pub struct ArchiveValidator<'a> {
198 bytes: &'a [u8],
199 subtree_range: Range<*const u8>,
200 subtree_depth: usize,
201 max_subtree_depth: usize,
202}
203
204unsafe impl<'a> Send for ArchiveValidator<'a> {}
207
208unsafe impl<'a> Sync for ArchiveValidator<'a> {}
211
212impl<'a> ArchiveValidator<'a> {
213 #[inline]
215 pub fn new(bytes: &'a [u8]) -> Self {
216 Self::with_max_depth(bytes, usize::MAX)
217 }
218
219 #[inline]
221 pub fn with_max_depth(bytes: &'a [u8], max_subtree_depth: usize) -> Self {
222 Self {
223 bytes,
224 subtree_range: bytes.as_ptr_range(),
225 subtree_depth: 0,
226 max_subtree_depth,
227 }
228 }
229
230 #[inline]
235 pub fn log_alignment(&self) -> usize {
236 (self.bytes.as_ptr() as usize).trailing_zeros() as usize
237 }
238
239 #[inline]
241 pub fn alignment(&self) -> usize {
242 1 << self.log_alignment()
243 }
244}
245
246impl<'a> Fallible for ArchiveValidator<'a> {
247 type Error = ArchiveError;
248}
249
250impl<'a> ArchiveContext for ArchiveValidator<'a> {
251 type PrefixRange = PrefixRange;
252 type SuffixRange = SuffixRange;
253
254 #[inline]
255 unsafe fn bounds_check_ptr(
256 &mut self,
257 base: *const u8,
258 offset: isize,
259 ) -> Result<*const u8, Self::Error> {
260 let base_pos = base.offset_from(self.bytes.as_ptr());
261 let target_pos = base_pos
262 .checked_add(offset)
263 .ok_or(ArchiveError::Overflow { base, offset })?;
264 if target_pos < 0 || target_pos as usize > self.bytes.len() {
265 Err(ArchiveError::OutOfBounds {
266 base,
267 offset,
268 range: self.bytes.as_ptr_range(),
269 })
270 } else {
271 Ok(base.offset(offset))
272 }
273 }
274
275 #[inline]
276 unsafe fn bounds_check_layout(
277 &mut self,
278 data_address: *const u8,
279 layout: &Layout,
280 ) -> Result<(), Self::Error> {
281 if self.alignment() < layout.align() {
282 Err(ArchiveError::Underaligned {
283 expected_align: layout.align(),
284 actual_align: self.alignment(),
285 })
286 } else if (data_address as usize) & (layout.align() - 1) != 0 {
287 Err(ArchiveError::Unaligned {
288 ptr: data_address,
289 align: layout.align(),
290 })
291 } else {
292 let available_space = self.bytes.as_ptr_range().end.offset_from(data_address) as usize;
293 if available_space < layout.size() {
294 Err(ArchiveError::Overrun {
295 ptr: data_address,
296 size: layout.size(),
297 range: self.bytes.as_ptr_range(),
298 })
299 } else {
300 Ok(())
301 }
302 }
303 }
304
305 #[inline]
306 unsafe fn bounds_check_subtree_ptr_layout(
307 &mut self,
308 data_address: *const u8,
309 layout: &Layout,
310 ) -> Result<(), Self::Error> {
311 if layout.size() == 0 {
312 if data_address < self.subtree_range.start || data_address > self.subtree_range.end {
313 Err(ArchiveError::SubtreePointerOutOfBounds {
314 ptr: data_address,
315 subtree_range: self.subtree_range.clone(),
316 })
317 } else {
318 Ok(())
319 }
320 } else if !self.subtree_range.contains(&data_address) {
321 Err(ArchiveError::SubtreePointerOutOfBounds {
322 ptr: data_address,
323 subtree_range: self.subtree_range.clone(),
324 })
325 } else {
326 let available_space = self.subtree_range.end.offset_from(data_address) as usize;
327 if available_space < layout.size() {
328 Err(ArchiveError::SubtreePointerOverrun {
329 ptr: data_address,
330 size: layout.size(),
331 subtree_range: self.subtree_range.clone(),
332 })
333 } else {
334 Ok(())
335 }
336 }
337 }
338
339 #[inline]
340 unsafe fn push_prefix_subtree_range(
341 &mut self,
342 root: *const u8,
343 end: *const u8,
344 ) -> Result<PrefixRange, Self::Error> {
345 if self.subtree_depth >= self.max_subtree_depth {
346 Err(ArchiveError::ExceededMaximumSubtreeDepth {
347 max_subtree_depth: self.max_subtree_depth,
348 })
349 } else {
350 let result = PrefixRange {
351 range: Range {
352 start: end,
353 end: self.subtree_range.end,
354 },
355 depth: self.subtree_depth,
356 };
357 self.subtree_depth += 1;
358 self.subtree_range.end = root;
359 Ok(result)
360 }
361 }
362
363 #[inline]
364 fn pop_prefix_range(&mut self, range: PrefixRange) -> Result<(), Self::Error> {
365 if self.subtree_depth - 1 != range.depth {
366 Err(ArchiveError::RangePoppedOutOfOrder {
367 expected_depth: self.subtree_depth - 1,
368 actual_depth: range.depth,
369 })
370 } else {
371 self.subtree_range = range.range;
372 self.subtree_depth = range.depth;
373 Ok(())
374 }
375 }
376
377 #[inline]
378 unsafe fn push_suffix_subtree_range(
379 &mut self,
380 start: *const u8,
381 root: *const u8,
382 ) -> Result<SuffixRange, Self::Error> {
383 let result = SuffixRange {
384 start: self.subtree_range.start,
385 depth: self.subtree_depth,
386 };
387 self.subtree_depth += 1;
388 self.subtree_range.start = start;
389 self.subtree_range.end = root;
390 Ok(result)
391 }
392
393 #[inline]
394 fn pop_suffix_range(&mut self, range: SuffixRange) -> Result<(), Self::Error> {
395 if self.subtree_depth - 1 != range.depth {
396 Err(ArchiveError::RangePoppedOutOfOrder {
397 expected_depth: self.subtree_depth - 1,
398 actual_depth: range.depth,
399 })
400 } else {
401 self.subtree_range.end = self.subtree_range.start;
402 self.subtree_range.start = range.start;
403 self.subtree_depth = range.depth;
404 Ok(())
405 }
406 }
407
408 #[inline]
409 fn finish(&mut self) -> Result<(), Self::Error> {
410 if self.subtree_depth != 0 {
411 Err(ArchiveError::UnpoppedSubtreeRanges {
412 last_range: self.subtree_depth - 1,
413 })
414 } else {
415 Ok(())
416 }
417 }
418}